2015-04-27 16 views
8

Sto provando a scrivere il codice per il problema sopra descritto. Ho provato a trovare una soluzione. Questo è ciò che attualmente ho.Disegna linee continue su tela HTML una dopo l'altra

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>

Il problema è sia vengono attratti allo stesso tempo. Uno dovrebbe seguire l'altro. Usando le promesse è possibile ritardare la seconda funzione mentre la prima funzione viene eseguita e successivamente eseguire la seconda funzione? Ho provato a leggere un po 'su Promises, ma non sono riuscito a tradurre in codice ciò che ho capito.

Grazie in anticipo.

risposta

5

Sì, è possibile utilizzare le promesse, benche a fini di apprendimento si potrebbe desiderare di scrivere una soluzione richiamata pura prima.

Avrai voglia di dare un'occhiata al mio rules of thumb per lo sviluppo di promessa. Appliciamoli qui:

  1. Ogni funzione asincrona deve restituire una promessa.

    Questi sarebbero drawColorLine, draw e requestAnimationFrame nel tuo caso.

  2. Come requestAnimationFrame è un nativo, la funzione primitiva asincrona che richiede purtroppo ancora una richiamata, dovremo promisify esso:

    function getAnimationFrame() { 
        return new Promise(function(resolve) { 
         requestAnimationFrame(resolve); // this promise never gets rejected 
         // TODO: cancellation support :-) 
        }); 
    } 
    
  3. Tutto ciò che segue un'azione asincrona va in una .then() callback:

    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

Inizialmente ho scritto una soluzione con callback. Ho dovuto disegnare molte linee. Voglio farlo in sequenza. Il callback non sembrava la via da percorrere o non riuscivo a trovare un modo carino per estendere la mia funzione. Ho provato a leggere le promesse da vari posti, ma non ho ancora una buona idea di come usarle in modo efficace. Qual è il modo di imparare a rileggere di nuovo le cose? –

+0

Puoi trovare molte informazioni su https://github.com/kriskowal/q/wiki/General-Promise-Resources – Bergi

+0

Le callback funzionerebbero altrettanto bene, dovresti solo trasformare le regole un po ': "ogni async la funzione deve prendere una richiamata e chiamarla quando è finita "," tutto dopo che una cosa asincrona deve andare nella sua callback, e poi richiamare alla fine ". Passa continuazioni attorno a quando si ritorna una promessa. – Bergi

2

Prova utilizzando .animate(), 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>