mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-01 10:48:38 -05:00
Give view proper Matrix transformation functions, just like on Item.
Relates to #832
This commit is contained in:
parent
b3e81af9b6
commit
3a3d46692b
6 changed files with 158 additions and 59 deletions
|
@ -220,8 +220,6 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
* @return {Matrix} this affine transform
|
||||
*/
|
||||
scale: function(/* scale, center */) {
|
||||
// Do not modify scale, center, since that would arguments of which
|
||||
// we're reading from!
|
||||
var scale = Point.read(arguments),
|
||||
center = Point.read(arguments, 0, { readNull: true });
|
||||
if (center)
|
||||
|
@ -761,10 +759,10 @@ var Matrix = Base.extend(/** @lends Matrix# */{
|
|||
this._tx, this._ty);
|
||||
}
|
||||
}
|
||||
}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(name) {
|
||||
}, Base.each(['a', 'c', 'b', 'd', 'tx', 'ty'], function(key) {
|
||||
// Create getters and setters for all internal attributes.
|
||||
var part = Base.capitalize(name),
|
||||
prop = '_' + name;
|
||||
var part = Base.capitalize(key),
|
||||
prop = '_' + key;
|
||||
this['get' + part] = function() {
|
||||
return this[prop];
|
||||
};
|
||||
|
|
|
@ -947,10 +947,10 @@ var Point = Base.extend(/** @lends Point# */{
|
|||
* /*#=*/Numerical.TRIGONOMETRIC_EPSILON;
|
||||
}
|
||||
}
|
||||
}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
|
||||
}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
|
||||
// Inject round, ceil, floor, abs:
|
||||
var op = Math[name];
|
||||
this[name] = function() {
|
||||
var op = Math[key];
|
||||
this[key] = function() {
|
||||
return new Point(op(this.x), op(this.y));
|
||||
};
|
||||
}, {}));
|
||||
|
|
|
@ -524,10 +524,10 @@ var Size = Base.extend(/** @lends Size# */{
|
|||
return new Size(Math.random(), Math.random());
|
||||
}
|
||||
}
|
||||
}, Base.each(['round', 'ceil', 'floor', 'abs'], function(name) {
|
||||
}, Base.each(['round', 'ceil', 'floor', 'abs'], function(key) {
|
||||
// Inject round, ceil, floor, abs:
|
||||
var op = Math[name];
|
||||
this[name] = function() {
|
||||
var op = Math[key];
|
||||
this[key] = function() {
|
||||
return new Size(op(this.width), op(this.height));
|
||||
};
|
||||
}, {}));
|
||||
|
|
|
@ -35,7 +35,9 @@ var ChangeFlag = {
|
|||
// Raster pixels
|
||||
PIXELS: 0x200,
|
||||
// Clipping in one of the child items
|
||||
CLIPPING: 0x400
|
||||
CLIPPING: 0x400,
|
||||
// The view has been transformed
|
||||
VIEW: 0x800
|
||||
};
|
||||
|
||||
// Shortcuts to often used ChangeFlag values including APPEARANCE
|
||||
|
@ -51,5 +53,6 @@ var Change = {
|
|||
STYLE: ChangeFlag.STYLE | ChangeFlag.APPEARANCE,
|
||||
ATTRIBUTE: ChangeFlag.ATTRIBUTE | ChangeFlag.APPEARANCE,
|
||||
CONTENT: ChangeFlag.CONTENT | ChangeFlag.GEOMETRY | ChangeFlag.APPEARANCE,
|
||||
PIXELS: ChangeFlag.PIXELS | ChangeFlag.APPEARANCE
|
||||
PIXELS: ChangeFlag.PIXELS | ChangeFlag.APPEARANCE,
|
||||
VIEW: ChangeFlag.VIEW | ChangeFlag.APPEARANCE
|
||||
};
|
||||
|
|
|
@ -2936,11 +2936,19 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* @property
|
||||
* @type Color
|
||||
*/
|
||||
|
||||
}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
|
||||
var rotate = key === 'rotate';
|
||||
this[key] = function(/* value, center */) {
|
||||
var value = (rotate ? Base : Point).read(arguments),
|
||||
center = Point.read(arguments, 0, { readNull: true });
|
||||
return this.transform(new Matrix()[key](value,
|
||||
center || this.getPosition(true)));
|
||||
};
|
||||
}, /** @lends Item# */{
|
||||
/**
|
||||
* {@grouptitle Transform Functions}
|
||||
*
|
||||
* Translates (moves) the item by the given offset point.
|
||||
* Translates (moves) the item by the given offset views.
|
||||
*
|
||||
* @param {Point} delta the offset to translate the item by
|
||||
*/
|
||||
|
@ -2950,13 +2958,15 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
},
|
||||
|
||||
/**
|
||||
* Rotates the item by a given angle around the given point.
|
||||
* Rotates the item by a given angle around the given center point.
|
||||
*
|
||||
* Angles are oriented clockwise and measured in degrees.
|
||||
*
|
||||
* @name Item#rotate
|
||||
* @function
|
||||
* @param {Number} angle the rotation angle
|
||||
* @param {Point} [center={@link Item#position}]
|
||||
* @see Matrix#rotate
|
||||
* @see Matrix#rotate(angle[, center])
|
||||
*
|
||||
* @example {@paperscript}
|
||||
* // Rotating an item:
|
||||
|
@ -2993,20 +3003,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* path.rotate(3, view.center);
|
||||
* }
|
||||
*/
|
||||
rotate: function(angle /*, center */) {
|
||||
return this.transform(new Matrix().rotate(angle,
|
||||
Point.read(arguments, 1, { readNull: true })
|
||||
|| this.getPosition(true)));
|
||||
}
|
||||
}, Base.each(['scale', 'shear', 'skew'], function(name) {
|
||||
this[name] = function() {
|
||||
// See Matrix#scale for explanation of this:
|
||||
var point = Point.read(arguments),
|
||||
center = Point.read(arguments, 0, { readNull: true });
|
||||
return this.transform(new Matrix()[name](point,
|
||||
center || this.getPosition(true)));
|
||||
};
|
||||
}, /** @lends Item# */{
|
||||
|
||||
/**
|
||||
* Scales the item by the given value from its center point, or optionally
|
||||
* from a supplied point.
|
||||
|
@ -3078,7 +3075,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* @function
|
||||
* @param {Point} shear the horziontal and vertical shear factors as a point
|
||||
* @param {Point} [center={@link Item#position}]
|
||||
* @see Matrix#shear
|
||||
* @see Matrix#shear(shear[, center])
|
||||
*/
|
||||
/**
|
||||
* Shears the item by the given values from its center point, or optionally
|
||||
|
@ -3089,7 +3086,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* @param {Number} hor the horizontal shear factor
|
||||
* @param {Number} ver the vertical shear factor
|
||||
* @param {Point} [center={@link Item#position}]
|
||||
* @see Matrix#shear
|
||||
* @see Matrix#shear(hor, ver[, center])
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -3100,7 +3097,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* @function
|
||||
* @param {Point} skew the horziontal and vertical skew angles in degrees
|
||||
* @param {Point} [center={@link Item#position}]
|
||||
* @see Matrix#shear
|
||||
* @see Matrix#shear(skew[, center])
|
||||
*/
|
||||
/**
|
||||
* Skews the item by the given angles from its center point, or optionally
|
||||
|
@ -3111,9 +3108,9 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
* @param {Number} hor the horizontal skew angle in degrees
|
||||
* @param {Number} ver the vertical sskew angle in degrees
|
||||
* @param {Point} [center={@link Item#position}]
|
||||
* @see Matrix#shear
|
||||
* @see Matrix#shear(hor, ver[, center])
|
||||
*/
|
||||
}), /** @lends Item# */{
|
||||
|
||||
/**
|
||||
* Transform the item.
|
||||
*
|
||||
|
@ -3331,7 +3328,7 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
*/
|
||||
fitBounds: function(rectangle, fill) {
|
||||
// TODO: Think about passing options with various ways of defining
|
||||
// fitting.
|
||||
// fitting. Compare with InDesign fitting to see possible options.
|
||||
rectangle = Rectangle.read(arguments);
|
||||
var bounds = this.getBounds(),
|
||||
itemRatio = bounds.height / bounds.width,
|
||||
|
@ -3343,8 +3340,8 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
new Size(bounds.width * scale, bounds.height * scale));
|
||||
newBounds.setCenter(rectangle.getCenter());
|
||||
this.setBounds(newBounds);
|
||||
},
|
||||
|
||||
}
|
||||
}), /** @lends Item# */{
|
||||
/**
|
||||
* {@grouptitle Event Handlers}
|
||||
*
|
||||
|
@ -4070,10 +4067,10 @@ var Item = Base.extend(Emitter, /** @lends Item# */{
|
|||
_canComposite: function() {
|
||||
return false;
|
||||
}
|
||||
}, Base.each(['down', 'drag', 'up', 'move'], function(name) {
|
||||
this['removeOn' + Base.capitalize(name)] = function() {
|
||||
}, Base.each(['down', 'drag', 'up', 'move'], function(key) {
|
||||
this['removeOn' + Base.capitalize(key)] = function() {
|
||||
var hash = {};
|
||||
hash[name] = true;
|
||||
hash[key] = true;
|
||||
return this.removeOn(hash);
|
||||
};
|
||||
}, /** @lends Item# */{
|
||||
|
|
135
src/view/View.js
135
src/view/View.js
|
@ -261,18 +261,13 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
/**
|
||||
* Private notifier that is called whenever a change occurs in this view.
|
||||
* Used only by Matrix for now.
|
||||
*
|
||||
* @param {ChangeFlag} flags describes what exactly has changed
|
||||
*/
|
||||
_changed: function(flags) {
|
||||
this._project._changed(flags);
|
||||
},
|
||||
|
||||
_transform: function(matrix) {
|
||||
this._matrix.concatenate(matrix);
|
||||
_changed: function() {
|
||||
// The only one calling View._changed() is Matrix, so it can only mean
|
||||
// one thing:
|
||||
this._project._changed(/*#=*/Change.VIEW);
|
||||
// Force recalculation of these values next time they are requested.
|
||||
this._bounds = null;
|
||||
this._update();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -329,13 +324,13 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
return;
|
||||
this._viewSize.set(size.width, size.height);
|
||||
this._setViewSize(size);
|
||||
this._bounds = null; // Force recalculation
|
||||
// Call onResize handler on any size change
|
||||
this.emit('resize', {
|
||||
size: size,
|
||||
delta: delta
|
||||
});
|
||||
this._update();
|
||||
this._changed();
|
||||
this.update();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -382,7 +377,7 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
|
||||
setCenter: function(/* center */) {
|
||||
var center = Point.read(arguments);
|
||||
this.scrollBy(center.subtract(this.getCenter()));
|
||||
this.translate(this.getCenter().subtract(center));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -396,8 +391,7 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
},
|
||||
|
||||
setZoom: function(zoom) {
|
||||
// TODO: Clamp the view between 1/32 and 64, just like Illustrator?
|
||||
this._transform(new Matrix().scale(zoom / this._zoom,
|
||||
this.transform(new Matrix().scale(zoom / this._zoom,
|
||||
this.getCenter()));
|
||||
this._zoom = zoom;
|
||||
},
|
||||
|
@ -438,17 +432,124 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
|||
*/
|
||||
isInserted: function() {
|
||||
return DomElement.isInserted(this._element);
|
||||
}
|
||||
}, Base.each(['rotate', 'scale', 'shear', 'skew'], function(key) {
|
||||
var rotate = key === 'rotate';
|
||||
this[key] = function(/* value, center */) {
|
||||
var value = (rotate ? Base : Point).read(arguments),
|
||||
center = Point.read(arguments, 0, { readNull: true });
|
||||
return this.transform(new Matrix()[key](value,
|
||||
center || this.getCenter(true)));
|
||||
};
|
||||
}, /** @lends View# */{
|
||||
/**
|
||||
* {@grouptitle Transform Functions}
|
||||
*
|
||||
* Translates (scrolls) the view by the given offset vector.
|
||||
*
|
||||
* @param {Point} delta the offset to translate the view by
|
||||
*/
|
||||
translate: function(/* delta */) {
|
||||
var mx = new Matrix();
|
||||
return this.transform(mx.translate.apply(mx, arguments));
|
||||
},
|
||||
|
||||
/**
|
||||
* Rotates the view by a given angle around the given center point.
|
||||
*
|
||||
* Angles are oriented clockwise and measured in degrees.
|
||||
*
|
||||
* @name View#rotate
|
||||
* @function
|
||||
* @param {Number} angle the rotation angle
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
* @see Matrix#rotate(angle[, center])
|
||||
*/
|
||||
|
||||
/**
|
||||
* Scales the view by the given value from its center point, or optionally
|
||||
* from a supplied point.
|
||||
*
|
||||
* @name View#scale
|
||||
* @function
|
||||
* @param {Number} scale the scale factor
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
*/
|
||||
/**
|
||||
* Scales the view by the given values from its center point, or optionally
|
||||
* from a supplied point.
|
||||
*
|
||||
* @name View#scale
|
||||
* @function
|
||||
* @param {Number} hor the horizontal scale factor
|
||||
* @param {Number} ver the vertical scale factor
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
*/
|
||||
|
||||
/**
|
||||
* Shears the view by the given value from its center point, or optionally
|
||||
* by a supplied point.
|
||||
*
|
||||
* @name View#shear
|
||||
* @function
|
||||
* @param {Point} shear the horziontal and vertical shear factors as a point
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
* @see Matrix#shear(shear[, center])
|
||||
*/
|
||||
/**
|
||||
* Shears the view by the given values from its center point, or optionally
|
||||
* by a supplied point.
|
||||
*
|
||||
* @name View#shear
|
||||
* @function
|
||||
* @param {Number} hor the horizontal shear factor
|
||||
* @param {Number} ver the vertical shear factor
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
* @see Matrix#shear(hor, ver[, center])
|
||||
*/
|
||||
|
||||
/**
|
||||
* Skews the view by the given angles from its center point, or optionally
|
||||
* by a supplied point.
|
||||
*
|
||||
* @name View#skew
|
||||
* @function
|
||||
* @param {Point} skew the horziontal and vertical skew angles in degrees
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
* @see Matrix#shear(skew[, center])
|
||||
*/
|
||||
/**
|
||||
* Skews the view by the given angles from its center point, or optionally
|
||||
* by a supplied point.
|
||||
*
|
||||
* @name View#skew
|
||||
* @function
|
||||
* @param {Number} hor the horizontal skew angle in degrees
|
||||
* @param {Number} ver the vertical sskew angle in degrees
|
||||
* @param {Point} [center={@link View#getCenter()}]
|
||||
* @see Matrix#shear(hor, ver[, center])
|
||||
*/
|
||||
|
||||
/**
|
||||
* Transform the view.
|
||||
*
|
||||
* @param {Matrix} matrix the matrix by which the view shall be transformed
|
||||
*/
|
||||
transform: function(matrix) {
|
||||
this._matrix.concatenate(matrix);
|
||||
},
|
||||
|
||||
/**
|
||||
* Scrolls the view by the given vector.
|
||||
*
|
||||
* @param {Point} point
|
||||
* @deprecated use {@link #translate(delta)} instead (using opposite
|
||||
* direction).
|
||||
*/
|
||||
scrollBy: function(/* point */) {
|
||||
this._transform(new Matrix().translate(Point.read(arguments).negate()));
|
||||
},
|
||||
|
||||
this.translate(Point.read(arguments).negate());
|
||||
}
|
||||
}), /** @lends View# */{
|
||||
/**
|
||||
* Makes all animation play by adding the view to the request animation
|
||||
* loop.
|
||||
|
|
Loading…
Reference in a new issue