Merge branch 'master' into fix-unscalable-strokes

This commit is contained in:
MaxGraey 2018-03-21 16:56:13 +02:00
commit 7e1a6dbd1b
9 changed files with 913 additions and 531 deletions

View File

@ -14,6 +14,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).
* Fixed flow for `contextmenu` event. Not it will be triggered on shapes too
## Fixed
* some bugs fixes for `group.getClientRect()`
## [2.0.2][2018-03-15]
## Fixed

152
konva.js
View File

@ -2,7 +2,7 @@
* Konva JavaScript Framework v2.0.2
* http://konvajs.github.io/
* Licensed under the MIT
* Date: Tue Mar 20 2018
* Date: Wed Mar 21 2018
*
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@ -743,6 +743,16 @@
firstChar === firstChar.toUpperCase()
);
},
_sign: function(number) {
if (number === 0) {
return 0;
}
if (number > 0) {
return 1;
} else {
return -1;
}
},
createCanvasElement: function() {
var canvas = Konva.isBrowser
? Konva.document.createElement('canvas')
@ -2434,7 +2444,6 @@
Konva.Util.addMethods(Konva.Node, {
_init: function(config) {
var that = this;
this._id = Konva.idCounter++;
this.eventListeners = {};
this.attrs = {};
@ -2446,21 +2455,21 @@
// event bindings for cache handling
this.on(TRANSFORM_CHANGE_STR, function() {
this._clearCache(TRANSFORM);
that._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
});
this.on(SCALE_CHANGE_STR, function() {
that._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
});
this.on('visibleChange.konva', function() {
that._clearSelfAndDescendantCache(VISIBLE);
this._clearSelfAndDescendantCache(VISIBLE);
});
this.on('listeningChange.konva', function() {
that._clearSelfAndDescendantCache(LISTENING);
this._clearSelfAndDescendantCache(LISTENING);
});
this.on('opacityChange.konva', function() {
that._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
});
},
_clearCache: function(attr) {
@ -8034,7 +8043,10 @@
context.rect(clipX, clipY, clipWidth, clipHeight);
}
context.clip();
m = transform.copy().invert().getMatrix();
m = transform
.copy()
.invert()
.getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
@ -8079,6 +8091,7 @@
if (!child.isVisible()) {
return;
}
var rect = child.getClientRect({ relativeTo: that });
// skip invisible children (like empty groups)
@ -8101,7 +8114,18 @@
}
});
if (this.children.length !== 0) {
// if child is group we need to make sure it has visible shapes inside
var shapes = this.find('Shape');
var hasVisible = false;
for (var i = 0; i < shapes.length; i++) {
var shape = shapes[i];
if (shape.isVisible()) {
hasVisible = true;
break;
}
}
if (hasVisible) {
selfRect = {
x: minX,
y: minY,
@ -18557,20 +18581,7 @@
return 'crosshair';
}
var angle;
if (anchorName === 'top-left' || anchorName === 'bottom-right') {
angle = -45;
} else if (anchorName === 'top-right' || anchorName === 'bottom-left') {
angle = 45;
} else if (anchorName === 'top-center' || anchorName === 'bottom-center') {
angle = 0;
} else if (anchorName === 'middle-left' || anchorName === 'middle-right') {
angle = 90;
} else {
angle = 0;
}
angle = (angle + Konva.Util._radToDeg(rad) + 360) % 360;
var angle = (Konva.Util._radToDeg(rad) % 360 + 360) % 360;
if (
Konva.Util._inRange(angle, 315 + 22.5, 360) ||
@ -18602,6 +18613,9 @@
} else {
// how can we can there?
// TODO: throw error
Konva.Util.error(
'Transformer has unknown angle for cursor detection: ' + angle
);
return 'pointer';
}
}
@ -18683,8 +18697,8 @@
this._createElements();
// bindings
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this._handleMouseMove = this._handleMouseMove.bind(this);
this._handleMouseUp = this._handleMouseUp.bind(this);
this.update = this.update.bind(this);
// update transformer data for certain attr changes
@ -18717,10 +18731,12 @@
TRANSFORM_CHANGE_STR,
function() {
this._clearCache(NODE_RECT);
this._clearCache('transform');
this._clearSelfAndDescendantCache('absoluteTransform');
}.bind(this)
);
node.on(TRANSFORM_CHANGE_STR, this.requestUpdate.bind(this));
node.on('dragmove.resizer', this.requestUpdate.bind(this));
// node.on(TRANSFORM_CHANGE_STR, this.requestUpdate.bind(this));
// node.on('dragmove.resizer', this.requestUpdate.bind(this));
var elementsCreated = !!this.findOne('.top-left');
if (elementsCreated) {
@ -18735,7 +18751,11 @@
detach: function() {
if (this.getNode()) {
this.getNode().off('.resizer');
this._node = undefined;
}
this._clearCache(NODE_RECT);
this._clearCache('transform');
this._clearSelfAndDescendantCache('absoluteTransform');
},
_getNodeRect: function() {
@ -18815,16 +18835,36 @@
});
var self = this;
anchor.on('mousedown touchstart', function(e) {
self.handleResizerMouseDown(e);
self._handleMouseDown(e);
});
// add hover styling
anchor.on('mouseenter', function() {
var layer = this.getLayer();
var rad = Konva.getAngle(this.getParent().rotation());
var cursor = getCursor(name, rad);
anchor.getStage().getContainer().style.cursor = cursor;
this.fill('lightgrey');
var tr = this.getParent();
// TODO: I guess there are some ways to simplify that calculations
// the basic idea is to find "angle" of handler
var rad = Konva.getAngle(tr.rotation());
var cdx = tr.getWidth() / 2;
var cdy = tr.getHeight() / 2;
var parentPos = tr.getAbsolutePosition(tr.getParent());
var center = {
x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
};
var pos = this.getAbsolutePosition(tr.getParent());
var dx = -pos.x + center.x;
var dy = -pos.y + center.y;
var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
var cursor = getCursor(name, angle);
anchor.getStage().content.style.cursor = cursor;
layer.batchDraw();
});
anchor.on('mouseout', function() {
@ -18832,8 +18872,7 @@
if (!layer) {
return;
}
anchor.getStage().getContainer().style.cursor = '';
this.fill('white');
anchor.getStage().content.style.cursor = '';
layer.batchDraw();
});
this.add(anchor);
@ -18858,7 +18897,10 @@
);
ctx.moveTo(this.width() / 2, -padding);
if (tr.rotateEnabled()) {
ctx.lineTo(this.width() / 2, -tr.rotateHandlerOffset());
ctx.lineTo(
this.width() / 2,
-tr.rotateHandlerOffset() * Konva.Util._sign(this.height())
);
}
ctx.fillStrokeShape(this);
@ -18867,7 +18909,7 @@
this.add(back);
},
handleResizerMouseDown: function(e) {
_handleMouseDown: function(e) {
this.movingResizer = e.target.name();
// var node = this.getNode();
@ -18878,10 +18920,10 @@
this.sin = height / hypotenuse;
this.cos = width / hypotenuse;
window.addEventListener('mousemove', this.handleMouseMove);
window.addEventListener('touchmove', this.handleMouseMove);
window.addEventListener('mouseup', this.handleMouseUp);
window.addEventListener('touchend', this.handleMouseUp);
window.addEventListener('mousemove', this._handleMouseMove);
window.addEventListener('touchmove', this._handleMouseMove);
window.addEventListener('mouseup', this._handleMouseUp);
window.addEventListener('touchend', this._handleMouseUp);
this._transforming = true;
@ -18889,7 +18931,7 @@
this.getNode().fire('transformstart');
},
handleMouseMove: function(e) {
_handleMouseMove: function(e) {
var x, y, newHypotenuse;
var resizerNode = this.findOne('.' + this.movingResizer);
var stage = resizerNode.getStage();
@ -18988,7 +19030,10 @@
y = -resizerNode.y() + attrs.height / 2;
var dAlpha = Math.atan2(-y, x) + Math.PI / 2;
// var attrs = this._getAttrs();
if (attrs.height < 0) {
dAlpha -= Math.PI;
}
var rot = Konva.getAngle(this.rotation());
@ -19015,8 +19060,7 @@
var dx = padding;
var dy = padding;
this._fitNodeInto(
Object.assign(attrs, {
this._fitNodeInto({
rotation: Konva.angleDeg
? newRotation
: Konva.Util._degToRad(newRotation),
@ -19036,8 +19080,7 @@
(dy * Math.cos(rot) + dx * Math.sin(rot)),
width: attrs.width + padding * 2,
height: attrs.height + padding * 2
})
);
});
} else {
console.error(
new Error(
@ -19071,17 +19114,17 @@
});
},
handleMouseUp: function() {
_handleMouseUp: function() {
this._removeEvents();
},
_removeEvents: function() {
if (this._transforming) {
this._transforming = false;
window.removeEventListener('mousemove', this.handleMouseMove);
window.removeEventListener('touchmove', this.handleMouseMove);
window.removeEventListener('mouseup', this.handleMouseUp);
window.removeEventListener('touchend', this.handleMouseUp);
window.removeEventListener('mousemove', this._handleMouseMove);
window.removeEventListener('touchmove', this._handleMouseMove);
window.removeEventListener('mouseup', this._handleMouseUp);
window.removeEventListener('touchend', this._handleMouseUp);
this.fire('transformend');
this.getNode().fire('transformend');
}
@ -19144,13 +19187,8 @@
},
update: function() {
var attrs = this._getNodeRect();
var x = attrs.x;
var y = attrs.y;
var width = attrs.width;
var height = attrs.height;
this.x(x);
this.y(y);
this.rotation(attrs.rotation);
var enabledHandlers = this.enabledHandlers();
var resizeEnabled = this.resizeEnabled();
@ -19199,7 +19237,7 @@
this.findOne('.rotater').setAttrs({
x: width / 2,
y: -this.rotateHandlerOffset(),
y: -this.rotateHandlerOffset() * Konva.Util._sign(height),
visible: this.rotateEnabled()
});

6
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -395,7 +395,10 @@
context.rect(clipX, clipY, clipWidth, clipHeight);
}
context.clip();
m = transform.copy().invert().getMatrix();
m = transform
.copy()
.invert()
.getMatrix();
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
}
@ -440,6 +443,7 @@
if (!child.isVisible()) {
return;
}
var rect = child.getClientRect({ relativeTo: that });
// skip invisible children (like empty groups)
@ -462,7 +466,18 @@
}
});
if (this.children.length !== 0) {
// if child is group we need to make sure it has visible shapes inside
var shapes = this.find('Shape');
var hasVisible = false;
for (var i = 0; i < shapes.length; i++) {
var shape = shapes[i];
if (shape.isVisible()) {
hasVisible = true;
break;
}
}
if (hasVisible) {
selfRect = {
x: minX,
y: minY,

View File

@ -52,7 +52,6 @@
Konva.Util.addMethods(Konva.Node, {
_init: function(config) {
var that = this;
this._id = Konva.idCounter++;
this.eventListeners = {};
this.attrs = {};
@ -64,21 +63,21 @@
// event bindings for cache handling
this.on(TRANSFORM_CHANGE_STR, function() {
this._clearCache(TRANSFORM);
that._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
});
this.on(SCALE_CHANGE_STR, function() {
that._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
});
this.on('visibleChange.konva', function() {
that._clearSelfAndDescendantCache(VISIBLE);
this._clearSelfAndDescendantCache(VISIBLE);
});
this.on('listeningChange.konva', function() {
that._clearSelfAndDescendantCache(LISTENING);
this._clearSelfAndDescendantCache(LISTENING);
});
this.on('opacityChange.konva', function() {
that._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
this._clearSelfAndDescendantCache(ABSOLUTE_OPACITY);
});
},
_clearCache: function(attr) {

View File

@ -498,6 +498,16 @@
firstChar === firstChar.toUpperCase()
);
},
_sign: function(number) {
if (number === 0) {
return 0;
}
if (number > 0) {
return 1;
} else {
return -1;
}
},
createCanvasElement: function() {
var canvas = Konva.isBrowser
? Konva.document.createElement('canvas')

View File

@ -28,20 +28,7 @@
return 'crosshair';
}
var angle;
if (anchorName === 'top-left' || anchorName === 'bottom-right') {
angle = -45;
} else if (anchorName === 'top-right' || anchorName === 'bottom-left') {
angle = 45;
} else if (anchorName === 'top-center' || anchorName === 'bottom-center') {
angle = 0;
} else if (anchorName === 'middle-left' || anchorName === 'middle-right') {
angle = 90;
} else {
angle = 0;
}
angle = (angle + Konva.Util._radToDeg(rad) + 360) % 360;
var angle = (Konva.Util._radToDeg(rad) % 360 + 360) % 360;
if (
Konva.Util._inRange(angle, 315 + 22.5, 360) ||
@ -73,6 +60,9 @@
} else {
// how can we can there?
// TODO: throw error
Konva.Util.error(
'Transformer has unknown angle for cursor detection: ' + angle
);
return 'pointer';
}
}
@ -129,8 +119,8 @@
this._createElements();
// bindings
this.handleMouseMove = this.handleMouseMove.bind(this);
this.handleMouseUp = this.handleMouseUp.bind(this);
this._handleMouseMove = this._handleMouseMove.bind(this);
this._handleMouseUp = this._handleMouseUp.bind(this);
this.update = this.update.bind(this);
// update transformer data for certain attr changes
@ -163,10 +153,12 @@
TRANSFORM_CHANGE_STR,
function() {
this._clearCache(NODE_RECT);
this._clearCache('transform');
this._clearSelfAndDescendantCache('absoluteTransform');
}.bind(this)
);
node.on(TRANSFORM_CHANGE_STR, this.requestUpdate.bind(this));
node.on('dragmove.resizer', this.requestUpdate.bind(this));
// node.on(TRANSFORM_CHANGE_STR, this.requestUpdate.bind(this));
// node.on('dragmove.resizer', this.requestUpdate.bind(this));
var elementsCreated = !!this.findOne('.top-left');
if (elementsCreated) {
@ -181,7 +173,11 @@
detach: function() {
if (this.getNode()) {
this.getNode().off('.resizer');
this._node = undefined;
}
this._clearCache(NODE_RECT);
this._clearCache('transform');
this._clearSelfAndDescendantCache('absoluteTransform');
},
_getNodeRect: function() {
@ -261,16 +257,36 @@
});
var self = this;
anchor.on('mousedown touchstart', function(e) {
self.handleResizerMouseDown(e);
self._handleMouseDown(e);
});
// add hover styling
anchor.on('mouseenter', function() {
var layer = this.getLayer();
var rad = Konva.getAngle(this.getParent().rotation());
var cursor = getCursor(name, rad);
anchor.getStage().getContainer().style.cursor = cursor;
this.fill('lightgrey');
var tr = this.getParent();
// TODO: I guess there are some ways to simplify that calculations
// the basic idea is to find "angle" of handler
var rad = Konva.getAngle(tr.rotation());
var cdx = tr.getWidth() / 2;
var cdy = tr.getHeight() / 2;
var parentPos = tr.getAbsolutePosition(tr.getParent());
var center = {
x: parentPos.x + (cdx * Math.cos(rad) + cdy * Math.sin(-rad)),
y: parentPos.y + (cdy * Math.cos(rad) + cdx * Math.sin(rad))
};
var pos = this.getAbsolutePosition(tr.getParent());
var dx = -pos.x + center.x;
var dy = -pos.y + center.y;
var angle = -Math.atan2(-dy, dx) - Math.PI / 2;
var cursor = getCursor(name, angle);
anchor.getStage().content.style.cursor = cursor;
layer.batchDraw();
});
anchor.on('mouseout', function() {
@ -278,8 +294,7 @@
if (!layer) {
return;
}
anchor.getStage().getContainer().style.cursor = '';
this.fill('white');
anchor.getStage().content.style.cursor = '';
layer.batchDraw();
});
this.add(anchor);
@ -304,7 +319,10 @@
);
ctx.moveTo(this.width() / 2, -padding);
if (tr.rotateEnabled()) {
ctx.lineTo(this.width() / 2, -tr.rotateHandlerOffset());
ctx.lineTo(
this.width() / 2,
-tr.rotateHandlerOffset() * Konva.Util._sign(this.height())
);
}
ctx.fillStrokeShape(this);
@ -313,7 +331,7 @@
this.add(back);
},
handleResizerMouseDown: function(e) {
_handleMouseDown: function(e) {
this.movingResizer = e.target.name();
// var node = this.getNode();
@ -324,10 +342,10 @@
this.sin = height / hypotenuse;
this.cos = width / hypotenuse;
window.addEventListener('mousemove', this.handleMouseMove);
window.addEventListener('touchmove', this.handleMouseMove);
window.addEventListener('mouseup', this.handleMouseUp);
window.addEventListener('touchend', this.handleMouseUp);
window.addEventListener('mousemove', this._handleMouseMove);
window.addEventListener('touchmove', this._handleMouseMove);
window.addEventListener('mouseup', this._handleMouseUp);
window.addEventListener('touchend', this._handleMouseUp);
this._transforming = true;
@ -335,7 +353,7 @@
this.getNode().fire('transformstart');
},
handleMouseMove: function(e) {
_handleMouseMove: function(e) {
var x, y, newHypotenuse;
var resizerNode = this.findOne('.' + this.movingResizer);
var stage = resizerNode.getStage();
@ -434,7 +452,10 @@
y = -resizerNode.y() + attrs.height / 2;
var dAlpha = Math.atan2(-y, x) + Math.PI / 2;
// var attrs = this._getAttrs();
if (attrs.height < 0) {
dAlpha -= Math.PI;
}
var rot = Konva.getAngle(this.rotation());
@ -461,8 +482,7 @@
var dx = padding;
var dy = padding;
this._fitNodeInto(
Object.assign(attrs, {
this._fitNodeInto({
rotation: Konva.angleDeg
? newRotation
: Konva.Util._degToRad(newRotation),
@ -482,8 +502,7 @@
(dy * Math.cos(rot) + dx * Math.sin(rot)),
width: attrs.width + padding * 2,
height: attrs.height + padding * 2
})
);
});
} else {
console.error(
new Error(
@ -517,17 +536,17 @@
});
},
handleMouseUp: function() {
_handleMouseUp: function() {
this._removeEvents();
},
_removeEvents: function() {
if (this._transforming) {
this._transforming = false;
window.removeEventListener('mousemove', this.handleMouseMove);
window.removeEventListener('touchmove', this.handleMouseMove);
window.removeEventListener('mouseup', this.handleMouseUp);
window.removeEventListener('touchend', this.handleMouseUp);
window.removeEventListener('mousemove', this._handleMouseMove);
window.removeEventListener('touchmove', this._handleMouseMove);
window.removeEventListener('mouseup', this._handleMouseUp);
window.removeEventListener('touchend', this._handleMouseUp);
this.fire('transformend');
this.getNode().fire('transformend');
}
@ -590,13 +609,8 @@
},
update: function() {
var attrs = this._getNodeRect();
var x = attrs.x;
var y = attrs.y;
var width = attrs.width;
var height = attrs.height;
this.x(x);
this.y(y);
this.rotation(attrs.rotation);
var enabledHandlers = this.enabledHandlers();
var resizeEnabled = this.resizeEnabled();
@ -645,7 +659,7 @@
this.findOne('.rotater').setAttrs({
x: width / 2,
y: -this.rotateHandlerOffset(),
y: -this.rotateHandlerOffset() * Konva.Util._sign(height),
visible: this.rotateEnabled()
});

View File

@ -2148,6 +2148,46 @@ suite('Container', function() {
});
});
test('get client rect with deep nested hidden shape', function() {
var stage = addStage();
var layer = new Konva.Layer();
var group = new Konva.Group({
draggable: true,
x: 100,
y: 40
});
var rect = new Konva.Rect({
height: 100,
width: 100,
fill: 'red'
});
group.add(rect);
layer.add(group);
var subGroup = new Konva.Group();
group.add(subGroup);
subGroup.add(
new Konva.Rect({
visible: false
})
);
stage.add(layer);
stage.draw();
var clientRect = group.getClientRect();
assert.deepEqual(clientRect, {
x: 100,
y: 40,
width: 100,
height: 100
});
});
test('getClientRect - test empty group with invisible child', function() {
var stage = addStage();
var layer = new Konva.Layer();
@ -2256,7 +2296,10 @@ suite('Container', function() {
data[3]
);
data = layer.getHitCanvas().getContext().getImageData(76, 50, 1, 1).data;
data = layer
.getHitCanvas()
.getContext()
.getImageData(76, 50, 1, 1).data;
isTransparent = data[3] == 0;
assert.equal(
@ -2272,7 +2315,10 @@ suite('Container', function() {
data[3]
);
data = layer.getHitCanvas().getContext().getImageData(50, 76, 1, 1).data;
data = layer
.getHitCanvas()
.getContext()
.getImageData(50, 76, 1, 1).data;
isTransparent = data[3] == 0;
assert.equal(
isTransparent,
@ -2369,8 +2415,10 @@ suite('Container', function() {
stage.scale({ x: 2, y: 2 });
stage.draw();
var data = layer.getHitCanvas().getContext().getImageData(48, 100, 1, 1)
.data;
var data = layer
.getHitCanvas()
.getContext()
.getImageData(48, 100, 1, 1).data;
var isTransparent = data[3] == 0;
assert.equal(
isTransparent,
@ -2385,7 +2433,10 @@ suite('Container', function() {
data[3]
);
data = layer.getHitCanvas().getContext().getImageData(100, 48, 1, 1).data;
data = layer
.getHitCanvas()
.getContext()
.getImageData(100, 48, 1, 1).data;
isTransparent = data[3] == 0;
assert.equal(
isTransparent,
@ -2400,7 +2451,10 @@ suite('Container', function() {
data[3]
);
data = layer.getHitCanvas().getContext().getImageData(152, 100, 1, 1).data;
data = layer
.getHitCanvas()
.getContext()
.getImageData(152, 100, 1, 1).data;
isTransparent = data[3] == 0;
assert.equal(
isTransparent,
@ -2415,7 +2469,10 @@ suite('Container', function() {
data[3]
);
data = layer.getHitCanvas().getContext().getImageData(100, 152, 1, 1).data;
data = layer
.getHitCanvas()
.getContext()
.getImageData(100, 152, 1, 1).data;
isTransparent = data[3] == 0;
assert.equal(
isTransparent,

View File

@ -746,4 +746,249 @@ suite('Transformer', function() {
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 90);
});
test('transformer should automatically track attr changes of a node', 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({
node: rect
});
layer.add(tr);
layer.draw();
assert.equal(tr.x(), 100);
assert.equal(tr.y(), 60);
assert.equal(tr.width(), 100);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
rect.x(0);
assert.equal(tr.x(), 0);
rect.y(0);
assert.equal(tr.y(), 0);
rect.width(50);
assert.equal(tr.width(), 50);
rect.height(50);
assert.equal(tr.height(), 50);
rect.scaleX(2);
assert.equal(tr.width(), 100);
rect.scaleY(2);
assert.equal(tr.height(), 100);
// manual check position
var back = tr.findOne('.back');
assert.equal(back.getAbsolutePosition().x, 0);
layer.batchDraw();
});
test('on detach should remove all listeners', 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({
node: rect
});
layer.add(tr);
layer.draw();
tr.detach();
rect.width(200);
assert.equal(tr.width(), 0);
layer.draw();
var called = false;
// clear cache is called on each update
// make sure we don't call it
tr._clearCache = function() {
called = true;
};
rect.width(50);
assert.equal(called, false, 'don not call clear cache');
});
test('check transformer with drag&drop', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 0,
y: 0,
width: 100,
height: 100,
fill: 'green',
draggable: true
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
stage.simulateMouseDown({
x: 20,
y: 20
});
stage.simulateMouseMove({
x: 30,
y: 30
});
assert.equal(rect.x(), 10);
assert.equal(rect.y(), 10);
assert.equal(tr.x(), 10);
assert.equal(tr.y(), 10);
stage.simulateMouseUp({
x: 30,
y: 30
});
});
test('on negative scaleY should move rotater', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 160,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
scaleY: -1
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
var rotater = tr.findOne('.rotater');
var pos = rotater.getAbsolutePosition();
assert.equal(pos.x, 100);
assert.equal(pos.y, 210);
});
test('try rotated scaled rect', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 100,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
scaleY: -1
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
var rotater = tr.findOne('.rotater');
var pos = rotater.getAbsolutePosition();
stage.simulateMouseDown({
x: pos.x,
y: pos.y
});
var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({
target: rotater,
clientX: pos.x + 100,
clientY: pos.y - 100 + top
});
// here is duplicate, because transformer is listening window events
tr._handleMouseUp({
clientX: pos.x + 100,
clientY: pos.y - 50 + top
});
stage.simulateMouseUp({
x: 100,
y: 100
});
assert.equal(rect.rotation(), -90);
});
test('check correct cursor on scaled shape', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 100,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
scaleY: -1
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
stage.simulateMouseMove({
x: 50,
y: 1
});
assert.equal(stage.content.style.cursor, 'nwse-resize');
});
});