merged pull request #65 and updated manual tests. Also removed dragConstraint and dragBounds as they are now redundant. I may introduce a set of dragBounds helper functions, similar to filters, that provide common functions out of the box, such as Horizontal and Vertical

This commit is contained in:
ericdrowell 2012-09-25 21:23:35 -07:00
commit 900f02f912
6 changed files with 192 additions and 305 deletions

112
dist/kinetic-core.js vendored
View File

@ -1253,6 +1253,7 @@ requestAnimFrame = (function(callback) {
* @param {Number} [config.dragBounds.right]
* @param {Number} [config.dragBounds.bottom]
* @param {Number} [config.dragBounds.left]
* @param {Function} [config.dragBoundFunc] dragBoundFunc(pos, evt) should return new position
*/
Kinetic.Node = function(config) {
this._nodeInit(config);
@ -2220,7 +2221,7 @@ Kinetic.Node._addGetter = function(constructor, attr) {
};
};
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'rotation', 'opacity', 'name', 'id', 'draggable', 'dragConstraint', 'dragBounds', 'listening', 'visible']);
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'rotation', 'opacity', 'name', 'id', 'draggable', 'listening', 'visible', 'dragBoundFunc']);
Kinetic.Node.addGetters(Kinetic.Node, ['scale', 'offset']);
// mappings
@ -2386,6 +2387,7 @@ Kinetic.Node.prototype.isDraggable = Kinetic.Node.prototype.getDraggable;
* @name getListening
* @methodOf Kinetic.Node.prototype
*/
///////////////////////////////////////////////////////////////////////
// Container
///////////////////////////////////////////////////////////////////////
@ -2704,7 +2706,7 @@ Kinetic.Stage.prototype = {
},
setContainer: function(container) {
/*
/*
* if container is a string, assume it's an id for
* a DOM element
*/
@ -2734,26 +2736,25 @@ Kinetic.Stage.prototype = {
this.setWidth(size.width);
this.setHeight(size.height);
},
/**
* set height
* @name setHeight
* @methodOf Kinetic.Stage.prototype
* @param {Number} height
*/
/**
* set height
* @name setHeight
* @methodOf Kinetic.Stage.prototype
* @param {Number} height
*/
setHeight: function(height) {
this.setAttr('height', height);
this._resizeDOM();
this.setAttr('height', height);
this._resizeDOM();
},
/**
* set width
* @name setWidth
* @methodOf Kinetic.Stage.prototype
* @param {Number} width
*/
/**
* set width
* @name setWidth
* @methodOf Kinetic.Stage.prototype
* @param {Number} width
*/
setWidth: function(width) {
this.setAttr('width', width);
this._resizeDOM();
this.setAttr('width', width);
this._resizeDOM();
},
/**
* get stage size
@ -2814,6 +2815,7 @@ Kinetic.Stage.prototype = {
return obj;
}
return JSON.stringify(addNode(this));
},
/**
@ -2871,6 +2873,7 @@ Kinetic.Stage.prototype = {
}
}
}
var obj = JSON.parse(json);
// copy over stage properties
@ -2974,6 +2977,7 @@ Kinetic.Stage.prototype = {
};
imageObj.src = layerUrl;
}
drawLayer(0);
},
/**
@ -3038,24 +3042,24 @@ Kinetic.Stage.prototype = {
return null;
},
_resizeDOM: function() {
if (this.content) {
var width = this.attrs.width;
var height = this.attrs.height;
// set content dimensions
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.bufferCanvas.setSize(width, height);
// set user defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
layer.getCanvas().setSize(width, height);
layer.bufferCanvas.setSize(width, height);
layer.draw();
}
}
if(this.content) {
var width = this.attrs.width;
var height = this.attrs.height;
// set content dimensions
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.bufferCanvas.setSize(width, height);
// set user defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
layer.getCanvas().setSize(width, height);
layer.bufferCanvas.setSize(width, height);
layer.draw();
}
}
},
/**
* add layer to stage
@ -3326,43 +3330,19 @@ Kinetic.Stage.prototype = {
if(node) {
var pos = that.getUserPosition();
var dc = node.attrs.dragConstraint;
var db = node.attrs.dragBounds;
var lastNodePos = {
x: node.attrs.x,
y: node.attrs.y
};
var dbf = node.attrs.dragBoundFunc;
// default
var newNodePos = {
x: pos.x - go.drag.offset.x,
y: pos.y - go.drag.offset.y
};
// bounds overrides
if(db.left !== undefined && newNodePos.x < db.left) {
newNodePos.x = db.left;
}
if(db.right !== undefined && newNodePos.x > db.right) {
newNodePos.x = db.right;
}
if(db.top !== undefined && newNodePos.y < db.top) {
newNodePos.y = db.top;
}
if(db.bottom !== undefined && newNodePos.y > db.bottom) {
newNodePos.y = db.bottom;
if(dbf !== undefined) {
newNodePos = dbf.call(node, newNodePos, evt);
}
node.setAbsolutePosition(newNodePos);
// constraint overrides
if(dc === 'horizontal') {
node.attrs.y = lastNodePos.y;
}
else if(dc === 'vertical') {
node.attrs.x = lastNodePos.x;
}
if(!go.drag.moving) {
go.drag.moving = true;
// execute dragstart events if defined
@ -3469,7 +3449,7 @@ Kinetic.Node.addGetters(Kinetic.Stage, ['width', 'height', 'container']);
* @name getContainer
* @methodOf Kinetic.Stage.prototype
*/
/**
* get width
* @name getWidth
@ -3481,8 +3461,6 @@ Kinetic.Node.addGetters(Kinetic.Stage, ['width', 'height', 'container']);
* @name getHeight
* @methodOf Kinetic.Stage.prototype
*/
///////////////////////////////////////////////////////////////////////
// Layer
///////////////////////////////////////////////////////////////////////

File diff suppressed because one or more lines are too long

View File

@ -30,6 +30,7 @@
* @param {Number} [config.dragBounds.right]
* @param {Number} [config.dragBounds.bottom]
* @param {Number} [config.dragBounds.left]
* @param {Function} [config.dragBoundFunc] dragBoundFunc(pos, evt) should return new position
*/
Kinetic.Node = function(config) {
this._nodeInit(config);
@ -997,7 +998,7 @@ Kinetic.Node._addGetter = function(constructor, attr) {
};
};
// add getters setters
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'rotation', 'opacity', 'name', 'id', 'draggable', 'dragConstraint', 'dragBounds', 'listening', 'visible']);
Kinetic.Node.addGettersSetters(Kinetic.Node, ['x', 'y', 'rotation', 'opacity', 'name', 'id', 'draggable', 'listening', 'visible', 'dragBoundFunc']);
Kinetic.Node.addGetters(Kinetic.Node, ['scale', 'offset']);
// mappings
@ -1162,4 +1163,4 @@ Kinetic.Node.prototype.isDraggable = Kinetic.Node.prototype.getDraggable;
* determine if listening to events or not
* @name getListening
* @methodOf Kinetic.Node.prototype
*/
*/

View File

@ -59,7 +59,7 @@ Kinetic.Stage.prototype = {
},
setContainer: function(container) {
/*
/*
* if container is a string, assume it's an id for
* a DOM element
*/
@ -89,26 +89,25 @@ Kinetic.Stage.prototype = {
this.setWidth(size.width);
this.setHeight(size.height);
},
/**
* set height
* @name setHeight
* @methodOf Kinetic.Stage.prototype
* @param {Number} height
*/
/**
* set height
* @name setHeight
* @methodOf Kinetic.Stage.prototype
* @param {Number} height
*/
setHeight: function(height) {
this.setAttr('height', height);
this._resizeDOM();
this.setAttr('height', height);
this._resizeDOM();
},
/**
* set width
* @name setWidth
* @methodOf Kinetic.Stage.prototype
* @param {Number} width
*/
/**
* set width
* @name setWidth
* @methodOf Kinetic.Stage.prototype
* @param {Number} width
*/
setWidth: function(width) {
this.setAttr('width', width);
this._resizeDOM();
this.setAttr('width', width);
this._resizeDOM();
},
/**
* get stage size
@ -169,6 +168,7 @@ Kinetic.Stage.prototype = {
return obj;
}
return JSON.stringify(addNode(this));
},
/**
@ -226,6 +226,7 @@ Kinetic.Stage.prototype = {
}
}
}
var obj = JSON.parse(json);
// copy over stage properties
@ -329,6 +330,7 @@ Kinetic.Stage.prototype = {
};
imageObj.src = layerUrl;
}
drawLayer(0);
},
/**
@ -393,24 +395,24 @@ Kinetic.Stage.prototype = {
return null;
},
_resizeDOM: function() {
if (this.content) {
var width = this.attrs.width;
var height = this.attrs.height;
// set content dimensions
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.bufferCanvas.setSize(width, height);
// set user defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
layer.getCanvas().setSize(width, height);
layer.bufferCanvas.setSize(width, height);
layer.draw();
}
}
if(this.content) {
var width = this.attrs.width;
var height = this.attrs.height;
// set content dimensions
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.bufferCanvas.setSize(width, height);
// set user defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
layer.getCanvas().setSize(width, height);
layer.bufferCanvas.setSize(width, height);
layer.draw();
}
}
},
/**
* add layer to stage
@ -681,43 +683,19 @@ Kinetic.Stage.prototype = {
if(node) {
var pos = that.getUserPosition();
var dc = node.attrs.dragConstraint;
var db = node.attrs.dragBounds;
var lastNodePos = {
x: node.attrs.x,
y: node.attrs.y
};
var dbf = node.attrs.dragBoundFunc;
// default
var newNodePos = {
x: pos.x - go.drag.offset.x,
y: pos.y - go.drag.offset.y
};
// bounds overrides
if(db.left !== undefined && newNodePos.x < db.left) {
newNodePos.x = db.left;
}
if(db.right !== undefined && newNodePos.x > db.right) {
newNodePos.x = db.right;
}
if(db.top !== undefined && newNodePos.y < db.top) {
newNodePos.y = db.top;
}
if(db.bottom !== undefined && newNodePos.y > db.bottom) {
newNodePos.y = db.bottom;
if(dbf !== undefined) {
newNodePos = dbf.call(node, newNodePos, evt);
}
node.setAbsolutePosition(newNodePos);
// constraint overrides
if(dc === 'horizontal') {
node.attrs.y = lastNodePos.y;
}
else if(dc === 'vertical') {
node.attrs.x = lastNodePos.x;
}
if(!go.drag.moving) {
go.drag.moving = true;
// execute dragstart events if defined
@ -824,7 +802,7 @@ Kinetic.Node.addGetters(Kinetic.Stage, ['width', 'height', 'container']);
* @name getContainer
* @methodOf Kinetic.Stage.prototype
*/
/**
* get width
* @name getWidth
@ -835,5 +813,4 @@ Kinetic.Node.addGetters(Kinetic.Stage, ['width', 'height', 'container']);
* get height
* @name getHeight
* @methodOf Kinetic.Stage.prototype
*/
*/

View File

@ -14,7 +14,7 @@ Test.prototype.tests = {
stroke: 'black',
strokeWidth: 4
});
circle.on('mousedown', function() {
log('mousedown');
});
@ -203,6 +203,7 @@ Test.prototype.tests = {
});
});
}
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@ -361,7 +362,7 @@ Test.prototype.tests = {
layer.add(star);
stage.add(layer);
//document.body.appendChild(layer.bufferCanvas.element)
},
'EVENTS - drag events click': function(containerId) {
@ -444,10 +445,10 @@ Test.prototype.tests = {
layer.add(greenCircle);
stage.add(layer);
//greenCircle.hide();
layer.draw();
//document.body.appendChild(layer.bufferCanvas.element);
},
'EVENTS - move mouse from shape in one group to shape in another group': function(containerId) {
@ -979,6 +980,90 @@ Test.prototype.tests = {
stage.draw();
},
'DRAG AND DROP - drag bound function': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
height: 200
});
var layer = new Kinetic.Layer();
var rectHeight = 50;
var rectWidth = 100;
var rectY = (stage.getHeight() - rectHeight) / 2;
var hbox = new Kinetic.Text({
x: 380,
y: 70,
fill: "#00D2FF",
strokeWidth: 4,
fontSize: 18,
fontFamily: "Calibri",
text: "shiftKey",
textFill: "black",
padding: 15,
draggable: true,
dragBoundFunc: function(pos, evt) {
var newPos = pos;
if(evt.shiftKey) {
newPos.x = Math.round(pos.x / 20) * 20;
newPos.y = Math.round(pos.y / 20) * 20;
}
return pos;
}
});
var vbox = new Kinetic.Text({
x: 70,
y: 70,
fill: "yellow",
strokeWidth: 4,
draggable: true,
fontSize: 18,
fontFamily: "Calibri",
text: "diagonal",
textFill: "black",
padding: 15,
draggable: true,
dragBoundFunc: function(pos) {
p = (pos.y + pos.x) / 2;
return {
y: p,
x: p
};
}
});
var circle = new Kinetic.Circle({
x: 280,
y: 45,
radius: 50,
fill: "red",
strokeWidth: 4,
draggable: true,
fontSize: 18,
draggable: true,
dragBoundFunc: function(pos) {
var circle = {
x: 280,
y: 95,
r: 50
};
var scale = circle.r / Math.sqrt(Math.pow(pos.x - circle.x, 2) + Math.pow(pos.y - circle.y, 2));
if(scale < 1)
return {
y: Math.round((pos.y - circle.y) * scale + circle.y),
x: Math.round((pos.x - circle.x) * scale + circle.x)
};
else
return pos;
}
});
layer.add(hbox);
layer.add(vbox);
layer.add(circle);
stage.add(layer);
},
'DRAG AND DROP - set stage scale to 1.5 before add layer then drag and drop shape': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
@ -1037,7 +1122,7 @@ Test.prototype.tests = {
layer.add(Circle2);
stage.add(layer);
},
'DRAG AND DROP - drag and drop constrianed horiztontally inside positioned group': function(containerId) {
'DRAG AND DROP - drag and drop constrianed horizontally inside positioned group': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,
@ -1049,62 +1134,22 @@ Test.prototype.tests = {
y: 10
});
var Circle = new Kinetic.Circle({
x: stage.getWidth() / 2,
y: stage.getHeight() / 2,
x: 200,
y: 100,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragConstraint: 'horizontal'
dragBoundFunc: function(pos) {
return {x:pos.x, y:this.getAbsolutePosition().y};
}
});
group.add(Circle);
layer.add(group);
stage.add(layer);
},
'DRAG AND DROP - drag and drop constrianed vertically': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragConstraint: 'vertical'
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with explicit no constraint': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragConstraint: 'none'
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with left bounds': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
@ -1120,109 +1165,16 @@ Test.prototype.tests = {
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragBounds: {
left: 150
dragBoundFunc: function(pos) {
var newX = pos.x > 50 ? pos.x : 50;
return {x: newX, y:this.getY()}
}
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with right bounds': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragBounds: {
right: 400
}
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with top bounds': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80
}
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with bottom bounds': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragBounds: {
bottom: 120
}
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop with full rect bounds': 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.getWidth() / 2,
y: stage.getHeight() / 2,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4,
draggable: true,
dragBounds: {
top: 80,
bottom: 120,
left: 150,
right: 578 - 150
}
});
layer.add(Circle);
stage.add(layer);
},
'DRAG AND DROP - drag and drop shape inside scrollable div': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,

View File

@ -3995,33 +3995,12 @@ Test.prototype.tests = {
// test defaults
test(circle.attrs.draggable === false, 'draggable should be false');
test(circle.attrs.dragConstraint === 'none', 'drag constraint should be none');
test(circle.attrs.dragBounds.left === undefined, 'drag left should be undefined');
test(circle.attrs.dragBounds.top === undefined, 'drag top should be undefined');
test(circle.attrs.dragBounds.right === undefined, 'drag right should be undefined');
test(circle.attrs.dragBounds.bottom === undefined, 'drag bottom should be undefined');
test(circle.getDragConstraint() === 'none', 'drag constraint should be none');
test(circle.getDragBounds().bottom === undefined, 'drag bottom should be undefined');
//change properties
circle.setDraggable(true);
circle.setDragConstraint('vertical');
circle.setDragBounds({
left: 50,
top: 100,
right: 150,
bottom: 200
});
// test new properties
test(circle.attrs.draggable === true, 'draggable should be true');
test(circle.attrs.dragConstraint === 'vertical', 'drag constraint should be vertical');
test(circle.attrs.dragBounds.left === 50, 'drag left should be 50');
test(circle.attrs.dragBounds.top === 100, 'drag top should be 100');
test(circle.attrs.dragBounds.right === 150, 'drag right should be 150');
test(circle.attrs.dragBounds.bottom === 200, 'drag bottom should be 200');
test(circle.getDragConstraint() === 'vertical', 'drag constraint should be vertical');
test(circle.getDragBounds().bottom === 200, 'drag bottom should be 200');
},
'NODE - translate, rotate, scale shape': function(containerId) {
var stage = new Kinetic.Stage({