Fixes to zoom for groups and brushes.

This commit is contained in:
Tom French 2013-11-19 16:21:29 +00:00
parent 88b589b3d6
commit 08d575422c
15 changed files with 255 additions and 283 deletions

173
dist/all.js vendored
View file

@ -8976,6 +8976,21 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
return new fabric.Point(this.getWidth()/2 + x, this.getHeight()/2 + y);
},
/**
* Sets viewport transform of this canvas instance
* @param {Array} vpt the transform in the form of context.transform
* @return {fabric.Canvas} instance
* @chainable true
*/
setViewportTransform: function (vpt) {
this.viewportTransform = vpt
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},
/**
* Sets zoom level of this canvas instance
* @param {Number} value to set zoom to, less than 1 zooms out
@ -9008,6 +9023,9 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
this.viewportTransform[4] = x - wh.x/2;
this.viewportTransform[5] = y - wh.y/2;
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},
@ -9072,13 +9090,15 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
_onObjectAdded: function(obj) {
this.stateful && obj.setupState();
obj.canvas = this;
obj.setCoords();
if (obj._objects) {
obj._calcBounds();
for (var i = 0, len = obj._objects.length; i < len; i++) {
obj._objects[i].canvas = this;
obj._objects[i].setCoords();
this._onObjectAdded(obj._objects[i]);
}
obj._updateObjectsCoords()
}
obj.setCoords();
this.fire('object:added', { target: obj });
obj.fire('added');
},
@ -9949,6 +9969,9 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
*/
_render: function() {
var ctx = this.canvas.contextTop;
var v = this.canvas.viewportTransform;
ctx.save();
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
ctx.beginPath();
var p1 = this._points[0];
@ -9978,6 +10001,7 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
// the bezier control point
ctx.lineTo(p1.x, p1.y);
ctx.stroke();
ctx.restore();
},
/**
@ -9986,10 +10010,6 @@ fabric.BaseBrush = fabric.util.createClass(/** @lends fabric.BaseBrush.prototype
* @private
*/
_getSVGPathData: function() {
var ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
for (var i = 0, len = this._points.length; i < len; i++) {
this._points[i] = fabric.util.transformPoint(this._points[i], ivt);
}
this.box = this.getPathBoundingBox(this._points);
return this.convertPointsToSVGPath(
this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy);
@ -10151,11 +10171,17 @@ fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric
var point = this.addPoint(pointer);
var ctx = this.canvas.contextTop;
var v = this.canvas.viewportTransform;
ctx.save();
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
ctx.fillStyle = point.fill;
ctx.beginPath();
ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
ctx.restore();
},
/**
@ -10188,10 +10214,10 @@ fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric
for (var i = 0, len = this.points.length; i < len; i++) {
var point = this.points[i];
var circle = new fabric.Circle({
radius: point.radius,
radius: this.points[i].radius,
left: point.x,
top: point.y,
fill: point.fill
fill: this.points[i].fill
});
this.shadow && circle.setShadow(this.shadow);
@ -10382,14 +10408,13 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
render: function() {
var ctx = this.canvas.contextTop;
ctx.fillStyle = this.color;
var v = this.canvas.viewportTransform;
ctx.save();
var ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {
var point = this.sprayChunkPoints[i];
var tpoint = fabric.util.transformPoint({x: point.x, y: point.y}, ivt);
point.x = tpoint.x;
point.y = tpoint.y;
if (typeof point.opacity !== 'undefined') {
ctx.globalAlpha = point.opacity;
}
@ -10405,7 +10430,6 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
this.sprayChunkPoints = [ ];
var x, y, width, radius = this.width / 2;
var vpt = this.canvas.viewportTransform;
for (var i = 0; i < this.density; i++) {
@ -10423,7 +10447,6 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
}
var point = new fabric.Point(x, y);
point = fabric.util.transformPoint(point, vpt);
point.width = width
if (this.randomOpacity) {
@ -11001,7 +11024,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
var isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target);
var group = new fabric.Group(
isActiveLower ? [ target, this._activeObject ] : [ this._activeObject, target ]);
group.canvas = this;
this.setActiveGroup(group);
this._activeObject = null;
@ -11281,7 +11303,6 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
}
else if (group.length > 1) {
group = new fabric.Group(group.reverse());
group.canvas = this;
this.setActiveGroup(group);
group.saveCoords();
this.fire('selection:created', { target: group });
@ -11516,6 +11537,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
this._activeGroup = group;
if (group) {
group.canvas = this;
group._calcBounds();
group._updateObjectsCoords();
group.setCoords();
group.set('active', true);
}
return this;
@ -11860,7 +11884,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
if (this.clipTo) {
fabric.util.clipContext(this, this.contextTop);
}
this.freeDrawingBrush.onMouseDown(this.getPointer(e, true));
var ivt = fabric.util.invertTransform(this.viewportTransform);
var pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
this.freeDrawingBrush.onMouseDown(pointer);
this.fire('mouse:down', { e: e });
},
@ -11987,7 +12013,9 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
if (this.isDrawingMode) {
if (this._isCurrentlyDrawing) {
this.freeDrawingBrush.onMouseMove(this.getPointer(e, true));
var ivt = fabric.util.invertTransform(this.viewportTransform);
pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
this.freeDrawingBrush.onMouseMove(pointer);
}
this.upperCanvasEl.style.cursor = this.freeDrawingCursor;
this.fire('mouse:move', { e: e });
@ -13723,7 +13751,23 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
this.clipTo && ctx.restore();
this._removeShadow(ctx);
ctx.restore();
this._renderControls(ctx, noTransform);
},
/**
* Renders controls and borders for the object
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} [noTransform] When true, context is not transformed
*/
_renderControls: function(ctx, noTransform) {
var v;
if (this.canvas) {
v = this.canvas.viewportTransform;
}
else {
v = [1, 0, 0, 1, 0, 0]; // TODO: this isn't a solution
}
ctx.save();
if (this.active && !noTransform) {
var center;
@ -15141,8 +15185,8 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
sx= sxy.x,
sy= sxy.y;
if (this.group) {
w = w * this.group.scaleX;
h = h * this.group.scaleY;
w = w * this.group.scaleX;
h = h * this.group.scaleY;
}
ctx.strokeRect(
@ -17388,16 +17432,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._removeShadow(ctx);
ctx.restore();
ctx.save();
if (!noTransform && this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**
@ -17752,16 +17787,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._removeShadow(ctx);
ctx.restore();
ctx.save();
if (this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx);
},
/**
@ -17964,25 +17990,26 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
initialize: function(objects, options) {
options = options || { };
// NOTE: all the coords calculations need to have a canvas before they make sense
this._objects = objects || [];
for (var i = this._objects.length; i--; ) {
this._objects[i].group = this;
this._objects[i].setCoords();
//this._objects[i].setCoords();
}
this.originalState = { };
this.callSuper('initialize');
this._calcBounds();
this._updateObjectsCoords();
//this._calcBounds();
//this._updateObjectsCoords();
if (options) {
extend(this, options);
}
this._setOpacityIfSame();
this.setCoords(true);
this.saveCoords();
//this.setCoords(true);
//this.saveCoords();
},
/**
@ -18130,12 +18157,13 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
// do not render if object is not visible
if (!this.visible) return;
ctx.save();
var v = this.canvas.viewportTransform;
ctx.save();
var sxy = fabric.util.transformPoint(
new fabric.Point(this.scaleX, this.scaleY),
v, true),
v,
true
),
groupScaleFactor = Math.max(sxy.x, sxy.y);
this.clipTo && fabric.util.clipContext(this, ctx);
@ -18157,13 +18185,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
}
this.clipTo && ctx.restore();
if (this.active && !noTransform) {
var center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
this.callSuper('_renderControls', ctx, noTransform);
ctx.restore();
},
@ -18325,7 +18347,14 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
}
}
var ivt = fabric.util.invertTransform(canvas.viewportTransform);
var ivt;
if (this.canvas) {
ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
}
else { // BUG: this always happens when new groups are created
ivt = [1, 0, 0, 1, 0, 0];
console.log('no canvas');
}
minXY = new fabric.Point(min(aX), min(aY));
maxXY = new fabric.Point(max(aX), max(aY));
@ -18555,25 +18584,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.restore();
ctx.restore();
ctx.save();
if (this.active && !noTransform) {
var center;
if (this.group) {
center = fabric.util.transformPoint(this.group.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(degreesToRadians(this.group.angle));
}
center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group);
if (this.group) {
center.x *= this.group.scaleX;
center.y *= this.group.scaleY;
}
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**
@ -20842,16 +20853,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
this._render(ctx);
ctx.restore();
ctx.save();
if (!noTransform && this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**

192
dist/all.require.js vendored
View file

@ -8665,13 +8665,6 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
*/
viewportTransform: [1, 0, 0, 1, 0, 0],
/**
* Color of canvas border
* @type String
* @default
*/
canvasBorderColor: '',
/**
* Callback; invoked right before object is about to be scaled/rotated
* @param {fabric.Object} target Object that's about to be scaled/rotated
@ -8993,6 +8986,10 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
// TODO: just change the scale, preserve other transformations
this.viewportTransform[0] = value;
this.viewportTransform[3] = value;
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},
@ -9010,6 +9007,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
);
this.viewportTransform[4] = x - wh.x/2;
this.viewportTransform[5] = y - wh.y/2;
this.renderAll();
return this;
},
@ -9076,7 +9074,7 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
obj.canvas = this;
obj.setCoords();
if (obj._objects) {
for (var i = 0, len = obj._objects; i < len; i++) {
for (var i = 0, len = obj._objects.length; i < len; i++) {
obj._objects[i].canvas = this;
obj._objects[i].setCoords();
}
@ -9182,10 +9180,6 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
if (typeof this.backgroundImage === 'object') {
this._drawBackroundImage(canvasToDrawOn);
}
if (this.canvasBorderColor) {
this._drawCanvasBorder(canvasToDrawOn);
}
var activeGroup = this.getActiveGroup();
for (var i = 0, length = this._objects.length; i < length; ++i) {
@ -9242,23 +9236,6 @@ fabric.Pattern = fabric.util.createClass(/** @lends fabric.Pattern.prototype */
canvasToDrawOn.restore();
},
/**
* @private
* @param {CanvasRenderingContext2D} canvasToDrawOn Context to render on
*/
_drawCanvasBorder: function(canvasToDrawOn) {
var xy = fabric.util.transformPoint(new fabric.Point(0, 0), this.viewportTransform),
wh = fabric.util.transformPoint(
new fabric.Point(this.getWidth(), this.getHeight()),
this.viewportTransform, true
);
canvasToDrawOn.save();
canvasToDrawOn.lineWidth = 1;
canvasToDrawOn.strokeStyle = this.canvasBorderColor;
canvasToDrawOn.strokeRect(xy.x - 1.5, xy.y - 1.5, wh.x + 2, wh.y + 2);
canvasToDrawOn.restore();
},
/**
* Method to render only the top canvas.
* Also used to render the group selection box.
@ -10369,6 +10346,8 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
}
var group = new fabric.Group(rects);
group.canvas = this.canvas;
this.canvas.add(group);
this.canvas.fire('path:created', { path: group });
@ -10404,9 +10383,13 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
var ctx = this.canvas.contextTop;
ctx.fillStyle = this.color;
ctx.save();
var ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {
var point = this.sprayChunkPoints[i];
var tpoint = fabric.util.transformPoint({x: point.x, y: point.y}, ivt);
point.x = tpoint.x;
point.y = tpoint.y;
if (typeof point.opacity !== 'undefined') {
ctx.globalAlpha = point.opacity;
}
@ -10439,7 +10422,7 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
width = this.dotWidth;
}
var point = fabric.point(x, y);
var point = new fabric.Point(x, y);
point = fabric.util.transformPoint(point, vpt);
point.width = width
@ -10899,7 +10882,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
var action = 'drag',
corner,
pointer = getPointer(e, target.canvas.UpperCanvasEl);
pointer = fabric.util.transformPoint(
getPointer(e, this.upperCanvasEl),
fabric.util.invertTransform(this.viewportTransform)
);
corner = target._findTargetCorner(e, this._offset);
if (corner) {
@ -12040,7 +12026,10 @@ fabric.PatternBrush = fabric.util.createClass(fabric.PencilBrush, /** @lends fab
}
else {
// object is being transformed (scaled/rotated/moved/etc.)
pointer = this.getPointer(e);
pointer = fabric.util.transformPoint(
getPointer(e, this.upperCanvasEl),
fabric.util.invertTransform(this.viewportTransform)
);
var x = pointer.x,
y = pointer.y,
@ -13404,6 +13393,9 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
* @param {Boolean} fromLeft When true, context is transformed to object's top/left corner. This is used when rendering text on Node
*/
transform: function(ctx, fromLeft) {
if (this.group) {
this.group.transform(ctx, fromLeft);
}
ctx.globalAlpha = this.opacity;
var center = fromLeft ? this._getLeftTopCoords() : this.getCenterPoint();
@ -13701,9 +13693,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
}
if (!noTransform) {
if (this.group) {
this.group.transform(ctx);
}
this.transform(ctx);
}
@ -14735,10 +14724,21 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
var strokeWidth = this.strokeWidth > 1 ? this.strokeWidth : 0,
padding = this.padding,
theta = degreesToRadians(this.angle);
theta = degreesToRadians(this.angle),
vpt;
if (this.canvas) {
vpt = this.canvas.viewportTransform;
}
if (!vpt) { // TODO
vpt = [1, 0, 0, 1, 0, 0];
};
this.currentWidth = (this.width + strokeWidth) * this.scaleX + padding * 2;
this.currentHeight = (this.height + strokeWidth) * this.scaleY + padding * 2;
var f = function (p) {
return fabric.util.transformPoint(p, vpt);
}
this.currentWidth = (this.width + strokeWidth) * this.scaleX;
this.currentHeight = (this.height + strokeWidth) * this.scaleY;
// If width is negative, make postive. Fixes path selection issue
if (this.currentWidth < 0) {
@ -14758,42 +14758,32 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
cosTh = Math.cos(theta),
coords = this.getCenterPoint(),
wh = new fabric.Point(this.currentWidth, this.currentHeight);
var tl = {
x: coords.x - offsetX,
y: coords.y - offsetY
};
var tr = {
x: tl.x + (wh.x * cosTh),
y: tl.y + (wh.x * sinTh)
};
var br = {
x: tr.x - (wh.y * sinTh),
y: tr.y + (wh.y * cosTh)
};
var bl = {
x: tl.x - (wh.y * sinTh),
y: tl.y + (wh.y * cosTh)
};
var ml = {
x: tl.x - (wh.y/2 * sinTh),
y: tl.y + (wh.y/2 * cosTh)
};
var mt = {
x: tl.x + (wh.x/2 * cosTh),
y: tl.y + (wh.x/2 * sinTh)
};
var mr = {
x: tr.x - (wh.y/2 * sinTh),
y: tr.y + (wh.y/2 * cosTh)
};
var mb = {
x: bl.x + (wh.x/2 * cosTh),
y: bl.y + (wh.x/2 * sinTh)
};
var mtr = {
x: mt.x,
y: mt.y
};
var _tl = new fabric.Point(coords.x - offsetX, coords.y - offsetY);
var _tr = new fabric.Point(_tl.x + (wh.x * cosTh), _tl.y + (wh.x * sinTh));
var _bl = new fabric.Point(_tl.x - (wh.y * sinTh), _tl.y + (wh.y * cosTh));
var _mt = new fabric.Point(_tl.x + (wh.x/2 * cosTh), _tl.y + (wh.x/2 * sinTh));
var tl = f(_tl);
var tr = f(_tr);
var br = f(new fabric.Point(_tr.x - (wh.y * sinTh), _tr.y + (wh.y * cosTh)));
var bl = f(_bl);
var ml = f(new fabric.Point(_tl.x - (wh.y/2 * sinTh), _tl.y + (wh.y/2 * cosTh)));
var mt = f(_mt);
var mr = f(new fabric.Point(_tr.x - (wh.y/2 * sinTh), _tr.y + (wh.y/2 * cosTh)));
var mb = f(new fabric.Point(_bl.x + (wh.x/2 * cosTh), _bl.y + (wh.x/2 * sinTh)));
var mtr = f(new fabric.Point(_mt.x, _mt.y));
// padding
var padX = Math.cos(_angle + theta) * this.padding * Math.sqrt(2),
padY = Math.sin(_angle + theta) * this.padding * Math.sqrt(2);
tl = tl.add(new fabric.Point(-padX, -padY));
tr = tr.add(new fabric.Point(padY, -padX));
br = br.add(new fabric.Point(padX, padY));
bl = bl.add(new fabric.Point(-padY, padX));
ml = ml.add(new fabric.Point((-padX - padY) / 2, (-padY + padX) / 2));
mt = mt.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2));
mr = mr.add(new fabric.Point((padY + padX) / 2, (padY - padX) / 2));
mb = mb.add(new fabric.Point((padX - padY) / 2, (padX + padY) / 2));
mtr = mtr.add(new fabric.Point((padY - padX) / 2, -(padY + padX) / 2));
// debugging
@ -14818,17 +14808,6 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
mtr: mtr
};
var vpt;
if (this.canvas) {
vpt = this.canvas.viewportTransform;
}
if (!vpt) { // TODO
vpt = [1, 0, 0, 1, 0, 0];
}
for (c in this.oCoords) {
this.oCoords[c] = fabric.util.transformPoint(this.oCoords[c], vpt);
}
// set coordinates of the draggable boxes in the corners used to scale/rotate the image
this._setCornerCoords && this._setCornerCoords();
@ -14902,9 +14881,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
_findTargetCorner: function(e, offset) {
if (!this.hasControls || !this.active) return false;
var pointer = getPointer(e, this.canvas.upperCanvasEl),
ex = pointer.x - offset.left,
ey = pointer.y - offset.top,
var pointer = this.canvas.getPointer(e, true),
ex = pointer.x,
ey = pointer.y,
xPoints,
lines;
@ -15154,22 +15133,16 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
ctx.lineWidth = 1 / this.borderScaleFactor;
var vpt = this.canvas.viewportTransform;
// debugging
if (!vpt) {
vpt = [1, 0, 0, 1, 0, 0]
console.log("No vpt! interactivity", this.canvas, this.get('canvas'), this);
}
var wh = fabric.util.transformPoint(new fabric.Point(this.getWidth(), this.getHeight()), vpt, true),
var vpt = this.canvas.viewportTransform,
wh = fabric.util.transformPoint(new fabric.Point(this.getWidth(), this.getHeight()), vpt, true),
sxy = fabric.util.transformPoint(new fabric.Point(scaleX, scaleY), vpt, true),
w = wh.x,
h = wh.y,
sx= sxy.x,
sy= sxy.y;
if (this.get('group')) {
w = w * this.get('group').scaleX;
h = h * this.get('group').scaleY;
if (this.group) {
w = w * this.group.scaleX;
h = h * this.group.scaleY;
}
ctx.strokeRect(
@ -17994,6 +17967,7 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
this._objects = objects || [];
for (var i = this._objects.length; i--; ) {
this._objects[i].group = this;
this._objects[i].setCoords();
}
this.originalState = { };
@ -18338,16 +18312,9 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
_calcBounds: function() {
var aX = [],
aY = [],
minX, minY, maxX, maxY, o, width, height, minXY, maxXY, ivt, // TODO: cleanup
minX, minY, maxX, maxY, o, width, height, minXY, maxXY,
i = 0,
len = this._objects.length,
vpt;
if (this.canvas) {
vpt = this.canvas.viewportTransform;
}
if (!vpt) { // TODO: this always happens when new groups are created
vpt = [1, 0, 0, 1, 0, 0];
}
len = this._objects.length;
for (; i < len; ++i) {
o = this._objects[i];
@ -18357,19 +18324,18 @@ fabric.util.object.extend(fabric.Object.prototype, /** @lends fabric.Object.prot
aY.push(o.oCoords[prop].y);
}
}
var ivt = fabric.util.invertTransform(canvas.viewportTransform) || [1, 0, 0, 1, 0, 0];
minXY = new fabric.Point(min(aX), min(aY));
maxXY = new fabric.Point(max(aX), max(aY));
ivt = fabric.util.invertTransform(vpt);
this.width = (maxXY.x - minXY.x) || 0;
this.height = (maxXY.y - minXY.y) || 0;
minXY = fabric.util.transformPoint(minXY, ivt);
maxXY = fabric.util.transformPoint(maxXY, ivt);
this.width = (maxXY.x - minXY.x) || 0;
this.height = (maxXY.y - minXY.y) || 0;
this.left = (minXY.x + maxXY.x) / 2 || 0;
this.top = (minXY.y + maxXY.y) / 2 || 0;
},

View file

@ -28,11 +28,17 @@ fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric
var point = this.addPoint(pointer);
var ctx = this.canvas.contextTop;
var v = this.canvas.viewportTransform;
ctx.save();
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
ctx.fillStyle = point.fill;
ctx.beginPath();
ctx.arc(point.x, point.y, point.radius, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
ctx.restore();
},
/**
@ -65,10 +71,10 @@ fabric.CircleBrush = fabric.util.createClass(fabric.BaseBrush, /** @lends fabric
for (var i = 0, len = this.points.length; i < len; i++) {
var point = this.points[i];
var circle = new fabric.Circle({
radius: point.radius,
radius: this.points[i].radius,
left: point.x,
top: point.y,
fill: point.fill
fill: this.points[i].fill
});
this.shadow && circle.setShadow(this.shadow);

View file

@ -104,6 +104,9 @@
*/
_render: function() {
var ctx = this.canvas.contextTop;
var v = this.canvas.viewportTransform;
ctx.save();
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
ctx.beginPath();
var p1 = this._points[0];
@ -133,6 +136,7 @@
// the bezier control point
ctx.lineTo(p1.x, p1.y);
ctx.stroke();
ctx.restore();
},
/**
@ -141,10 +145,6 @@
* @private
*/
_getSVGPathData: function() {
var ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
for (var i = 0, len = this._points.length; i < len; i++) {
this._points[i] = fabric.util.transformPoint(this._points[i], ivt);
}
this.box = this.getPathBoundingBox(this._points);
return this.convertPointsToSVGPath(
this._points, this.box.minx, this.box.maxx, this.box.miny, this.box.maxy);

View file

@ -146,14 +146,13 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
render: function() {
var ctx = this.canvas.contextTop;
ctx.fillStyle = this.color;
var v = this.canvas.viewportTransform;
ctx.save();
var ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
for (var i = 0, len = this.sprayChunkPoints.length; i < len; i++) {
var point = this.sprayChunkPoints[i];
var tpoint = fabric.util.transformPoint({x: point.x, y: point.y}, ivt);
point.x = tpoint.x;
point.y = tpoint.y;
if (typeof point.opacity !== 'undefined') {
ctx.globalAlpha = point.opacity;
}
@ -169,7 +168,6 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
this.sprayChunkPoints = [ ];
var x, y, width, radius = this.width / 2;
var vpt = this.canvas.viewportTransform;
for (var i = 0; i < this.density; i++) {
@ -187,7 +185,6 @@ fabric.SprayBrush = fabric.util.createClass( fabric.BaseBrush, /** @lends fabric
}
var point = new fabric.Point(x, y);
point = fabric.util.transformPoint(point, vpt);
point.width = width
if (this.randomOpacity) {

View file

@ -504,7 +504,6 @@
var isActiveLower = objects.indexOf(this._activeObject) < objects.indexOf(target);
var group = new fabric.Group(
isActiveLower ? [ target, this._activeObject ] : [ this._activeObject, target ]);
group.canvas = this;
this.setActiveGroup(group);
this._activeObject = null;
@ -784,7 +783,6 @@
}
else if (group.length > 1) {
group = new fabric.Group(group.reverse());
group.canvas = this;
this.setActiveGroup(group);
group.saveCoords();
this.fire('selection:created', { target: group });
@ -1019,6 +1017,9 @@
this._activeGroup = group;
if (group) {
group.canvas = this;
group._calcBounds();
group._updateObjectsCoords();
group.setCoords();
group.set('active', true);
}
return this;

View file

@ -235,7 +235,9 @@
if (this.clipTo) {
fabric.util.clipContext(this, this.contextTop);
}
this.freeDrawingBrush.onMouseDown(this.getPointer(e, true));
var ivt = fabric.util.invertTransform(this.viewportTransform);
var pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
this.freeDrawingBrush.onMouseDown(pointer);
this.fire('mouse:down', { e: e });
},
@ -362,7 +364,9 @@
if (this.isDrawingMode) {
if (this._isCurrentlyDrawing) {
this.freeDrawingBrush.onMouseMove(this.getPointer(e, true));
var ivt = fabric.util.invertTransform(this.viewportTransform);
pointer = fabric.util.transformPoint(this.getPointer(e, true), ivt);
this.freeDrawingBrush.onMouseMove(pointer);
}
this.upperCanvasEl.style.cursor = this.freeDrawingCursor;
this.fire('mouse:move', { e: e });

View file

@ -275,8 +275,8 @@
sx= sxy.x,
sy= sxy.y;
if (this.group) {
w = w * this.group.scaleX;
h = h * this.group.scaleY;
w = w * this.group.scaleX;
h = h * this.group.scaleY;
}
ctx.strokeRect(

View file

@ -50,25 +50,26 @@
initialize: function(objects, options) {
options = options || { };
// NOTE: all the coords calculations need to have a canvas before they make sense
this._objects = objects || [];
for (var i = this._objects.length; i--; ) {
this._objects[i].group = this;
this._objects[i].setCoords();
//this._objects[i].setCoords();
}
this.originalState = { };
this.callSuper('initialize');
this._calcBounds();
this._updateObjectsCoords();
//this._calcBounds();
//this._updateObjectsCoords();
if (options) {
extend(this, options);
}
this._setOpacityIfSame();
this.setCoords(true);
this.saveCoords();
//this.setCoords(true);
//this.saveCoords();
},
/**
@ -216,12 +217,13 @@
// do not render if object is not visible
if (!this.visible) return;
ctx.save();
var v = this.canvas.viewportTransform;
ctx.save();
var sxy = fabric.util.transformPoint(
new fabric.Point(this.scaleX, this.scaleY),
v, true),
v,
true
),
groupScaleFactor = Math.max(sxy.x, sxy.y);
this.clipTo && fabric.util.clipContext(this, ctx);
@ -243,13 +245,7 @@
}
this.clipTo && ctx.restore();
if (this.active && !noTransform) {
var center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
this.callSuper('_renderControls', ctx, noTransform);
ctx.restore();
},
@ -411,7 +407,14 @@
}
}
var ivt = fabric.util.invertTransform(canvas.viewportTransform);
var ivt;
if (this.canvas) {
ivt = fabric.util.invertTransform(this.canvas.viewportTransform);
}
else { // BUG: this always happens when new groups are created
ivt = [1, 0, 0, 1, 0, 0];
console.log('no canvas');
}
minXY = new fabric.Point(min(aX), min(aY));
maxXY = new fabric.Point(max(aX), max(aY));

View file

@ -135,25 +135,7 @@
ctx.restore();
ctx.restore();
ctx.save();
if (this.active && !noTransform) {
var center;
if (this.group) {
center = fabric.util.transformPoint(this.group.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(degreesToRadians(this.group.angle));
}
center = fabric.util.transformPoint(this.getCenterPoint(), v, null != this.group);
if (this.group) {
center.x *= this.group.scaleX;
center.y *= this.group.scaleY;
}
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**

View file

@ -1060,7 +1060,23 @@
this.clipTo && ctx.restore();
this._removeShadow(ctx);
ctx.restore();
this._renderControls(ctx, noTransform);
},
/**
* Renders controls and borders for the object
* @param {CanvasRenderingContext2D} ctx Context to render on
* @param {Boolean} [noTransform] When true, context is not transformed
*/
_renderControls: function(ctx, noTransform) {
var v;
if (this.canvas) {
v = this.canvas.viewportTransform;
}
else {
v = [1, 0, 0, 1, 0, 0]; // TODO: this isn't a solution
}
ctx.save();
if (this.active && !noTransform) {
var center;

View file

@ -476,16 +476,7 @@
this._removeShadow(ctx);
ctx.restore();
ctx.save();
if (!noTransform && this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**

View file

@ -93,16 +93,7 @@
this._removeShadow(ctx);
ctx.restore();
ctx.save();
if (this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx);
},
/**

View file

@ -767,16 +767,8 @@
ctx.transform(v[0], v[1], v[2], v[3], v[4], v[5]);
this._render(ctx);
ctx.restore();
ctx.save();
if (!noTransform && this.active) {
var center;
center = fabric.util.transformPoint(this.getCenterPoint(), v);
ctx.translate(center.x, center.y);
ctx.rotate(fabric.util.degreesToRadians(this.angle));
this.drawBorders(ctx);
this.drawControls(ctx);
}
ctx.restore();
this.callSuper('_renderControls', ctx, noTransform);
},
/**

View file

@ -457,6 +457,21 @@
return new fabric.Point(this.getWidth()/2 + x, this.getHeight()/2 + y);
},
/**
* Sets viewport transform of this canvas instance
* @param {Array} vpt the transform in the form of context.transform
* @return {fabric.Canvas} instance
* @chainable true
*/
setViewportTransform: function (vpt) {
this.viewportTransform = vpt
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},
/**
* Sets zoom level of this canvas instance
* @param {Number} value to set zoom to, less than 1 zooms out
@ -489,6 +504,9 @@
this.viewportTransform[4] = x - wh.x/2;
this.viewportTransform[5] = y - wh.y/2;
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},
@ -553,13 +571,15 @@
_onObjectAdded: function(obj) {
this.stateful && obj.setupState();
obj.canvas = this;
obj.setCoords();
if (obj._objects) {
obj._calcBounds();
for (var i = 0, len = obj._objects.length; i < len; i++) {
obj._objects[i].canvas = this;
obj._objects[i].setCoords();
this._onObjectAdded(obj._objects[i]);
}
obj._updateObjectsCoords()
}
obj.setCoords();
this.fire('object:added', { target: obj });
obj.fire('added');
},