0

我目前正在编写一个网站,单击导航链接后,HTML 画布会在相关内容框上画一条线(我在这里使用了 markE 的精彩答案https://stackoverflow.com/a/23941786作为动画教程)。我正在为这些线条制作动画,我遇到了以下问题:

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

我已经尝试在几次迭代中创建一个标志和 cancelAnimationFrame,但并不高兴。

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

HTML

<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>

JavaScript

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

重申一下,以防我不清楚:当我点击“关于”然后立即点击“联系”时,我希望在我第一次点击“关于”时初始化的绘制动画完全停止(包括清除画布)和“接触”动画开始。目前,“接触”动画确实开始了,但“关于”动画也坚持结束。当我单击“大约”两次时,也会发生同样的事情 - 动画同时运行两次......

4

1 回答 1

0

万一它对任何人有帮助,我设法解决了它(逻辑中有一些错误,并且 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);
    }
}

我希望这是有道理的!

于 2020-05-20T09:03:53.203 回答