canvas에서 대상 상호작용의 누추한 실현 보이기
5006 단어 프런트엔드
원인:
csdn의 지난 친구가 canvas에 표시된 대상의 hover 방법을 어떤 방법으로 측정하는지 물었습니다. 본 블로그의'포럼 댓글은 손으로 쓴다'분류에 기록되어 있습니다. 관심 있는 분들은 보실 수 있습니다.
당시에 썼을 때 실현을 목적으로 했을 뿐 확장성이 없고 통용되지 않아서 통용되는 것을 생각했습니다.
그러나 시간 문제로 계속 미루다가 미루다가 잊어버릴지도 모른다.
마침 회사 결정층이 생각을 바꿔서 진행 중인 프로젝트가 좀 바뀌었고 한가해지면 개canvas의 애니메이션 효과와 마우스 클릭 사건의 감청을 간단하게 실현했다.
원리:
[애니메이션]: 사실은 타이머, 윈도우 대상의 setInterval 방법으로 애니메이션을 실현하는 것이다. 플래시 ActionScript 프로그래밍을 한 학생들은 비교적 익숙할 것이다.
[마우스 이벤트]: 초라한 모형에서 마우스 이벤트는 canvas에 마우스가 클릭한 위치를 판단한 다음에 클릭 위치가 도형 구역 안에 있는지 확인하고 hover 이벤트는mousemove 이벤트로 이루어진다. 물론 setInterval의 순환에서 실현될 수 있다.사건 대리, 저는 canvas에 직접 추가하는 습관이 있습니다. 많은 학우들이 canvas에 div를 해서 대리를 했습니다. 그 중의 장점을 잘 모르고 똑똑한 학우들도 많이 가르쳐 주었습니다.
다중 도형 커버의 효과는 이전의 호버 사건 감청에서 이루어졌다.
하위 대상 목록, 이벤트 거품 따위는 시간이 지나면 업데이트합시다.아득히 멀지 않았으면 좋겠는데..
코드는 다음과 같습니다.
한 곳의this는thisthis입니다. 포럼의 코드 포맷에 문제가 있기 때문에 쓴 문제가 아닙니다. 복사한 후에 스스로 수정하고 실행하십시오.클릭 이벤트가 터치된 후 일정 시간 동안 클릭 이벤트를 터치할 수 없는 것은alert가 라인을 막았기 때문입니다. 그러나 setInterval은 계속 실행되기 때문에console로 변경되었습니다.로그는 버그가 아닌 정상적으로 인쇄할 수 있습니다.
that's all.
canvas
<br>// point <br>var CPoint = function(x,y){<br> this.x = x;<br> this.y = y;<br>}<br>CPoint.prototype = {<br> getType:function(){<br> return 'point';<br> },<br> hitTestPoint:function(p){<br> return p.x == this.x && p.y == this.y;<br> },<br> toString:function(){<br> return '[object CPoint]';<br> }<br>};<br>// circle <br>var CCircle = function(radius){<br> this.x = this.y = 0;<br> this.radius = radius;<br>}<br>CCircle.prototype = {<br> getType:function(){<br> return 'circle';<br> },<br> hitTestPoint:function(p){<br> return (this.x - p.x) * (this.x - p.x) + (this.y - p.y)*(this.y - p.y) <= this.radius * this.radius;<br> },<br> toString:function(){<br> return '[object CCircle]';<br> }<br>}<br>// rectangle <br>var CRectangle = function(width,height){<br> this.x = this.y = 0;<br> this.width = width;<br> this.height = height;<br>}<br>CRectangle.prototype = {<br> getType:function(){<br> return 'rectangle';<br> },<br> hitTestPoint:function(p){<br> return p.x > (this.x-this.width/2) && p.x < (this.x + this.width/2) && p.y > (this.y-this.height/2) && p.y < (this.y + this.height/2);<br> },<br> toString:function(){<br> return '[object CRectangle]';<br> }<br>}<br>// root <br>var root = [];<br>root.addChild = function (s){<br> this.push(s);<br>}<br>root.start = function (){<br> this.timer = setInterval(function(){<br> UpdateCtx(root.ctx);<br> root.onEnterFrame && root.onEnterFrame();<br> },25);<br>}<br>root.stop = function (){<br> clearInterval(this.timer);<br>}<br>root.toString = function (){<br> return '[object root]';<br>}<br>// <br>function DrawShapeOnCtx(ctx,s){<br> ctx.beginPath();<br> ctx.lineWidth = 2;<br> ctx.strokeStyle = '#333'<br> switch(s.getType()){<br> case 'circle':<br> ctx.arc(s.x,s.y,s.radius,0,Math.PI*2,false);<br> break;<br> case 'rectangle':<br> ctx.strokeRect(s.x - s.width/2,s.y-s.height/2,s.width,s.height);<br> break;<br> }<br> ctx.stroke();<br> ctx.closePath();<br>}<br>// canvas <br>function UpdateCtx (ctx){<br> ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);<br> for(var i=root.length-1;i>-1;i--)<br> DrawShapeOnCtx(ctx,root[i]);<br>}<br>// <br>var c = new CCircle(20);;<br>c.x = 100;<br>c.y = 100;<br>var r = new CRectangle(100,20);<br>r.x = 100;<br>r.y = 300;<br>root.addChild(c);<br>root.addChild(r);<br>root.ctx = document.getElementById('cvs').getContext('2d');<br>root.onEnterFrame = function (){<br> c.x += 5;<br> if(c.x > root.ctx.canvas.width-c.radius){<br> c.x = -c.radius;<br> }<br>}<br>root.start();<br>root.ctx.canvas.onclick = function(e){<br> var p = new CPoint(e.clientX,e.clientY);<br> if(r.hitTestPoint(p) || c.hitTestPoint(p)){<br> alert('You have clicked the shape!');<br> };<br>}<br>