代码之家  ›  专栏  ›  技术社区  ›  Neniariel

当再次调用相同的函数时,如何停止画布动画?

  •  0
  • Neniariel  · 技术社区  · 4 年前

    (我在这里用了马克的绝妙回答 https://stackoverflow.com/a/23941786 作为动画教程)

    当单击另一个链接时,如何阻止第一个动画完成?

    我试过在几次迭代中创建一个flag和cancelAnimationFrame,但都没有成功。

    下面是一些简化的代码,目前使用的是一个标志:

    <div class="container">
        <nav>
            <ul>
                <li>
                    <a href="#about" id="about" onclick="draw(this.id);">About</a>
                </li>
                <li>
                    <a href="#contact" id="contact" onclick="draw(this.id);">Work</a>
                </li>
            </ul>
        </nav>
    </div>
    <canvas id="canvas"  width="500" height="500"></canvas>
    

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var isRunning = false;
    function draw(contentId) {
        if (isRunning) return;
        isRunning = true;
        var t = 1;
        var vertices = [];
        function calcWaypoints(vertices) {
            var waypoints = [];
            for (var i = 1; i < vertices.length; i++) {
                var pt0 = vertices[i - 1];
                var pt1 = vertices[i];
                var dx = pt1.x - pt0.x;
                var dy = pt1.y - pt0.y;
                for (var j = 0; j < 100; j++) {
                    var x = pt0.x + dx * j / 100;
                    var y = pt0.y + dy * j / 100;
                    waypoints.push({
                        x: x,
                        y: y
                    });
                }
            }
            return (waypoints);
        }
    
        function animate() {
            if (t < points.length - 1) {
                window.requestAnimationFrame(animate);
            }
    
            ctx.beginPath();
            ctx.moveTo(points[t - 1].x, points[t - 1].y);
            ctx.lineTo(points[t].x, points[t].y);
            ctx.stroke();
            t++;
            isRunning = false;
        }
    
    // Clear the canvas before drawing
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    // Assign coordinates
        if (contentId == 'about') {
            vertices.push({x: 50, y: 0}, {x: 50, y: 50});
            vertices.push({x: 40, y: 60}, {x: 0, y: 60});
    // Animate lines
            ctx.lineCap = "round";
            ctx.lineWidth = border;
            ctx.strokeStyle = "green";
            var points = calcWaypoints(vertices);
            animate(points);
        }
        if (contentId == 'contact') {
            vertices.push({x: 150, y: 0}, {x: 150, y: 50});
            vertices.push({x: 160, y: 60}, {x: 300, y: 60});
            vertices.push({x: 300, y: 70}, {x: 310, y: 70});
            ctx.lineCap = "round";
            ctx.lineWidth = border;
            ctx.strokeStyle = "green";
            var points = calcWaypoints(vertices);
            animate(points);
        }
    }
    

    只是重申一下,以防我不清楚:当我点击“关于”,然后直接点击“接触”,我想画动画是初始化时,我第一次点击“关于”完全停止(包括清除画布)和“接触”动画开始而不是。目前,“接触”动画确实开始了,但“关于”动画也坚持要完成。当我两次点击“about”时,同样的事情发生了-动画同时运行两次。。。

    0 回复  |  直到 4 年前
        1
  •  0
  •   Neniariel    4 年前

    如果它对任何人都有帮助,我设法解决了它(逻辑中出现了一些错误,cancelAnimationFrame最终做了我需要的事情,而不是使用标志):

    HTML格式

    <div class="container">
        <nav>
            <ul>
                <li>
                    <a href="#about" id="about" onclick="checkDraw(this.id);">About</a>
                </li>
                <li>
                    <a href="#contact" id="contact" onclick="checkDraw(this.id);">Work</a>
                </li>
            </ul>
        </nav>
    </div>
    <canvas id="canvas"  width="500" height="500"></canvas>
    

    JavaScript语言

    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    var requestId;
    function checkDraw(contentId) {
        stopAnimation();
        draw(contentId);
    }
    
    function stopAnimation(e) {
        cancelAnimationFrame(requestId);
    }
    
    function draw(contentId) {
        currentID = contentId;
        var t = 1;
        var vertices = [];
        function calcWaypoints(vertices) {
            var waypoints = [];
            for (var i = 1; i < vertices.length; i++) {
                var pt0 = vertices[i - 1];
                var pt1 = vertices[i];
                var dx = pt1.x - pt0.x;
                var dy = pt1.y - pt0.y;
                for (var j = 0; j < 100; j++) {
                    var x = pt0.x + dx * j / 100;
                    var y = pt0.y + dy * j / 100;
                    waypoints.push({
                        x: x,
                        y: y
                    });
                }
            }
            return (waypoints);
        }
    
        function animate() {
            if (t < points.length - 1) {
                requestId = requestAnimationFrame(animate);
            }
    
            ctx.beginPath();
            ctx.moveTo(points[t - 1].x, points[t - 1].y);
            ctx.lineTo(points[t].x, points[t].y);
            ctx.stroke();
            t++;
        }
    
    // Clear the canvas before drawing
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    // Assign coordinates
        if (contentId == 'about') {
            vertices.push({x: 50, y: 0}, {x: 50, y: 50});
            vertices.push({x: 40, y: 60}, {x: 0, y: 60});
    // Animate lines
            ctx.lineCap = "round";
            ctx.lineWidth = border;
            ctx.strokeStyle = "green";
            var points = calcWaypoints(vertices);
            animate(points);
        }
        if (contentId == 'contact') {
            vertices.push({x: 150, y: 0}, {x: 150, y: 50});
            vertices.push({x: 160, y: 60}, {x: 300, y: 60});
            vertices.push({x: 300, y: 70}, {x: 310, y: 70});
            ctx.lineCap = "round";
            ctx.lineWidth = border;
            ctx.strokeStyle = "green";
            var points = calcWaypoints(vertices);
            animate(points);
        }
    }