Skip to content

Commit

Permalink
Get pointer change (#3144)
Browse files Browse the repository at this point in the history
* fix normalized pointer
* more tests
  • Loading branch information
asturur committed Aug 7, 2016
1 parent 03d2768 commit ad7e564
Show file tree
Hide file tree
Showing 5 changed files with 536 additions and 220 deletions.
171 changes: 131 additions & 40 deletions src/canvas.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,13 @@
*/
isDrawingMode: false,

/**
* Indicates whether objects should remain in current stack position when selected. When false objects are brought to top and rendered as part of the selection group
* @type Boolean
* @default
*/
preserveObjectStacking: false,

/**
* @private
*/
Expand All @@ -242,6 +249,73 @@
this.calcOffset();
},

/**
* Divides objects in two groups, one to render immediately
* and one to render as activeGroup.
* @return {Array} objects to render immediately and pushes the other in the activeGroup.
*/
_chooseObjectsToRender: function() {
var activeGroup = this.getActiveGroup(),
activeObject = this.getActiveObject(),
object, objsToRender = [ ], activeGroupObjects = [ ];

if ((activeGroup || activeObject) && !this.preserveObjectStacking) {
for (var i = 0, length = this._objects.length; i < length; i++) {
object = this._objects[i];
if ((!activeGroup || !activeGroup.contains(object)) && object !== activeObject) {
objsToRender.push(object);
}
else {
activeGroupObjects.push(object);
}
}
if (activeGroup) {
activeGroup._set('_objects', activeGroupObjects);
objsToRender.push(activeGroup);
}
activeObject && objsToRender.push(activeObject);
}
else {
objsToRender = this._objects;
}
return objsToRender;
},

/**
* Renders both the top canvas and the secondary container canvas.
* @param {Boolean} [allOnTop] Whether we want to force all images to be rendered on the top canvas
* @return {fabric.Canvas} instance
* @chainable
*/
renderAll: function () {
if (this.selection && !this._groupSelector && !this.isDrawingMode) {
this.clearContext(this.contextTop);
}
var canvasToDrawOn = this.contextContainer;
this.renderCanvas(canvasToDrawOn, this._chooseObjectsToRender());
return this;
},

/**
* Method to render only the top canvas.
* Also used to render the group selection box.
* @return {fabric.Canvas} thisArg
* @chainable
*/
renderTop: function () {
var ctx = this.contextTop;
this.clearContext(ctx);

// we render the top context - last object
if (this.selection && this._groupSelector) {
this._drawSelection(ctx);
}

this.fire('after:render');

return this;
},

/**
* Resets the current transform to its original values and chooses the type of resizing based on the event
* @private
Expand Down Expand Up @@ -299,8 +373,9 @@
* @return {Boolean} true if point is contained within an area of given object
*/
containsPoint: function (e, target, point) {
var pointer = point || this.getPointer(e, true),
xy = this._normalizePointer(target, pointer);
var ignoreZoom = true,
pointer = point || this.getPointer(e, ignoreZoom),
xy;

if (target.group && target.group === this.getActiveGroup()) {
xy = this._normalizePointer(target.group, pointer);
Expand All @@ -317,18 +392,13 @@
* @private
*/
_normalizePointer: function (object, pointer) {
var lt, m;

m = fabric.util.multiplyTransformMatrices(
this.viewportTransform,
object.calcTransformMatrix());

m = fabric.util.invertTransform(m);
pointer = fabric.util.transformPoint(pointer, m , false);
lt = fabric.util.transformPoint(object.getCenterPoint(), m , false);
pointer.x -= lt.x;
pointer.y -= lt.y;
return { x: pointer.x, y: pointer.y };
var m = object.calcTransformMatrix(),
invertedM = fabric.util.invertTransform(m),
vpt = this.viewportTransform,
vptPointer = this.restorePointerVpt(pointer),
p = fabric.util.transformPoint(vptPointer, invertedM);
return fabric.util.transformPoint(p, vpt);
//return { x: p.x * vpt[0], y: p.y * vpt[3] };
},

/**
Expand Down Expand Up @@ -864,6 +934,7 @@
},

/**
* @param {fabric.Object} target to reset transform
* @private
*/
_resetObjectTransform: function (target) {
Expand All @@ -876,10 +947,10 @@

/**
* @private
* @param {CanvasRenderingContext2D} ctx to draw the selection on
*/
_drawSelection: function () {
var ctx = this.contextTop,
groupSelector = this._groupSelector,
_drawSelection: function (ctx) {
var groupSelector = this._groupSelector,
left = groupSelector.left,
top = groupSelector.top,
aleft = abs(left),
Expand Down Expand Up @@ -933,9 +1004,10 @@
return;
}

var pointer = this.getPointer(e, true),
activeGroup = this.getActiveGroup(),
activeObject = this.getActiveObject();
var ignoreZoom = true,
pointer = this.getPointer(e, ignoreZoom),
activeGroup = this.getActiveGroup(),
activeObject = this.getActiveObject();

// first check current group (if one exists)
// active group does not check sub targets like normal groups.
Expand Down Expand Up @@ -1020,6 +1092,18 @@
return target;
},

/**
* Returns pointer coordinates without the effect of the viewport
* @param {Object} pointer with "x" and "y" number values
* @return {Object} object with "x" and "y" number values
*/
restorePointerVpt: function(pointer) {
return fabric.util.transformPoint(
pointer,
fabric.util.invertTransform(this.viewportTransform)
);
},

/**
* Returns pointer coordinates relative to canvas.
* @param {Event} e
Expand Down Expand Up @@ -1049,10 +1133,7 @@
pointer.x = pointer.x - this._offset.left;
pointer.y = pointer.y - this._offset.top;
if (!ignoreZoom) {
pointer = fabric.util.transformPoint(
pointer,
fabric.util.invertTransform(this.viewportTransform)
);
pointer = this.restorePointerVpt(pointer);
}

if (boundsWidth === 0 || boundsHeight === 0) {
Expand Down Expand Up @@ -1195,6 +1276,20 @@
return this._activeObject;
},

/**
* @private
* @param {fabric.Object} obj Object that was removed
*/
_onObjectRemoved: function(obj) {
// removing active object should fire "selection:cleared" events
if (this.getActiveObject() === obj) {
this.fire('before:selection:cleared', { target: obj });
this._discardActiveObject();
this.fire('selection:cleared');
}
this.callSuper('_onObjectRemoved', obj);
},

/**
* @private
*/
Expand Down Expand Up @@ -1323,6 +1418,18 @@
return this;
},

/**
* Clears all contexts (background, main, top) of an instance
* @return {fabric.Canvas} thisArg
* @chainable
*/
clear: function () {
this.discardActiveGroup();
this.discardActiveObject();
this.clearContext(this.contextTop);
return this.callSuper('clear');
},

/**
* Draws objects' controls (borders/controls)
* @param {CanvasRenderingContext2D} ctx Context to render controls on
Expand Down Expand Up @@ -1350,22 +1457,6 @@
}
},

/**
* @private
* @param {fabric.Object} obj Object that was removed
*/
_onObjectRemoved: function(obj) {
this.callSuper('_onObjectRemoved', obj);
},

/**
* Clears all contexts (background, main, top) of an instance
* @return {fabric.Canvas} thisArg
* @chainable
*/
clear: function () {
return this.callSuper('clear');
}
});

// copying static properties manually to work around Opera's bug,
Expand Down
12 changes: 6 additions & 6 deletions src/mixins/canvas_events.mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,7 @@
if (this.clipTo) {
fabric.util.clipContext(this, this.contextTop);
}
var ivt = fabric.util.invertTransform(this.viewportTransform),
pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
var pointer = this.getPointer(e);
this.freeDrawingBrush.onMouseDown(pointer);
this._handleEvent(e, 'down');
},
Expand All @@ -395,8 +394,7 @@
*/
_onMouseMoveInDrawingMode: function(e) {
if (this._isCurrentlyDrawing) {
var ivt = fabric.util.invertTransform(this.viewportTransform),
pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
var pointer = this.getPointer(e);
this.freeDrawingBrush.onMouseMove(pointer);
}
this.setCursor(this.freeDrawingCursor);
Expand Down Expand Up @@ -672,11 +670,13 @@

/**
* @private
* @param {Event} e Event object
* @param {Object} transform current tranform
* @param {Number} x mouse position x from origin
* @param {Number} y mouse poistion y from origin
* @return {Boolean} true if the scaling occurred
*/
_onScale: function(e, transform, x, y) {
// rotate object only if shift key is not pressed
// and if it is not a group we are transforming
if ((e[this.uniScaleKey] || this.uniScaleTransform) && !transform.target.get('lockUniScaling')) {
transform.currentAction = 'scale';
return this._scaleObject(x, y);
Expand Down
Loading

0 comments on commit ad7e564

Please sign in to comment.