2015-04-27 6 views
8

Ich versuche, Code für das oben beschriebene Problem zu schreiben. Ich habe versucht, eine Lösung zu finden. Das habe ich derzeit.Zeichnen Sie fortlaufende Zeilen auf HTML-Canvas nacheinander

var canvas = document.getElementById('canvas'); 
 
var context = canvas.getContext('2d'); 
 

 
var drawColorLine = function(start, end, color) { 
 
    var deltaX, deltaY, i = 0, 
 
    currLength = 0, 
 
    isHor, isVert; 
 

 
    deltaX = end[0] - start[0]; 
 
    deltaY = end[1] - start[1]; 
 
    context.strokeStyle = color; 
 

 
    isHor = deltaX === 0 ? 0 : 1; 
 
    isVert = deltaY === 0 ? 0 : 1; 
 

 
    function draw() { 
 
    context.beginPath(); 
 
    context.moveTo(start[0] + currLength * isHor, start[1] + currLength * isVert); 
 

 
    currLength = currLength + 0.5 * i; 
 
    context.lineTo(start[0] + currLength * isHor, start[1] + currLength * isVert); 
 
    context.stroke(); 
 

 
    if (currLength <= Math.max(deltaX, deltaY)) { 
 
     i = i + 1; 
 
     requestAnimationFrame(draw); 
 
    } 
 
    } 
 
    draw(); 
 
}; 
 

 
drawColorLine([40, 40], [100, 40], '#116699'); 
 
drawColorLine([40, 40], [40, 100], '#bb11dd');
<canvas id='canvas' width='400' height='400'></canvas>

Das Problem ist, sind beide zur gleichen Zeit gezogen werden. Einer sollte dem anderen folgen. Mit Promis ist es möglich, die zweite Funktion zu verzögern, während die erste Funktion ausgeführt wird und später die zweite Funktion ausführt? Ich habe versucht, etwas auf Promises zu lesen, aber ich konnte nicht übersetzen, was ich verstanden habe.

Vielen Dank im Voraus.

Antwort

5

Ja, Sie verspricht verwenden können, altough für Lernzwecke möchten Sie vielleicht zunächst eine reine Callback-Lösung schreiben.

Sie sollten sich meine rules of thumb für die Entwicklung von Versprechen ansehen. Lassen Sie uns sie hier anwenden:

  1. Jede asynchrone Funktion muss eine Zusage zurückgeben.

    Diese wären drawColorLine, draw und requestAnimationFrame in Ihrem Fall.

  2. Als requestAnimationFrame ist eine native, primitiv asynchrone Funktion, die leider immer noch einen Rückruf nimmt, werden wir zu promisify haben es:

    function getAnimationFrame() { 
        return new Promise(function(resolve) { 
         requestAnimationFrame(resolve); // this promise never gets rejected 
         // TODO: cancellation support :-) 
        }); 
    } 
    
  3. Alles, was geht in einen .then() Rückruf eine asynchrone Aktion folgt:

    function drawColorLine(start, end, color) { 
        … // initialisation 
    
        function draw() { 
         … // do work 
         // always return a promise: 
         if (/* furter work */) { 
          i++; 
          return getAnimationFrame().then(draw); // magic happens here :-) 
         } else { 
          return Promise.resolve(…); // maybe have a path object as eventual result? 
                 // or anything else, including nothing (no arg) 
         } 
        } 
        return draw(); // returns a promise - but don't forget the `return` 
    } 
    

Voila!

drawColorLine([40, 40], [100, 40], '#116699').then(function() { 
    return drawColorLine([40, 40], [40, 100], '#bb11dd'); 
}).then(console.log.bind(console, "both lines drawn")); 
+0

Ich schrieb ursprünglich eine Lösung mit Callback. Ich musste viele Zeilen zeichnen. Ich möchte es sequentiell machen. Callback schien nicht der richtige Weg zu sein, oder ich fand keine gute Möglichkeit, meine Funktion zu erweitern. Ich habe versucht, Versprechungen von verschiedenen Orten zu lesen, aber ich habe immer noch keine gute Idee, wie man sie effektiv benutzt. Was ist der Weg zu lernen, das Zeug noch einmal zu lesen? –

+0

Sie können viele Sachen unter https://github.com/kriskowal/q/wiki/General-Promise-Resources finden – Bergi

+0

Callbacks würde genauso gut funktionieren, Sie müssten nur die Regeln ein wenig umwandeln: "Jeder Async Funktion muss einen Rückruf nehmen, und es aufrufen, wenn es fertig ist "," alles nach einer asynchronen Sache muss in seinen Callback gehen und dann am Ende zurückrufen ". Es gibt Fortsetzungen, wann immer Sie ein Versprechen "zurückgeben" würden. – Bergi

2

Versuchen .animate() Verwendung jQuery.Deferred()

var canvas = document.getElementById('canvas'); 
 
var context = canvas.getContext('2d'); 
 

 
var drawColorLine = function(start, end, color) { 
 
    // create new `deferred` object 
 
    var dfd = new $.Deferred(), 
 
    deltaX, deltaY, i = 0, 
 
    currLength = 0, 
 
    isHor, isVert, 
 
    // create animation object 
 
    props = $({"prop":i}); 
 

 
    deltaX = end[0] - start[0]; 
 
    deltaY = end[1] - start[1]; 
 
    context.strokeStyle = color; 
 

 
    isHor = deltaX === 0 ? 0 : 1; 
 
    isVert = deltaY === 0 ? 0 : 1; 
 

 
    function draw(n) { 
 
    context.beginPath(); 
 
    context.moveTo(start[0] + currLength * isHor 
 
        , start[1] + currLength * isVert); 
 

 
    currLength = currLength + 0.5 * n; 
 
    context.lineTo(start[0] + currLength * isHor 
 
        , start[1] + currLength * isVert); 
 
    context.stroke(); 
 

 
    if (currLength <= Math.max(deltaX, deltaY)) { 
 
     // create object to animate, 
 
     // do animation stuff  
 
     props.animate({"prop":1}, { 
 
     // set duration of animation 
 
     duration:10, 
 
     complete:function() { 
 
      // increment `n`:`i` 
 
      n = n + 1; 
 
      // call `draw` with `n` as parameter 
 
      draw(n) 
 
     } 
 
     })   
 
    } else { 
 
     // if `currLength > Math.max(deltaX, deltaY)`, 
 
     // resolve `deferred` object, 
 
     // set `canvas` element as `this` at `.then()` 
 
     // pass `deltaX`, `deltaY`, `currLength`, `n`` 
 
     // arguments to `.then()` 
 
     dfd.resolveWith(canvas, [deltaX, deltaY, currLength, n]); 
 
    } 
 

 
    } 
 
    draw(i); 
 
    // return jQuery promise object 
 
    return dfd.promise() 
 
}; 
 
// draw first line 
 
drawColorLine([40, 40], [100, 40], '#116699') 
 
.then(function() { 
 
    console.log("first line complete", arguments, this); 
 
    // draw sencond line 
 
    return drawColorLine([40, 40], [40, 100], '#bb11dd'); 
 
}).then(function() { 
 
    console.log("second line complete", arguments, this); 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"> 
 
</script> 
 
<canvas id='canvas' width='400' height='400'></canvas>

Verwandte Themen