我正在整合一个城市交通系统的模拟,并试图提高我的Javascript和画布技能。我在这里提供了一个简单的版本:https://jsfiddle.net/ftmzm9vp/
两个问题:
( 1)我希望“吊舱”以统一的速度运行。现在他们都同时到达目的地,这意味着他们以不同的速度旅行。我该怎么纠正呢?
2)显然我还有更多的工作要做--让吊舱沿着现有线路行驶,找出到达目的地的最佳路径,扩大线路和站点的数量--所有这些都将增加计算开销。现在,随着我想要使用的500荚,动画开始爬行。我重写了全部内容,以使用requestAnimFrame,因为我认为它会更快,但它似乎不像它应该是顺利的。我能做些什么来改善这一点呢?谢谢!
<!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>发布于 2015-08-17 18:20:55
您的车辆都在同一时间到达他们的目的地,因为你正在根据百分比改变他们的位置。因此,当pct==1.00所有的车辆都同时到达自己的终点时,无论到达目的地所需的距离有多远。
// increment the percent (from 0.00 to 1.00)
pct += .01;基于距离旅行的使车辆到达
Question#1:你可以计算出每一个路径点(waypoint==unique像素),车辆必须通过旅行才能完成它的路线。前进车辆到它的下一个方向点与每一个新的动画帧。这导致每一辆车根据其路线的长度而不是一个统一的百分比到达。
Question#2:对于每个车辆,如果您预先计算并将其路径点保存到一个数组中,您可以在每个动画帧中轻松地在画布上绘制500辆车辆。
这里有注解和演示:
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);
}body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }<canvas id="canvas" width=350 height=300></canvas>
发布于 2015-08-17 15:35:36
为了让你的豆荚保持同样的速度,你可能需要使用毕达哥拉斯定理。低音是指每次rAF出现时,希望节点移动的距离。然后计算出你的x和y。
我不太清楚我是否理解pct的工作。
要加快rAF的速度,您需要:
Prerending是一个多一点的工作,但不是每次画每一个圆圈,每次你有画布,不是在DOM中,你画的。然后,您基本上可以将“隐藏”画布放置在任何您想要的可见DOM画布之上。这样就能把画保存在记忆中。
在for-循环结束时,还可以在画布上绘制每个圆圈。用这种方式将填充方法拉到它外面,这样画布就可以批量绘制,而不是一堆小调用(这确实会降低性能)。
每次设置字体都可以删除。
画布在性能上是很棒的,但是你只需要小心一点,因为一个小错误可能会导致一个巨大的瓶颈。
这是一篇很好的文章:http://www.html5rocks.com/en/tutorials/canvas/performance/
如果你还有什么问题请告诉我。
https://stackoverflow.com/questions/32054032
复制相似问题