dam*_*zzi 1 javascript css jquery html5-canvas requestanimationframe
我想知道如何只在真正需要时调用该animate函数requestAnimationFrame.目前,我animate一直在调用产生开销的东西.
我已经尝试在我的animate函数内部进行比较targetRadius和初始化radius并在它们相同时返回false.不幸的是,这根本不起作用.
有人可以解释我如何解决这个问题吗?
HTML:
<canvas id="ddayCanvas" width="288" height="288" data-image="http://www.topdesignmag.com/wp-content/uploads/2011/07/64.png">
<div>
<div class="product-image"></div>
<div class="product-box">...</div>
<a href="#" class="overlay">...</a>
</div>
</canvas>
Run Code Online (Sandbox Code Playgroud)
JS:
// Options
var maxImageWidth = 250,
maxImageHeight = 196;
var canvas = $('#ddayCanvas'),
canvasWidth = canvas.width(),
canvasHeight = canvas.height(),
sectorColor = $('.product-box').css('background-color'),
context = canvas[0].getContext('2d'),
imageSrc = canvas.data('image'),
imageObj = new Image(),
imageWidth, imageHeight,
mouseover = false;
imageObj.onload = function() {
imageWidth = this.width;
imageHeight = this.height;
if (imageWidth > maxImageWidth){
imageHeight = imageHeight - (imageWidth - maxImageWidth);
imageWidth = maxImageWidth;
}
if (imageHeight > maxImageHeight) {
imageWidth = imageWidth - (imageHeight - maxImageHeight);
imageHeight = maxImageHeight;
}
drawDday(90);
};
imageObj.src = imageSrc;
function drawDday (radius) {
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.drawImage(imageObj, Math.ceil((canvasWidth - imageWidth) / 2), Math.ceil((canvasHeight - imageHeight) / 2), imageWidth, imageHeight);
context.fillStyle = sectorColor;
context.beginPath();
context.rect(0, 0, canvasWidth, canvasHeight);
context.arc(canvasWidth/2, canvasHeight/2, radius, 0, Math.PI*2, true);
context.closePath();
context.fill();
// Check out the console
console.log('test');
}
var radius = baseRadius = 90,
targetRadius = 110,
ease = 50,
speed = 2;
function animate(){
if(mouseover){
radius += ((targetRadius-radius)/ease)*speed;
} else {
radius -= ((radius-baseRadius)/ease)*speed;
}
if(radius > targetRadius) radius = targetRadius;
if(radius < baseRadius) radius = baseRadius;
drawDday(radius);
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
canvas.on('mouseover', function(e){
mouseover = true;
}).on('mouseout', function(){
mouseover = false;
});
Run Code Online (Sandbox Code Playgroud)
小智 5
您需要实现一个条件,以便您可以打破循环,例如(根据需要采用):
var isRunning = true;
function loop() {
... funky stuff here ...
/// test condition before looping
if (isRunning) requestAnimationFrame(loop);
}
Run Code Online (Sandbox Code Playgroud)
现在,当你设置isRunning为false循环将打破.为方便起见,建议您使用方法来启动和停止循环:
function startLoop(state) {
if (state && !isRunning) {
isRunning = true;
loop(); /// starts loop
} else if (!state && isRunning) {
isRunning = false;
}
}
Run Code Online (Sandbox Code Playgroud)
条件可以由你需要设置的任何东西来设置,例如在动画完成后的回调等等.重要的部分是条件标志可用于使用它的两个范围(即最常见的全局)范围).
更新:
在这种情况下更具体的是,您的条件(半径)将永远不会达到最终停止循环所需的条件.
您可以采取以下措施来解决此问题:
var isPlaying = false;
function animate(){
/**
* To make sure you will reach the condition required you need
* to either make sure you have a fall-out for the steps or the
* step will become 0 not adding/subtracting anything so your
* checks below won't trigger. Here we can use a simple max of
* the step and a static value to make sure the value is always > 0
*/
if(mouseover){
radius += Math.max( ((targetRadius-radius)/ease)*speed, 0.5);
} else {
radius -= Math.max( ((radius-baseRadius)/ease)*speed, 0.5);
}
/**
* Now the checks will trigger properly and we can use the
* isPlaying flag to stop the loop when targets are reached.
*/
if(radius >= targetRadius) {
radius = targetRadius;
isPlaying = false; /// stop loop after this
} else if (radius <= baseRadius) {
radius = baseRadius;
isPlaying = false; /// stop loop after this
}
drawDday(radius);
/// loop?
if (isPlaying === true) requestAnimationFrame(animate);
}
Run Code Online (Sandbox Code Playgroud)
为了触发循环,我们使用一种方法来检查循环是否正在运行,如果不是,它将重置isPlaying标志并启动循环.我们这样做既里面mouseover和mouseout:
canvas.on('mouseover', function(e){
mouseover = true;
startAnim();
}).on('mouseout', function(){
mouseover = false;
startAnim();
});
Run Code Online (Sandbox Code Playgroud)
该方法只是检查isPlaying,如果没有设置它将其设置为true并启动循环 - 这样循环只启动一次:
function startAnim() {
if (!isPlaying) {
isPlaying = true;
requestAnimationFrame(animate);
}
}
Run Code Online (Sandbox Code Playgroud)
在演示中,我添加了控制台日志记录,以显示循环何时运行以及何时命中目标.
希望这可以帮助.