js制御canvasで実現したwindows上のラジオ、マルチ選択、ドラッグ制御を模したtoyプログラム
17066 ワード
機能には、マウスクリックラジオ、ドラッグマルチ選択、ctrl+クリックコンビネーション効果、選択した単一または複数のcanvasレイヤをマウスドラッグ、方向キー移動、delete削除レイヤなどがあります.
複雑な感じがするのは主に制御ロジックで、以下はすべてのコード(注釈付きですよ)で、htmlファイルに直接コピーして保存してブラウザで効果を見ることができます
複雑な感じがするのは主に制御ロジックで、以下はすべてのコード(注釈付きですよ)で、htmlファイルに直接コピーして保存してブラウザで効果を見ることができます
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="/jqplot/excanvas.min.js"></script><![endif]-->
<script type="text/javascript">
var list=[];
var currentC;
var selected=[];
var _e={};
var showTimer;
var keyBoardTimer;
var move=false;
var hit=false;
var inZoom=false;
var exist=false;
var ctrlDown=false;
var directDown='';
var cricle = function(x,y,r){
this.x=x;
this.y=y;
this.r=r;
this.angle=10;
this.posB={};
this.isCurrent=false;
/* flag , , */
this.drawC=function(ctx,x,y,posA){
ctx.save();
ctx.beginPath();
ctx.moveTo(this.x,this.y-this.r);
ctx.arc(this.x,this.y,this.r,2*Math.PI,0,true);
/* */
for(var i=selected.length;i--;){
if(this===selected[i]){
exist=true;
console.log('exits');
}
}
console.log('exitfor');
/*1. , posA ,
*2. x,y .( )
*/
if (!posA && x && y && this.isCurrent) {
ctx.fillStyle = '#ff0000';
currentC=this;
this.isCurrent=true;
if(selected.length>0){
console.log(selected.length);
if(!exist){
console.log('notexits');
selected.push(this);
}
exist=false;/* , */
}else{
selected.push(this);
}
}else{
if(posA){/* , */
//console.log('1');
/* posB:{ , , }*/
this.posB={'x1':(this.x-this.r),'y1':(this.y-this.r),'x2':(this.x+this.r),'y2':(this.y+this.r),'x3':(this.x+this.r),'y3':(this.y-this.r),'x4':(this.x-this.r),'y4':(this.y+this.r),'x':this.x,'y':this.y,'angle':this.angle};
/* posB:{ , , , }*/
//this.posB={x1,y1,x2,y2,x3,y3,x4,y4,x,y,angle}
var flag=testCollision(posA,this.posB);
if(flag){
//console.log('2');
if(selected.length>0){
if(!exist){
console.log('notexits');
selected.push(this);
}
exist=false;/* , */
}else{
selected.push(this);
}
console.log('selected',selected.length);
ctx.fillStyle = '#ff0000';
}else{
//console.log('3');
ctx.fillStyle = '#999999';
}
}else{/* , 。( , )*/
if(exist){
ctx.fillStyle = '#ff0000';
}else{
ctx.fillStyle = '#999999';
}
exist=false;/* , */
}
}
ctx.fill();
ctx.restore();
}
/* , */
this.testHit=function(ctx,x,y){
/* */
if(currentC){
currentC.isCurrent=false;
currentC=null;
}
ctx.save();
ctx.beginPath();
ctx.moveTo(this.x,this.y-this.r);
ctx.arc(this.x,this.y,this.r,2*Math.PI,0,true);
if (ctx.isPointInPath(x, y)){
hit=true;
currentC=this;
this.isCurrent=true;
}
ctx.restore();
}
}
function draw(action){
console.log('draw func');
var canvas = document.getElementById('tutorial');
canvas.height = canvas.height;// ,
if (canvas.getContext){
var ctx = canvas.getContext('2d');
console.log(['directDown',directDown]);
if(action===undefined){/* */
for(var i=0;i<10;i++){
var c=new cricle(20*i,20*i,5*i);
c.drawC(ctx);//
list.push(c);
}
}else{/* */
console.log('delete');
for(var i=0;i<list.length;i++){
var c=list[i];
c.drawC(ctx);
}
}
}
}
function reDraw(e,posA){// flag
console.log('reDraw func');
if(e){
e=e||event;
var canvas = document.getElementById('tutorial');
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
}
/* selected, */
if(posA){
selected=[];
}
canvas.height = canvas.height;// ,
//var ctx = canvas.getContext('2d');
//ctx.clearRect(0,0,canvas.width,canvas.height);
if (canvas.getContext){
var ctx = canvas.getContext('2d');
for(var i=0;i<list.length;i++){
var c=list[i];
if(posA){
c.drawC(ctx,x,y,posA);//
}else{
console.log('ininin');
c.drawC(ctx,x,y);// : 、 、
}
}
}
}
function show(e){
console.log('show func');
move=true;
e=e||event;
var canvas = document.getElementById('tutorial');
var ctx = canvas.getContext('2d');
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
var _x = _e.clientX - canvas.offsetLeft;
var _y = _e.clientY - canvas.offsetTop;
//showTimer=setInterval(function(e){reDraw(e);console.log('showTimer');},10,_e);//
/* , , showTimer
* , showTimer ,
*/
if(!hit){
console.log('not hit');
console.log('dragrect');
//clearInterval(showTimer);
dragRect(e,_e,__e);
}else{
if(selected.length>1){/* */
if(inZoom){
/* */
console.log('length>1 inzoom');
for(var i=selected.length;i--;){
var c=selected[i];
c.x=c.x+(x-_x);
c.y=c.y+(y-_y);
}
reDraw(e);
}else{
/* , */
console.log('length>1 notinzoom');
selected=[];
if(currentC){
currentC.x=currentC.x+(x-_x);
currentC.y=currentC.y+(y-_y);
reDraw(e)
}
}
}else{/* */
/* */
console.log('length<=1 inzoom');
if(currentC){
currentC.x=currentC.x+(x-_x);
currentC.y=currentC.y+(y-_y);
reDraw(e)
}
}
}
_e=e;
}
function dragRect(e,_e,__e){
console.log('dragRect func');
var pos={};
var canvas = document.getElementById('tutorial');
canvas.style.zIndex='100';
//
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
//
var _x = _e.clientX - canvas.offsetLeft;
var _y = _e.clientY - canvas.offsetTop;
//
var __x = __e.clientX - canvas.offsetLeft;
var __y = __e.clientY - canvas.offsetTop;
pos.x1=x;
pos.y1=y;
pos.x2=__x;
pos.y2=__y;
reDraw(e,pos);
var context=canvas.getContext("2d");
//context.save();
// context.clearRect(__x,__y,(_x-__x),(_y-__y));
// reDraw(e,pos);
// context.fillStyle="rgba(10%,25%,10%,0.1)"; //
// context.strokeStyle="000"; //
// context.linewidth=1; //
// context.fillRect(x,y,(__x-x),(__y-y)); // x y
//context.strokeRect(x,y,(__x-x),(__y-y)); // x y
//context.restore();
context.beginPath();
context.setLineDash([5,2]);
context.rect(__x,__y,(_x-__x),(_y-__y));
context.stroke();
}
window.onload=function(){
var canvas = document.getElementById('tutorial');
draw();// ,(x,y) ,
canvas.onmousedown=function(e){
move=false;
e=e||event;
var x = e.clientX - canvas.offsetLeft;
var y = e.clientY - canvas.offsetTop;
//if(currentC) currentC.isCurrent=false;// ,
//currentC=null;//
/* , */
if (canvas.getContext){
var ctx = canvas.getContext('2d');
for(var i=list.length;i--;){
var c=list[i];
c.testHit(ctx,x,y);
if(hit) break;
}
}
/* , selected 0 */
if(selected.length>0){
for(var i=selected.length;i--;){
var c=selected[i];
if(currentC===selected[i]){
inZoom=true;
break;
}
}
}
/* ctrl */
if(hit && !ctrlDown){
if(inZoom){/* */
console.log(selected.length);
console.log('inZoom');
/* , ( hit ), : , */
}else{/* */
/* : , */
console.log('notinZoom');
selected=[];
reDraw(e);
}
}else{
/* , ctrl , , */
//selected=[];
}
_e=e;
__e=e;
//showTimer=setInterval(function(e){reDraw(e);},10,_e);//
canvas.onmousemove=show;//
document.onmouseup=function(){
/* , , */
if(!move){
if(!hit){/* , 、 */
if(currentC){
currentC.isCurrent=false;
currentC=null;
}
selected=[];
}else{/* */
hit=false;/* */
if(ctrlDown){/* ctrl*/
if(!inZoom){/* selected , , selected , */
selected.push(currentC);
}else{
if(currentC){
currentC.isCurrent=false;
currentC=null;
}
console.log(['splice',selected.length]);
selected.splice(i,1);
console.log(['splice',selected.length]);
}
}else{/* ctrl, selected, */
selected=[];
}
}
inZoom=false;
reDraw(e);
}else{
move=false;/* , */
hit=false;/* , */
inZoom=false;/* , */
}
// ,
// ,
canvas.onmousemove=null;//
//reDraw(e);
clearInterval(showTimer);//
console.log('up');
}
}
document.onkeydown=function(e){
var ev = window.event || e;
console.log(['keydown',ev.keyCode]);
switch(ev.keyCode){
case 17:
ctrlDown=true;
break;
case 37:
ev.preventDefault();
directDown=true;
keyboardMove(-1,0);
break;
case 38:
directDown=true;
ev.preventDefault();
keyboardMove(0,-1);
break;
case 39:
directDown=true;
ev.preventDefault();
keyboardMove(1,0);
break;
case 40:
directDown=true;
ev.preventDefault();
keyboardMove(0,1);
break;
case 46:
keyboardDelete();
break;
}
}
document.onkeyup=function(e){
var ev=window.event || e;
//ev.preventDefault();
console.log(['keyup',ev.keyCode]);
switch(ev.keyCode){
case 17:
ctrlDown=false;
break;
case 37:
case 38:
case 39:
case 40:
directDown=false;
break;
case 46:
}
}
}
/* */
function keyboardMove(x,y){
if(selected.length>0){
for(var i=selected.length;i--;){
var c=selected[i];
c.x+=x;
c.y+=y;
}
}else if(currentC){
currentC.x+=x;
currentC.y+=y;
}
draw('direct');
}
/*delete */
function keyboardDelete(){
/* */
var tempList=[];
if(selected.length>0){
for(var j=list.length;j--;){
var flag=true;
for(var i=selected.length;i--;){
if(list[j]===selected[i]){
flag=false;
break
}
}
if(flag){
tempList.push(list[j]);
}
}
list=tempList;
}else if(currentC){
for(var j=list.length;j--;){
if(list[j]===currentC){
list.splice(j,1);
break
}
}
}
draw('delete');
}
/* */
function testCollision(posA,posB){
//console.log(['posA',posA]);
//console.log(['posB',posB]);
var crossA=lineSpace(posA.x1,posA.y1,posA.x2,posA.y2);
var crossB=lineSpace(posB.x1,posB.y1,posB.x2,posB.y2);
var centerB={};
var crossPos={};
var centerA={};
var max={};
var min={};
var sh={};
var flag=false;
centerA.x=((posA.x1-posA.x2)>0)?(posA.x1-(posA.x1-posA.x2)/2):(posA.x2-(posA.x2-posA.x1)/2);
centerA.y=((posA.y1-posA.y2)>0)?(posA.y1-(posA.y1-posA.y2)/2):(posA.y2-(posA.y2-posA.y1)/2);
var centerAToB=lineSpace(centerA.x,centerA.y,posB.x,posB.y);
if(centerAToB>((crossA+crossB)/2)){
//console.log('4');
return flag;
}
if(posB.angle===0){
//console.log('5');
/* */
/*crossPos:{ : , , : , }*/
if(posA.x1>posA.x2 && posA.y1>posA.y2){
/* */
crossPos={'x1':posB.x1,'y1':posB.y1,'x2':posB.x2,'y2':posB.y2,'x3':posA.x2,'y3':posA.y2,'x4':posA.x1,'y4':posA.y1};
flag=simpleTest(crossPos);
return flag;
}else if(posA.x1<posA.x2 && posA.y1<posA.y2){
/* */
//console.log('6');
crossPos={'x1':posB.x1,'y1':posB.y1,'x2':posB.x2,'y2':posB.y2,'x3':posA.x1,'y3':posA.y1,'x4':posA.x2,'y4':posA.y2};
flag=simpleTest(crossPos);
//console.log(flag);
return flag;
}else if(posA.x1<posA.x2 && posA.y1>posA.y2){
/* */
var x1=posA.x1;
var y1=posA.y2;
var x2=posA.x2;
var y2=posA.y1;
crossPos={'x1':posB.x1,'y1':posB.y1,'x2':posB.x2,'y2':posB.y2,'x3':x1,'y3':y1,'x4':x2,'y4':y2};
flag=simpleTest(crossPos);
return flag;
}else if(posA.x1>posA.x2 && posA.y1<posA.y2){
/* */
var x1=posA.x2;
var y1=posA.y1;
var x2=posA.x1;
var y2=posA.y2;
crossPos={'x1':posB.x1,'y1':posB.y1,'x2':posB.x2,'y2':posB.y2,'x3':x1,'y3':y1,'x4':x2,'y4':y2};
flag=simpleTest(crossPos);
return flag;
}
}else{
//console.log(' ');
/* */
/* x、y , */
max.Bx1=Math.max(posB.x1,posB.x2,posB.x3,posB.x4);
max.By1=Math.max(posB.y1,posB.y2,posB.y3,posB.y4);
min.Bx1=Math.min(posB.x1,posB.x2,posB.x3,posB.x4);
min.By1=Math.min(posB.y1,posB.y2,posB.y3,posB.y4);
max.Ax1=Math.max(posA.x1,posA.x2);
max.Ay1=Math.max(posA.y1,posA.y2);
min.Ax1=Math.min(posA.x1,posA.x2);
min.Ay1=Math.min(posA.y1,posA.y2);
if(max.Bx1<min.Ax1 || max.Ax1<min.Bx1 || max.By1<min.Ay1 || max.Ay1<min.By1){
return false;
}
/* */
/* B14 */
sh.x=posB.y4-posB.y1;
sh.y=posB.x1-posB.x4;
sh.x1=posA.x1-posA.x3;
sh.y1=posA.y1-posA.y3;
var lineA1=getShadow(sh);
sh.x1=posA.x1-posA.x4;
sh.y1=posA.y1-posA.y4;
var lineA2=getShadow(sh);
sh.x1=posA.x2-posA.x3;
sh.y1=posA.y2-posA.y3;
var lineA3=getShadow(sh);
sh.x1=posA.x2-posA.x4;
sh.y1=posA.y2-posA.y4;
var lineA4=getShadow(sh);
var maxB=lineSpace(posB.x1,posB.y1,posB.x3,posB.y3);
var maxA=Math.max(lineA1,lineA2,lineA3,lineA4);
var minA=Math.min(lineA1,lineA2,lineA3,lineA4);
if(maxB<minA || maxA<0){
return false;
}
/* B13 */
sh.x=posB.y3-posB.y1;
sh.y=posB.x1-posB.x3;
sh.x1=posA.x1-posA.x3;
sh.y1=posA.y1-posA.y3;
var lineA1=getShadow(sh);
sh.x1=posA.x1-posA.x4;
sh.y1=posA.y1-posA.y4;
var lineA2=getShadow(sh);
sh.x1=posA.x2-posA.x3;
sh.y1=posA.y2-posA.y3;
var lineA3=getShadow(sh);
sh.x1=posA.x2-posA.x4;
sh.y1=posA.y2-posA.y4;
var lineA4=getShadow(sh);
var maxB=lineSpace(posB.x1,posB.y1,posB.x4,posB.y4);
var maxA=Math.max(lineA1,lineA2,lineA3,lineA4);
var minA=Math.min(lineA1,lineA2,lineA3,lineA4);
if(maxB<minA || maxA<0){
return false;
}
return true;
}
}
/*shadow:{ :x,y, :x1,y1}*/
function getShadow(sh){
var temp1,temp2,length;
temp1=sh.x*sh.y1+sh.y*sh.x1;
temp2=Math.sqrt(sh.x*sh.x+sh.y*sh.y);
length=temp1/temp2;
return length;
}
function simpleTest(crossPos){
//console.log(['crossPos',crossPos]);
/* */
var maxx=Math.max(crossPos.x1,crossPos.x3);
var maxy=Math.max(crossPos.y1,crossPos.y3);
/* */
var minx=Math.min(crossPos.x2,crossPos.x4);
var miny=Math.min(crossPos.y2,crossPos.y4);
if(maxx>minx || maxy>miny){
return false;
}else{
return true;
}
}
function pointToLine(x0,y0,x1,y1,x2,y2){
var space=0;
var a=lineSpace(x1,y1,x2,y2);//
var b=lineSpace(x0,y0,x1,y1);//(x1,y1)
var c=lineSpace(x0,y0,x2,y2);//(x2,y2)
if(c+b===a){
space=0;
return space;
}
if(a<=0.000001){
alert(' ');
return;
}
var p=(a+b+c)/2;
var s=Math.sqrt(p*(p-a)*(p-b)*(p-c));
space=2*s/a;
return space;
}
function lineSpace(x1,y1,x2,y2){
var lineLength=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
return lineLength;
}
</script>
<style type="text/css">
canvas { border: 1px solid black; }
</style>
</head>
<body style="background:#eeeeee;">
<canvas id="tutorial" width="1000" height="550" style="z-index:100;display:block;position:absolute;"></canvas>
</body>
</html>