javascript面向对象特性实现连线应用,开放代码,求交流 canvasjavascript面向对象连线 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 晒个代码顶一下! 欢迎帖子回复或qq交流 114-021-5489。<!doctype html><html><head> <title>javascript面向对象特性实现连线应用</title> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <style> *{padding:0;margin:0;font: 18px 'Microsoft Yahei';} .matchByLineBox{margin:50px;width: 500px;height: 250px;border: 1px solid red;position:relative;float: left;} .matchSide{border: 1px solid #333;position: absolute;} .mlBoxCol .matchSide{width:200px;min-height: 200px;top: 5px; } .mlBoxCol .matchSideQue{left: 5px;} .mlBoxCol .matchSideAns{right: 5px;} .matchOne{border: 1px solid #ccc;margin: 2px;min-width: 50px;min-height: 50px;}</style><script src="http://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script><script type="text/javascript"> //适配移动端 AdaptUtil={ touchAble:'ontouchstart' in window, eventNameInit:function(){ mousedown =this.touchAble ? "touchstart ":"mousedown "; mouseup =this.touchAble ? "touchend ":"mouseup "; mousemove =this.touchAble ? "touchmove ":"mousemove "; mouseout=this.touchAble ? "touchcancel ":"mouseout "; }, //转成可以直接获取坐标的事件对象 getAdaptEvt:function(e,index){//jqEvent,触点索引 if(this.touchAble){ index=index==undefined ? 0 :index; e=e.originalEvent.changedTouches[index]; } return e; } } /***********************************以上PC移动端兼容处理*****************************/ function MatchByLine(cvsBox){//构造函数 this.cvsBox =cvsBox; this.cvs=undefined; this.begin=undefined; this.beginOne=undefined; this.beginIsQue=false; } MatchByLine.prototype={//类方法 init:function(){ var self=this; var cvsBox=self.cvsBox; self.cvs=document.createElement("canvas"); cvsBox.prepend(self.cvs); cvsBox.on(mousedown,function (e) { var pointEvt=AdaptUtil.getAdaptEvt(e); var ot=$(pointEvt.target); if(! ot.hasClass('matchOne') && ot.parents(".matchOne").length==0) return false; self.begin=self.getEvtCoorInMatchCvs(pointEvt); self.beginOne=ot.hasClass('matchOne') ? ot :ot.parents(".matchOne");//起点的matchOne self.beginIsQue=self.beginOne.parents(".matchSide").hasClass('matchSideQue'); return false; }).on(mousemove,function (e) { var begin=self.begin; var beginOne=self.beginOne; var beginIsQue=self.beginIsQue; if(begin==undefined) return false; var pointEvt=AdaptUtil.getAdaptEvt(e); var clientX=pointEvt.clientX,clientY=pointEvt.clientY; end=self.getEvtCoorInMatchCvs(pointEvt); var endOne=self.getOverMatchOne(clientX,clientY); if(endOne==null){//落点不在matchOne内 self.drawMatchLine(begin,end); return false; } var endIsQue=endOne.parents(".matchSide").hasClass('matchSideQue'); if(beginIsQue ^ endIsQue){//起落点在不同侧 var matchOne_que,matchOne_ans; if(beginIsQue){//判断起落点分别在问题侧还是答案侧 matchOne_que=beginOne; matchOne_ans=endOne; }else{ matchOne_que=endOne; matchOne_ans=beginOne; } matchOne_que.attr('ans', matchOne_ans.text()); self.drawMatchLine(); self.begin=undefined; }else{//起点和落点在同一侧 无效 答案不更新 self.drawMatchLine(begin,end); } }).on(mouseup,function (e) { self.begin=undefined; self.drawMatchLine(); }) }, getOverMatchOne:function(clientX,clientY){ var one=null; var cvsBox=this.cvsBox; var mos=cvsBox.find('.matchOne'); mos.each(function(i){ var cr=mos.eq(i)[0].getBoundingClientRect(); var minLeft=cr.left,minTop=cr.top,width=cr.width,height=cr.height; var maxLeft=minLeft+width,maxTop=minTop+height; if(clientX>= minLeft && clientX<=maxLeft && clientY>=minTop && clientY<=maxTop){ one=mos.eq(i); return false; } }) return one; }, drawLine :function(begin,end){ var ctx=this.cvs.getContext('2d'); ctx.beginPath(); ctx.moveTo(begin.x,begin.y); ctx.lineTo(end.x,end.y); ctx.strokeStyle="green"; ctx.lineWidth = 2; ctx.stroke(); }, drawMatchLine:function(begin,end){ var self=this; var cvsBox= self.cvsBox; var cvs = self.cvs; cvs.width=cvsBox.width(),cvs.height=cvsBox.height(); var ctx=cvs.getContext('2d'); ctx.clearRect(0,0,cvs.width,cvs.height); var ques=cvsBox.find('.matchSideQue .matchOne'); var ans=cvsBox.find('.matchSideAns .matchOne'); for (var i = 0; i < ques.length; i++) { var queOne=ques.eq(i); var ansText=queOne.attr('ans'); if(typeof ansText=="undefined") continue; for(var j=0;j<ans.length;j++){ var ansOne=ans.eq(j); if(ansText==ansOne.text()){ var oldBegin=self.getMatchOneJunctionCoor (queOne,"matchByLineBox"); var oldEnd=self.getMatchOneJunctionCoor (ansOne,"matchByLineBox"); self.drawLine(oldBegin,oldEnd); } } } if(typeof begin!="undefined") self.drawLine(begin,end);//up时cvs重绘不执行此句 }, getEvtCoorInMatchCvs:function(pe) { var pageX=pe.pageX,pageY=pe.pageY; var offset=this.getOffsetInParent(this.cvsBox[0],document.body); var x=pageX-offset.left,y=pageY-offset.top; return {x:x,y:y}; }, getOffsetInParent:function(ele,parent){//js ele var left=0,top=0; while(ele && ele!=parent){ left+=ele.offsetLeft; top+=ele.offsetTop; ele=ele.offsetParent; } return {left:left,top:top}; }, getMatchOneJunctionCoor:function(one) { var x=0,y=one.height()/2; if(one.parent().hasClass('matchSideQue')){ x=one.width(); } var offset=this.getOffsetInParent(one[0],this.cvsBox[0]); x+=offset.left,y+=offset.top; return {x:x,y:y}; } }//End MatchByLine.prototype /*********************************以上为MatchByLine类*******************************/ AdaptUtil.eventNameInit(); $(function() { var mblBoxs=$(".matchByLineBox"); mblArr=[];//全局 存储所有mbl实例 mblBoxs.each(function(x){ var mbl=new MatchByLine(mblBoxs.eq(x)); mbl.init(); mblArr.push(mbl); }); addOneMatchLineAns({"id":1,"answer":"B"}); addOneMatchLineAns({"id":4,"answer":"D"}); }) //答案设置接口 如addOneMatchLineAns({id:2,answer:"A"}) function addOneMatchLineAns(ansOneObj){ var ansText=ansOneObj.answer; var queId=ansOneObj.id; var matchOne=$(".matchOne[queId="+queId+"]"); matchOne.attr("ans",ansText); var cvsBox=matchOne.parents(".matchByLineBox"); var mblIndex=$(".matchByLineBox").index(cvsBox); for(var x in mblArr){ if($(".matchByLineBox").index(mblArr[x].cvsBox)==mblIndex){ mblArr[x].drawMatchLine();//找到dom索引相同的实例对象,调用划线方法 } } }</script></head><body> <div class="matchByLineBox mlBoxCol"> <div class="matchSide matchSideQue"> <div class="matchOne" queId="1">甲</div> <div class="matchOne" queId="2">乙</div> </div> <div class="matchSide matchSideAns"> <div class="matchOne">A</div> <div class="matchOne">B</div> </div> </div> <div class="matchByLineBox mlBoxCol"> <div class="matchSide matchSideQue"> <div class="matchOne" queId="3">丙</div> <div class="matchOne" queId="4">丁</div> </div> <div class="matchSide matchSideAns"> <div class="matchOne">C</div> <div class="matchOne">D</div> </div> </div></body></html> javascript设计模式推荐楼主看这本书 doSubmit后html:cancel按钮如何变有效???[ javascript air大侠帮忙解释下 隐藏状态栏?? 如何写这样子的一个正则表达式!! 第二例:js格式化当前时间为yyyy-mm-dd形式 请问大家我用frameset可以分为上下中三部分吗? 如何修改opetion中select属性? javascript函数参数的定义 100分求一正则表达式 你答对我给分 jquery.validationEngine插件 用ajax验证和funcCall验证,验证不通过也提交给服务器啦 新人求教:如何在ASP里获取JS联动菜单的变量值?
<html>
<head>
<title>javascript面向对象特性实现连线应用</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<style>
*{padding:0;margin:0;font: 18px 'Microsoft Yahei';}
.matchByLineBox{margin:50px;width: 500px;height: 250px;border: 1px solid red;position:relative;float: left;}
.matchSide{border: 1px solid #333;position: absolute;}
.mlBoxCol .matchSide{width:200px;min-height: 200px;top: 5px; }
.mlBoxCol .matchSideQue{left: 5px;}
.mlBoxCol .matchSideAns{right: 5px;}
.matchOne{border: 1px solid #ccc;margin: 2px;min-width: 50px;min-height: 50px;}
</style>
<script src="http://cdn.bootcss.com/jquery/2.1.0/jquery.min.js"></script>
<script type="text/javascript">
//适配移动端
AdaptUtil={
touchAble:'ontouchstart' in window,
eventNameInit:function(){
mousedown =this.touchAble ? "touchstart ":"mousedown ";
mouseup =this.touchAble ? "touchend ":"mouseup ";
mousemove =this.touchAble ? "touchmove ":"mousemove ";
mouseout=this.touchAble ? "touchcancel ":"mouseout ";
},
//转成可以直接获取坐标的事件对象
getAdaptEvt:function(e,index){//jqEvent,触点索引
if(this.touchAble){
index=index==undefined ? 0 :index;
e=e.originalEvent.changedTouches[index];
}
return e;
}
} /***********************************以上PC移动端兼容处理*****************************/
function MatchByLine(cvsBox){//构造函数
this.cvsBox =cvsBox;
this.cvs=undefined;
this.begin=undefined;
this.beginOne=undefined;
this.beginIsQue=false;
} MatchByLine.prototype={//类方法
init:function(){
var self=this;
var cvsBox=self.cvsBox;
self.cvs=document.createElement("canvas");
cvsBox.prepend(self.cvs);
cvsBox.on(mousedown,function (e) {
var pointEvt=AdaptUtil.getAdaptEvt(e);
var ot=$(pointEvt.target);
if(! ot.hasClass('matchOne') && ot.parents(".matchOne").length==0) return false;
self.begin=self.getEvtCoorInMatchCvs(pointEvt);
self.beginOne=ot.hasClass('matchOne') ? ot :ot.parents(".matchOne");//起点的matchOne
self.beginIsQue=self.beginOne.parents(".matchSide").hasClass('matchSideQue');
return false;
}).on(mousemove,function (e) {
var begin=self.begin;
var beginOne=self.beginOne;
var beginIsQue=self.beginIsQue;
if(begin==undefined) return false;
var pointEvt=AdaptUtil.getAdaptEvt(e);
var clientX=pointEvt.clientX,clientY=pointEvt.clientY;
end=self.getEvtCoorInMatchCvs(pointEvt);
var endOne=self.getOverMatchOne(clientX,clientY);
if(endOne==null){//落点不在matchOne内
self.drawMatchLine(begin,end);
return false;
}
var endIsQue=endOne.parents(".matchSide").hasClass('matchSideQue');
if(beginIsQue ^ endIsQue){//起落点在不同侧
var matchOne_que,matchOne_ans;
if(beginIsQue){//判断起落点分别在问题侧还是答案侧
matchOne_que=beginOne;
matchOne_ans=endOne;
}else{
matchOne_que=endOne;
matchOne_ans=beginOne;
}
matchOne_que.attr('ans', matchOne_ans.text());
self.drawMatchLine();
self.begin=undefined;
}else{//起点和落点在同一侧 无效 答案不更新
self.drawMatchLine(begin,end);
}
}).on(mouseup,function (e) {
self.begin=undefined;
self.drawMatchLine();
})
},
getOverMatchOne:function(clientX,clientY){
var one=null;
var cvsBox=this.cvsBox;
var mos=cvsBox.find('.matchOne');
mos.each(function(i){
var cr=mos.eq(i)[0].getBoundingClientRect();
var minLeft=cr.left,minTop=cr.top,width=cr.width,height=cr.height;
var maxLeft=minLeft+width,maxTop=minTop+height;
if(clientX>= minLeft && clientX<=maxLeft && clientY>=minTop && clientY<=maxTop){
one=mos.eq(i);
return false;
}
})
return one;
},
drawLine :function(begin,end){
var ctx=this.cvs.getContext('2d');
ctx.beginPath();
ctx.moveTo(begin.x,begin.y);
ctx.lineTo(end.x,end.y);
ctx.strokeStyle="green";
ctx.lineWidth = 2;
ctx.stroke();
},
drawMatchLine:function(begin,end){
var self=this;
var cvsBox= self.cvsBox;
var cvs = self.cvs;
cvs.width=cvsBox.width(),cvs.height=cvsBox.height();
var ctx=cvs.getContext('2d');
ctx.clearRect(0,0,cvs.width,cvs.height);
var ques=cvsBox.find('.matchSideQue .matchOne');
var ans=cvsBox.find('.matchSideAns .matchOne');
for (var i = 0; i < ques.length; i++) {
var queOne=ques.eq(i);
var ansText=queOne.attr('ans');
if(typeof ansText=="undefined") continue;
for(var j=0;j<ans.length;j++){
var ansOne=ans.eq(j);
if(ansText==ansOne.text()){
var oldBegin=self.getMatchOneJunctionCoor (queOne,"matchByLineBox");
var oldEnd=self.getMatchOneJunctionCoor (ansOne,"matchByLineBox");
self.drawLine(oldBegin,oldEnd);
}
}
}
if(typeof begin!="undefined") self.drawLine(begin,end);//up时cvs重绘不执行此句
},
getEvtCoorInMatchCvs:function(pe) {
var pageX=pe.pageX,pageY=pe.pageY;
var offset=this.getOffsetInParent(this.cvsBox[0],document.body);
var x=pageX-offset.left,y=pageY-offset.top;
return {x:x,y:y};
},
getOffsetInParent:function(ele,parent){//js ele
var left=0,top=0;
while(ele && ele!=parent){
left+=ele.offsetLeft;
top+=ele.offsetTop;
ele=ele.offsetParent;
}
return {left:left,top:top};
},
getMatchOneJunctionCoor:function(one) {
var x=0,y=one.height()/2;
if(one.parent().hasClass('matchSideQue')){
x=one.width();
}
var offset=this.getOffsetInParent(one[0],this.cvsBox[0]);
x+=offset.left,y+=offset.top;
return {x:x,y:y};
}
}//End MatchByLine.prototype /*********************************以上为MatchByLine类*******************************/
AdaptUtil.eventNameInit();
$(function() {
var mblBoxs=$(".matchByLineBox");
mblArr=[];//全局 存储所有mbl实例
mblBoxs.each(function(x){
var mbl=new MatchByLine(mblBoxs.eq(x));
mbl.init();
mblArr.push(mbl);
}); addOneMatchLineAns({"id":1,"answer":"B"});
addOneMatchLineAns({"id":4,"answer":"D"});
}) //答案设置接口 如addOneMatchLineAns({id:2,answer:"A"})
function addOneMatchLineAns(ansOneObj){
var ansText=ansOneObj.answer;
var queId=ansOneObj.id;
var matchOne=$(".matchOne[queId="+queId+"]");
matchOne.attr("ans",ansText);
var cvsBox=matchOne.parents(".matchByLineBox");
var mblIndex=$(".matchByLineBox").index(cvsBox);
for(var x in mblArr){
if($(".matchByLineBox").index(mblArr[x].cvsBox)==mblIndex){
mblArr[x].drawMatchLine();//找到dom索引相同的实例对象,调用划线方法
}
}
}</script>
</head><body>
<div class="matchByLineBox mlBoxCol">
<div class="matchSide matchSideQue">
<div class="matchOne" queId="1">甲</div>
<div class="matchOne" queId="2">乙</div>
</div>
<div class="matchSide matchSideAns">
<div class="matchOne">A</div>
<div class="matchOne">B</div>
</div>
</div>
<div class="matchByLineBox mlBoxCol">
<div class="matchSide matchSideQue">
<div class="matchOne" queId="3">丙</div>
<div class="matchOne" queId="4">丁</div>
</div>
<div class="matchSide matchSideAns">
<div class="matchOne">C</div>
<div class="matchOne">D</div>
</div>
</div>
</body>
</html>