Search code examples
createjseaseljstweenjs

Createjs. Line follow element fiddle


I created this jsfiddle.

A line i connecting two elements, and I want the line to stay connected to both elements no matter where they go.

I've sort of succeeded, but with one pretty obvious error. It keeps drawing new lines instead of redrawing the existing line. Please help me on how to make it update the line position instead.

var stage = new createjs.Stage("canvas");
createjs.Ticker.setFPS(60);
createjs.Ticker.addEventListener("tick", tick);
var arrDots = [];
var arrLines = [];

var circle1 = new createjs.Shape().set({
  x: stage.canvas.width/2,
  y: 50,
  cursor: "pointer",
  name:"target"
});
circle1.graphics.f(createjs.Graphics.getRGB(Math.random()*0xFFFFFF))
  .dc(0,0,20);
stage.addChild(circle1);
arrDots.push(circle1);

var circle2 = new createjs.Shape().set({
  x: stage.canvas.width/2,
  y: stage.canvas.height - 50,
  cursor: "pointer",
  name:"target"
});
circle2.graphics.f(createjs.Graphics.getRGB(Math.random()*0xFFFFFF))
  .dc(0,0,20);
stage.addChild(circle2);
arrDots.push(circle2);

var line = new createjs.Shape().set({
  graphics: new createjs.Graphics().s("#00f").mt(arrDots[0].x, 
arrDots[0].y).lt(arrDots[1].x, arrDots[1].y)
});
stage.addChild(line);
arrLines.push([arrDots[0], arrDots[1], line]);


createjs.Tween.get(circle1, {loop: true}).to({x:50}, 
3000).to({x:stage.canvas.width/2}, 3000);

function tick(event) {
  keepLineConnection();

  stage.update();
}
function keepLineConnection() {
  for(var i = 0; i < arrLines.length; i++) {
    arrLines[i][2].graphics.mt(arrLines[i][0].x, arrLines[i][0].y).lt(arrLines[i][1].x, arrLines[i][1].y);
  }
}

Solution

  • The reason it keeps drawing is because you keep adding commmands to the graphics. Basically, you are doing this:

     graphics.mt().lt().mt().lt().mt().lt().mt().etc();
    

    Since you are just adding new instrucitons, they will pile up over time, and will eventually kill your processor.

    An easy fix for that is to clear the graphics first before adding new ones:

    graphics.clear().mt().lt();
    

    A better approach is to use commands. Since EaselJS 0.7.0, all graphics commands are objects, and at any time you can update properties of those objects directly. For example, the MoveTo and LineTo commands both have an x and y property. Here is more info on Commands: http://blog.createjs.com/update-width-height-in-easeljs/

    Here is a modified fiddle that stores of commands on the line, and then updates them on tick. I also made a few other updates, such as changing the timing mode to RAF, which is smoother than using interval-based timers at 60FPS.

    https://jsfiddle.net/tck7x8u2/

    // Store commands:
    line.cmd1 = line.graphics.mt(0,0).command;
    line.cmd2 = line.graphics.lt(0,0).command;
    
    // Update commands:
    var instr = arrLines[i],
    line = instr[2];
    line.cmd1.x = instr[0].x;
    line.cmd1.y = instr[0].y;
    line.cmd2.x = instr[1].x; 
    line.cmd2.y = instr[1].y;
    

    Cheers!

    Edit: Here is are some demos using that idea that I made a while back: