我正在继续制作运输系统模型的动画。代码构建工作站,用线连接它们,构建“pods”以沿着它们运行,然后计算随机起始站和终端站之间的最短路径。
The problems I am having are a) the pods are traveling one at a time, rather than simultaneously. b) the pod color is supposed to be related to the number of passengers, but this is clearly not happening. c) I suspect I am producing a bottleneck in calculating the animation points, as it seems to run more hesitantly than it should.
我还希望能够标记每个吊舱的到来,以便重新加载,并开始新的旅程。
动画部分出了问题,但我无法解决问题。任何帮助将不胜感激!
animate();
var lastTime = 0;
var speed = 1; // higher is slower
function animate(time) {
for (var i = 0; i < podArray.length; i++) {
var aPod = podArray[i];
// calculate incremental points along the path
var points = calcWaypoints(aPod.wayStations);
// return if the desired time hasn't elapsed
if ((time - lastTime) < speed) {
requestAnimationFrame(animate);
return;
}
lastTime = time;
//function animate(){
ctx3.clearRect(0, 0, layer3.width, layer3.height);
if (t < points.length - 1) {
requestAnimationFrame(animate);
}
// draw pod from the last waypoint to the current waypoint
ctx3.beginPath();
ctx3.moveTo(aPod.startX, aPod.startY); //(points[t - 1].x, points[t - 1].y);
ctx3.arc(points[t].x, points[t].y, 4, 0, Math.PI * 2, true);
ctx3.fillStyle = aPod.color;
ctx3.fill();
t++;
}
}
答案 0 :(得分:2)
a)您的calcWaypoints
函数采用的是一个参数,这是一个Waystation列表,然后您忽略该参数并计算所有pod的所有点。这是创建所有点的一个大数组,从第一个pod点开始,然后是第二个点,等等。这就是为什么它从第一个开始,然后是第二个,然后是第三个。
function calcWaypoints(nextArray) {
var frams = 100;
var waypoints = [];
for (var i = 1; i < nextArray.length; i++) {
var pt0 = nextArray[i - 1];
var pt1 = nextArray[i];
var dx = pt1[0] - pt0[0];
var dy = pt1[1] - pt0[1];
for (var j = 0; j < frams; j++) {
var x = pt0[0] + dx * j / frams //+ dxOff;
var y = pt0[1] + dy * j / frams //+ dyOff;
waypoints.push({
x: x,
y: y
});
};
}
return waypoints;
}
b)这与前一个原因相同,因为您对每个窗格使用相同的点,所以窗格会相互叠加。此外,您正在清除每个点之间的画布。这个明确应该移出循环。 ctx3.clearRect(0, 0, layer3.width, layer3.height);
requestAnimationFrame
的过多调用。我在上面修改了一些上述更改并且正在运行。你还应该把它清理得更多:
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);
};
})();
//STATIONS*************************************
var station = [
['A', 150, 100],
['B', 300, 100],
['C', 200, 175],
['D', 100, 250],
['E', 300, 250],
['G', 400, 250],
['F', 350, 200],
['Airport', 500, 200],
['Central', 500, 350]
];
function draw2() {
for (var i = 0; i < station.length; i++) {
var radius = 10;
ctx2.beginPath();
ctx2.arc(station[i][1], station[i][2], radius, 0, 2 * Math.PI);
ctx2.stroke();
ctx2.fillStyle = 'yellow';
ctx2.fill();
//ADD STATION LETTERS
ctx2.font = '10pt Calibri';
ctx2.fillStyle = 'black';
ctx2.textAlign = 'center';
ctx2.fillText(station[i][0], station[i][1], (station[i][2]) + 4);
}
}
draw2();
//END STATIONS*************************************
//START LINES**************************************
var lineArray = [
['A', 'B', ],
['B', 'A', 'C'],
['C', 'B', 'D', 'E'],
['D', 'C', 'E'],
['E', 'D', 'F', 'G', 'Central'],
['F', 'E', 'G'],
['G', 'F', 'E', 'Airport'],
['Airport', 'G', 'Central'],
['Central', 'E', 'Airport']
];
function drawLines() {
for (m = 0; m < lineArray.length; m++) {
ctx1.lineWidth = 1;
ctx1.beginPath();
for (p = 1; p < lineArray[m].length; p++) {
var startStat = lineArray[m][0];
var stat = lookUp(startStat);
var beginX = station[stat][1];
var beginY = station[stat][2];
ctx1.moveTo(beginX, beginY);
var endStat = lineArray[m][p];
var endSt = lookUp(endStat);
var closeX = station[endSt][1];
var closeY = station[endSt][2];
ctx1.lineTo(closeX, closeY);
}
ctx1.stroke();
}
}
drawLines();
//END LINES*************************************
//SHORTEST PATH*********************************
function Graph() {
var neighbors = this.neighbors = {}; // Key = vertex, value = array of neighbors.
this.addEdge = function (u, v) {
if (neighbors[u] === undefined) { // Add the edge u -> v.
neighbors[u] = [];
}
neighbors[u].push(v);
if (neighbors[v] === undefined) { // Also add the edge v -> u in order
neighbors[v] = []; // to implement an undirected graph.
} // For a directed graph, delete
neighbors[v].push(u); // these four lines.
};
return this;
}
function shortestPath(graph, source, target) {
var stationPath = [];
var coordPath = [];
if (source == target) { // Delete these four lines if
print(source); // you want to look for a cycle
return; // when the source is equal to
} // the target.
var queue = [source],
visited = {
source: true
},
predecessor = {},
tail = 0;
while (tail < queue.length) {
var u = queue[tail++], // Pop a vertex off the queue.
neighbors = graph.neighbors[u];
for (var i = 0; i < neighbors.length; ++i) {
var v = neighbors[i];
if (visited[v]) {
continue;
}
visited[v] = true;
if (v === target) { // Check if the path is complete.
var path = [v]; // If so, backtrack through the path.
while (u !== source) {
path.push(u);
u = predecessor[u];
}
path.push(u);
path.reverse();
print(path.join(' → '));
//console.log('Path: ' + path);
for (s = 1; s < path.length; s++) {
stationPath.push(path[s]);
}
//console.log('Waypoints: ' + stationPath);
for (t = 0; t < stationPath.length; t++) {
staCo = lookUp(stationPath[t]);
staCoX = station[staCo][1];
staCoY = station[staCo][2];
coordPath.push([staCoX, staCoY]);
}
//console.log(coordPath);
return coordPath;
}
predecessor[v] = u;
queue.push(v);
}
}
print('there is no path from ' + source + ' to ' + target);
}
function print(s) { // A quick and dirty way to display output.
s = s || '';
document.getElementById('display').innerHTML += s + '<br>';
}
function findShortestPath(s1, s2) {
var graph = new Graph();
for (w = 0; w < lineArray.length; w++) {
var baseStation = lineArray[w][0];
for (z = 1; z < lineArray[w].length; z++) {
graph.addEdge(baseStation, lineArray[w][z]);
}
}
return (shortestPath(graph, s1, s2));
};
function lookUp(sta) {
//console.log(sta);
for (n = 0; n < station.length; n++) {
if (sta == station[n][0]) {
return n;
break;
}
}
}
//BUILD PODS*************************************
var podArray = [];
function Pod(startX, startY, wayStations, riders, color) {
this.startX = startX;
this.startY = startY;
this.wayStations = wayStations;
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;
}
//PROGRAM PODS*********************************************
for (i = 0; i < 3; i++) { //NUMBER OF PODS
//Start Station
var startOff = Math.floor(Math.random() * station.length);
var begSta = station[startOff][0];
var fromX = station[startOff][1];
var fromY = station[startOff][2];
//END STATION
var destNum = Math.floor(Math.random() * station.length);
while (startOff == destNum) {
destNum = Math.floor(Math.random() * station.length);
}
var endSta = station[destNum][0];
function getWayStations(beg, end) {
var fsp = findShortestPath(beg, end);
var nextArray = [];
nextArray.push([fromX, fromY]);
for (var f = 0; f < fsp.length; f++) {
nextArray.push(fsp[f]);
}
return nextArray;
}
//LOAD POD DATA
podArray.push(new Pod(
startX = fromX,
startY = fromY,
wayStations = getWayStations(begSta, endSta),
riders = randomPass(),
color = colorArray[riders - 1]))
}
//END PROGRAM PODS*********************************************
// calc waypoints traveling along nextArray
function calcWaypoints(nextArray) {
var frams = 100;
var waypoints = [];
for (var i = 1; i < nextArray.length; i++) {
var pt0 = nextArray[i - 1];
var pt1 = nextArray[i];
var dx = pt1[0] - pt0[0];
var dy = pt1[1] - pt0[1];
for (var j = 0; j < frams; j++) {
var x = pt0[0] + dx * j / frams //+ dxOff;
var y = pt0[1] + dy * j / frams //+ dyOff;
waypoints.push({
x: x,
y: y
});
};
}
return (waypoints);
}
animate();
var lastTime = 0;
var speed = 1; // higher is slower
function animate(time) {
// return if the desired time hasn't elapsed
if ((time - lastTime) < speed) {
requestAnimationFrame(animate);
return;
}
lastTime = time;
ctx3.clearRect(0, 0, layer3.width, layer3.height);
var callAgain = false;
for (var i = 0; i < podArray.length; i++) {
var aPod = podArray[i];
// calculate incremental points along the path
var points = calcWaypoints(aPod.wayStations);
if (t < points.length - 1) {
callAgain = true;
}
// draw pod from the last waypoint to the current waypoint
if(points.length > t){
ctx3.beginPath();
ctx3.moveTo(aPod.startX, aPod.startY); //(points[t - 1].x, points[t - 1].y);
ctx3.fillStyle = aPod.color;
ctx3.arc(points[t].x, points[t].y, 4, 0, Math.PI * 2, true);
ctx3.fill();
}
}
t++;
if(callAgain) requestAnimationFrame(animate);
}
<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>
<div id="display">
</id>