update CHANGELOG with new version

This commit is contained in:
Anton Lavrenov 2020-04-22 19:20:44 -05:00
parent 718531f50a
commit e7e2efe230
6 changed files with 1526 additions and 113 deletions

View File

@ -5,9 +5,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Not released: ## Not released:
* Fixes for `Konva.Transformer` when parent scale is changed
## 5.0.0 - 2020-03-26 ## 5.0.1 - 2020-04-22
* Fixes for `Konva.Transformer` when parent scale is changed
* Fixes for `Konva.Transformer` when parent is draggable
* Performance optimizations
## 5.0.0 - 2020-04-21
* **New `Konva.Transformer` implementation!**. Old API should work. But I mark this release is `major` (breaking) just for smooth updates. Changes: * **New `Konva.Transformer` implementation!**. Old API should work. But I mark this release is `major` (breaking) just for smooth updates. Changes:
* Support of transforming multiple nodes at once: `tr.nodes([shape1, shape2])`. * Support of transforming multiple nodes at once: `tr.nodes([shape1, shape2])`.

1465
konva.js

File diff suppressed because it is too large Load Diff

4
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -199,6 +199,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
_cache: Map<string, any> = new Map<string, any>(); _cache: Map<string, any> = new Map<string, any>();
_lastPos: Vector2d = null; _lastPos: Vector2d = null;
_attrsAffectingSize!: string[]; _attrsAffectingSize!: string[];
_batchingTransformChange = false;
_needClearTransformCache = false;
_filterUpToDate = false; _filterUpToDate = false;
_isUnderCache = false; _isUnderCache = false;
@ -212,14 +214,14 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
// event bindings for cache handling // event bindings for cache handling
this.on(TRANSFORM_CHANGE_STR, () => { this.on(TRANSFORM_CHANGE_STR, () => {
if (this._batchingTransformChange) {
this._needClearTransformCache = true;
return;
}
this._clearCache(TRANSFORM); this._clearCache(TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM); this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
}); });
this.on(SCALE_CHANGE_STR, () => {
this._clearSelfAndDescendantCache(ABSOLUTE_SCALE);
});
this.on('visibleChange.konva', () => { this.on('visibleChange.konva', () => {
this._clearSelfAndDescendantCache(VISIBLE); this._clearSelfAndDescendantCache(VISIBLE);
}); });
@ -268,8 +270,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
_clearSelfAndDescendantCache(attr?: string, forceEvent?: boolean) { _clearSelfAndDescendantCache(attr?: string, forceEvent?: boolean) {
this._clearCache(attr); this._clearCache(attr);
// trigger clear cache, so transformer can use it // trigger clear cache, so transformer can use it
if (forceEvent) { if (forceEvent && attr === ABSOLUTE_TRANSFORM) {
this.fire('clearCache'); this.fire('_clearTransformCache');
} }
// skip clearing if node is cached with canvas // skip clearing if node is cached with canvas
@ -1154,9 +1156,27 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
} }
return depth; return depth;
} }
// sometimes we do several attributes changes
// like node.position(pos)
// for performance reasons, lets batch transform reset
// so it work faster
_batchTransformChanges(func) {
this._batchingTransformChange = true;
func();
this._batchingTransformChange = false;
if (this._needClearTransformCache) {
this._clearCache(TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM, true);
}
this._needClearTransformCache = false;
}
setPosition(pos) { setPosition(pos) {
this.x(pos.x); this._batchTransformChanges(() => {
this.y(pos.y); this.x(pos.x);
this.y(pos.y);
});
return this; return this;
} }
getPosition() { getPosition() {
@ -1200,8 +1220,9 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
delete origTrans.x; delete origTrans.x;
delete origTrans.y; delete origTrans.y;
// unravel transform // important, use non cached value
it = this.getAbsoluteTransform(); this._clearCache(TRANSFORM);
it = this._getAbsoluteTransform();
it.invert(); it.invert();
it.translate(pos.x, pos.y); it.translate(pos.x, pos.y);
@ -1209,7 +1230,6 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
x: this.attrs.x + it.getTranslation().x, x: this.attrs.x + it.getTranslation().x,
y: this.attrs.y + it.getTranslation().y y: this.attrs.y + it.getTranslation().y
}; };
this._setTransform(origTrans); this._setTransform(origTrans);
this.setPosition({ x: pos.x, y: pos.y }); this.setPosition({ x: pos.x, y: pos.y });
@ -1221,9 +1241,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
for (key in trans) { for (key in trans) {
this.attrs[key] = trans[key]; this.attrs[key] = trans[key];
} }
// this._clearCache(TRANSFORM);
this._clearCache(TRANSFORM); // this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
} }
_clearTransform() { _clearTransform() {
var trans = { var trans = {
@ -1248,9 +1267,6 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
this.attrs.skewX = 0; this.attrs.skewX = 0;
this.attrs.skewY = 0; this.attrs.skewY = 0;
this._clearCache(TRANSFORM);
this._clearSelfAndDescendantCache(ABSOLUTE_TRANSFORM);
// return original transform // return original transform
return trans; return trans;
} }
@ -1730,15 +1746,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
* var scaleX = node.getAbsoluteScale().x; * var scaleX = node.getAbsoluteScale().x;
*/ */
getAbsoluteScale(top?) { getAbsoluteScale(top?) {
// if using an argument, we can't cache the result. // do not cache this calculations,
if (top) { // because it use cache transform
return this._getAbsoluteScale(top);
} else {
// if no argument, we can cache the result
return this._getCache(ABSOLUTE_SCALE, this._getAbsoluteScale);
}
}
_getAbsoluteScale(top) {
// this is special logic for caching with some shapes with shadow // this is special logic for caching with some shapes with shadow
var parent: Node = this; var parent: Node = this;
while (parent) { while (parent) {

View File

@ -395,7 +395,7 @@ export class Transformer extends Group {
}; };
node.on(additionalEvents, onChange); node.on(additionalEvents, onChange);
node.on(TRANSFORM_CHANGE_STR, onChange); node.on(TRANSFORM_CHANGE_STR, onChange);
node.on(`clearCache.${EVENTS_NAME}`, onChange); node.on(`_clearTransformCache.${EVENTS_NAME}`, onChange);
node.on(`xChange.${EVENTS_NAME} yChange.${EVENTS_NAME}`, onChange); node.on(`xChange.${EVENTS_NAME} yChange.${EVENTS_NAME}`, onChange);
this._proxyDrag(node); this._proxyDrag(node);
}); });
@ -559,13 +559,22 @@ export class Transformer extends Group {
strokeWidth: 1, strokeWidth: 1,
name: name + ' _anchor', name: name + ' _anchor',
dragDistance: 0, dragDistance: 0,
draggable: false, // make it draggable,
// so activating the anchror will not start drag&drop of any parent
draggable: true,
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', e => {
anchor.stopDrag();
e.cancelBubble = true;
});
anchor.on('dragend', e => {
e.cancelBubble = true;
});
// add hover styling // add hover styling
anchor.on('mouseenter', () => { anchor.on('mouseenter', () => {

View File

@ -238,6 +238,76 @@ suite('Transformer', function() {
layer.draw(); layer.draw();
}); });
test('try to resize on draggable stage', function() {
var stage = addStage();
stage.draggable(true);
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 50,
draggable: true,
width: 100,
height: 100,
fill: 'yellow'
});
layer.add(rect);
var tr = new Konva.Transformer({
nodes: [rect]
});
layer.add(tr);
layer.draw();
var dragstart = 0;
var dragmove = 0;
var dragend = 0;
stage.on('dragstart', function() {
dragstart += 1;
});
stage.on('dragmove', function() {
dragmove += 1;
});
stage.on('dragend', function() {
dragend += 1;
});
tr.simulateMouseDown({
x: 50,
y: 50
});
tr.simulateMouseMove({
x: 60,
y: 60
});
assert.equal(stage.isDragging(), false);
assert.equal(dragstart, 0);
tr.simulateMouseUp({ x: 60, y: 60 });
assert.equal(dragmove, 0);
assert.equal(dragend, 0);
stage.simulateMouseDown({
x: 40,
y: 40
});
stage.simulateMouseMove({
x: 45,
y: 45
});
stage.simulateMouseMove({
x: 50,
y: 50
});
assert.equal(stage.isDragging(), true);
assert.equal(stage.x(), 10);
assert.equal(stage.y(), 10);
stage.simulateMouseUp({
x: 45,
y: 45
});
});
test('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();
@ -1748,16 +1818,16 @@ suite('Transformer', function() {
y: 30 y: 30
}); });
stage.simulateMouseUp({
x: 30,
y: 30
});
assert.equal(rect.x(), 10); assert.equal(rect.x(), 10);
assert.equal(rect.y(), 10); assert.equal(rect.y(), 10);
assert.equal(tr.x(), 10); assert.equal(tr.x(), 10);
assert.equal(tr.y(), 10); assert.equal(tr.y(), 10);
stage.simulateMouseUp({
x: 30,
y: 30
});
}); });
test('check transformer with drag&drop and scaled shape', function() { test('check transformer with drag&drop and scaled shape', function() {
@ -1995,9 +2065,9 @@ suite('Transformer', function() {
layer.scaleX(2); layer.scaleX(2);
assert.equal(tr.width(), 200);
layer.draw(); layer.draw();
assert.equal(tr.width(), 200);
}); });
test('check fit and correct cursor on rotated parent', function() { test('check fit and correct cursor on rotated parent', function() {
@ -2649,7 +2719,6 @@ suite('Transformer', function() {
}); });
}); });
// TODO: fix
test('centered scaling on flip + keep ratio', function() { test('centered scaling on flip + keep ratio', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
@ -2704,6 +2773,8 @@ suite('Transformer', function() {
}); });
layer.draw(); layer.draw();
console.log(start, end);
// move from start to end // move from start to end
tr.simulateMouseDown(start); tr.simulateMouseDown(start);
tr.simulateMouseMove(end); tr.simulateMouseMove(end);