2015-03-03 1 views
1

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

Heres код:

function meter(){ 
     requestAnimationFrame(meter); 

     setTimeout(function() { 

     var radius = 40; 
     ctx.clearRect(500, 200, 100, 100); 
     ctx.beginPath(); 
     ctx.arc(550, 250, radius, 0, 2 * Math.PI, false); 
     ctx.fillStyle = 'rgba(192, 192, 192, 0.4)'; 
     ctx.fill(); 
     ctx.lineWidth = 2; 
     ctx.strokeStyle = '#000000'; 
     ctx.stroke(); 

     ctx.fillStyle = "#ffcc4a"; 
     ctx.fillRect(525, 220, 50, 60); 
     ctx.fillStyle = "#ffffff"; 
     ctx.fillRect(528, 225, 44, 45); 


     var grd = ctx.createLinearGradient(510, 0, 670, 0); 
     grd.addColorStop(0, "black"); 
     grd.addColorStop(0.25, "yellow"); 
     grd.addColorStop(0.5, "red"); 
     ctx.fillStyle = grd; 
     ctx.fillRect(530, 228, 40, 30); 

      ctx.beginPath(); 
      ctx.fillStyle = "#000000"; 
      ctx.arc(550, 264, 5, 0, 2 * Math.PI, false); 
      ctx.moveTo(549, 260); 
      ctx.lineTo(548, 240); 
      ctx.fill(); 
      ctx.lineWidth = 2; 
      ctx.strokeStyle = '#000000'; 
      ctx.stroke(); 
      ctx.closePath(); 


     ctx.closePath(); 
     //ctx.clearRect(500, 200, 100, 100);  

      }, 2000); 

      setTimeout(function() { 

     var radius = 40; 
     ctx.clearRect(500, 200, 100, 100); 
     ctx.beginPath(); 
     ctx.arc(550, 250, radius, 0, 2 * Math.PI, false); 
     ctx.fillStyle = 'rgba(192, 192, 192, 0.4)'; 
     ctx.fill(); 
     ctx.lineWidth = 2; 
     ctx.strokeStyle = '#000000'; 
     ctx.stroke(); 

     ctx.fillStyle = "#ffcc4a"; 
     ctx.fillRect(525, 220, 50, 60); 
     ctx.fillStyle = "#ffffff"; 
     ctx.fillRect(528, 225, 44, 45); 


     var grd = ctx.createLinearGradient(510, 0, 670, 0); 
     grd.addColorStop(0, "black"); 
     grd.addColorStop(0.25, "yellow"); 
     grd.addColorStop(0.5, "red"); 
     ctx.fillStyle = grd; 
     ctx.fillRect(530, 228, 40, 30); 

      ctx.beginPath(); 
      ctx.fillStyle = "#000000"; 
      ctx.arc(550, 264, 5, 0, 2 * Math.PI, false); 
      ctx.moveTo(549, 260); 
      ctx.lineTo(558, 240); 
      ctx.fill(); 
      ctx.lineWidth = 2; 
      ctx.strokeStyle = '#000000'; 
      ctx.stroke(); 
      ctx.closePath(); 


     ctx.closePath(); 
     //ctx.clearRect(500, 200, 100, 100);  

      }, 2500); 

      setTimeout(function() { 

     var radius = 40; 
     ctx.clearRect(500, 200, 100, 100); 
     ctx.beginPath(); 
     ctx.arc(550, 250, radius, 0, 2 * Math.PI, false); 
     ctx.fillStyle = 'rgba(192, 192, 192, 0.4)'; 
     ctx.fill(); 
     ctx.lineWidth = 2; 
     ctx.strokeStyle = '#000000'; 
     ctx.stroke(); 

     ctx.fillStyle = "#ffcc4a"; 
     ctx.fillRect(525, 220, 50, 60); 
     ctx.fillStyle = "#ffffff"; 
     ctx.fillRect(528, 225, 44, 45); 


     var grd = ctx.createLinearGradient(510, 0, 670, 0); 
     grd.addColorStop(0, "black"); 
     grd.addColorStop(0.25, "yellow"); 
     grd.addColorStop(0.5, "red"); 
     ctx.fillStyle = grd; 
     ctx.fillRect(530, 228, 40, 30); 

      ctx.beginPath(); 
      ctx.fillStyle = "#000000"; 
      ctx.arc(550, 264, 5, 0, 2 * Math.PI, false); 
      ctx.moveTo(549, 260); 
      ctx.lineTo(568, 240); 
      ctx.fill(); 
      ctx.lineWidth = 2; 
      ctx.strokeStyle = '#000000'; 
      ctx.stroke(); 
      ctx.closePath(); 


     ctx.closePath(); 
     //ctx.clearRect(500, 200, 100, 100);  

      }, 3000); 



    } 
+1

Вы должны удалить функцию SetTimeout, что у вас есть. Теперь происходит то, что с requestAnimationFrame() вы спрашиваете своего браузера, готов ли он сделать, и он скажет «да!», И вы запустите 3-секундный таймер для анимации. Проблема в том, что, поскольку вы ничего не рисуете в течение 3 секунд, вы будете продолжать спрашивать своего браузера, если он готов рисовать, довольно часто, и вы будете делать много запросов анимации, которые не будут срабатывать с 3 секундами задержка, более вероятно, в течение миллисекунд. – Niddro

+0

Привет @Niddro вы можете дать больше намеков относительно того, что мне нужно будет добавить вместо функции setTimeout? – raymar

ответ

1

Мне кажется, что у вас будет достаточно времени для вызова функции requestAnimationFrame кучу раз в то время как первые SetTimeout Funtions ждут, чтобы стрелять и рисовать вещи. Это означает, что вы, вероятно, в конечном итоге запустите таймеры setTimeout несколько раз, прежде чем начнется первый.

Это в основном то, что у вас есть:

function meter(){ 
    requestAnimationFrame(meter); 

    setTimeout(function() { 
     //drawing stuff 
    }, 2000); 

    setTimeout(function() { 
     //drawing stuff 
    }, 2500); 

    setTimeout(function() { 
     //drawing stuff 
    }, 3000); 
} 

Вы тянете одно и то же три раза с одним небольшим изменением. Вместо этого, сделать его в 1 функцию с параметром:

function meter(indicatorPosition){ 
    //black circle 
    var radius = 40; 
    ctx.clearRect(500, 200, 100, 100); 
    ctx.beginPath(); 
    ctx.arc(550, 250, radius, 0, 2 * Math.PI, false); 
    ctx.fillStyle = 'rgba(192, 192, 192, 0.4)'; 
    ctx.fill(); 
    ctx.lineWidth = 2; 
    ctx.strokeStyle = '#000000'; 
    ctx.stroke(); 

    //yellow rectangle 
    ctx.fillStyle = "#ffcc4a"; 
    ctx.fillRect(525, 220, 50, 60); 
    //white rectangle over yellow 
    ctx.fillStyle = "#ffffff"; 
    ctx.fillRect(528, 225, 44, 45); 

    //meter gradient background 
    var grd = ctx.createLinearGradient(510, 0, 670, 0); 
    grd.addColorStop(0, "black"); 
    grd.addColorStop(0.25, "yellow"); 
    grd.addColorStop(0.5, "red"); 
    ctx.fillStyle = grd; 
    ctx.fillRect(530, 228, 40, 30); 

    //circle and indicator 
    ctx.beginPath(); 
    ctx.fillStyle = "#000000"; 
    ctx.arc(550, 264, 5, 0, 2 * Math.PI, false); 
    ctx.moveTo(549, 260); 
    ctx.lineTo(indicatorPosition, 240); //this is the only variable! 
    ctx.fill(); 
    ctx.lineWidth = 2; 
    ctx.strokeStyle = '#000000'; 
    ctx.stroke(); 
    ctx.closePath(); 
} 

Теперь, чтобы сделать это движение:

, если вы хотите, чтобы двигаться через каждые 0,5 секунд, то лучше использовать setInterval.

var meterPosition = 548 //your starting position 
var myInterval = setInterval(function() { 
    //each run we draw the meter 
    meter(meterPosition); 
    //Then we want to add 10 to the meter position 
    meterPosition+=10; 
    //We don't want the meter to go nuts and disappear to the right, so we'll make it reset after 3 moves 
    if (meterPosition > 568) { 
     meterPosition = 548; 
    } 
},500); 

Вот скрипка с кодом в действии: http://jsfiddle.net/Niddro/7jxknwk4/

+0

отлично, спасибо большое. Если бы я хотел просто остановить индикатор на 568, могу ли я просто использовать функцию stop()? – raymar

+0

Да, введите, что вы остановили интервал, используя функцию clearInterval(); на переменной интервала, например: 'clearInterval (myInterval);' – Niddro

+0

Может ли это быть сделано с помощью setTimeout? У меня есть другие анимации внутри этой, которая использует setInterval, и я думаю, что они могут быть взаимоисключающими друг с другом. – raymar

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