0

I need to create draggable random rectangles using Shape object. This function creates new rectangle where the mouse was clicked.

var rects = [];
var i=0;
var stage;
window.onload = function() {
canvas = document.getElementById("drawingCanvas");
context = canvas.getContext("2d");
stage = new createjs.Stage("drawingCanvas");

canvas.onclick = canvasClick;
}

function canvasClick(e) {
var d=Math.random()*150;  
rects[i] = new createjs.Shape();
rects[i].graphics.beginStroke("black").
beginFill("RGB"+"(" + parseInt(Math.random()*255) +"," + 
parseInt(Math.random()*255)+"," +parseInt(Math.random()*255)+")").
drawRect(e.offsetX-d/2,e.offsetY-d/2,d,d);
stage.addChild(rects[i]);
rects[i].on("mousedown", function (evant) {
console.log("jdfh");
var offset = {
     x: evant.target.x - evant.stageX,
     y: evant.target.y - evant.stageY
                         };
                         rects[i].on("pressmove", function (evant) {
                             evant.target.x = evant.stageX + offset.x;
                             evant.target.y = evant.stageY + offset.y;
                             stage.update();
                         });
                     });
i++;
stage.update();
}

But when I try to drag rectngle it says: rect.js:47 Uncaught TypeError: Cannot read property 'on' of undefined

at a.<anonymous> (file:///C:/Users/Vasya/Downloads/redactor%20(1)/rect/public_html/rect.js:47:39)
at easeljs-0.8.2.min.js:12
at a.b._dispatchEvent (easeljs-0.8.2.min.js:12)
at a.b.dispatchEvent (easeljs-0.8.2.min.js:12)
at a.b._dispatchMouseEvent (easeljs-0.8.2.min.js:13)
at a.b._handlePointerDown (easeljs-0.8.2.min.js:13)
at a.b._handleMouseDown (easeljs-0.8.2.min.js:13)
at HTMLCanvasElement.f (easeljs-0.8.2.min.js:13)
Lanny
  • 11,244
  • 1
  • 22
  • 30
  • In you given code the variable _i_ is never instantiated or set to 0. Please consider creating a [Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve). – Capricorn May 10 '18 at 21:24
  • @Capricorn mind looking at the edited version? – Ольга Кужикова May 10 '18 at 21:40
  • Possible duplicate of [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Andy Ray May 14 '18 at 16:47

1 Answers1

1

In your latest update, the i variable in the mousedown handler is always one more than the last item you created, because it is referenced later, after the i variable has been incremented.

Instead, you can use evant.target for that too.

rects[i].on("mousedown", function (evant) {
  console.log("jdfh");
  var offset = {
     x: evant.target.x - evant.stageX,
     y: evant.target.y - evant.stageY
  };

  // Note: store the listener handler to remove it later
  var listener = evant.target.on("pressmove", function (evant) {
    evant.target.x = evant.stageX + offset.x;
    evant.target.y = evant.stageY + offset.y;
    stage.update();
  });

  // Remove the pressmove handler
  evant.target.on("pressup", function(evant) {
    evant.target.off("pressmove", listener);
    evant.remove(); // Remove this pressup handler too
  });
});

Reminder to remove the pressmove handler, since it will get added again each time you press on the object. This is because your handler is just an anonymous function, so a new one is created each time. You don't have to add the "pressmove" event each time, you could just add it once, but you would have to make your offset global, or store it on your object.

Hope that helps.

Lanny
  • 11,244
  • 1
  • 22
  • 30