防止requestAnimationFrame一直运行

2023-11-30

我想知道如何致电animate功能通过requestAnimationFrame仅当确实需要时。目前animate我猜一直被调用会产生开销。

我已经在我的内部尝试过animate比较函数targetRadius和最初的radius一旦它们相同就返回 false。不幸的是这根本不起作用。

有人可以解释一下如何解决这个问题吗?

jsfiddle

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>

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;
});

你需要实施一个状况因此您可以打破循环,例如(根据需要采用):

var isRunning = true;

function loop() {

    ... funky stuff here ...

    /// test condition before looping
    if (isRunning) requestAnimationFrame(loop);
}

现在当你设置isRunning to false循环将会中断。为了方便起见,建议您有一个启动和停止循环的方法:

function startLoop(state) {

    if (state && !isRunning) {
        isRunning = true;
        loop();             /// starts loop

    } else if (!state && isRunning) {
        isRunning = false;
    }
}

条件可以通过您需要设置的任何内容来设置,例如在动画完成后的回调上等。重要的是条件标志可用于使用它的两个作用域(即最常见于全局范围)。

UPDATE:

在这种情况下更具体的是,您的条件(半径)永远不会达到最终停止循环所需的条件。

您可以采取以下措施来解决此问题:

DEMO

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);
}

为了触发循环,我们使用一种方法来检查循环是否正在运行,如果没有,它将重置isPlaying标记并开始循环。我们在两个内部都这样做mouseover and mouseout:

canvas.on('mouseover', function(e){
    mouseover = true;
    startAnim();

}).on('mouseout', function(){
    mouseover = false;
    startAnim();
});

方法很简单,检查一下isPlaying如果没有设置,则将其设置为 true 并启动循环 - 这样循环只启动一次:

function startAnim() {
    if (!isPlaying) {
        isPlaying = true;
        requestAnimationFrame(animate);
    }
}

在演示中,我添加了控制台日志记录以显示循环何时运行以及何时命中目标。

希望这可以帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

防止requestAnimationFrame一直运行 的相关文章

随机推荐

  • 自定义 Orchard 导航菜单

    抱歉我问了这么笼统的问题 我正在使用 Orchard CMS 创建一个网站 网站的设计和交互性是关键要求 我有一个固定大小 900 px 宽 的导航菜单 但应该能够调整尽可能多的菜单项 我通过修改 css 手动执行此操作 我使用了一些 jQ
  • 如何使用ajax更改事件对象后刷新fullcalendar v4

    我使用 fullcalendar v4 来显示事件 事件正常显示在加载中 但我需要使用多个复选框添加一个过滤器 并在使用 ajax 的 onchange 复选框后刷新 fullcalendar 事件 更改后 我得到新的对象事件 但我需要刷新
  • 使用 Windows 8 SDK 为 Windows 7 进行编译

    这个问题使用 zlib 作为示例 但并不特定于它 我正在尝试使用它附带的 MSVC 项目文件在 Windows 上编译 zlib 我使用 VS2012 和 Windows 8 SDK 但我的构建机器是 Windows 7 Zlib包含以下代
  • 有关 Google Workspace SCIM 实施的文档吗?

    我需要为 Azure 和 Google Workspace 开发 SCIM 端点 Azure 和 Okta 有关于它的很好的技术文档 但我在 Google 方面找不到任何内容 我所能找到的只是有关如何从目录中配置应用程序的一些帮助 我需要知
  • Excel 电子表格的数据驱动单元测试

    如何在 VS2012 中设置从 Excel xlsx 电子表格读取数据的数据驱动单元测试方法 我尝试用谷歌搜索解决方案 但结果要么引用旧版本的 Visual Studio 要么不针对 xlsx 文件 到目前为止 我有一个测试类 测试方法和数
  • PYTHON:*函数*中的双下划线前缀参数

    下面是在builtins pyi def max arg1 T arg2 T args T key Callable T SupportsLessThan gt T 我确实知道名称修饰的含义 并且知道名称修饰将影响类定义字段中的每个 xxx
  • R:在 nlsLM() 语句内进行汇总

    我在用着nlsLM 制作幂函数的模型 但我需要在函数调用中汇总数据以找到适当的系数和指数 更具体地说 我的模型代码如下所示 Jmod nlsLM value a summarise funs mean MW b start list a 1
  • 通过变量引用的 VBA 宏 workbook.open 或 workbook.activate

    如何引用我的主工作簿和通过此子过程打开的第二个工作簿 我尝试做workbooks client path activate因为我使用这个宏的目标是打开一个单独的工作簿 该工作簿被分配给变量client path并将 A A 列中的每个 1
  • 在函数中传递矩阵 (C)

    我在将矩阵传递给 C 中的函数时遇到问题 我想创建一个函数 void ins int matrix int row int column 但我注意到与向量相反 矩阵给了我一个错误 我怎样才能将我的矩阵传递给函数呢 编辑 gt 有代码 Mat
  • javascript 参数对象的 python 版本 - 它存在吗?

    在 JavaScript 中 每个函数都有一个特殊的arguments预定义对象 其中保存有关传递给函数调用的参数的信息 例如 function test var args Array prototype slice call argume
  • JPA 2.0:TYPE 表达式异常

    我有一个类的继承结构 假设父类 作为根类 和子类作为子类 因此 对于 JPA 2 0 我只能使用以下方式选择父类 SELECT p FROM Parent p WHERE TYPE p Parent 这只应该返回父项的条目 而不返回子项的条
  • MySQL INSERT INTO 与 IF NOT EXIST 的双重条件

    如果电子邮件地址在 list email email addr 中不存在且在 list no email email addr 中不存在 我尝试插入新记录 INSERT INTO list email fname lname email a
  • Java多次使用扫描仪[重复]

    这个问题在这里已经有答案了 我经常遇到这个问题 当我多次使用扫描仪时 它不会从用户那里获取输入 Scanner scan new Scanner System in System out println 1 int try1 scan ne
  • R 正则表达式引擎在 3.2.0 中发生了变化?

    将R更新到3 2 0版本后 来自 春之舞 3 1 0 我遇到了不可预见的正则表达式错误 我有以下代码来查找包含 X 的字符 后跟四个或更多数字 library stringr vec c X12345 X12 X235252 X442 st
  • 如何在 Swift 中对绘图进行动画处理,同时更改 UIImageView 比例?

    我想为绘图序列制作动画 我的代码在 UIImageView image 中绘制了一个螺旋 序列改变了图像内容 也改变了scale周围的 UIImageView 该代码针对螺旋的转数进行参数化 func drawSpiral rotation
  • javascript while 循环或设置具有动态延迟的间隔

    我需要在 JavaScript 中有一个永无止境的循环 这几乎就像设定的间隔一样 但对于每个循环 需要动态应用时间延迟 每个循环的延迟值都会改变 那么是否可以将 while 与某种睡眠功能一起使用 或者是否可以更改每次迭代的设置间隔时间 以
  • 删除包含特定字符串的组

    我有一个关于删除行中包含某些字符串的组的问题 例如 如果包含 我希望在不破坏管道的情况下实现这一目标 我的意思是不使用任何join功能 示例数据 vals lt c good bad ugly good bad ugly gr lt gl
  • 当文件中出现文本行时如何使用 Bash 执行某些操作

    我想在日志文件中出现特定文本时立即运行命令 我如何在 Bash 中做到这一点 使用命令 tail f file log grep line buffered my pattern while read line do echo line d
  • 如何让Python中的字符串重复出现

    如何使字符串重复自身 例如 而不是写作print 我该怎么做print 60 你之前是so close gt gt gt print 60 你需要乘以str value not的返回值print 功能
  • 防止requestAnimationFrame一直运行

    我想知道如何致电animate功能通过requestAnimationFrame仅当确实需要时 目前animate我猜一直被调用会产生开销 我已经在我的内部尝试过animate比较函数targetRadius和最初的radius一旦它们相同