#javascript #animation #html5-canvas
#javascript #Анимация #html5-холст
Вопрос:
Я пытаюсь запускать простую анимацию каждый раз, когда пользователь нажимает на холст. Я уверен, что сделал что-то не так, поскольку анимация даже не срабатывает время от времени. Я никогда раньше не использовал анимацию холста и с трудом понимаю, как она должна быть построена в for
цикле.
fgCanvas.on('mousedown', function(e) {
var cX = Math.round((e.offsetX - m) / gS),
cY = Math.round((e.offsetY - m) / gS);
clickDot({x:cX,y:cY});
});
function clickDot(data) {
for (var i = 1; i < 100; i ) {
fctx.clearRect(0, 0, pW, pH);
fctx.beginPath();
fctx.arc(data.x * gS m, data.y * gS m, i/10, 0, Math.PI * 2);
fctx.strokeStyle = 'rgba(255,255,255,' i/10 ')';
fctx.stroke();
}
requestAnimationFrame(clickDot);
}
Полный код здесь: http://jsfiddle.net/3Nk4A /
Другой вопрос в том, как можно замедлить анимацию или добавить некоторое ослабление, чтобы кольца рисовались медленнее к концу, когда они исчезают?
Ответ №1:
Вы можете использовать requestAnimationFrame
plus easing functions
для создания желаемого эффекта:
Демонстрация: http://jsfiddle.net/m1erickson/cevGf /
requestAnimationFrame создает цикл анимации сам по себе — поэтому нет необходимости использовать цикл for внутри цикла анимации requestAnimationFrame.
В своей простейшей форме этот цикл requestAnimationFrame будет анимировать ваш круг:
var counter=1;
animate();
function animate(){
// stop the animation after it has run 100 times
if(counter>100){return;}
// there's more animating to do, so request another loop
requestAnimationFrame(animate);
// calc the circle radius
var radius=counter/10;
// draw your circle
}
Чтобы ускорить или замедлить анимацию, вы можете использовать easings
. Ослабления со временем изменяют значение (например, ваш радиус), но они изменяют это значение неравномерно. Ослабляет ускорение и замедление в течение всего времени анимации.
Роберт Пеннер создал отличный набор алгоритмов упрощения. Дэн Роджерс закодировал их на javascript:
https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
Вы можете увидеть рабочие примеры его функций смягчения здесь:
Вот аннотированный код, использующий requestAnimationFrame
plus easings
для анимации ваших кругов.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
// canvas related variables
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;
var scrollX=$canvas.scrollLeft();
var scrollY=$canvas.scrollTop();
// set the context styles
ctx.lineWidth=1;
ctx.strokeStyle="gold";
ctx.fillStyle="#888";
// variables used to draw amp; animate the ring
var PI2=Math.PI*2;
var ringX,ringY,ringRadius,ingCounter,ringCounterVelocity;
// fill the canvas with a background color
ctx.fillRect(0,0,canvas.width,canvas.height);
// tell handleMouseDown to handle all mousedown events
$("#canvas").mousedown(function(e){handleMouseDown(e);});
// set the ring variables and start the animation
function ring(x,y){
ringX=x;
ringY=y;
ringRadius=0;
ringCounter=0;
ringCounterVelocity=4;
requestAnimationFrame(animate);
}
// the animation loop
function animate(){
// return if the animation is complete
if(ringCounter>200){return;}
// otherwise request another animation loop
requestAnimationFrame(animate);
// ringCounter<100 means the ring is expanding
// ringCounter>=100 means the ring is shrinking
if(ringCounter<100){
// expand the ring using easeInCubic easing
ringRadius=easeInCubic(ringCounter,0,15,100);
}else{
// shrink the ring using easeOutCubic easing
ringRadius=easeOutCubic(ringCounter-100,15,-15,100);
}
// draw the ring at the radius set using the easing functions
ctx.fillRect(0,0,canvas.width,canvas.height);
ctx.beginPath();
ctx.arc(ringX,ringY,ringRadius,0,PI2);
ctx.closePath();
ctx.stroke();
// increment the ringCounter for the next loop
ringCounter =ringCounterVelocity;
}
// Robert Penner's easing functions coded by Dan Rogers
//
// https://github.com/danro/jquery-easing/blob/master/jquery.easing.js
//
// now=elapsed time,
// startValue=value at start of easing,
// deltaValue=amount the value will change during the easing,
// duration=total time for easing
function easeInCubic(now, startValue, deltaValue, duration) {
return deltaValue*(now/=duration)*now*now startValue;
}
function easeOutCubic(now, startValue, deltaValue, duration) {
return deltaValue*((now=now/duration-1)*now*now 1) startValue;
}
// handle mousedown events
function handleMouseDown(e){
// tell the browser we'll handle this event
e.preventDefault();
e.stopPropagation();
// calc the mouse position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// animate a ring at the mouse position
ring(mouseX,mouseY);
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>Click in the canvas to draw animated circle with easings.</h4>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
Комментарии:
1. Отличный ответ! Спасибо.