mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-05 20:32:00 -05:00
Reflect View#zoom through matrix decomposition, and implement additional decomposed properties.
Closes #1107
This commit is contained in:
parent
4d9c0c9f05
commit
f874b927bf
2 changed files with 112 additions and 62 deletions
|
@ -779,13 +779,11 @@ new function() { // Injection scope for various item event handlers
|
||||||
* @type Point
|
* @type Point
|
||||||
* @default null
|
* @default null
|
||||||
*/
|
*/
|
||||||
getPivot: function(_dontLink) {
|
getPivot: function() {
|
||||||
var pivot = this._pivot;
|
var pivot = this._pivot;
|
||||||
if (pivot) {
|
return pivot
|
||||||
var ctor = _dontLink ? Point : LinkedPoint;
|
? new LinkedPoint(pivot.x, pivot.y, this, 'setPivot')
|
||||||
pivot = new ctor(pivot.x, pivot.y, this, 'setPivot');
|
: null;
|
||||||
}
|
|
||||||
return pivot;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
setPivot: function(/* point */) {
|
setPivot: function(/* point */) {
|
||||||
|
@ -1088,11 +1086,12 @@ new function() { // Injection scope for various item event handlers
|
||||||
* @bean
|
* @bean
|
||||||
* @type Point
|
* @type Point
|
||||||
*/
|
*/
|
||||||
getScaling: function(_dontLink) {
|
getScaling: function() {
|
||||||
var decomposed = this._decompose(),
|
var decomposed = this._decompose(),
|
||||||
scaling = decomposed && decomposed.scaling,
|
scaling = decomposed && decomposed.scaling;
|
||||||
ctor = _dontLink ? Point : LinkedPoint;
|
return scaling
|
||||||
return scaling && new ctor(scaling.x, scaling.y, this, 'setScaling');
|
? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')
|
||||||
|
: undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
setScaling: function(/* scaling */) {
|
setScaling: function(/* scaling */) {
|
||||||
|
|
155
src/view/View.js
155
src/view/View.js
|
@ -107,7 +107,6 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
||||||
// Link this id to our view
|
// Link this id to our view
|
||||||
View._viewsById[this._id] = this;
|
View._viewsById[this._id] = this;
|
||||||
(this._matrix = new Matrix())._owner = this;
|
(this._matrix = new Matrix())._owner = this;
|
||||||
this._zoom = 1;
|
|
||||||
// Make sure the first view is focused for keyboard input straight away
|
// Make sure the first view is focused for keyboard input straight away
|
||||||
if (!View._focused)
|
if (!View._focused)
|
||||||
View._focused = this;
|
View._focused = this;
|
||||||
|
@ -331,7 +330,7 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
||||||
// one thing:
|
// one thing:
|
||||||
this._project._changed(/*#=*/Change.VIEW);
|
this._project._changed(/*#=*/Change.VIEW);
|
||||||
// Force recalculation of these values next time they are requested.
|
// Force recalculation of these values next time they are requested.
|
||||||
this._bounds = null;
|
this._bounds = this._decomposed = undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -436,56 +435,6 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
||||||
return this.getBounds().getSize();
|
return this.getBounds().getSize();
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* The center of the visible area in project coordinates.
|
|
||||||
*
|
|
||||||
* @bean
|
|
||||||
* @type Point
|
|
||||||
*/
|
|
||||||
getCenter: function() {
|
|
||||||
return this.getBounds().getCenter();
|
|
||||||
},
|
|
||||||
|
|
||||||
setCenter: function(/* center */) {
|
|
||||||
var center = Point.read(arguments);
|
|
||||||
this.translate(this.getCenter().subtract(center));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The zoom factor by which the project coordinates are magnified.
|
|
||||||
*
|
|
||||||
* @bean
|
|
||||||
* @type Number
|
|
||||||
*/
|
|
||||||
getZoom: function() {
|
|
||||||
return this._zoom;
|
|
||||||
},
|
|
||||||
|
|
||||||
setZoom: function(zoom) {
|
|
||||||
this.transform(new Matrix().scale(zoom / this._zoom,
|
|
||||||
this.getCenter()));
|
|
||||||
this._zoom = zoom;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The view's transformation matrix, defining the view onto the project's
|
|
||||||
* contents (position, zoom level, rotation, etc).
|
|
||||||
*
|
|
||||||
* @bean
|
|
||||||
* @type Matrix
|
|
||||||
*/
|
|
||||||
getMatrix: function() {
|
|
||||||
return this._matrix;
|
|
||||||
},
|
|
||||||
|
|
||||||
setMatrix: function() {
|
|
||||||
// Use Matrix#initialize to easily copy over values.
|
|
||||||
// NOTE: calling initialize() also calls #_changed() for us, through its
|
|
||||||
// call to #set() / #reset(), and this also handles _applyMatrix for us.
|
|
||||||
var matrix = this._matrix;
|
|
||||||
matrix.initialize.apply(matrix, arguments);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the view is currently visible within the current browser
|
* Checks whether the view is currently visible within the current browser
|
||||||
* viewport.
|
* viewport.
|
||||||
|
@ -539,6 +488,10 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
||||||
center || this.getCenter(true)));
|
center || this.getCenter(true)));
|
||||||
};
|
};
|
||||||
}, /** @lends View# */{
|
}, /** @lends View# */{
|
||||||
|
_decompose: function() {
|
||||||
|
return this._decomposed || (this._decomposed = this._matrix.decompose());
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@grouptitle Transform Functions}
|
* {@grouptitle Transform Functions}
|
||||||
*
|
*
|
||||||
|
@ -551,6 +504,104 @@ var View = Base.extend(Emitter, /** @lends View# */{
|
||||||
return this.transform(mx.translate.apply(mx, arguments));
|
return this.transform(mx.translate.apply(mx, arguments));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The center of the visible area in project coordinates.
|
||||||
|
*
|
||||||
|
* @bean
|
||||||
|
* @type Point
|
||||||
|
*/
|
||||||
|
getCenter: function() {
|
||||||
|
return this.getBounds().getCenter();
|
||||||
|
},
|
||||||
|
|
||||||
|
setCenter: function(/* center */) {
|
||||||
|
var center = Point.read(arguments);
|
||||||
|
this.translate(this.getCenter().subtract(center));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The view's zoom factor by which the project coordinates are magnified.
|
||||||
|
*
|
||||||
|
* @bean
|
||||||
|
* @type Number
|
||||||
|
* @see #getScaling()
|
||||||
|
*/
|
||||||
|
getZoom: function() {
|
||||||
|
var decomposed = this._decompose(),
|
||||||
|
scaling = decomposed && decomposed.scaling;
|
||||||
|
// Use average since it can be non-uniform, and return 0 when it can't
|
||||||
|
// be decomposed.
|
||||||
|
return scaling ? (scaling.x + scaling.y) / 2 : 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
setZoom: function(zoom) {
|
||||||
|
this.transform(new Matrix().scale(zoom / this.getZoom(),
|
||||||
|
this.getCenter()));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current rotation angle of the view, as described by its
|
||||||
|
* {@link #matrix}.
|
||||||
|
*
|
||||||
|
* @bean
|
||||||
|
* @type Number
|
||||||
|
*/
|
||||||
|
getRotation: function() {
|
||||||
|
var decomposed = this._decompose();
|
||||||
|
return decomposed && decomposed.rotation;
|
||||||
|
},
|
||||||
|
|
||||||
|
setRotation: function(rotation) {
|
||||||
|
var current = this.getRotation();
|
||||||
|
if (current != null && rotation != null) {
|
||||||
|
this.rotate(rotation - current);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current scale factor of the view, as described by its
|
||||||
|
* {@link #matrix}.
|
||||||
|
*
|
||||||
|
* @bean
|
||||||
|
* @type Point
|
||||||
|
* @see #getZoom()
|
||||||
|
*/
|
||||||
|
getScaling: function() {
|
||||||
|
var decomposed = this._decompose(),
|
||||||
|
scaling = decomposed && decomposed.scaling;
|
||||||
|
return scaling
|
||||||
|
? new LinkedPoint(scaling.x, scaling.y, this, 'setScaling')
|
||||||
|
: undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
setScaling: function(/* scaling */) {
|
||||||
|
var current = this.getScaling(),
|
||||||
|
// Clone existing points since we're caching internally.
|
||||||
|
scaling = Point.read(arguments, 0, { clone: true, readNull: true });
|
||||||
|
if (current && scaling) {
|
||||||
|
this.scale(scaling.x / current.x, scaling.y / current.y);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The view's transformation matrix, defining the view onto the project's
|
||||||
|
* contents (position, zoom level, rotation, etc).
|
||||||
|
*
|
||||||
|
* @bean
|
||||||
|
* @type Matrix
|
||||||
|
*/
|
||||||
|
getMatrix: function() {
|
||||||
|
return this._matrix;
|
||||||
|
},
|
||||||
|
|
||||||
|
setMatrix: function() {
|
||||||
|
// Use Matrix#initialize to easily copy over values.
|
||||||
|
// NOTE: calling initialize() also calls #_changed() for us, through its
|
||||||
|
// call to #set() / #reset(), and this also handles _applyMatrix for us.
|
||||||
|
var matrix = this._matrix;
|
||||||
|
matrix.initialize.apply(matrix, arguments);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotates the view by a given angle around the given center point.
|
* Rotates the view by a given angle around the given center point.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue