闲话少叙,先上图:
什么,还要代码?
HTML:
<div>
<label class="am-padding-xs">选择区域</label>
<input class="am-text-left am-text-xs"id="area"type="text"value="陕西,西安,碑林">
<input type="hidden" name="areaId" id="areaId" value="27,428,2920" required>
</div>
JS:
// 城市级联选择
varcityData;
$.ajax({
url:'/res/common/city.json',
async:false,
success:function(data){
cityData=data;
}
});
vararea =newLArea();
area.init({
'trigger':'#area',// 触发选择控件的文本框,同时选择完毕后name属性输出到该位置
'valueTo':'#areaId',// 选择完毕后id属性输出到该位置
'keys': {
city_id:'city_id',
title:'title'
},
'type':1,// 数据源类型
'data': cityData// 数据源
});
area.value=[27,428,2920];// 初始位置,注意:该方法并不会影响到input的value
JS插件代码:
window.LArea=(function() {
varMobileArea=function() {
this.gearArea;
this.data;
this.index=0;
this.value=[0,0,0];
}
MobileArea.prototype={
init:function(params) {
this.params=params;
this.trigger=document.querySelector(params.trigger);
if(params.valueTo){
this.valueTo=document.querySelector(params.valueTo);
}
this.keys=params.keys;
this.type=params.type||1;
switch(this.type) {
case1:
case2:
break;
default:
thrownewError('错误提示: 没有这种数据源类型');
break;
}
this.bindEvent();
},
getData:function(callback) {
var_self=this;
if(typeof_self.params.data=="object") {
_self.data=_self.params.data;
callback();
}else{
varxhr=newXMLHttpRequest();
xhr.open('get', _self.params.data);
xhr.onload=function(e) {
if((xhr.status>=200&&xhr.status<300)||xhr.status===0) {
varresponseData=JSON.parse(xhr.responseText);
_self.data=responseData.data;
if(callback) {
callback()
};
}
}
xhr.send();
}
},
bindEvent:function() {
var_self=this;
//呼出插件
functionpopupArea(e) {
_self.gearArea=document.createElement("div");
_self.gearArea.className="gearArea";
_self.gearArea.innerHTML='
'
'
'
''+
'
'
'
'
'+'
''+
''+
'
'
'+'
''+
''+
'
'
'+'
''+
''+
''+
''+
'';
document.body.appendChild(_self.gearArea);
areaCtrlInit();
varlarea_cancel=_self.gearArea.querySelector(".larea_cancel");
larea_cancel.addEventListener('touchstart',function(e) {
_self.close(e);
});
varlarea_finish=_self.gearArea.querySelector(".larea_finish");
larea_finish.addEventListener('touchstart',function(e) {
_self.finish(e);
});
vararea_province=_self.gearArea.querySelector(".area_province");
vararea_city=_self.gearArea.querySelector(".area_city");
vararea_county=_self.gearArea.querySelector(".area_county");
area_province.addEventListener('touchstart', gearTouchStart);
area_city.addEventListener('touchstart', gearTouchStart);
area_county.addEventListener('touchstart', gearTouchStart);
area_province.addEventListener('touchmove', gearTouchMove);
area_city.addEventListener('touchmove', gearTouchMove);
area_county.addEventListener('touchmove', gearTouchMove);
area_province.addEventListener('touchend', gearTouchEnd);
area_city.addEventListener('touchend', gearTouchEnd);
area_county.addEventListener('touchend', gearTouchEnd);
}
//初始化插件默认值
functionareaCtrlInit() {
_self.gearArea.querySelector(".area_province").setAttribute("val", _self.value[0]);
_self.gearArea.querySelector(".area_city").setAttribute("val", _self.value[1]);
_self.gearArea.querySelector(".area_county").setAttribute("val", _self.value[2]);
switch(_self.type) {
case1:
_self.setGearTooth(_self.data);
break;
case2:
_self.setGearTooth(_self.data[0]);
break;
}
}
//触摸开始
functiongearTouchStart(e) {
e.preventDefault();
vartarget=e.target;
while(true) {
if(!target.classList.contains("gear")) {
target=target.parentElement;
}else{
break
}
}
clearInterval(target["int_"+target.id]);
target["old_"+target.id]=e.targetTouches[0].screenY;
target["o_t_"+target.id]=(newDate()).getTime();
vartop=target.getAttribute('top');
if(top) {
target["o_d_"+target.id]=parseFloat(top.replace(/em/g,""));
}else{
target["o_d_"+target.id]=0;
}
target.style.webkitTransitionDuration=target.style.transitionDuration='0ms';
}
//手指移动
functiongearTouchMove(e) {
e.preventDefault();
vartarget=e.target;
while(true) {
if(!target.classList.contains("gear")) {
target=target.parentElement;
}else{
break
}
}
target["new_"+target.id]=e.targetTouches[0].screenY;
target["n_t_"+target.id]=(newDate()).getTime();
varf=(target["new_"+target.id]-target["old_"+target.id])*30/window.innerHeight;
target["pos_"+target.id]=target["o_d_"+target.id]+f;
target.style["-webkit-transform"]='translate3d(0,'+target["pos_"+target.id]+'em,0)';
target.setAttribute('top', target["pos_"+target.id]+'em');
if(e.targetTouches[0].screenY<1){
gearTouchEnd(e);
};
}
//离开屏幕
functiongearTouchEnd(e) {
e.preventDefault();
vartarget=e.target;
while(true) {
if(!target.classList.contains("gear")) {
target=target.parentElement;
}else{
break;
}
}
varflag=(target["new_"+target.id]-target["old_"+target.id])/(target["n_t_"+target.id]-target["o_t_"+target.id]);
if(Math.abs(flag)<=0.2) {
target["spd_"+target.id]=(flag<0?-0.08:0.08);
}else{
if(Math.abs(flag)<=0.5) {
target["spd_"+target.id]=(flag<0?-0.16:0.16);
}else{
target["spd_"+target.id]=flag/2;
}
}
if(!target["pos_"+target.id]) {
target["pos_"+target.id]=0;
}
rollGear(target);
}
//缓动效果
functionrollGear(target) {
vard=0;
varstopGear=false;
functionsetDuration() {
target.style.webkitTransitionDuration=target.style.transitionDuration='200ms';
stopGear=true;
}
clearInterval(target["int_"+target.id]);
target["int_"+target.id]=setInterval(function() {
varpos=target["pos_"+target.id];
varspeed=target["spd_"+target.id]*Math.exp(-0.03*d);
pos+=speed;
if(Math.abs(speed)>0.1) {}else{
varb=Math.round(pos/2)*2;
pos=b;
setDuration();
}
if(pos>0) {
pos=0;
setDuration();
}
varminTop=-(target.dataset.len-1)*2;
if(pos
pos=minTop;
setDuration();
}
if(stopGear) {
vargearVal=Math.abs(pos)/2;
setGear(target, gearVal);
clearInterval(target["int_"+target.id]);
}
target["pos_"+target.id]=pos;
target.style["-webkit-transform"]='translate3d(0,'+pos+'em,0)';
target.setAttribute('top', pos+'em');
d++;
},30);
}
//控制插件滚动后停留的值
functionsetGear(target, val) {
val=Math.round(val);
target.setAttribute("val", val);
switch(_self.type) {
case1:
_self.setGearTooth(_self.data);
break;
case2:
switch(target.dataset['areatype']){
case'area_province':
_self.setGearTooth(_self.data[0]);
break;
case'area_city':
varref=target.childNodes[val].getAttribute('ref');
varchildData=[];
varnextData=_self.data[2];
for(variinnextData) {
if(i==ref){
childData=nextData[i];
break;
}
};
_self.index=2;
_self.setGearTooth(childData);
break;
}
}
}
_self.getData(function() {
_self.trigger.addEventListener('click', popupArea);
});
},
//重置节点个数
setGearTooth:function(data) {
var_self=this;
varitem=data||[];
varl=item.length;
vargearChild=_self.gearArea.querySelectorAll(".gear");
vargearVal=gearChild[_self.index].getAttribute('val');
varmaxVal=l-1;
if(gearVal>maxVal) {
gearVal=maxVal;
}
gearChild[_self.index].setAttribute('data-len', l);
if(l>0) {
varid=item[gearVal][this.keys['city_id']];
varchildData;
switch(_self.type) {
case1:
childData=item[gearVal].children
break;
case2:
varnextData=_self.data[_self.index+1]
for(variinnextData) {
if(i==id){
childData=nextData[i];
break;
}
};
break;
}
varitemStr="";
for(vari=0; i
itemStr+="
}
gearChild[_self.index].innerHTML=itemStr;
gearChild[_self.index].style["-webkit-transform"]='translate3d(0,'+(-gearVal*2)+'em,0)';
gearChild[_self.index].setAttribute('top',-gearVal*2+'em');
gearChild[_self.index].setAttribute('val', gearVal);
_self.index++;
if(_self.index>2) {
_self.index=0;
return;
}
_self.setGearTooth(childData);
}else{
gearChild[_self.index].innerHTML="
";gearChild[_self.index].setAttribute('val',0);
if(_self.index==1){
gearChild[2].innerHTML="
";gearChild[2].setAttribute('val',0);
}
_self.index=0;
}
},
finish:function(e) {
var_self=this;
vararea_province=_self.gearArea.querySelector(".area_province");
vararea_city=_self.gearArea.querySelector(".area_city");
vararea_county=_self.gearArea.querySelector(".area_county");
varprovinceVal=parseInt(area_province.getAttribute("val"));
varprovinceText=area_province.childNodes[provinceVal].textContent;
varprovinceCode=area_province.childNodes[provinceVal].getAttribute('ref');
varcityVal=parseInt(area_city.getAttribute("val"));
varcityText=area_city.childNodes[cityVal].textContent;
varcityCode=area_city.childNodes[cityVal].getAttribute('ref');
varcountyVal=parseInt(area_county.getAttribute("val"));
varcountyText=area_county.childNodes[countyVal].textContent;
varcountyCode=area_county.childNodes[countyVal].getAttribute('ref');
_self.trigger.value=provinceText+((cityText)?(','+cityText):(''))+((countyText)?(','+countyText):(''));
_self.value=[provinceVal, cityVal, countyVal];
if(this.valueTo){
this.valueTo.value=provinceCode+((cityCode)?(','+cityCode):(''))+((countyCode)?(','+countyCode):(''));
}
_self.close(e);
},
close:function(e) {
e.preventDefault();
var_self=this;
varevt=newCustomEvent('input');
_self.trigger.dispatchEvent(evt);
document.body.removeChild(_self.gearArea);
_self.gearArea=null;
}
}
returnMobileArea;
})()