Язык программирования:
Javascript
Среда программирования:
HTML5 + JS
<body style="background:#000"> <canvas id="myCanvas" style="background: #666; z-index:1; position:absolute; left: 500px; top: 300px"></canvas> <canvas id="myCanvas2" style="background: rgba(0,0,0,0); z-index:2; position:absolute; left: 500px; top: 300px"></canvas> </body> <script> var click = false //тригерим нажатие (для рисованя и смещения лампочки) var mouse = false var go = false var e = 3 canvas = document.getElementById("myCanvas") //динамический слой (обновляется каждый фрейм) canvas2 = document.getElementById("myCanvas2") //статический (на нем рисуем) ctx = canvas.getContext("2d") ctx2 = canvas2.getContext("2d") w = canvas2.width = canvas.width = 500 h = canvas2.height = canvas.height = 500 source = {x:w/2,y:h/2} //источник света segments = [] // массив для хранения отрисованных отрезков var temp var lightmove = false ctx.lineWidth = 2 ctx2.lineWidth = 5 document.addEventListener("mousedown", function(e){ if(e.clientX-500>source.x-20&&e.clientX-500<source.x+20&&e.clientY-300>source.y-20&&e.clientY-300<source.y+20){ lightmove=true mouse=e } else {click=e; go=true} })//передаем событие в переменную (в нем содержатся координаты нажатия) document.addEventListener("mousemove", function(e){mouse=e}) document.addEventListener("mouseup", function(e){ mouse=false ctx2.closePath() go=false lightmove=false }) function shadow(a,b){ //отрисовка тени //немного смещаем границы отреезка, чтобы тень от фигуры сливалась в одну a1 = {x: a.x-b.x, y: a.y-b.y} len1 = Math.sqrt(a1.x*a1.x + a1.y*a1.y) b1 = {x: b.x-a.x, y: b.y-a.y} len2 = Math.sqrt(b1.x*b1.x + b1.y*b1.y) aNew = {x: a.x+a1.x/len1, y:a.y+a1.y/len1} bNew = {x: b.x+b1.x/len1, y:b.y+b1.y/len1} a=aNew;b=bNew //векторы-проекторы заведомо большего размера v1 = {x:(a.x-source.x)*1000,y:(a.y-source.y)*1000} v2 = {x:(b.x-source.x)*1000,y:(b.y-source.y)*1000} //заливаем четырехугольник, состоящий из точек отрезка и точек пересечения лучей с границами ctx.beginPath() ctx.moveTo(a.x,a.y) ctx.lineTo(a.x+v1.x,a.y+v1.y) ctx.lineTo(b.x+v2.x,b.y+v2.y) ctx.lineTo(b.x,b.y) ctx.lineTo(a.x,a.y) ctx.fillStyle="#333" ctx.fill() ctx.closePath() } var first function draw(){ ctx.clearRect(0,0,w,h) //очищаем canvas (только 1ый) ctx.beginPath() if(lightmove){source.x=mouse.clientX-500;source.y=mouse.clientY-300}//двигаем лампу var grd=ctx.createRadialGradient(source.x,source.y,300,source.x,source.y,10) grd.addColorStop(1,"white") grd.addColorStop(0,"#666") ctx.arc(source.x,source.y,310,0,Math.PI*2)//русуем источник света ctx.fillStyle=grd ctx.fill() ctx.closePath() if(click){//рисуем первую точку ctx2.beginPath() ctx2.moveTo(click.clientX-500, click.clientY-300) first = temp = {x:click.clientX-500,y:click.clientY-300} click=false } if(mouse&&go){ ctx2.lineTo(mouse.clientX-500, mouse.clientY-300) segments.push({a:temp,b:{x:mouse.clientX-500,y:mouse.clientY-300}}) temp = {x:mouse.clientX-500,y:mouse.clientY-300} if(temp.x>first.x-8&&temp.x<first.x+8&&temp.y>first.y-8&&temp.y<first.y+8){ ctx2.fillStyle = "#000" //если контур замкнулся - заливаем ctx2.fill() } ctx2.strokeStyle = "#000" ctx2.stroke() } for (i of segments){ //отбрасываем тень от всех сегментов shadow(i.a,i.b) } requestAnimationFrame(draw) } draw() </script>
Прикрепленный файл | Размер |
---|---|
sirota_shadow.rar | 1.67 кб |