some transformer fixes

This commit is contained in:
Anton Lavrenov
2020-04-06 21:51:03 -05:00
parent 185c599257
commit 55c812425d
4 changed files with 932 additions and 1540 deletions

1543
konva.js

File diff suppressed because it is too large Load Diff

View File

@@ -218,7 +218,7 @@ export abstract class BaseLayer extends Container<Group | Shape> {
this.getContext()._context.imageSmoothingEnabled = this.imageSmoothingEnabled(); this.getContext()._context.imageSmoothingEnabled = this.imageSmoothingEnabled();
} }
/** /**
* get/set width of layer.getter return width of stage. setter doing nothing. * get/set width of layer. getter return width of stage. setter doing nothing.
* if you want change width use `stage.width(value);` * if you want change width use `stage.width(value);`
* @name Konva.BaseLayer#width * @name Konva.BaseLayer#width
* @method * @method
@@ -302,10 +302,8 @@ BaseLayer.prototype.nodeType = 'BaseLayer';
* // get imageSmoothingEnabled flag * // get imageSmoothingEnabled flag
* var imageSmoothingEnabled = layer.imageSmoothingEnabled(); * var imageSmoothingEnabled = layer.imageSmoothingEnabled();
* *
* // disable clear before draw
* layer.imageSmoothingEnabled(false); * layer.imageSmoothingEnabled(false);
* *
* // enable clear before draw
* layer.imageSmoothingEnabled(true); * layer.imageSmoothingEnabled(true);
*/ */
Factory.addGetterSetter(BaseLayer, 'imageSmoothingEnabled', true); Factory.addGetterSetter(BaseLayer, 'imageSmoothingEnabled', true);

View File

@@ -145,7 +145,15 @@ var ANCHORS_NAMES = [
var MAX_SAFE_INTEGER = 100000000; var MAX_SAFE_INTEGER = 100000000;
function getCenter(shape) { type SHAPE = {
x: number;
y: number;
width: number;
height: number;
rotation: number;
};
function getCenter(shape: SHAPE) {
return { return {
x: x:
shape.x + shape.x +
@@ -158,7 +166,7 @@ function getCenter(shape) {
}; };
} }
function rotateAroundPoint(shape, angleRad, point) { function rotateAroundPoint(shape: SHAPE, angleRad: number, point: Point) {
const x = const x =
point.x + point.x +
(shape.x - point.x) * Math.cos(angleRad) - (shape.x - point.x) * Math.cos(angleRad) -
@@ -175,12 +183,12 @@ function rotateAroundPoint(shape, angleRad, point) {
}; };
} }
function rotateAroundCenter(shape, deltaRad) { function rotateAroundCenter(shape: SHAPE, deltaRad: number) {
const center = getCenter(shape); const center = getCenter(shape);
return rotateAroundPoint(shape, deltaRad, center); return rotateAroundPoint(shape, deltaRad, center);
} }
function getShapeRect(shape) { function getShapeRect(shape: SHAPE) {
const angleRad = shape.rotation; const angleRad = shape.rotation;
const x1 = shape.x; const x1 = shape.x;
const y1 = shape.y; const y1 = shape.y;
@@ -209,7 +217,7 @@ function getShapeRect(shape) {
}; };
} }
function getShapesRect(shapes) { function getShapesRect(shapes: Array<SHAPE>) {
// if (shapes.length === 1) { // if (shapes.length === 1) {
// const shape = shapes[0]; // const shape = shapes[0];
@@ -242,25 +250,16 @@ function getShapesRect(shapes) {
}; };
} }
function isOverlap(rect1, rect2) { function transformShape(
const offset = 0; shape: SHAPE,
if (rect1.x - offset > rect2.x + rect2.width) { oldSelection: SHAPE,
return false; newSelection: SHAPE,
} keepOffset = 1
if (rect1.x + rect1.width + offset < rect2.x) { ) {
return false; const offset = rotateAroundPoint(shape, -oldSelection.rotation, {
} x: oldSelection.x,
if (rect1.y - offset > rect2.y + rect2.height) { y: oldSelection.y
return false; });
}
if (rect1.y + rect1.height + offset < rect2.y) {
return false;
}
return true;
}
function transformShape(shape, oldSelection, newSelection, keepOffset = 1) {
const offset = rotateAroundPoint(shape, -oldSelection.rotation, oldSelection);
const offsetX = offset.x - oldSelection.x; const offsetX = offset.x - oldSelection.x;
const offsetY = offset.y - oldSelection.y; const offsetY = offset.y - oldSelection.y;
@@ -279,14 +278,19 @@ function transformShape(shape, oldSelection, newSelection, keepOffset = 1) {
offsetX * scaleX * Math.sin(angle) + offsetX * scaleX * Math.sin(angle) +
offsetY * scaleY * Math.cos(angle), offsetY * scaleY * Math.cos(angle),
width: shape.width * scaleX, width: shape.width * scaleX,
height: shape.height * scaleY height: shape.height * scaleY,
rotation: shape.rotation
}; };
} }
function transformAndRotateShape(shape, oldSelection, newSelection) { function transformAndRotateShape(
shape: SHAPE,
oldSelection: SHAPE,
newSelection: SHAPE
) {
const updated = transformShape(shape, oldSelection, newSelection); const updated = transformShape(shape, oldSelection, newSelection);
return rotateAroundPoint( return rotateAroundPoint(
{ ...updated, rotation: shape.rotation }, updated,
newSelection.rotation - oldSelection.rotation, newSelection.rotation - oldSelection.rotation,
newSelection newSelection
); );
@@ -580,22 +584,22 @@ export class Transformer extends Group {
strokeWidth: 1, strokeWidth: 1,
name: name + ' _anchor', name: name + ' _anchor',
dragDistance: 0, dragDistance: 0,
draggable: true, draggable: false,
hitStrokeWidth: TOUCH_DEVICE ? 10 : 'auto' hitStrokeWidth: TOUCH_DEVICE ? 10 : 'auto'
}); });
var self = this; var self = this;
anchor.on('mousedown touchstart', function(e) { anchor.on('mousedown touchstart', function(e) {
self._handleMouseDown(e); self._handleMouseDown(e);
}); });
anchor.on('dragstart', function(e) { // anchor.on('dragstart', function(e) {
e.cancelBubble = true; // e.cancelBubble = true;
}); // });
anchor.on('dragmove', function(e) { // anchor.on('dragmove', function(e) {
e.cancelBubble = true; // e.cancelBubble = true;
}); // });
anchor.on('dragend', function(e) { // anchor.on('dragend', function(e) {
e.cancelBubble = true; // e.cancelBubble = true;
}); // });
// add hover styling // add hover styling
anchor.on('mouseenter', () => { anchor.on('mouseenter', () => {
@@ -697,13 +701,47 @@ export class Transformer extends Group {
x: pp.x - this._anchorDragOffset.x, x: pp.x - this._anchorDragOffset.x,
y: pp.y - this._anchorDragOffset.y y: pp.y - this._anchorDragOffset.y
}; };
const oldAbs = anchorNode.getAbsolutePosition();
anchorNode.setAbsolutePosition(newNodePos); anchorNode.setAbsolutePosition(newNodePos);
const newAbs = anchorNode.getAbsolutePosition();
if (oldAbs.x === newAbs.x && oldAbs.y === newAbs.y) {
return;
}
var centeredScaling = this.centeredScaling() || e.altKey;
// if (centeredScaling && this._movingAnchorName.indexOf('left') >= 0) {
// var topLeft = this.findOne('.top-left');
// var bottomRight = this.findOne('.bottom-right');
// var topOffsetX = topLeft.x() + padding;
// var topOffsetY = topLeft.y() + padding;
// var bottomOffsetX = this.getWidth() - bottomRight.x() + padding;
// var bottomOffsetY = this.getHeight() - bottomRight.y() + padding;
// bottomRight.move({
// x: -anchorNode.x(),
// y: -anchorNode.y()
// });
// topLeft.move({
// x: bottomOffsetX,
// y: bottomOffsetY
// });
// }
var keepProportion = this.keepRatio() || e.shiftKey; var keepProportion = this.keepRatio() || e.shiftKey;
var padding = 0; var padding = 0;
if (this._movingAnchorName === 'top-left') { if (this._movingAnchorName === 'top-left') {
// if (centeredScaling) {
// this.findOne('.bottom-right').move({
// x: -anchorNode.x(),
// y: -anchorNode.y()
// });
// }
if (keepProportion) { if (keepProportion) {
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
Math.pow( Math.pow(
@@ -737,8 +775,32 @@ export class Transformer extends Group {
); );
} }
} else if (this._movingAnchorName === 'top-center') { } else if (this._movingAnchorName === 'top-center') {
// if (centeredScaling) {
// this.findOne('.bottom-right').move({
// x: 0,
// y: -anchorNode.y()
// });
// }
this.findOne('.top-left').y(anchorNode.y()); this.findOne('.top-left').y(anchorNode.y());
} else if (this._movingAnchorName === 'top-right') { } else if (this._movingAnchorName === 'top-right') {
if (centeredScaling) {
// this.findOne('.bottom-left').move({
// x: -(anchorNode.x() - this.width()),
// y: -anchorNode.y()
// });
// this.findOne('.top-left').move({
// x: -(anchorNode.x() - this.width()),
// y: anchorNode.y()
// });
// this.findOne('.bottom-right').move({
// x: -(anchorNode.x() - this.width()),
// y: anchorNode.y()
// });
}
// var center = getCenter({
// x
// })
if (keepProportion) { if (keepProportion) {
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
Math.pow( Math.pow(
@@ -770,14 +832,31 @@ export class Transformer extends Group {
); );
} }
var pos = anchorNode.position(); var pos = anchorNode.position();
this.findOne('.top-left').y(pos.y); this.findOne('.top-left').y(pos.y);
this.findOne('.bottom-right').x(pos.x); this.findOne('.bottom-right').x(pos.x);
} else if (this._movingAnchorName === 'middle-left') { } else if (this._movingAnchorName === 'middle-left') {
// if (centeredScaling) {
// this.findOne('.bottom-right').move({
// x: -anchorNode.x(),
// y: 0
// });
// }
this.findOne('.top-left').x(anchorNode.x()); this.findOne('.top-left').x(anchorNode.x());
} else if (this._movingAnchorName === 'middle-right') { } else if (this._movingAnchorName === 'middle-right') {
// if (centeredScaling) {
// this.findOne('.top-left').move({
// x: -(anchorNode.x() - this.width()),
// y: 0
// });
// }
this.findOne('.bottom-right').x(anchorNode.x()); this.findOne('.bottom-right').x(anchorNode.x());
} else if (this._movingAnchorName === 'bottom-left') { } else if (this._movingAnchorName === 'bottom-left') {
// if (centeredScaling) {
// this.findOne('.bottom-right').move({
// x: -anchorNode.x(),
// y: -(anchorNode.y() - this.height())
// });
// }
if (keepProportion) { if (keepProportion) {
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
Math.pow( Math.pow(
@@ -814,8 +893,21 @@ export class Transformer extends Group {
this.findOne('.top-left').x(pos.x); this.findOne('.top-left').x(pos.x);
this.findOne('.bottom-right').y(pos.y); this.findOne('.bottom-right').y(pos.y);
} else if (this._movingAnchorName === 'bottom-center') { } else if (this._movingAnchorName === 'bottom-center') {
// if (centeredScaling) {
// this.findOne('.top-left').move({
// x: 0,
// y: -(anchorNode.y() - this.height())
// });
// }
this.findOne('.bottom-right').y(anchorNode.y()); this.findOne('.bottom-right').y(anchorNode.y());
} else if (this._movingAnchorName === 'bottom-right') { } else if (this._movingAnchorName === 'bottom-right') {
// if (centeredScaling) {
// this.findOne('.top-left').move({
// x: -(anchorNode.x() - this.width()),
// y: -(anchorNode.y() - this.height())
// });
// }
if (keepProportion) { if (keepProportion) {
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
Math.pow(this.findOne('.bottom-right').x() - padding, 2) + Math.pow(this.findOne('.bottom-right').x() - padding, 2) +
@@ -910,9 +1002,7 @@ export class Transformer extends Group {
}); });
} }
var absPos = this.findOne('.top-left').getAbsolutePosition( var absPos = this.findOne('.top-left').getAbsolutePosition();
this.getParent()
);
x = absPos.x; x = absPos.x;
y = absPos.y; y = absPos.y;
@@ -924,8 +1014,8 @@ export class Transformer extends Group {
this._fitNodesInto( this._fitNodesInto(
{ {
x: x + this.offsetX(), x: x,
y: y + this.offsetY(), y: y,
width: width, width: width,
height: height, height: height,
rotation: Konva.getAngle(this.rotation()) rotation: Konva.getAngle(this.rotation())
@@ -956,43 +1046,88 @@ export class Transformer extends Group {
} }
} }
_fitNodesInto(newAttrs, evt) { _fitNodesInto(newAttrs, evt) {
// console.log(newAttrs, oldAttrs);
// waring! in this attrs padding is included
var oldAttrs = this._getNodeRect(); var oldAttrs = this._getNodeRect();
var boundBoxFunc = this.boundBoxFunc(); var boundBoxFunc = this.boundBoxFunc();
if (boundBoxFunc) { if (boundBoxFunc) {
newAttrs = boundBoxFunc.call(this, oldAttrs, newAttrs); newAttrs = boundBoxFunc.call(this, oldAttrs, newAttrs);
} }
console.log(newAttrs.width, newAttrs.height);
if (newAttrs.width < 1 && newAttrs.width > - this.padding() * 2) { const minSize = 1;
if (Util._inRange(newAttrs.width, -this.padding() * 2 - minSize, minSize)) {
this.update(); this.update();
return; return;
} }
if (Math.abs(newAttrs.height) < 1) { if (
Util._inRange(newAttrs.height, -this.padding() * 2 - minSize, minSize)
) {
this.update(); this.update();
return; return;
} }
// if (newAttrs.width < 0) {
// debugger;
// }
const an = this._movingAnchorName; const an = this._movingAnchorName;
const allowNegativeScale = true;
var t = new Transform();
t.rotate(Konva.getAngle(this.rotation()));
if (an && newAttrs.width < 0 && an.indexOf('left') >= 0) { if (an && newAttrs.width < 0 && an.indexOf('left') >= 0) {
const offset = t.point({
x: -this.padding() * 2,
y: 0
});
newAttrs.x += offset.x;
newAttrs.y += offset.y;
newAttrs.width += this.padding() * 2;
this._movingAnchorName = an.replace('left', 'right'); this._movingAnchorName = an.replace('left', 'right');
this._anchorDragOffset.x += this.padding() * 2; this._anchorDragOffset.x -= offset.x;
this.update(); this._anchorDragOffset.y -= offset.y;
return; if (!allowNegativeScale) {
this.update();
return;
}
} else if (an && newAttrs.width < 0 && an.indexOf('right') >= 0) { } else if (an && newAttrs.width < 0 && an.indexOf('right') >= 0) {
const offset = t.point({
x: this.padding() * 2,
y: 0
});
this._movingAnchorName = an.replace('right', 'left'); this._movingAnchorName = an.replace('right', 'left');
this._anchorDragOffset.x -= this.padding() * 2; this._anchorDragOffset.x -= offset.x;
this.update(); this._anchorDragOffset.y -= offset.y;
return; newAttrs.width += this.padding() * 2;
} else if (an && newAttrs.height < 0 && an.indexOf('top') >= 0) { if (!allowNegativeScale) {
this.update();
return;
}
}
if (an && newAttrs.height < 0 && an.indexOf('top') >= 0) {
const offset = t.point({
x: 0,
y: -this.padding() * 2
});
newAttrs.x += offset.x;
newAttrs.y += offset.y;
this._movingAnchorName = an.replace('top', 'bottom'); this._movingAnchorName = an.replace('top', 'bottom');
this._anchorDragOffset.y += this.padding() * 2; this._anchorDragOffset.x -= offset.x;
this.update(); this._anchorDragOffset.y -= offset.y;
return; newAttrs.height += this.padding() * 2;
if (!allowNegativeScale) {
this.update();
return;
}
} else if (an && newAttrs.height < 0 && an.indexOf('bottom') >= 0) { } else if (an && newAttrs.height < 0 && an.indexOf('bottom') >= 0) {
const offset = t.point({
x: 0,
y: this.padding() * 2
});
this._movingAnchorName = an.replace('bottom', 'top'); this._movingAnchorName = an.replace('bottom', 'top');
this._anchorDragOffset.y -= this.padding() * 2; this._anchorDragOffset.x -= offset.x;
this.update(); this._anchorDragOffset.y -= offset.y;
return; newAttrs.height += this.padding() * 2;
if (!allowNegativeScale) {
this.update();
return;
}
} }
this._nodes.forEach(node => { this._nodes.forEach(node => {
var oldRect = this.__getNodeShape(node, 0); var oldRect = this.__getNodeShape(node, 0);

View File

@@ -1,4 +1,26 @@
suite.only('Transformer', function() { suite.only('Transformer', function() {
function isClose(a, b) {
return Math.abs(a - b) < 0.000001;
}
Konva.Transformer.prototype.simulateMouseDown = function(pos) {
this.getStage().simulateMouseDown(pos);
};
Konva.Transformer.prototype.simulateMouseMove = function(pos) {
var top = this.getStage().content.getBoundingClientRect().top;
this._handleMouseMove({
clientX: pos.x,
clientY: pos.y + top
});
this.getStage().simulateMouseMove(pos);
};
Konva.Transformer.prototype.simulateMouseUp = function(pos) {
this._handleMouseUp(pos);
this.getStage().simulateMouseUp(pos || { x: 1, y: 1 });
};
// ====================================================== // ======================================================
test('init transformer on simple rectangle', function() { test('init transformer on simple rectangle', function() {
var stage = addStage(); var stage = addStage();
@@ -196,7 +218,7 @@ suite.only('Transformer', function() {
assert.equal(tr.rotation(), rect.rotation()); assert.equal(tr.rotation(), rect.rotation());
}); });
test.skip('try to fit simple rectangle into negative scale', function() { test('try to fit simple rectangle into negative scale', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
stage.add(layer); stage.add(layer);
@@ -227,8 +249,6 @@ suite.only('Transformer', function() {
tr._fitNodesInto(box); tr._fitNodesInto(box);
assert.deepEqual(box, tr.__getNodeRect());
assert.equal(rect.x(), 100); assert.equal(rect.x(), 100);
assert.equal(rect.y(), 0); assert.equal(rect.y(), 0);
assert.equal(rect.width(), 100); assert.equal(rect.width(), 100);
@@ -939,14 +959,14 @@ suite.only('Transformer', function() {
}); });
}); });
test.only('can add padding', function() { test('can add padding', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
stage.add(layer); stage.add(layer);
var rect = new Konva.Rect({ var rect = new Konva.Rect({
x: 100, x: 30,
y: 60, y: 30,
draggable: true, draggable: true,
width: 100, width: 100,
height: 100, height: 100,
@@ -956,77 +976,36 @@ suite.only('Transformer', function() {
var tr = new Konva.Transformer({ var tr = new Konva.Transformer({
node: rect, node: rect,
padding: 50 padding: 20
});
layer.add(tr);
tr._fitNodesInto({
x: 20,
y: 20,
width: 100,
height: 100,
rotation: 0
});
layer.draw();
assert.equal(rect.x(), 20);
assert.equal(rect.y(), 20);
assert.equal(rect.width(), 120);
assert.equal(rect.height(), 120);
});
test.skip('test padding + keep ratio', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 50,
width: 180,
height: 50,
fill: 'red',
draggable: true
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect,
padding: 40,
keepRatio: true
}); });
layer.add(tr); layer.add(tr);
layer.draw(); layer.draw();
stage.simulateMouseDown({ stage.simulateMouseDown({
x: 250, x: 10,
y: 150 y: 80
}); });
var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ var top = stage.content.getBoundingClientRect().top;
target: tr.findOne('.bottom-right'), tr._handleMouseMove({
clientX: 200, clientX: 60,
clientY: 150 + top clientY: 80 + top
}); });
// here is duplicate, because transformer is listening window events
tr._handleMouseUp({ tr._handleMouseUp({
clientX: 200, clientX: 200,
clientY: 150 + top clientY: 150
}); });
stage.simulateMouseUp({ stage.simulateMouseUp({
x: 200, x: 200,
y: 150 y: 150
}); });
layer.draw(); assert.equal(rect.x(), 80);
assert.equal(rect.y(), 30);
assert.equal(rect.x(), 50);
assert.equal(rect.y(), 50);
assert.equal(rect.width(), 100); assert.equal(rect.width(), 100);
assert.equal(rect.height(), 50); assert.equal(rect.scaleX(), 0.5);
assert.equal(rect.scaleX(), 1); assert.equal(rect.height(), 100);
assert.equal(rect.scaleY(), 1); assert.equal(rect.scaleY(), 1);
}); });
@@ -1051,6 +1030,11 @@ suite.only('Transformer', function() {
layer.add(tr); layer.add(tr);
layer.draw(); layer.draw();
// rect.on('transform', () => {
// console.log(tr.getActiveAnchor(), tr._anchorDragOffset);
// });
// throw 1;
var anchor = tr.findOne('.top-right'); var anchor = tr.findOne('.top-right');
var pos = anchor.getAbsolutePosition(); var pos = anchor.getAbsolutePosition();
@@ -1059,9 +1043,7 @@ suite.only('Transformer', function() {
y: pos.y y: pos.y
}); });
var box = stage.content.getBoundingClientRect(); var box = stage.content.getBoundingClientRect();
// debugger;
tr._handleMouseMove({ tr._handleMouseMove({
target: anchor,
clientX: box.left + pos.x - 100, clientX: box.left + pos.x - 100,
clientY: box.top + pos.y + 100 clientY: box.top + pos.y + 100
}); });
@@ -1080,14 +1062,36 @@ suite.only('Transformer', function() {
assert.equal(rect.scaleY(), -1); assert.equal(rect.scaleY(), -1);
}); });
test('can add padding with rotation', function() { test.skip('visual test', function(done) {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var src = 'assets/darth-vader.jpg';
Konva.Image.fromURL(src, function(image) {
image.setAttrs({
draggable: true,
scaleX: 0.5,
scaleY: 0.5
});
layer.add(image);
var tr = new Konva.Transformer({
node: image,
keepRatio: false
});
layer.add(tr);
layer.draw();
done();
});
});
test('switch scaling with padding - x', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
stage.add(layer); stage.add(layer);
var rect = new Konva.Rect({ var rect = new Konva.Rect({
x: 100, x: 10,
y: 60, y: 10,
draggable: true, draggable: true,
width: 100, width: 100,
height: 100, height: 100,
@@ -1101,21 +1105,411 @@ suite.only('Transformer', function() {
}); });
layer.add(tr); layer.add(tr);
tr._fitNodesInto({ layer.draw();
x: 120,
y: 0, tr.simulateMouseDown({
width: 120, x: 0,
height: 120, y: 60
rotation: Konva.getAngle(90)
}); });
tr.simulateMouseMove({
x: 125,
y: 60
});
assert.equal(rect.x(), 115);
assert.equal(rect.y(), 10);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), -0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
tr.simulateMouseMove({
x: 125,
y: 60
});
assert.equal(rect.x(), 115);
assert.equal(rect.y(), 10);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.scaleY(), -1);
// switch again
tr.simulateMouseMove({
x: 90,
y: 60
});
assert.equal(rect.x(), 100);
assert.equal(rect.y(), 10);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleY(), -1);
assert.equal(rect.scaleX() + 0.1 < 0.0001, true);
assert.equal(rect.height(), 100);
tr.simulateMouseUp();
});
test('switch scaling with padding - y', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 10,
y: 10,
draggable: true,
width: 100,
height: 100,
fill: 'yellow'
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect,
padding: 10
});
layer.add(tr);
layer.draw(); layer.draw();
tr.simulateMouseDown({
x: 60,
y: 0
});
tr.simulateMouseMove({
x: 60,
y: 125
});
assert.equal(rect.x(), 10);
assert.equal(rect.y(), 115);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleY(), -0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
tr.simulateMouseMove({
x: 60,
y: 125
});
assert.equal(rect.x(), 10);
assert.equal(rect.y(), 115);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleY(), -0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
// switch again
tr.simulateMouseMove({
x: 60,
y: 90
});
assert.equal(rect.x(), 10);
assert.equal(rect.y(), 100);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.scaleY(), 0.1);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
tr.simulateMouseUp();
});
test('switch horizontal scaling with (top-left anchor)', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 0,
y: 0,
draggable: true,
width: 100,
height: 100,
fill: 'yellow'
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
tr.simulateMouseDown({
x: 0,
y: 0
});
tr.simulateMouseMove({
x: 150,
y: 50
});
layer.draw();
assert.equal(rect.x(), 150);
assert.equal(rect.y(), 50);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), -0.5);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
tr.simulateMouseMove({
x: 98,
y: 2.859375
});
tr.simulateMouseMove({
x: 98,
y: 2.859375
});
tr.simulateMouseMove({
x: 98,
y: 2.859375
});
tr.simulateMouseMove({
x: 100,
y: 2.859375
});
layer.draw();
tr.simulateMouseMove({
x: 101,
y: 2.859375
});
layer.draw();
tr.simulateMouseMove({
x: 101,
y: 2.859375
});
layer.draw();
tr.simulateMouseMove({
x: 101,
y: 2.859375
});
layer.draw();
tr.simulateMouseMove({
x: 102,
y: 2.859375
});
layer.draw();
// switch again
tr.simulateMouseMove({
x: 0,
y: 0
});
assert.equal(isClose(rect.x(), 0), true);
assert.equal(Math.round(rect.y()), 0);
assert.equal(rect.width(), 100);
assert.equal(Math.round(rect.scaleY()), -1);
assert.equal(Math.round(rect.scaleX()), -1);
assert.equal(rect.height(), 100);
tr.simulateMouseUp();
});
// TODO: doesn't work!!!
test.skip('switch vertical scaling with (top-left anchor)', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 0,
y: 0,
draggable: true,
width: 100,
height: 100,
fill: 'yellow'
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
tr.simulateMouseDown({
x: 0,
y: 0
});
tr.simulateMouseMove({
x: 0,
y: 200
});
layer.draw();
assert.equal(rect.x(), 0);
assert.equal(rect.y(), 200);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
tr.simulateMouseMove({
x: 0,
y: 0
});
layer.draw();
tr.simulateMouseUp();
assert.equal(rect.x(), 0);
assert.equal(rect.y(), 100);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 0);
assert.equal(rect.scaleY(), -1);
});
test('switch scaling with padding for rotated - x', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 110,
y: 10,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
rotation: 90
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect,
padding: 10
});
layer.add(tr);
layer.draw();
tr.simulateMouseDown({
x: 60,
y: 0
});
tr.simulateMouseMove({
x: 60,
y: 125
});
assert.equal(rect.x(), 110);
assert.equal(rect.y(), 115);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), -0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 90);
tr.simulateMouseMove({
x: 60,
y: 125
});
assert.equal(rect.x(), 110);
assert.equal(rect.y(), 115);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.scaleY(), -1);
// switch again
tr.simulateMouseMove({
x: 60,
y: 90
});
assert.equal(rect.x(), 110);
assert.equal(rect.y() - 120 < 0.001, true);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX() + 0.1 < 0.0001, true);
assert.equal(rect.scaleY(), -1);
assert.equal(rect.height(), 100);
tr.simulateMouseUp();
});
test('switch scaling with padding for rotated - y', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 110,
y: 10,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
rotation: 90
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect,
padding: 10
});
layer.add(tr);
layer.draw();
tr.simulateMouseDown({
x: 0,
y: 60
});
tr.simulateMouseMove({
x: 125,
y: 60
});
assert.equal(rect.x(), 110); assert.equal(rect.x(), 110);
assert.equal(rect.y(), 10); assert.equal(rect.y(), 10);
assert.equal(rect.width(), 100); assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.scaleY(), -0.05);
assert.equal(rect.height(), 100); assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 90); assert.equal(rect.rotation(), 90);
tr.simulateMouseMove({
x: 125,
y: 60
});
assert.equal(rect.x(), 110);
assert.equal(rect.y(), 10);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.scaleY(), -0.05);
assert.equal(rect.height(), 100);
assert.equal(rect.rotation(), 90);
// switch again
tr.simulateMouseMove({
x: 90,
y: 60
});
assert.equal(rect.x(), 110);
assert.equal(rect.y() - 120 < 0.001, true);
assert.equal(rect.width(), 100);
assert.equal(rect.scaleX(), 1);
assert.equal(rect.scaleY(), 0.1);
assert.equal(rect.height(), 100);
tr.simulateMouseUp();
}); });
test('transformer should automatically track attr changes of a node', function() { test('transformer should automatically track attr changes of a node', function() {
@@ -1368,7 +1762,6 @@ suite.only('Transformer', function() {
}); });
var top = stage.content.getBoundingClientRect().top; var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ tr._handleMouseMove({
target: rotater,
clientX: pos.x + 100, clientX: pos.x + 100,
clientY: pos.y - 100 + top clientY: pos.y - 100 + top
}); });
@@ -1453,7 +1846,6 @@ suite.only('Transformer', function() {
}); });
var top = stage.content.getBoundingClientRect().top; var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ tr._handleMouseMove({
target: target,
clientX: 120, clientX: 120,
clientY: 100 + top clientY: 100 + top
}); });
@@ -1581,7 +1973,6 @@ suite.only('Transformer', function() {
var top = stage.content.getBoundingClientRect().top; var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ tr._handleMouseMove({
target: tr.findOne('.top-left'),
clientX: 60, clientX: 60,
clientY: 60 + top clientY: 60 + top
}); });
@@ -1670,7 +2061,6 @@ suite.only('Transformer', function() {
var top = stage.content.getBoundingClientRect().top; var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ tr._handleMouseMove({
target: tr.findOne('.top-left'),
clientX: 60, clientX: 60,
clientY: 60 + top clientY: 60 + top
}); });
@@ -1984,6 +2374,71 @@ suite.only('Transformer', function() {
}); });
}); });
test('centered scaling - no keep ratio', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
draggable: true,
fill: 'yellow'
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect,
centeredScaling: true,
keepRatio: false
});
layer.add(tr);
tests.forEach(function(test) {
rect.setAttrs({
x: 0,
y: 0,
width: 100,
height: 100,
scaleX: 1,
scaleY: 1
});
tr.update();
layer.draw();
stage.simulateMouseDown(test.startPos);
var target = stage.getIntersection(test.startPos);
var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({
target: target,
clientX: test.endPos.x,
clientY: test.endPos.y + top
});
// here is duplicate, because transformer is listening window events
tr._handleMouseUp({
clientX: test.endPos.x,
clientY: test.endPos.y + top
});
stage.simulateMouseUp({
x: test.endPos.x,
y: test.endPos.y
});
layer.draw();
assert.equal(
rect.width() * rect.scaleX(),
test.expectedWidth,
test.name + ' width check'
);
assert.equal(
rect.height() * rect.scaleY(),
test.expectedHeight,
test.name + ' height check'
);
});
});
test('centered scaling', function() { test('centered scaling', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
@@ -2048,7 +2503,7 @@ suite.only('Transformer', function() {
}); });
}); });
test.skip('centered scaling on flip', function() { test.only('centered scaling on flip + keep ratio', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
stage.add(layer); stage.add(layer);
@@ -2062,14 +2517,14 @@ suite.only('Transformer', function() {
var tr = new Konva.Transformer({ var tr = new Konva.Transformer({
node: rect, node: rect,
centeredScaling: true, centeredScaling: true,
keepRatio: false keepRatio: true
}); });
layer.add(tr); layer.add(tr);
rect.setAttrs({ rect.setAttrs({
x: 0, x: 0,
y: 0, y: 0,
width: 100, width: 200,
height: 100, height: 100,
scaleX: 1, scaleX: 1,
scaleY: 1 scaleY: 1
@@ -2078,39 +2533,36 @@ suite.only('Transformer', function() {
layer.draw(); layer.draw();
// stage.simulateMouseDown({x: 0, y: 0}); tr.simulateMouseDown({
x: 0,
y: 0
});
tr.simulateMouseMove({
x: 200,
y: 0
});
assert.equal(isClose(rect.x(), 200), true);
assert.equal(isClose(rect.y(), 0), true);
assert.equal(rect.width(), 200);
assert.equal(Math.round(rect.scaleY()), 1);
assert.equal(Math.round(rect.scaleX()), -1);
assert.equal(rect.height(), 100);
var target = stage.getIntersection({ x: 0, y: 0 }); tr.simulateMouseMove({
var top = stage.content.getBoundingClientRect().top; x: 200,
throw 11; y: 0
debugger;
tr._handleMouseMove({
target: target,
clientX: 100,
clientY: 0 + top
}); });
console.log(rect.width() * rect.scaleX()); tr.simulateMouseUp({
tr._handleMouseMove({ x: 0,
target: target,
clientX: 100,
clientY: 0 + top
});
console.log(rect.width() * rect.scaleX());
// here is duplicate, because transformer is listening window events
tr._handleMouseUp({
clientX: 100,
clientY: 0 + top
});
stage.simulateMouseUp({
x: 100,
y: 0 y: 0
}); });
layer.draw(); layer.draw();
assert.equal(isClose(rect.x(), 200), true);
assert.equal(rect.width() * rect.scaleX(), -100); assert.equal(isClose(rect.y(), 0), true);
assert.equal(rect.height() * rect.scaleY(), -100); assert.equal(rect.width(), 200);
assert.equal(Math.round(rect.scaleY()), -1);
throw 1; assert.equal(Math.round(rect.scaleX()), 1);
assert.equal(rect.height(), 100);
}); });
test('transform scaled (in one direction) node', function() { test('transform scaled (in one direction) node', function() {
@@ -2149,7 +2601,6 @@ suite.only('Transformer', function() {
}); });
var top = Math.round(stage.content.getBoundingClientRect().top); var top = Math.round(stage.content.getBoundingClientRect().top);
tr._handleMouseMove({ tr._handleMouseMove({
target: target,
clientX: 100, clientX: 100,
clientY: 100 + top clientY: 100 + top
}); });
@@ -2800,7 +3251,6 @@ suite.only('Transformer', function() {
}); });
var top = stage.content.getBoundingClientRect().top; var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({ tr._handleMouseMove({
target: target,
clientX: 100, clientX: 100,
clientY: 50 + top clientY: 50 + top
}); });