mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 11:42:17 +08:00
bugs fixes
This commit is contained in:
parent
d50b0fe1ea
commit
2e878aa79b
@ -6,6 +6,8 @@
|
|||||||
'rotateHandlerOffsetChange'
|
'rotateHandlerOffsetChange'
|
||||||
].join(' ');
|
].join(' ');
|
||||||
|
|
||||||
|
var NODE_RECT = 'nodeRect';
|
||||||
|
|
||||||
var TRANSFORM_CHANGE_STR = [
|
var TRANSFORM_CHANGE_STR = [
|
||||||
'xChange.resizer',
|
'xChange.resizer',
|
||||||
'yChange.resizer',
|
'yChange.resizer',
|
||||||
@ -75,6 +77,31 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transformer constructor. Transformer is a special type of group that allow you transform Konva
|
||||||
|
* primitives and shapes.
|
||||||
|
* @constructor
|
||||||
|
* @memberof Konva
|
||||||
|
* @augments Konva.Container
|
||||||
|
* @param {Object} config
|
||||||
|
* @param {Boolean} [config.resizeEnabled] Default is true
|
||||||
|
* @param {Boolean} [config.rotateEnabled] Default is true
|
||||||
|
* @param {Array} [config.rotationSnaps] Array of angles for rotation snaps. Default is []
|
||||||
|
* @param {Number} [config.rotateHandlerOffset] Default is 50
|
||||||
|
* @param {Number} [config.lineEnabled] Should we draw border? Default is true
|
||||||
|
* @param {Boolean} [config.keepRatio] Should we keep ratio when we are moving edges? Default is true
|
||||||
|
* @param {Array} [config.enabledHandlers] Array of names of enabled handles
|
||||||
|
* @@nodeParams
|
||||||
|
* @@containerParams
|
||||||
|
* @example
|
||||||
|
* var transformer = new Konva.Transformer({
|
||||||
|
* node: rectangle,
|
||||||
|
* rotateHandlerOffset: 60,
|
||||||
|
* enabledHandlers: ['top-left', 'top-right', 'bottom-left', 'bottom-right']
|
||||||
|
* });
|
||||||
|
* layer.add(transformer);
|
||||||
|
*/
|
||||||
|
|
||||||
Konva.Transformer = function(config) {
|
Konva.Transformer = function(config) {
|
||||||
this.____init(config);
|
this.____init(config);
|
||||||
};
|
};
|
||||||
@ -114,17 +141,39 @@
|
|||||||
);
|
);
|
||||||
warningShowed = true;
|
warningShowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.getNode()) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
attachTo: function(node) {
|
attachTo: function(node) {
|
||||||
if (this.node()) {
|
this.setNode(node);
|
||||||
|
},
|
||||||
|
|
||||||
|
setNode(node) {
|
||||||
|
if (this._node) {
|
||||||
this.detach();
|
this.detach();
|
||||||
}
|
}
|
||||||
this.setNode(node);
|
this._node = node;
|
||||||
node.on('dragmove.resizer', this.update);
|
|
||||||
node.on(TRANSFORM_CHANGE_STR, this.update);
|
|
||||||
|
|
||||||
this.update();
|
node.on(
|
||||||
|
TRANSFORM_CHANGE_STR,
|
||||||
|
function() {
|
||||||
|
this._clearCache(NODE_RECT);
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
|
node.on(TRANSFORM_CHANGE_STR, this.requestUpdate.bind(this));
|
||||||
|
node.on('dragmove.resizer', this.requestUpdate);
|
||||||
|
|
||||||
|
var elementsCreated = !!this.findOne('.top-left');
|
||||||
|
if (elementsCreated) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getNode() {
|
||||||
|
return this._node;
|
||||||
},
|
},
|
||||||
|
|
||||||
detach: function() {
|
detach: function() {
|
||||||
@ -132,7 +181,20 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
_getNodeRect: function() {
|
_getNodeRect: function() {
|
||||||
|
return this._getCache(NODE_RECT, this.__getNodeRect);
|
||||||
|
},
|
||||||
|
|
||||||
|
__getNodeRect: function() {
|
||||||
var node = this.getNode();
|
var node = this.getNode();
|
||||||
|
if (!node) {
|
||||||
|
return {
|
||||||
|
x: -Number.MAX_SAFE_INTEGER,
|
||||||
|
y: -Number.MAX_SAFE_INTEGER,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
rotation: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
var rect = node.getClientRect({ skipTransform: true });
|
var rect = node.getClientRect({ skipTransform: true });
|
||||||
var rotation = Konva.getAngle(node.rotation());
|
var rotation = Konva.getAngle(node.rotation());
|
||||||
|
|
||||||
@ -484,6 +546,23 @@
|
|||||||
this.update();
|
this.update();
|
||||||
this.getLayer().batchDraw();
|
this.getLayer().batchDraw();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
requestUpdate: function() {
|
||||||
|
if (this.timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.timeout = setTimeout(
|
||||||
|
function() {
|
||||||
|
this.timeout = null;
|
||||||
|
this.update();
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
forceUpdate: function() {
|
||||||
|
this._clearCache(NODE_RECT);
|
||||||
|
this.update();
|
||||||
|
},
|
||||||
update: function() {
|
update: function() {
|
||||||
var attrs = this._getNodeRect();
|
var attrs = this._getNodeRect();
|
||||||
var x = attrs.x;
|
var x = attrs.x;
|
||||||
@ -494,48 +573,48 @@
|
|||||||
this.y(y);
|
this.y(y);
|
||||||
this.rotation(attrs.rotation);
|
this.rotation(attrs.rotation);
|
||||||
|
|
||||||
var enabledResizers = this.enabledResizers();
|
var enabledHandlers = this.enabledHandlers();
|
||||||
var resizeEnabled = this.resizeEnabled();
|
var resizeEnabled = this.resizeEnabled();
|
||||||
|
|
||||||
this.findOne('.top-left').setAttrs({
|
this.findOne('.top-left').setAttrs({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('top-left') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('top-left') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.top-center').setAttrs({
|
this.findOne('.top-center').setAttrs({
|
||||||
x: width / 2,
|
x: width / 2,
|
||||||
y: 0,
|
y: 0,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('top-center') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('top-center') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.top-right').setAttrs({
|
this.findOne('.top-right').setAttrs({
|
||||||
x: width,
|
x: width,
|
||||||
y: 0,
|
y: 0,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('top-right') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('top-right') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.middle-left').setAttrs({
|
this.findOne('.middle-left').setAttrs({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: height / 2,
|
y: height / 2,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('middle-left') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('middle-left') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.middle-right').setAttrs({
|
this.findOne('.middle-right').setAttrs({
|
||||||
x: width,
|
x: width,
|
||||||
y: height / 2,
|
y: height / 2,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('middle-right') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('middle-right') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.bottom-left').setAttrs({
|
this.findOne('.bottom-left').setAttrs({
|
||||||
x: 0,
|
x: 0,
|
||||||
y: height,
|
y: height,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('bottom-left') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('bottom-left') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.bottom-center').setAttrs({
|
this.findOne('.bottom-center').setAttrs({
|
||||||
x: width / 2,
|
x: width / 2,
|
||||||
y: height,
|
y: height,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('bottom-center') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('bottom-center') >= 0
|
||||||
});
|
});
|
||||||
this.findOne('.bottom-right').setAttrs({
|
this.findOne('.bottom-right').setAttrs({
|
||||||
x: width,
|
x: width,
|
||||||
y: height,
|
y: height,
|
||||||
visible: resizeEnabled && enabledResizers.indexOf('bottom-right') >= 0
|
visible: resizeEnabled && enabledHandlers.indexOf('bottom-right') >= 0
|
||||||
});
|
});
|
||||||
|
|
||||||
this.findOne('.rotater').setAttrs({
|
this.findOne('.rotater').setAttrs({
|
||||||
@ -554,13 +633,18 @@
|
|||||||
Konva.Group.prototype.destroy.call(this);
|
Konva.Group.prototype.destroy.call(this);
|
||||||
this.getNode().off('.resizer');
|
this.getNode().off('.resizer');
|
||||||
this._removeEvents();
|
this._removeEvents();
|
||||||
|
},
|
||||||
|
// do not work as a container
|
||||||
|
// we will recreate inner nodes manually
|
||||||
|
toObject: function() {
|
||||||
|
return Konva.Node.prototype.toObject.call(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Konva.Util.extend(Konva.Transformer, Konva.Group);
|
Konva.Util.extend(Konva.Transformer, Konva.Group);
|
||||||
|
|
||||||
function validateResizers(val) {
|
function validateResizers(val) {
|
||||||
if (!(val instanceof Array)) {
|
if (!(val instanceof Array)) {
|
||||||
Konva.Util.warn('enabledResizers value should be an array');
|
Konva.Util.warn('enabledHandlers value should be an array');
|
||||||
}
|
}
|
||||||
if (val instanceof Array) {
|
if (val instanceof Array) {
|
||||||
val.forEach(function(name) {
|
val.forEach(function(name) {
|
||||||
@ -576,25 +660,125 @@
|
|||||||
}
|
}
|
||||||
return val || [];
|
return val || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set enabled handlers
|
||||||
|
* @name enabledHandlers
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get list of handlers
|
||||||
|
* var enabledHandlers = shape.enabledHandlers();
|
||||||
|
*
|
||||||
|
* // set handlers
|
||||||
|
* shape.enabledHandlers(['top-left', 'top-center', 'top-right', 'middle-right', 'middle-left', 'bottom-left', 'bottom-center', 'bottom-right']);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(
|
Konva.Factory.addGetterSetter(
|
||||||
Konva.Transformer,
|
Konva.Transformer,
|
||||||
'enabledResizers',
|
'enabledHandlers',
|
||||||
RESIZERS_NAMES
|
|
||||||
);
|
|
||||||
Konva.Factory.addGetterSetter(
|
|
||||||
Konva.Transformer,
|
|
||||||
'enabledResizers',
|
|
||||||
RESIZERS_NAMES,
|
RESIZERS_NAMES,
|
||||||
validateResizers
|
validateResizers
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set resize ability. If false it will automatically hide resizing handlers
|
||||||
|
* @name resizeEnabled
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var resizeEnabled = shape.resizeEnabled();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.resizeEnabled(false);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'resizeEnabled', true);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'resizeEnabled', true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set ability to rotate.
|
||||||
|
* @name rotateEnabled
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var rotateEnabled = shape.rotateEnabled();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.rotateEnabled(false);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotateEnabled', true);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotateEnabled', true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set rotation snaps angles.
|
||||||
|
* @name rotationSnaps
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var rotationSnaps = shape.rotationSnaps();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.rotationSnaps([0, 90, 180, 270]);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotationSnaps', []);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotationSnaps', []);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set distance for rotation handler
|
||||||
|
* @name rotateHandlerOffset
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var rotateHandlerOffset = shape.rotateHandlerOffset();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.rotateHandlerOffset(100);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotateHandlerOffset', 50);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'rotateHandlerOffset', 50);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set visibility of border
|
||||||
|
* @name lineEnabled
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var lineEnabled = shape.lineEnabled();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.lineEnabled(false);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'lineEnabled', true);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'lineEnabled', true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get/set should we keep ration of resize?
|
||||||
|
* @name keepRatio
|
||||||
|
* @method
|
||||||
|
* @memberof Konva.Transformer.prototype
|
||||||
|
* @param {Array} array
|
||||||
|
* @returns {Array}
|
||||||
|
* @example
|
||||||
|
* // get
|
||||||
|
* var keepRatio = shape.keepRatio();
|
||||||
|
*
|
||||||
|
* // set
|
||||||
|
* shape.keepRatio(false);
|
||||||
|
*/
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'keepRatio', true);
|
Konva.Factory.addGetterSetter(Konva.Transformer, 'keepRatio', true);
|
||||||
|
|
||||||
Konva.Factory.addGetterSetter(Konva.Transformer, 'node');
|
Konva.Factory.addOverloadedGetterSetter(Konva.Transformer, 'node');
|
||||||
|
|
||||||
Konva.Collection.mapMethods(Konva.Transformer);
|
Konva.Collection.mapMethods(Konva.Transformer);
|
||||||
})(Konva);
|
})(Konva);
|
||||||
|
@ -15,9 +15,10 @@ suite('Transformer', function() {
|
|||||||
});
|
});
|
||||||
layer.add(rect);
|
layer.add(rect);
|
||||||
|
|
||||||
var tr = new Konva.Transformer();
|
var tr = new Konva.Transformer({
|
||||||
|
node: rect
|
||||||
|
});
|
||||||
layer.add(tr);
|
layer.add(tr);
|
||||||
tr.attachTo(rect);
|
|
||||||
|
|
||||||
layer.draw();
|
layer.draw();
|
||||||
assert.equal(tr.getClassName(), 'Transformer');
|
assert.equal(tr.getClassName(), 'Transformer');
|
||||||
@ -26,6 +27,12 @@ suite('Transformer', function() {
|
|||||||
assert.equal(tr.y(), rect.y());
|
assert.equal(tr.y(), rect.y());
|
||||||
assert.equal(tr.width(), rect.width());
|
assert.equal(tr.width(), rect.width());
|
||||||
assert.equal(tr.height(), rect.height());
|
assert.equal(tr.height(), rect.height());
|
||||||
|
|
||||||
|
// manual check of correct position of node
|
||||||
|
var handler = tr.findOne('.bottom-right');
|
||||||
|
var pos = handler.getAbsolutePosition();
|
||||||
|
assert.equal(pos.x, rect.x() + rect.width());
|
||||||
|
assert.equal(pos.y, rect.y() + rect.height());
|
||||||
});
|
});
|
||||||
|
|
||||||
test('try to fit simple rectangle', function() {
|
test('try to fit simple rectangle', function() {
|
||||||
@ -541,7 +548,7 @@ suite('Transformer', function() {
|
|||||||
assert.equal(tr.rotation(), 0);
|
assert.equal(tr.rotation(), 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('fit group', function() {
|
test.only('fit group', function() {
|
||||||
var stage = addStage();
|
var stage = addStage();
|
||||||
var layer = new Konva.Layer();
|
var layer = new Konva.Layer();
|
||||||
stage.add(layer);
|
stage.add(layer);
|
||||||
@ -596,4 +603,43 @@ suite('Transformer', function() {
|
|||||||
assert.equal(tr.width(), 200);
|
assert.equal(tr.width(), 200);
|
||||||
assert.equal(tr.height(), 100);
|
assert.equal(tr.height(), 100);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('toJSON should not save attached node and children', function() {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
|
var rect = new Konva.Rect({
|
||||||
|
x: 100,
|
||||||
|
y: 60,
|
||||||
|
draggable: true,
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
fill: 'yellow'
|
||||||
|
});
|
||||||
|
layer.add(rect);
|
||||||
|
|
||||||
|
var tr = new Konva.Transformer();
|
||||||
|
layer.add(tr);
|
||||||
|
tr.attachTo(rect);
|
||||||
|
|
||||||
|
layer.draw();
|
||||||
|
|
||||||
|
var json = tr.toJSON();
|
||||||
|
var object = JSON.parse(json);
|
||||||
|
|
||||||
|
assert.equal(object.attrs.node, undefined);
|
||||||
|
assert.equal(object.children, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('make sure we can work without inner node', function() {
|
||||||
|
var stage = addStage();
|
||||||
|
var layer = new Konva.Layer();
|
||||||
|
stage.add(layer);
|
||||||
|
|
||||||
|
var tr = new Konva.Transformer();
|
||||||
|
layer.add(tr);
|
||||||
|
|
||||||
|
layer.draw();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user