mirror of
https://github.com/konvajs/konva.git
synced 2025-06-27 19:25:43 +08:00
finished matrix integration. the stage, layers, groups, and nodes can be transformed in anyway, and drag and drop on any of these nodes now works great regardless of parent node transforms
This commit is contained in:
parent
7ced50f694
commit
68f9688575
111
dist/kinetic-core.js
vendored
111
dist/kinetic-core.js
vendored
@ -3,7 +3,7 @@
|
||||
* http://www.kineticjs.com/
|
||||
* Copyright 2012, Eric Rowell
|
||||
* Licensed under the MIT or GPL Version 2 licenses.
|
||||
* Date: Mar 22 2012
|
||||
* Date: Mar 23 2012
|
||||
*
|
||||
* Copyright (C) 2011 - 2012 by Eric Rowell
|
||||
*
|
||||
@ -52,6 +52,10 @@ Kinetic.GlobalObject = {
|
||||
offset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
start: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
extend: function(obj1, obj2) {
|
||||
@ -754,6 +758,35 @@ Kinetic.Node.prototype = {
|
||||
getDragBounds: function() {
|
||||
return this.dragBounds;
|
||||
},
|
||||
/**
|
||||
* get matrix transform of the node while taking into
|
||||
* account the matrix transforms of its parents
|
||||
*/
|
||||
getAbsoluteMatrix: function() {
|
||||
// absolute matrix
|
||||
var am = new Kinetic.Matrix();
|
||||
|
||||
var family = [];
|
||||
var parent = this.parent;
|
||||
|
||||
family.unshift(this);
|
||||
while(parent) {
|
||||
family.unshift(parent);
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
for(var n = 0; n < family.length; n++) {
|
||||
var node = family[n];
|
||||
var m = node.getMatrix();
|
||||
am.multiply(m);
|
||||
}
|
||||
|
||||
return am;
|
||||
},
|
||||
/**
|
||||
* get matrix transform of the node while not taking
|
||||
* into account the matrix transforms of its parents
|
||||
*/
|
||||
getMatrix: function() {
|
||||
var m = new Kinetic.Matrix();
|
||||
|
||||
@ -783,9 +816,13 @@ Kinetic.Node.prototype = {
|
||||
var pos = stage.getUserPosition();
|
||||
|
||||
if(pos) {
|
||||
var m = that.getMatrix().getTranslation();
|
||||
var am = that.getAbsoluteMatrix().getTranslation();
|
||||
go.drag.node = that;
|
||||
go.drag.offset.x = pos.x - that.x;
|
||||
go.drag.offset.y = pos.y - that.y;
|
||||
go.drag.start.x = m.x - am.x;
|
||||
go.drag.start.y = m.y - am.y;
|
||||
}
|
||||
});
|
||||
},
|
||||
@ -965,7 +1002,7 @@ Kinetic.Stage = function(config) {
|
||||
* if container is a string, assume it's an id for
|
||||
* a DOM element
|
||||
*/
|
||||
if(typeof config.container === 'string') {
|
||||
if( typeof config.container === 'string') {
|
||||
config.container = document.getElementById(config.container);
|
||||
}
|
||||
|
||||
@ -1536,18 +1573,21 @@ Kinetic.Stage.prototype = {
|
||||
var node = go.drag.node;
|
||||
if(node) {
|
||||
var pos = that.getUserPosition();
|
||||
var ds = node.dragConstraint;
|
||||
var dc = node.dragConstraint;
|
||||
var db = node.dragBounds;
|
||||
if(ds === 'none' || ds === 'horizontal') {
|
||||
var m = node.getMatrix().getTranslation();
|
||||
var am = node.getAbsoluteMatrix().getTranslation();
|
||||
|
||||
if(dc === 'none' || dc === 'horizontal') {
|
||||
var newX = pos.x - go.drag.offset.x;
|
||||
if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) {
|
||||
node.x = newX;
|
||||
node.x = newX + m.x - (am.x + go.drag.start.x);
|
||||
}
|
||||
}
|
||||
if(ds === 'none' || ds === 'vertical') {
|
||||
if(dc === 'none' || dc === 'vertical') {
|
||||
var newY = pos.y - go.drag.offset.y;
|
||||
if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) {
|
||||
node.y = newY;
|
||||
node.y = newY + m.y - (am.y + go.drag.start.y);
|
||||
}
|
||||
}
|
||||
go.drag.node.getLayer().draw();
|
||||
@ -1634,13 +1674,17 @@ Kinetic.Layer = function(config) {
|
||||
*/
|
||||
Kinetic.Layer.prototype = {
|
||||
/**
|
||||
* public draw children
|
||||
* draw children nodes. this includes any groups
|
||||
* or shapes
|
||||
*/
|
||||
draw: function() {
|
||||
this._draw();
|
||||
},
|
||||
/**
|
||||
* clear layer
|
||||
* clears the canvas context tied to the layer. Clearing
|
||||
* a layer does not remove its children. The nodes within
|
||||
* the layer will be redrawn whenever the .draw() method
|
||||
* is used again.
|
||||
*/
|
||||
clear: function() {
|
||||
var context = this.getContext();
|
||||
@ -1660,7 +1704,8 @@ Kinetic.Layer.prototype = {
|
||||
return this.context;
|
||||
},
|
||||
/**
|
||||
* add node to layer
|
||||
* add a node to the layer. New nodes are always
|
||||
* placed at the top.
|
||||
* @param {Node} node
|
||||
*/
|
||||
add: function(child) {
|
||||
@ -1863,8 +1908,9 @@ Kinetic.Shape.prototype = {
|
||||
context.save();
|
||||
for(var n = 0; n < family.length; n++) {
|
||||
var node = family[n];
|
||||
var m = node.getMatrix();
|
||||
m.transformContext(context);
|
||||
var m = node.getMatrix().toArray();
|
||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
|
||||
if(node.getAbsoluteAlpha() !== 1) {
|
||||
context.globalAlpha = node.getAbsoluteAlpha();
|
||||
}
|
||||
@ -2494,8 +2540,7 @@ Kinetic.GlobalObject.extend(Kinetic.Text, Kinetic.Shape);
|
||||
/*
|
||||
* The usage of this class was inspired by some of the work done by a forked
|
||||
* project, KineticJS-Ext by Wappworks, which is based on Simon's Transform
|
||||
* class. KineticJS has slightly modified the original class and added new methods
|
||||
* specific for canvas.
|
||||
* class.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -2543,11 +2588,41 @@ Kinetic.Matrix.prototype = {
|
||||
this.m[3] = m22;
|
||||
},
|
||||
/**
|
||||
* transform canvas context
|
||||
* Returns the translation
|
||||
* @returns {Object} 2D point(x, y)
|
||||
*/
|
||||
transformContext: function(context) {
|
||||
var m = this.m;
|
||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
getTranslation: function() {
|
||||
return {
|
||||
x: this.m[4],
|
||||
y: this.m[5]
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Transform multiplication
|
||||
* @param {Kinetic.Matrix} matrix
|
||||
*/
|
||||
multiply: function(matrix) {
|
||||
var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
|
||||
var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];
|
||||
|
||||
var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
|
||||
var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];
|
||||
|
||||
var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
|
||||
var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];
|
||||
|
||||
this.m[0] = m11;
|
||||
this.m[1] = m12;
|
||||
this.m[2] = m21;
|
||||
this.m[3] = m22;
|
||||
this.m[4] = dx;
|
||||
this.m[5] = dy;
|
||||
},
|
||||
/**
|
||||
* return matrix as array
|
||||
*/
|
||||
toArray: function() {
|
||||
return this.m;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,6 +24,10 @@ Kinetic.GlobalObject = {
|
||||
offset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
start: {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
},
|
||||
extend: function(obj1, obj2) {
|
||||
|
11
src/Layer.js
11
src/Layer.js
@ -26,13 +26,17 @@ Kinetic.Layer = function(config) {
|
||||
*/
|
||||
Kinetic.Layer.prototype = {
|
||||
/**
|
||||
* public draw children
|
||||
* draw children nodes. this includes any groups
|
||||
* or shapes
|
||||
*/
|
||||
draw: function() {
|
||||
this._draw();
|
||||
},
|
||||
/**
|
||||
* clear layer
|
||||
* clears the canvas context tied to the layer. Clearing
|
||||
* a layer does not remove its children. The nodes within
|
||||
* the layer will be redrawn whenever the .draw() method
|
||||
* is used again.
|
||||
*/
|
||||
clear: function() {
|
||||
var context = this.getContext();
|
||||
@ -52,7 +56,8 @@ Kinetic.Layer.prototype = {
|
||||
return this.context;
|
||||
},
|
||||
/**
|
||||
* add node to layer
|
||||
* add a node to the layer. New nodes are always
|
||||
* placed at the top.
|
||||
* @param {Node} node
|
||||
*/
|
||||
add: function(child) {
|
||||
|
@ -11,8 +11,7 @@
|
||||
/*
|
||||
* The usage of this class was inspired by some of the work done by a forked
|
||||
* project, KineticJS-Ext by Wappworks, which is based on Simon's Transform
|
||||
* class. KineticJS has slightly modified the original class and added new methods
|
||||
* specific for canvas.
|
||||
* class.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -60,10 +59,40 @@ Kinetic.Matrix.prototype = {
|
||||
this.m[3] = m22;
|
||||
},
|
||||
/**
|
||||
* transform canvas context
|
||||
* Returns the translation
|
||||
* @returns {Object} 2D point(x, y)
|
||||
*/
|
||||
transformContext: function(context) {
|
||||
var m = this.m;
|
||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
getTranslation: function() {
|
||||
return {
|
||||
x: this.m[4],
|
||||
y: this.m[5]
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Transform multiplication
|
||||
* @param {Kinetic.Matrix} matrix
|
||||
*/
|
||||
multiply: function(matrix) {
|
||||
var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
|
||||
var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];
|
||||
|
||||
var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
|
||||
var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];
|
||||
|
||||
var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
|
||||
var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];
|
||||
|
||||
this.m[0] = m11;
|
||||
this.m[1] = m12;
|
||||
this.m[2] = m21;
|
||||
this.m[3] = m22;
|
||||
this.m[4] = dx;
|
||||
this.m[5] = dy;
|
||||
},
|
||||
/**
|
||||
* return matrix as array
|
||||
*/
|
||||
toArray: function() {
|
||||
return this.m;
|
||||
}
|
||||
};
|
||||
|
33
src/Node.js
33
src/Node.js
@ -507,6 +507,35 @@ Kinetic.Node.prototype = {
|
||||
getDragBounds: function() {
|
||||
return this.dragBounds;
|
||||
},
|
||||
/**
|
||||
* get matrix transform of the node while taking into
|
||||
* account the matrix transforms of its parents
|
||||
*/
|
||||
getAbsoluteMatrix: function() {
|
||||
// absolute matrix
|
||||
var am = new Kinetic.Matrix();
|
||||
|
||||
var family = [];
|
||||
var parent = this.parent;
|
||||
|
||||
family.unshift(this);
|
||||
while(parent) {
|
||||
family.unshift(parent);
|
||||
parent = parent.parent;
|
||||
}
|
||||
|
||||
for(var n = 0; n < family.length; n++) {
|
||||
var node = family[n];
|
||||
var m = node.getMatrix();
|
||||
am.multiply(m);
|
||||
}
|
||||
|
||||
return am;
|
||||
},
|
||||
/**
|
||||
* get matrix transform of the node while not taking
|
||||
* into account the matrix transforms of its parents
|
||||
*/
|
||||
getMatrix: function() {
|
||||
var m = new Kinetic.Matrix();
|
||||
|
||||
@ -536,9 +565,13 @@ Kinetic.Node.prototype = {
|
||||
var pos = stage.getUserPosition();
|
||||
|
||||
if(pos) {
|
||||
var m = that.getMatrix().getTranslation();
|
||||
var am = that.getAbsoluteMatrix().getTranslation();
|
||||
go.drag.node = that;
|
||||
go.drag.offset.x = pos.x - that.x;
|
||||
go.drag.offset.y = pos.y - that.y;
|
||||
go.drag.start.x = m.x - am.x;
|
||||
go.drag.start.y = m.y - am.y;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -124,8 +124,9 @@ Kinetic.Shape.prototype = {
|
||||
context.save();
|
||||
for(var n = 0; n < family.length; n++) {
|
||||
var node = family[n];
|
||||
var m = node.getMatrix();
|
||||
m.transformContext(context);
|
||||
var m = node.getMatrix().toArray();
|
||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
|
||||
if(node.getAbsoluteAlpha() !== 1) {
|
||||
context.globalAlpha = node.getAbsoluteAlpha();
|
||||
}
|
||||
|
15
src/Stage.js
15
src/Stage.js
@ -16,7 +16,7 @@ Kinetic.Stage = function(config) {
|
||||
* if container is a string, assume it's an id for
|
||||
* a DOM element
|
||||
*/
|
||||
if(typeof config.container === 'string') {
|
||||
if( typeof config.container === 'string') {
|
||||
config.container = document.getElementById(config.container);
|
||||
}
|
||||
|
||||
@ -587,18 +587,21 @@ Kinetic.Stage.prototype = {
|
||||
var node = go.drag.node;
|
||||
if(node) {
|
||||
var pos = that.getUserPosition();
|
||||
var ds = node.dragConstraint;
|
||||
var dc = node.dragConstraint;
|
||||
var db = node.dragBounds;
|
||||
if(ds === 'none' || ds === 'horizontal') {
|
||||
var m = node.getMatrix().getTranslation();
|
||||
var am = node.getAbsoluteMatrix().getTranslation();
|
||||
|
||||
if(dc === 'none' || dc === 'horizontal') {
|
||||
var newX = pos.x - go.drag.offset.x;
|
||||
if((db.left === undefined || db.left < newX) && (db.right === undefined || db.right > newX)) {
|
||||
node.x = newX;
|
||||
node.x = newX + m.x - (am.x + go.drag.start.x);
|
||||
}
|
||||
}
|
||||
if(ds === 'none' || ds === 'vertical') {
|
||||
if(dc === 'none' || dc === 'vertical') {
|
||||
var newY = pos.y - go.drag.offset.y;
|
||||
if((db.top === undefined || db.top < newY) && (db.bottom === undefined || db.bottom > newY)) {
|
||||
node.y = newY;
|
||||
node.y = newY + m.y - (am.y + go.drag.start.y);
|
||||
}
|
||||
}
|
||||
go.drag.node.getLayer().draw();
|
||||
|
@ -979,27 +979,28 @@ Test.prototype.tests = {
|
||||
|
||||
circle.draggable(false);
|
||||
},
|
||||
'DRAG AND DROP - scale stage after add layer then drag and drop shape': function(containerId) {
|
||||
'DRAG AND DROP - scale and rotate stage after add layer then drag and drop shape': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
container: containerId,
|
||||
width: 578,
|
||||
height: 200
|
||||
});
|
||||
var layer = new Kinetic.Layer();
|
||||
var circle = new Kinetic.Circle({
|
||||
x: stage.width / 2,
|
||||
y: stage.height / 2,
|
||||
radius: 70,
|
||||
var rect = new Kinetic.Rect({
|
||||
x: 200,
|
||||
y: 80,
|
||||
width: 100,
|
||||
height: 50,
|
||||
fill: 'red',
|
||||
stroke: 'black',
|
||||
strokeWidth: 4
|
||||
strokeWidth: 4,
|
||||
draggable: true
|
||||
});
|
||||
|
||||
circle.draggable(true);
|
||||
|
||||
layer.add(circle);
|
||||
layer.add(rect);
|
||||
stage.add(layer);
|
||||
|
||||
stage.rotateDeg(20);
|
||||
stage.setScale(0.5);
|
||||
|
||||
stage.draw();
|
||||
|
Loading…
Reference in New Issue
Block a user