首页 > 解决方案 > Javascript用不同的参数链接相同的动画函数

问题描述

我正在尝试沿一条路径为一条线设置两条线,一条线然后另一条线。基本上它看起来就像画一条线,停在一个点,然后另一条线在其他地方画。到目前为止,我遇到了实现这一目标的承诺和回调,但作为一个 javascript 新手,这令人困惑

当前动画功能:

/*
*   Animation function draws a line between every point
*/              
var animate = function(p){
    return new Promise(function(resolve) {
        t = 1;
        var runAnimation = function(){
            if(t<p.length-1){
                context.beginPath();
                context.moveTo(p[t-1].x,p[t-1].y);
                context.lineTo(p[t].x,p[t].y);
                context.stroke();
                t++;
                requestAnimationFrame(function(){runAnimation()});
            } else {
                resolve()
            }
        };
        runAnimation();
    });
}

当前对动画函数的调用:

animate(points).then(animate(secondary_points));

这些点类似于:

var points = [{x:100, y:200}];

线条需要遵循的路径只是内部的多个坐标pointssecondary_points

我已经在 SO 上尝试了许多相似的解决方案,但小的差异会导致我搞砸或不理解解决方案。我似乎遇到的最大问题是调用 SAME animate 函数,该 animate 函数需要在不同的参数上运行。

如果没有这个解决方案,使用

animate(points);
animate(secondary_points);

线条是同时绘制的,但结果实际上只是沿路径随机放置点而不是平滑线,我假设是因为两者同时运行。

我将如何解决这个问题,以便沿着 path1 绘制一条线,然后沿着 path2 绘制第二条线?

这可能是一个简单的解决方案,但我已经使用 JS 工作了 3 天,但我的头脑仍然无法适应我必须修复的旧代码的一些语法

谢谢

编辑:

动画的完整流程如下:

我有一个 php 文件,其中包含 2 个画布,每个画布都包含一张地图的图像。php 文件有几个<script/>标签,其中一个调用我正在通过drawPath(source,destination,true)或编写动画的 js 脚本drawPath(source,destination,false)

drawPath 函数使用布尔值来确定要获取哪个画布的上下文,然后通过查找路径并创建points上述路径在从点 A 到点 B 的路径上绘制,然后使用animate(). 地图中有几个中断需要单独的行,这引发了我最初的问题。由于建议,我能够解决这个问题,但现在我遇到了一个更大的问题。

如果我需要从地图A上的A点到地图B上的B点,即

drawPath(source, end_point_of_map_A, true);被称为 then drawPath(start_point_of_map_B, destination, false);,这些线只在一张地图上绘制,它们与之前相似,它们是 1. 随机和 2. 不完整/仅点

我假设这又是由于动画造成的,因为它仅在静态绘制线条时起作用,并且每个动画在单个地图上从点 A 到 B 时起作用

任何帮助表示赞赏!

编辑:

绘图路径()

function drawPath(source, desti, flag) {
    /*
    * Define context
    */
    //lower
    if(!flag){
        var c = document.getElementById("myCanvas");
        context = c.getContext("2d");
    //upper
    } else {
        var cUpr = document.getElementById("myCanvasUpr");
        context = cUpr.getContext("2d");
    }
    /*
    * Clear the variables
    */
    points = [];
    secondary_points = [];
    vertices = [];
    secondary_vertices = [];
    t = 1;
    done = false;




    //check for invalid locations
    if (source != "" && desti != "") {
        context.lineCap = 'round';
        context.beginPath();

        /*
        * Get the coordinates from source and destination strings
        */
        var src = dict[source];
        var dst = dict[desti];

        /*
        * Get the point number of the point on the path that the source and destination connect to
        */

        var begin = point_num[source];
        var finish = point_num[desti];

        /*
        * Draw the green and red starting/ending circles (green is start, red is end)
        */
        context.beginPath();
        context.arc(src[0], src[1], 8, 0, 2 * Math.PI);
        context.fillStyle = 'green';
        context.fill();

        context.beginPath();
        context.arc(dst[0], dst[1], 6, 0, 2 * Math.PI);
        context.fillStyle = 'red';
        context.fill();

        /*
        * Call the function that draws the entire path
        */
        draw_segments(begin, finish, src, dst, flag);
        //window.alert(JSON.stringify(vertices, null, 4))
        /*
        * Edit what the line looks like
        */
        context.lineWidth = 5;
        context.strokeStyle = "#ff0000";
        context.stroke();

    }
}

标签: javascriptanimationpromise

解决方案


处理此问题的一个好方法是将您的线条放入一个数组中,其中每个元素都是线条的一组点。然后你可以调用reduce()它依次触发每个承诺。reduce()如果您是 javascript 新手,需要一点时间来适应,但c在这种情况下,它基本上需要数组的每个元素,做某事,然后某事成为下一个a. 你从一个 resolve promise 开始整个事情,这将是 initial a。承诺链将返回reduce给您,您可以添加最终then结果以了解整个事情何时完成。

例如:

let canvas = document.getElementById('canvas')
let context = canvas.getContext('2d');
var animate = function(p){

    return new Promise(function(resolve) {
        t = 1;
        var runAnimation = function(){
            if(t<p.length-1){
                context.beginPath();
                context.moveTo(p[t-1].x,p[t-1].y);
                context.lineTo(p[t].x,p[t].y);
                context.stroke();
                t++;
                requestAnimationFrame(function(){runAnimation()});
            } else {
                resolve()
            }
        };
        runAnimation();
    });
}

// make some points:

let points = Array.from({length: 200}, (_,i) => ({x:i+1, y:i+2}))
let points2 = Array.from({length: 200}, (_,i) => ({x:300-i, y:i+2}))
let points3 = Array.from({length: 200}, (_,i) => ({x:i*2, y:100+100*Math.sin(i/10)}))

// create an array holding each set

let sets = [points, points2, points3]

// use reduce to call each in sequence returning the promise each time
sets.reduce((a, c) => a.then(() => animate(c)), Promise.resolve())
.then(() => console.log("done"))
<canvas id="canvas" height="300" width="500"></canvas>


推荐阅读