1

I am using a fabric.js to draw a binary tree/graph, I want to introduce a delay so that the sequence of drawing is visible. I used setTimeout method in my code but problem is all the nodes are getting delayed and drawn at the same time which I don't want. I want one node,then little delay then another node. Kindly help me.

Code:

delaytime=5000;

function add(x){
   console.log(x);
   canvas.add(x);
}



function addRoot(value){

    var value=String(value);
    var x=new fabric.Circle({ radius: radius,left:width/2,fill:'red',top:radius,originX: 'center', originY: 'center',fill:'red'});
    var text= new fabric.Text(value, {fontSize: 10, originX: 'center', originY: 'center',left:width/2,top:radius});

    setTimeout(function(){ add(x);},delaytime);
  setTimeout(function(){ add(text);},delaytime);



    return x;
}

In the code above the two setTimeout calls are getting executed at the same time but I want the program waits until it returns from first setTimeout call even if it is 5 seconds and then execute the next statement. Please give hints.

Async/await is also not working. Only first call getting drawn which is addRoot

Test.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test for fabric</title>

</head>
<body>

<canvas id="canvas" width="800" height="800" style="border:1px solid #000000">


</canvas>
<script src="fabric.js"></script>
    <script src="testfunctions.js">

    </script>
<script src="./testfunctions.js"></script>
<script>

    var canvas = new fabric.Canvas('canvas');
    var a10=addRoot(10);
    var a20=addNode(a10,20,225);
    var a40=addNode(a10,40,315);
    var a30=addNode(a20,30,270);

</script>

</body>
</html>

Code with async:

var canvas = new fabric.Canvas('canvas');
var height = parseInt(document.getElementById('canvas').getAttribute('height'));
var width = parseInt(document.getElementById('canvas').getAttribute('width'));
var distance = 200;
var radius = 20;
var linelimit = 180;
var delaytime = 1000;

 async function delay (time) {
  return new Promise(function (resolve) {
    setTimeout(resolve, time)
  })
}


async function addRoot (value) {
    var value = String(value);
    var x = new fabric.Circle({ radius: radius, left: width / 2, fill: 'red', top: radius, originX: 'center', originY: 'center', fill: 'red'});
    var text = new fabric.Text(value, {fontSize: 10, originX: 'center', originY: 'center', left: width / 2, top: radius});
    await delay(1000);
    canvas.add(x);
    canvas.add(text);
    return x
}

function addline (x1, y1, x2, y2) {
  console.log("In addline");
  var line = new fabric.Line([x1, y1, x2, y2], {stroke: 'black', originX: 'center', originY: 'center'});
  canvas.add(line)
}


 async function  addNode (node1, node2, angle) {
  var intialx = parseInt(node1.left);

  var initialy = parseInt(node1.top);

   console.log("addNode");

  if (angle > 0 && angle <= 90) {
    var pointx = Math.abs(Math.abs(Math.cos(angle * Math.PI / 180) * distance) + intialx);
    var pointy = Math.abs(Math.abs(Math.sin(angle * Math.PI / 180) * distance) - initialy);

    var initiallinex = Math.abs(Math.abs(Math.cos(angle * Math.PI / 180) * radius) + intialx);
    var initialliney = Math.abs(Math.abs(Math.sin(angle * Math.PI / 180) * radius) - initialy);
    var finallinex = Math.abs(Math.abs(Math.cos(angle * Math.PI / 180) * linelimit) + intialx);
    var finalliney = Math.abs(Math.abs(Math.sin(angle * Math.PI / 180) * linelimit) - initialy)
  }
  if (angle > 90 && angle <= 180) {
    var pointx = Math.abs(Math.cos(angle * Math.PI / 180) * distance + intialx);
    var pointy = Math.abs(Math.sin(angle * Math.PI / 180) * distance - initialy);

    var initiallinex = Math.abs(Math.cos(angle * Math.PI / 180) * radius + intialx);
    var initialliney = Math.abs(Math.sin(angle * Math.PI / 180) * radius - initialy);
    var finallinex = Math.abs(Math.cos(angle * Math.PI / 180) * linelimit + intialx);
    var finalliney = Math.abs(Math.sin(angle * Math.PI / 180) * linelimit - initialy)
  }
  if (angle > 180 && angle <= 270) {
    if (angle == 270) {
      var pointx = Math.abs(Math.cos(angle * Math.PI / 180) * distance + intialx);
      var pointy = Math.abs(Math.sin(angle * Math.PI / 180) * distance - initialy);
      var initiallinex = Math.abs(Math.cos(angle * Math.PI / 180) * radius + intialx);
      var initialliney = Math.abs(Math.sin(angle * Math.PI / 180) * radius - initialy);
      var finallinex = Math.abs(Math.cos(angle * Math.PI / 180) * linelimit + intialx);
      var finalliney = Math.abs(Math.sin(angle * Math.PI / 180) * linelimit - initialy)
    } else {
      var pointx = Math.abs(Math.cos(angle * Math.PI / 180) * distance + intialx);
      var pointy = Math.abs(Math.sin(angle * Math.PI / 180) * distance - initialy);
      var initiallinex = Math.abs(Math.cos(angle * Math.PI / 180) * radius + intialx);
      var initialliney = Math.abs(Math.sin(angle * Math.PI / 180) * radius - initialy);
      var finallinex = Math.abs(Math.cos(angle * Math.PI / 180) * linelimit + intialx);
      var finalliney = Math.abs(Math.sin(angle * Math.PI / 180) * linelimit - initialy)
    }
  } else {
    var pointx = Math.abs(Math.cos(angle * Math.PI / 180) * distance + intialx);
    var pointy = Math.abs(Math.sin(angle * Math.PI / 180) * distance - initialy);
    var initiallinex = Math.abs(Math.cos(angle * Math.PI / 180) * radius + intialx);
    var initialliney = Math.abs(Math.sin(angle * Math.PI / 180) * radius - initialy);
    var finallinex = Math.abs(Math.cos(angle * Math.PI / 180) * linelimit + intialx);
    var finalliney = Math.abs(Math.sin(angle * Math.PI / 180) * linelimit - initialy)
  }

  var x = new fabric.Circle({ radius: radius, originX: 'center', originY: 'center', fill: 'red', left: pointx, top: pointy});
  var value1 = String(node2);
  var text = new fabric.Text(value1, {fontSize: 10, originX: 'center', originY: 'center', left: pointx, top: pointy});
  await delay(1000);
  canvas.add(x);
  canvas.add(text);
  await delay(1000);
  console.log("Executed");
  addline(initiallinex, initialliney, finallinex, finalliney);
  return x;
}
2
  • One simple fix is multiply delaytime x 2 in second timer. Problem is not specific enough if this needs to be done multiple times Commented Sep 23, 2017 at 23:56
  • 1
    move the setTimeout to where you want it to be called. Commented Sep 24, 2017 at 0:00

2 Answers 2

1

You can use ES2017 async / await:

function delay (time) {
  return new Promise(function (resolve) {
    setTimeout(resolve, time)
  })
}

let delaytime = 1000

async function addRoot (value) {
  console.log('do stuff')
  // var value=String(value);
  // var x=new fabric.Circle({ radius: radius,left:width/2,fill:'red',top:radius,originX: 'center', originY: 'center',fill:'red'});
  // var text= new fabric.Text(value, {fontSize: 10, originX: 'center', originY: 'center',left:width/2,top:radius});
  await delay(delaytime)
  console.log('add x')
  // add(x);
  await delay(delaytime)
  console.log('add text')
  // add(text);
  return { value: value }
  // return x;
}

// usage
addRoot('some value').then(function (returnedValue) {
  console.log(returnedValue)
})

Notice the delay in the timestamps next to each console.log() output in the demo.

Update

In order to properly use this code with minimal change to yours, change the following snippet:

var canvas = new fabric.Canvas('canvas');
var a10=addRoot(10);
var a20=addNode(a10,20,225);
var a40=addNode(a10,40,315);
var a30=addNode(a20,30,270);

to this:

// to support await operator
(async function () {
  // do not declare another canvas, you've already done so in other block
  var a10 = await addRoot(10)
  var a20 = await addNode(a10, 20, 225)
  var a40 = await addNode(a10, 40, 315)
  var a30 = await addNode(a20, 30, 270)
})()
Sign up to request clarification or add additional context in comments.

9 Comments

I want to use function like addRoot() only
@OmkarKeluskar I've placed console.log()s where you should put your application logic. Considering that your example code is incomplete, I would not be able to produce a working demo if I didn't use console.log()s.
Thanks Patrick, i am getting some error when copying the function delay , the errors are: a) expression expected at =>,{ expected at setTimeout function closing braces and expecting a new line or semicolon in the end. I am using WebStorm IDE any tips?
@OmkarKeluskar I am not familiar with WebStorm IDE, but I suspect it does not support arrow functions, so, I'll update my answer to remove them.
@OmkarKeluskar upon googling WebStorm ES2017 support, a link on the first page of results suggests changing your JavaScript language version.
|
0

There are two ways to achieve what you want to do

(1) add additional delaytime at the last setTimeout

setTimeout(function() {

  add(x);
}, delaytime);

setTimeout(function() {

  add(text);
}, delaytime * 2);

(2) Place the last setTimeout inside the first setTimeout

setTimeout(function() {

  add(x);
  setTimeout(function() {

    add(text);
  }, delaytime);
}, delaytime);

2 Comments

Basically there are other functions also which are used to draw so I dont think this approach would work
Problem with first approach is that i have several calls like: a)Addroot() and then addNode() so I want addroot to draw a root node with delay and then program should move to addNode() function which is not happening right now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.