Draw continuous lines on an HTML canvas one by one

I am trying to write code for the problem described above. I tried to find a solution. This is what I have.

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> 

The problem is that it runs simultaneously. Need to follow another. Using promsises, is it possible to delay the second function when the first function is executed and then performs the second function? I tried reading Promises a bit, but I could not translate what I understood into the code.

Thanks in advance.

+8
javascript promise canvas
Apr 27 '15 at 19:36
source share
2 answers

Yes, you can use promises, but for training purposes you can first write a clean inverse solution.

You want to look at my rules of thumb for developing promises. Apply them here:

  • Each asynchronous function should return a promise.

    In your case it will be drawColorLine , draw and requestAnimationFrame .

  • Since requestAnimationFrame is a native, primitive asynchronous function, which unfortunately still requires a callback, we have to promisify :

     function getAnimationFrame() { return new Promise(function(resolve) { requestAnimationFrame(resolve); // this promise never gets rejected // TODO: cancellation support :-) }); } 
  • Everything that follows the asynchronous action goes into the .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")); 
+5
Apr 27 '15 at 21:51
source share

Try to use . 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> 
+2
Apr 27 '15 at 20:19
source share



All Articles