首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >画布动画速度

画布动画速度
EN

Stack Overflow用户
提问于 2015-08-17 15:20:12
回答 2查看 2.6K关注 0票数 0

我正在整合一个城市交通系统的模拟,并试图提高我的Javascript和画布技能。我在这里提供了一个简单的版本:https://jsfiddle.net/ftmzm9vp/

两个问题:

( 1)我希望“吊舱”以统一的速度运行。现在他们都同时到达目的地,这意味着他们以不同的速度旅行。我该怎么纠正呢?

2)显然我还有更多的工作要做--让吊舱沿着现有线路行驶,找出到达目的地的最佳路径,扩大线路和站点的数量--所有这些都将增加计算开销。现在,随着我想要使用的500荚,动画开始爬行。我重写了全部内容,以使用requestAnimFrame,因为我认为它会更快,但它似乎不像它应该是顺利的。我能做些什么来改善这一点呢?谢谢!

代码语言:javascript
复制
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<title>Pod Stations Lines Test</title>
<body>
    <canvas id="layer1" style="z-index: 2;  
                position:absolute;
                left:0px;
                top:0px;
                " height="600px" width="1000">This text is displayed if your browser does not support HTML5 Canvas.</canvas>
    <canvas id="layer2" style="z-index: 3;
                position:absolute;
                left:0px;
                top:0px;
                " height="600px" width="1000">This text is displayed if your browser does not support HTML5 Canvas.</canvas>
    <canvas id="layer3" style="z-index: 1;
                position:absolute;
                left:0px;
                top:0px;
                " height="600px" width="1000">This text is displayed if your browser does not support HTML5 Canvas.</canvas>
    <script>
        //Modified Source: http://jsfiddle.net/m1erickson/HAbfm/
        //
        layer1 = document.getElementById("layer1");
        ctx1 = layer1.getContext("2d");
        layer2 = document.getElementById("layer2");
        ctx2 = layer2.getContext("2d");
        layer3 = document.getElementById("layer3");
        ctx3 = layer3.getContext("2d");

        window.requestAnimFrame = (function(callback) {
            return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback) {
                window.setTimeout(callback, 1000 / 60);
            };
        })();

        //STATION LIST
        var station = [
            ['A', 100, 50],
            ['B', 300, 50],
            ['C', 200, 150],
            ['D', 100, 250],
            ['E', 300, 250],
            ['F', 400, 250]
        ];


        //DRAW LINES
        function drawLines() {

            ctx1.clearRect(0, 0, layer3.width, layer3.height);

            var linkAB = ctx1.beginPath();
            ctx1.moveTo(station[0][1], station[0][2]);
            ctx1.lineTo(station[1][1], station[1][2]);
            ctx1.stroke();
            var linkBC = ctx1.beginPath();
            ctx1.moveTo(station[1][1], station[1][2]);
            ctx1.lineTo(station[2][1], station[2][2]);
            ctx1.stroke();
            var linkCD = ctx1.beginPath();
            ctx1.moveTo(station[2][1], station[2][2]);
            ctx1.lineTo(station[3][1], station[3][2]);
            ctx1.stroke();
            var linkDE = ctx1.beginPath();
            ctx1.moveTo(station[3][1], station[3][2]);
            ctx1.lineTo(station[4][1], station[4][2]);
            ctx1.stroke();
            var linkCE = ctx1.beginPath();
            ctx1.moveTo(station[2][1], station[2][2]);
            ctx1.lineTo(station[4][1], station[4][2]);
            ctx1.stroke();
            var linkEF = ctx1.beginPath();
            ctx1.moveTo(station[4][1], station[4][2]);
            ctx1.lineTo(station[5][1], station[5][2]);
            ctx1.stroke();

        }


        //CREATE PODS

        var podArray = [];

        function Pod(startX, startY, endX, endY, riders, color) {
            this.startX = startX;
            this.startY = startY;
            this.endX = endX;
            this.endY = endY;
            this.riders = riders;
            this.color = color;
        }

        var colorArray = ["gold", "orange", "red", "green", "blue", "black"];

        function randomPass() {
            occ = 1 + Math.floor(Math.random() * 6);
            return occ;
            console.log("Riders " + occ);
        }


        for (i = 0; i < 500; i++) {
            var origNum = Math.floor(Math.random() * station.length);
            var origin = {
                x: station[origNum][1],
                y: station[origNum][2]
            }
            var destNum = Math.floor(Math.random() * station.length);
            while (origNum == destNum) {
                destNum = Math.floor(Math.random() * station.length);
            }
            var destination = {
                x: station[destNum][1],
                y: station[destNum][2]
            }

            podArray.push(new Pod(
            startX = origin.x,
            startY = origin.y,
            endX = destination.x,
            endY = destination.y,
            riders = randomPass(),
            color = colorArray[riders - 1]

            ));
        }

        var pct = 0.00;
        var fps = 60;

        //CALL DRAWING AND ANIMATION
        drawLines();
        animate();

        function animate() {
            setTimeout(function() {

                if (pct <= 1.00) {
                    requestAnimFrame(animate)
                };

                // increment the percent (from 0.00 to 1.00)
                pct += .01;

                // clear the canvas
                ctx3.clearRect(0, 0, layer3.width, layer3.height);

                // draw all podArray
                for (var i = 0; i < podArray.length; i++) {

                    // get reference to next aPod
                    var aPod = podArray[i];

                    var dx = aPod.endX - aPod.startX;
                    var dy = aPod.endY - aPod.startY;
                    var nextX = aPod.startX + dx * pct;
                    var nextY = aPod.startY + dy * pct;

                    //create pod on screen
                    ctx3.fillStyle = aPod.color;
                    ctx3.beginPath();
                    ctx3.arc(nextX, nextY, 5, 0, Math.PI * 2, true);
                    ctx3.fillStyle = aPod.color;
                    ctx3.fill();
                    ctx3.closePath();

                    //STATION LETTERS

                    for (s = 0; s < station.length; s++) {
                        ctx2.font = '12pt Calibri';
                        ctx2.fillStyle = 'red';
                        ctx2.textAlign = 'center';
                        ctx2.fillText(station[s][0], station[s][1], (station[s][2]) + 4);
                    }

                }

            }, 1000 / fps);
        }
    </script>
</body>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-17 18:20:55

您的车辆都在同一时间到达他们的目的地,因为你正在根据百分比改变他们的位置。因此,当pct==1.00所有的车辆都同时到达自己的终点时,无论到达目的地所需的距离有多远。

代码语言:javascript
复制
// increment the percent (from 0.00 to 1.00)
pct += .01;

基于距离旅行的使车辆到达

Question#1:你可以计算出每一个路径点(waypoint==unique像素),车辆必须通过旅行才能完成它的路线。前进车辆到它的下一个方向点与每一个新的动画帧。这导致每一辆车根据其路线的长度而不是一个统一的百分比到达。

Question#2:对于每个车辆,如果您预先计算并将其路径点保存到一个数组中,您可以在每个动画帧中轻松地在画布上绘制500辆车辆。

这里有注解和演示:

代码语言:javascript
复制
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

ctx.lineWidth=2;

// define routes
var routes=[];
routes.push({
  points:linePoints({x:10,y:10},{x:150,y:10}),
  currentPoint:0,
  color:'red',
});
routes.push({
  points:linePoints({x:10,y:50},{x:250,y:65}),
  currentPoint:0,
  color:'green',
});
routes.push({
  points:linePoints({x:10,y:90},{x:325,y:105}),
  currentPoint:0,
  color:'blue',
});

// animation related vars
var lastTime=0;
var delay=1000/60*5;

// start animating
requestAnimationFrame(animate);

function animate(time){
  // return if the desired time hasn't elapsed
  if(time<lastTime){requestAnimationFrame(animate);return;}
  // redraw each route
  ctx.clearRect(0,0,cw,ch);
  // var used to stop animating if all routes are completed
  var isComplete=true;
  for(var i=0;i<routes.length;i++){
    var r=routes[i];
    // increase the currentPoint, but not beyond points.length-1
    if((r.currentPoint+1)<r.points.length-1){
      isComplete=false;
      r.currentPoint++;
    }
    // draw the route to its current point
    ctx.strokeStyle=r.color;
    ctx.beginPath();
    ctx.moveTo(r.points[0].x,r.points[0].y);
    ctx.lineTo(r.points[r.currentPoint].x,r.points[r.currentPoint].y);
    ctx.stroke();
    ctx.fillStyle=r.color;
    ctx.beginPath();
    ctx.arc(r.points[r.currentPoint].x,r.points[r.currentPoint].y,5,0,Math.PI*2);
    ctx.fill();
  }
  // request another frame unless all routes are completed
  if(!isComplete){
    requestAnimationFrame(animate);
  }
}

function linePoints(p1,p2){
  // start building a points array with the starting point
  var points=[p1];
  var dx=p2.x-p1.x;
  var dy=p2.y-p1.y;
  var count=Math.sqrt(dx*dx+dy*dy)*3;
  for(var pct=0;pct<count;pct++){
    // calc next waypoint on the line
    var x=p1.x+dx*pct/count;
    var y=p1.y+dy*pct/count;
    var lastPt=points[points.length-1];
    // add new waypoint if the its integer pixel value has
    // changed from last waypoint
    if(parseInt(x)!==parseInt(lastPt.x) || parseInt(y)!==parseInt(lastPt.y)){
      points.push({x:x,y:y});
    }
  }
  // force the last point to be the ending point
  points[points.length-1]=p2;
  // return a unique points[] forming a line from p1 to p2
  return(points);
}
代码语言:javascript
复制
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
代码语言:javascript
复制
<canvas id="canvas" width=350 height=300></canvas>

票数 1
EN

Stack Overflow用户

发布于 2015-08-17 15:35:36

为了让你的豆荚保持同样的速度,你可能需要使用毕达哥拉斯定理。低音是指每次rAF出现时,希望节点移动的距离。然后计算出你的x和y。

我不太清楚我是否理解pct的工作。

要加快rAF的速度,您需要:

  1. 取消设定的超时时间
  2. 预光机

Prerending是一个多一点的工作,但不是每次画每一个圆圈,每次你有画布,不是在DOM中,你画的。然后,您基本上可以将“隐藏”画布放置在任何您想要的可见DOM画布之上。这样就能把画保存在记忆中。

在for-循环结束时,还可以在画布上绘制每个圆圈。用这种方式将填充方法拉到它外面,这样画布就可以批量绘制,而不是一堆小调用(这确实会降低性能)。

每次设置字体都可以删除。

画布在性能上是很棒的,但是你只需要小心一点,因为一个小错误可能会导致一个巨大的瓶颈。

这是一篇很好的文章:http://www.html5rocks.com/en/tutorials/canvas/performance/

如果你还有什么问题请告诉我。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32054032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档