2015-08-17 4 views
0

Я собираю моделирование городской транспортной системы и пытаюсь улучшить свои навыки Javascript и Canvas. Я представил версию скелетной здесь: 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> 

ответ

1

Ваши транспортные средства достигают цели одновременно, поскольку вы меняете свое положение в зависимости от процента. Поэтому, когда pct == 1.00 все транспортные средства поступают одновременно на своих конечных точках, независимо от расстояния, которое им нужно проехать, чтобы добраться туда.

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

Для того, чтобы транспортное средство прибыть на основе пройденного расстояния

Вопрос № 1: Вы можете рассчитать каждую точку (путевую == уникальный пиксель) автомобиль должен пройти, чтобы закончить это маршрут.Продвиньте автомобиль до следующей путевой точки с каждой новой рамкой анимации. Это приводит к тому, что каждое транспортное средство прибывает на основе длины своего маршрута, а не равномерного процента.

Вопрос №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>

+0

По-прежнему пытается получить логику холста. Спасибо тебе за это! – Tyler330

+0

Я пробовал адаптировать свой код, но не могу заставить его ничего нарисовать на экране. Что я пропустил? [link] (https://jsfiddle.net/yL8udg9r/) – Tyler330

1

Чтобы сделать ваши стручки одинаковыми, вы, вероятно, захотите использовать теорему Пифагора. Гипотенуза - это расстояние, на которое вы хотите, чтобы узел путешествовал каждый раз, когда появляется rAF. Затем вычислите свои x и y из этого.

Я не совсем уверен, понимаю ли я, что делает pct.

Чтобы ускорить RAF вы хотите:

  1. убить ваш набор тайм-аут
  2. пререндер

Prerending немного больше работы, но вместо того, чтобы рисовать каждый круг каждый время у вас есть холсты, которых нет в DOM, на которые вы рисуете. Затем вы по существу кладете «скрытый» холст, где бы вы ни захотели, поверх видимого холста DOM. Таким образом, он сохраняет рисунок в памяти.

Вы также рисуете каждый круг на холсте в конце цикла for. Вытащите метод заполнения вне его таким образом, чтобы холст мог выставлять партии вместо нескольких маленьких звонков (это может действительно убить производительность).

Настройка шрифтов каждый раз может быть удалена.

Холст замечательный, но вы должны быть осторожны, потому что одна небольшая ошибка может привести к огромной бутылочной горловине.

Это хорошая статья: http://www.html5rocks.com/en/tutorials/canvas/performance/

Лемм знать, если у вас есть какие-либо другие вопросы.

+0

Я буду смотреть на это. Я видел это раньше, но не пытался его реализовать. – Tyler330

Смежные вопросы