Merge branch 'master' into fix-unscalable-strokes

This commit is contained in:
MaxGraey 2018-04-11 14:31:43 +03:00
commit 1bcea51047
17 changed files with 419 additions and 132 deletions

View File

@ -13,10 +13,14 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Changes ## Changes
* Fixed flow for `contextmenu` event. Not it will be triggered on shapes too * Fixed flow for `contextmenu` event. Not it will be triggered on shapes too
* `find()` method for Containers can use a function as a parameter
## Fixed ## Fixed
* some bugs fixes for `group.getClientRect()` * some bugs fixes for `group.getClientRect()`
* `Konva.Arrow` will not draw dash for pointers
* setAttr will trigger change event if new value is the same Object
* better behavior of `dblclick` event when you click fast on different shapes
## [2.0.2][2018-03-15] ## [2.0.2][2018-03-15]

2
konva.d.ts vendored
View File

@ -343,7 +343,7 @@ declare namespace Konva {
clipFunc(ctx: CanvasRenderingContext2D | undefined | null): void; clipFunc(ctx: CanvasRenderingContext2D | undefined | null): void;
destroyChildren(): void; destroyChildren(): void;
find(selector?: string | ((Node) => boolean)): Collection; find(selector?: string | ((Node) => boolean)): Collection;
findOne<T extends Node>(selector: string): T; findOne<T extends Node>(selector: string | ((Node) => boolean)): T;
getAllIntersections(pos: Vector2d): Shape[]; getAllIntersections(pos: Vector2d): Shape[];
hasChildren(): boolean; hasChildren(): boolean;
removeChildren(): void; removeChildren(): void;

125
konva.js
View File

@ -2,7 +2,7 @@
* Konva JavaScript Framework v2.0.2 * Konva JavaScript Framework v2.0.2
* http://konvajs.github.io/ * http://konvajs.github.io/
* Licensed under the MIT * Licensed under the MIT
* Date: Sun Mar 25 2018 * Date: Wed Apr 11 2018
* *
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS) * Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva) * Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@ -352,7 +352,10 @@
*/ */
/** /**
* Transform constructor * Transform constructor. Transform object is a private class of Konva framework.
* In most of the cases you don't need to use it in your app.
* But there is a documentation for that class in case you still want
* to make some manual calculations.
* @constructor * @constructor
* @param {Array} [m] Optional six-element matrix * @param {Array} [m] Optional six-element matrix
* @memberof Konva * @memberof Konva
@ -732,6 +735,10 @@
_isString: function(obj) { _isString: function(obj) {
return Object.prototype.toString.call(obj) === OBJECT_STRING; return Object.prototype.toString.call(obj) === OBJECT_STRING;
}, },
// arrays are objects too
isObject: function(val) {
return val instanceof Object;
},
isValidSelector: function(selector) { isValidSelector: function(selector) {
if (typeof selector !== 'string') { if (typeof selector !== 'string') {
return false; return false;
@ -4253,7 +4260,8 @@
_setAttr: function(key, val) { _setAttr: function(key, val) {
var oldVal; var oldVal;
oldVal = this.attrs[key]; oldVal = this.attrs[key];
if (oldVal === val) { var same = oldVal === val;
if (same && !Konva.Util.isObject(val)) {
return; return;
} }
if (val === undefined || val === null) { if (val === undefined || val === null) {
@ -7811,31 +7819,42 @@
* }); * });
*/ */
find: function(selector) { find: function(selector) {
var retArr = []; // protecting _generalFind to prevent user from accidentally adding
// second argument and getting unexpected `findOne` result
if (typeof selector === 'string') { return this._generalFind(selector, false);
retArr = this._findByString(selector);
} else if (typeof selector === 'function') {
retArr = this._findByFunction(selector);
}
return Konva.Collection.toCollection(retArr);
}, },
/** /**
* return a first node from `find` method * return a first node from `find` method
* @method * @method
* @memberof Konva.Container.prototype * @memberof Konva.Container.prototype
* @param {String} selector * @param {String | Function} selector
* @returns {Konva.Node} * @returns {Konva.Node | Undefined}
* @example * @example
* // select node with id foo * // select node with id foo
* var node = stage.findOne('#foo'); * var node = stage.findOne('#foo');
* *
* // select node with name bar inside layer * // select node with name bar inside layer
* var nodes = layer.findOne('.bar'); * var nodes = layer.findOne('.bar');
*
* // select the first node to return true in a function
* var node = stage.findOne(node => {
* return node.getType() === 'Shape'
* })
*/ */
findOne: function(selector) { findOne: function(selector) {
return this.find(selector)[0]; var result = this._generalFind(selector, true);
return result.length > 0 ? result[0] : undefined;
},
_generalFind: function(selector, findOne) {
var retArr = [];
if (typeof selector === 'string') {
retArr = this._findByString(selector, findOne);
} else if (typeof selector === 'function') {
retArr = this._findByFunction(selector, findOne);
}
return Konva.Collection.toCollection(retArr);
}, },
_findByString: function(selector) { _findByString: function(selector) {
var retArr = [], var retArr = [],
@ -7884,10 +7903,16 @@
return retArr; return retArr;
}, },
_findByFunction: function(fn) { // (fn: ((Node) => boolean, findOne?: boolean)
_findByFunction: function(fn, findOne) {
var retArr = []; var retArr = [];
var addItems = function(el) { var addItems = function(el) {
// escape function if we've already found one.
if (findOne && retArr.length > 0) {
return;
}
var children = el.getChildren(); var children = el.getChildren();
var clen = children.length; var clen = children.length;
@ -10631,7 +10656,8 @@
if (Konva.inDblClickWindow) { if (Konva.inDblClickWindow) {
fireDblClick = true; fireDblClick = true;
Konva.inDblClickWindow = false; clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else if (!dd || !dd.justDragged) { } else if (!dd || !dd.justDragged) {
// don't set inDblClickWindow after dragging // don't set inDblClickWindow after dragging
Konva.inDblClickWindow = true; Konva.inDblClickWindow = true;
@ -10639,7 +10665,7 @@
dd.justDragged = false; dd.justDragged = false;
} }
setTimeout(function() { this.dblTimeout = setTimeout(function() {
Konva.inDblClickWindow = false; Konva.inDblClickWindow = false;
}, Konva.dblClickWindow); }, Konva.dblClickWindow);
@ -10738,12 +10764,13 @@
if (Konva.inDblClickWindow) { if (Konva.inDblClickWindow) {
fireDblClick = true; fireDblClick = true;
Konva.inDblClickWindow = false; clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else { } else {
Konva.inDblClickWindow = true; Konva.inDblClickWindow = true;
} }
setTimeout(function() { this.dblTimeout = setTimeout(function() {
Konva.inDblClickWindow = false; Konva.inDblClickWindow = false;
}, Konva.dblClickWindow); }, Konva.dblClickWindow);
@ -14755,14 +14782,6 @@
context.closePath(); context.closePath();
context.fillStrokeShape(this); context.fillStrokeShape(this);
}, },
// _useBufferCanvas: function(caching) {
// var useIt = Konva.Shape.prototype._useBufferCanvas.call(this, caching);
// if (useIt) {
// return true;
// }
// return false;
// // return isFirefox && this.hasFill() && this.hasShadow();
// },
setText: function(text) { setText: function(text) {
var str = Konva.Util._isString(text) ? text : (text || '').toString(); var str = Konva.Util._isString(text) ? text : (text || '').toString();
this._setAttr(TEXT, str); this._setAttr(TEXT, str);
@ -18521,7 +18540,24 @@
ctx.closePath(); ctx.closePath();
ctx.restore(); ctx.restore();
} }
// here is a tricky part
// we need to disable dash for arrow pointers
var isDashEnabled = this.dashEnabled();
if (isDashEnabled) {
// manually disable dash for head
// it is better not to use setter here,
// because it will trigger attr change event
this.attrs.dashEnabled = false;
ctx.setLineDash([]);
}
ctx.fillStrokeShape(this); ctx.fillStrokeShape(this);
// restore old value
if (isDashEnabled) {
this.attrs.dashEnabled = true;
}
} }
}; };
@ -19159,31 +19195,32 @@
} }
}, },
_fitNodeInto: function(attrs) { _fitNodeInto: function(newAttrs) {
// waring! in this attrs padding may be included // waring! in this attrs padding may be included
var boundBoxFunc = this.getBoundBoxFunc();
if (boundBoxFunc) {
var oldAttrs = this._getNodeRect();
newAttrs = boundBoxFunc.call(this, oldAttrs, newAttrs);
}
this._settings = true; this._settings = true;
var node = this.getNode(); var node = this.getNode();
if (attrs.rotation !== undefined) { if (newAttrs.rotation !== undefined) {
this.getNode().rotation(attrs.rotation); this.getNode().rotation(newAttrs.rotation);
} }
var pure = node.getClientRect({ skipTransform: true }); var pure = node.getClientRect({ skipTransform: true });
var padding = this.getPadding(); var padding = this.getPadding();
var scaleX = (attrs.width - padding * 2) / pure.width; var scaleX = (newAttrs.width - padding * 2) / pure.width;
var scaleY = (attrs.height - padding * 2) / pure.height; var scaleY = (newAttrs.height - padding * 2) / pure.height;
var rotation = Konva.getAngle(node.getRotation()); var rotation = Konva.getAngle(node.getRotation());
// debugger;
var dx = pure.x * scaleX - padding; var dx = pure.x * scaleX - padding;
var dy = pure.y * scaleY - padding; var dy = pure.y * scaleY - padding;
// var dxo = node.offsetX() * scaleX;
// var dyo = node.offsetY() * scaleY;
this.getNode().setAttrs({ this.getNode().setAttrs({
scaleX: scaleX, scaleX: scaleX,
scaleY: scaleY, scaleY: scaleY,
x: attrs.x - (dx * Math.cos(rotation) + dy * Math.sin(-rotation)), x: newAttrs.x - (dx * Math.cos(rotation) + dy * Math.sin(-rotation)),
y: attrs.y - (dy * Math.cos(rotation) + dx * Math.sin(rotation)) y: newAttrs.y - (dy * Math.cos(rotation) + dx * Math.sin(rotation))
}); });
this._settings = false; this._settings = false;
@ -19276,6 +19313,14 @@
visible: this.lineEnabled() visible: this.lineEnabled()
}); });
}, },
isTransforming: function() {
return this._transforming;
},
stopTransform: function() {
if (this._transforming) {
this._removeEvents();
}
},
destroy: function() { destroy: function() {
Konva.Group.prototype.destroy.call(this); Konva.Group.prototype.destroy.call(this);
this.detach(); this.detach();
@ -19443,5 +19488,7 @@
Konva.Factory.addOverloadedGetterSetter(Konva.Transformer, 'node'); Konva.Factory.addOverloadedGetterSetter(Konva.Transformer, 'node');
Konva.Factory.addGetterSetter(Konva.Transformer, 'boundBoxFunc');
Konva.Collection.mapMethods(Konva.Transformer); Konva.Collection.mapMethods(Konva.Transformer);
})(Konva); })(Konva);

6
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -2,13 +2,7 @@
"name": "konva", "name": "konva",
"version": "2.0.2", "version": "2.0.2",
"author": "Anton Lavrenov", "author": "Anton Lavrenov",
"files": [ "files": ["README.md", "konva.js", "konva.min.js", "src", "konva.d.ts"],
"README.md",
"konva.js",
"konva.min.js",
"src",
"konva.d.ts"
],
"main": "konva.js", "main": "konva.js",
"typings": "./konva.d.ts", "typings": "./konva.d.ts",
"scripts": { "scripts": {
@ -17,7 +11,8 @@
"build": "gulp build", "build": "gulp build",
"full-build": "gulp lint test build", "full-build": "gulp lint test build",
"test": "gulp test", "test": "gulp test",
"prettier": "prettier --write \"src/**/*.js\" \"test/**/*.js\" --single-quote" "prettier":
"prettier --write \"src/**/*.js\" \"test/**/*.js\" --single-quote"
}, },
"devDependencies": { "devDependencies": {
"chai": "4.1.2", "chai": "4.1.2",
@ -35,12 +30,10 @@
"mocha": "4.0.1", "mocha": "4.0.1",
"prettier": "^1.9.2" "prettier": "^1.9.2"
}, },
"keywords": [ "keywords": ["canvas", "animations", "graphic", "html5"],
"canvas", "prettier": {
"animations", "singleQuote": true
"graphic", },
"html5"
],
"browser": { "browser": {
"canvas": false, "canvas": false,
"jsdom": false "jsdom": false

View File

@ -181,31 +181,42 @@
* }); * });
*/ */
find: function(selector) { find: function(selector) {
var retArr = []; // protecting _generalFind to prevent user from accidentally adding
// second argument and getting unexpected `findOne` result
if (typeof selector === 'string') { return this._generalFind(selector, false);
retArr = this._findByString(selector);
} else if (typeof selector === 'function') {
retArr = this._findByFunction(selector);
}
return Konva.Collection.toCollection(retArr);
}, },
/** /**
* return a first node from `find` method * return a first node from `find` method
* @method * @method
* @memberof Konva.Container.prototype * @memberof Konva.Container.prototype
* @param {String} selector * @param {String | Function} selector
* @returns {Konva.Node} * @returns {Konva.Node | Undefined}
* @example * @example
* // select node with id foo * // select node with id foo
* var node = stage.findOne('#foo'); * var node = stage.findOne('#foo');
* *
* // select node with name bar inside layer * // select node with name bar inside layer
* var nodes = layer.findOne('.bar'); * var nodes = layer.findOne('.bar');
*
* // select the first node to return true in a function
* var node = stage.findOne(node => {
* return node.getType() === 'Shape'
* })
*/ */
findOne: function(selector) { findOne: function(selector) {
return this.find(selector)[0]; var result = this._generalFind(selector, true);
return result.length > 0 ? result[0] : undefined;
},
_generalFind: function(selector, findOne) {
var retArr = [];
if (typeof selector === 'string') {
retArr = this._findByString(selector, findOne);
} else if (typeof selector === 'function') {
retArr = this._findByFunction(selector, findOne);
}
return Konva.Collection.toCollection(retArr);
}, },
_findByString: function(selector) { _findByString: function(selector) {
var retArr = [], var retArr = [],
@ -254,10 +265,16 @@
return retArr; return retArr;
}, },
_findByFunction: function(fn) { // (fn: ((Node) => boolean, findOne?: boolean)
_findByFunction: function(fn, findOne) {
var retArr = []; var retArr = [];
var addItems = function(el) { var addItems = function(el) {
// escape function if we've already found one.
if (findOne && retArr.length > 0) {
return;
}
var children = el.getChildren(); var children = el.getChildren();
var clen = children.length; var clen = children.length;

View File

@ -1879,7 +1879,8 @@
_setAttr: function(key, val) { _setAttr: function(key, val) {
var oldVal; var oldVal;
oldVal = this.attrs[key]; oldVal = this.attrs[key];
if (oldVal === val) { var same = oldVal === val;
if (same && !Konva.Util.isObject(val)) {
return; return;
} }
if (val === undefined || val === null) { if (val === undefined || val === null) {

View File

@ -550,7 +550,8 @@
if (Konva.inDblClickWindow) { if (Konva.inDblClickWindow) {
fireDblClick = true; fireDblClick = true;
Konva.inDblClickWindow = false; clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else if (!dd || !dd.justDragged) { } else if (!dd || !dd.justDragged) {
// don't set inDblClickWindow after dragging // don't set inDblClickWindow after dragging
Konva.inDblClickWindow = true; Konva.inDblClickWindow = true;
@ -558,7 +559,7 @@
dd.justDragged = false; dd.justDragged = false;
} }
setTimeout(function() { this.dblTimeout = setTimeout(function() {
Konva.inDblClickWindow = false; Konva.inDblClickWindow = false;
}, Konva.dblClickWindow); }, Konva.dblClickWindow);
@ -657,12 +658,13 @@
if (Konva.inDblClickWindow) { if (Konva.inDblClickWindow) {
fireDblClick = true; fireDblClick = true;
Konva.inDblClickWindow = false; clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else { } else {
Konva.inDblClickWindow = true; Konva.inDblClickWindow = true;
} }
setTimeout(function() { this.dblTimeout = setTimeout(function() {
Konva.inDblClickWindow = false; Konva.inDblClickWindow = false;
}, Konva.dblClickWindow); }, Konva.dblClickWindow);

View File

@ -107,7 +107,10 @@
*/ */
/** /**
* Transform constructor * Transform constructor. Transform object is a private class of Konva framework.
* In most of the cases you don't need to use it in your app.
* But there is a documentation for that class in case you still want
* to make some manual calculations.
* @constructor * @constructor
* @param {Array} [m] Optional six-element matrix * @param {Array} [m] Optional six-element matrix
* @memberof Konva * @memberof Konva
@ -487,6 +490,10 @@
_isString: function(obj) { _isString: function(obj) {
return Object.prototype.toString.call(obj) === OBJECT_STRING; return Object.prototype.toString.call(obj) === OBJECT_STRING;
}, },
// arrays are objects too
isObject: function(val) {
return val instanceof Object;
},
isValidSelector: function(selector) { isValidSelector: function(selector) {
if (typeof selector !== 'string') { if (typeof selector !== 'string') {
return false; return false;

View File

@ -66,7 +66,24 @@
ctx.closePath(); ctx.closePath();
ctx.restore(); ctx.restore();
} }
// here is a tricky part
// we need to disable dash for arrow pointers
var isDashEnabled = this.dashEnabled();
if (isDashEnabled) {
// manually disable dash for head
// it is better not to use setter here,
// because it will trigger attr change event
this.attrs.dashEnabled = false;
ctx.setLineDash([]);
}
ctx.fillStrokeShape(this); ctx.fillStrokeShape(this);
// restore old value
if (isDashEnabled) {
this.attrs.dashEnabled = true;
}
} }
}; };

View File

@ -222,14 +222,6 @@
context.closePath(); context.closePath();
context.fillStrokeShape(this); context.fillStrokeShape(this);
}, },
// _useBufferCanvas: function(caching) {
// var useIt = Konva.Shape.prototype._useBufferCanvas.call(this, caching);
// if (useIt) {
// return true;
// }
// return false;
// // return isFirefox && this.hasFill() && this.hasShadow();
// },
setText: function(text) { setText: function(text) {
var str = Konva.Util._isString(text) ? text : (text || '').toString(); var str = Konva.Util._isString(text) ? text : (text || '').toString();
this._setAttr(TEXT, str); this._setAttr(TEXT, str);

View File

@ -552,31 +552,32 @@
} }
}, },
_fitNodeInto: function(attrs) { _fitNodeInto: function(newAttrs) {
// waring! in this attrs padding may be included // waring! in this attrs padding may be included
var boundBoxFunc = this.getBoundBoxFunc();
if (boundBoxFunc) {
var oldAttrs = this._getNodeRect();
newAttrs = boundBoxFunc.call(this, oldAttrs, newAttrs);
}
this._settings = true; this._settings = true;
var node = this.getNode(); var node = this.getNode();
if (attrs.rotation !== undefined) { if (newAttrs.rotation !== undefined) {
this.getNode().rotation(attrs.rotation); this.getNode().rotation(newAttrs.rotation);
} }
var pure = node.getClientRect({ skipTransform: true }); var pure = node.getClientRect({ skipTransform: true });
var padding = this.getPadding(); var padding = this.getPadding();
var scaleX = (attrs.width - padding * 2) / pure.width; var scaleX = (newAttrs.width - padding * 2) / pure.width;
var scaleY = (attrs.height - padding * 2) / pure.height; var scaleY = (newAttrs.height - padding * 2) / pure.height;
var rotation = Konva.getAngle(node.getRotation()); var rotation = Konva.getAngle(node.getRotation());
// debugger;
var dx = pure.x * scaleX - padding; var dx = pure.x * scaleX - padding;
var dy = pure.y * scaleY - padding; var dy = pure.y * scaleY - padding;
// var dxo = node.offsetX() * scaleX;
// var dyo = node.offsetY() * scaleY;
this.getNode().setAttrs({ this.getNode().setAttrs({
scaleX: scaleX, scaleX: scaleX,
scaleY: scaleY, scaleY: scaleY,
x: attrs.x - (dx * Math.cos(rotation) + dy * Math.sin(-rotation)), x: newAttrs.x - (dx * Math.cos(rotation) + dy * Math.sin(-rotation)),
y: attrs.y - (dy * Math.cos(rotation) + dx * Math.sin(rotation)) y: newAttrs.y - (dy * Math.cos(rotation) + dx * Math.sin(rotation))
}); });
this._settings = false; this._settings = false;
@ -669,6 +670,14 @@
visible: this.lineEnabled() visible: this.lineEnabled()
}); });
}, },
isTransforming: function() {
return this._transforming;
},
stopTransform: function() {
if (this._transforming) {
this._removeEvents();
}
},
destroy: function() { destroy: function() {
Konva.Group.prototype.destroy.call(this); Konva.Group.prototype.destroy.call(this);
this.detach(); this.detach();
@ -836,5 +845,7 @@
Konva.Factory.addOverloadedGetterSetter(Konva.Transformer, 'node'); Konva.Factory.addOverloadedGetterSetter(Konva.Transformer, 'node');
Konva.Factory.addGetterSetter(Konva.Transformer, 'boundBoxFunc');
Konva.Collection.mapMethods(Konva.Transformer); Konva.Collection.mapMethods(Konva.Transformer);
})(Konva); })(Konva);

View File

@ -392,9 +392,7 @@ suite('MouseEvents', function() {
}); });
// ====================================================== // ======================================================
test('modify fill stroke and stroke width on hover with circle', function( test('modify fill stroke and stroke width on hover with circle', function(done) {
done
) {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer({ var layer = new Konva.Layer({
throttle: 999 throttle: 999
@ -464,9 +462,7 @@ suite('MouseEvents', function() {
}); });
// ====================================================== // ======================================================
test('mousedown mouseup mouseover mouseout mousemove click dblclick', function( test('mousedown mouseup mouseover mouseout mousemove click dblclick', function(done) {
done
) {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
var circle = new Konva.Circle({ var circle = new Konva.Circle({
@ -1191,14 +1187,14 @@ suite('MouseEvents', function() {
var group22 = new Konva.Group({ name: 'group22' }); var group22 = new Konva.Group({ name: 'group22' });
group21.add(group22); group21.add(group22);
var smallRect = new Konva.Rect({ var smallShape = new Konva.Rect({
x: 50, x: 50,
y: 50, y: 50,
width: 100, width: 100,
height: 100, height: 100,
fill: 'red' fill: 'red'
}); });
group22.add(smallRect); group22.add(smallShape);
stage.draw(); stage.draw();
var group1Mouseenter = 0; var group1Mouseenter = 0;
@ -1311,7 +1307,7 @@ suite('MouseEvents', function() {
}); });
// ====================================================== // ======================================================
test('test dblclick to a wrong target', function () { test('test dblclick to a wrong target', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer(); var layer = new Konva.Layer();
stage.add(layer); stage.add(layer);
@ -1340,13 +1336,13 @@ suite('MouseEvents', function() {
var rightRectSingleClick = 0; var rightRectSingleClick = 0;
var rightRectDblClick = 0; var rightRectDblClick = 0;
leftRect.on('click', function () { leftRect.on('click', function() {
leftRectSingleClick++; leftRectSingleClick++;
}); });
rightRect.on('click', function () { rightRect.on('click', function() {
rightRectSingleClick++; rightRectSingleClick++;
}); });
rightRect.on('dblclick', function () { rightRect.on('dblclick', function() {
rightRectDblClick++; rightRectDblClick++;
}); });
@ -1369,11 +1365,7 @@ suite('MouseEvents', function() {
y: 50 y: 50
}); });
assert.equal(rightRectSingleClick, 1, 'rightRect trigger a click'); assert.equal(rightRectSingleClick, 1, 'rightRect trigger a click');
assert.equal( assert.equal(rightRectDblClick, 0, 'rightRect dblClick should not trigger');
rightRectDblClick,
0,
'rightRect dblClick should not trigger'
);
}); });
// ====================================================== // ======================================================
@ -1701,7 +1693,10 @@ suite('MouseEvents', function() {
context.fillStrokeShape(this); context.fillStrokeShape(this);
}); });
layer.getHitCanvas().getContext().clear(); layer
.getHitCanvas()
.getContext()
.clear();
layer.drawHit(); layer.drawHit();
setTimeout(function() { setTimeout(function() {
@ -1787,4 +1782,89 @@ suite('MouseEvents', function() {
}); });
assert.equal(shape, circle); assert.equal(shape, circle);
}); });
it('double click after click should trigger event', function(done) {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var bigRect = new Konva.Rect({
x: 0,
y: 0,
width: 200,
height: 200,
fill: 'yellow'
});
layer.add(bigRect);
var smallShape = new Konva.Circle({
x: 100,
y: 100,
width: 100,
fill: 'red'
});
layer.add(smallShape);
layer.draw();
var bigClicks = 0;
var smallClicks = 0;
var smallDblClicks = 0;
bigRect.on('click', function() {
bigClicks += 1;
});
smallShape.on('click', function() {
smallClicks += 1;
});
smallShape.on('dblclick', function() {
smallDblClicks += 1;
});
stage.simulateMouseDown({
x: 10,
y: 10
});
stage.simulateMouseUp({
x: 10,
y: 10
});
assert.equal(bigClicks, 1, 'single click on big rect');
assert.equal(smallClicks, 0, 'no click on small rect');
assert.equal(smallDblClicks, 0, 'no dblclick on small rect');
setTimeout(function() {
stage.simulateMouseDown({
x: 100,
y: 100
});
stage.simulateMouseUp({
x: 100,
y: 100
});
assert.equal(bigClicks, 1, 'single click on big rect');
assert.equal(smallClicks, 1, 'single click on small rect');
assert.equal(smallDblClicks, 0, 'no dblclick on small rect');
setTimeout(function() {
stage.simulateMouseDown({
x: 100,
y: 100
});
stage.simulateMouseUp({
x: 100,
y: 100
});
assert.equal(bigClicks, 1, 'single click on big rect');
assert.equal(smallClicks, 2, 'second click on small rect');
assert.equal(smallDblClicks, 1, 'single dblclick on small rect');
done();
}, 200);
}, 200);
});
}); });

View File

@ -291,7 +291,7 @@ suite('Container', function() {
}); });
// ====================================================== // ======================================================
test('select shape by id and name with findOne', function() { test('select shape with findOne', function() {
var stage = addStage(); var stage = addStage();
var layer = new Konva.Layer({ var layer = new Konva.Layer({
id: 'myLayer' id: 'myLayer'
@ -330,6 +330,10 @@ suite('Container', function() {
assert.equal(node, undefined, 'node should be undefined'); assert.equal(node, undefined, 'node should be undefined');
node = stage.findOne('#myLayer'); node = stage.findOne('#myLayer');
assert.equal(node, layer, 'node type should be Layer'); assert.equal(node, layer, 'node type should be Layer');
node = stage.findOne(function(node) {
return node.getType() === 'Shape';
});
assert.equal(node, circle, 'findOne should work with functions');
}); });
// ====================================================== // ======================================================

View File

@ -35,4 +35,31 @@ suite('Arrow', function() {
layer.draw(); layer.draw();
showHit(layer); showHit(layer);
}); });
test('do not draw dash for head', function() {
var stage = addStage();
var layer = new Konva.Layer();
var arrow = new Konva.Arrow({
points: [50, 50, 100, 100],
stroke: 'red',
fill: 'blue',
strokeWidth: 5,
pointerWidth: 20,
pointerLength: 20,
dash: [5, 5]
});
layer.add(arrow);
stage.add(layer);
var trace = layer.getContext().getTrace();
// console.log(trace);
assert.equal(
trace,
'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(50,50);lineTo(100,100);setLineDash(5,5);lineDashOffset=0;lineWidth=5;strokeStyle=red;stroke();save();beginPath();translate(100,100);rotate(0.785);moveTo(0,0);lineTo(-20,10);lineTo(-20,-10);closePath();restore();setLineDash();fillStyle=blue;fill();lineWidth=5;strokeStyle=red;stroke();restore();'
);
});
}); });

View File

@ -309,4 +309,34 @@ suite('Line', function() {
layer2.hide(); layer2.hide();
compareLayers(layer, layer2); compareLayers(layer, layer2);
}); });
test('updating points with old mutable array should trigger recalculations', function() {
var stage = addStage();
var layer = new Konva.Layer();
var points = [-25, 50, 250, -30, 150, 50];
var blob = new Konva.Line({
x: 50,
y: 50,
points: points,
stroke: 'blue',
strokeWidth: 10,
draggable: true,
closed: true,
tension: 1
});
var tensionPoints = blob.getTensionPoints();
points.push(250, 100);
blob.setPoints(points);
layer.add(blob);
stage.add(layer);
assert.equal(
tensionPoints === blob.getTensionPoints(),
false,
'calculated points should change'
);
});
}); });

View File

@ -991,4 +991,59 @@ suite('Transformer', function() {
}); });
assert.equal(stage.content.style.cursor, 'nwse-resize'); assert.equal(stage.content.style.cursor, 'nwse-resize');
}); });
test('stopTransform method', function() {
var stage = addStage();
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({
node: rect
});
layer.add(tr);
layer.draw();
stage.simulateMouseDown({
x: 50,
y: 50
});
var top = stage.content.getBoundingClientRect().top;
tr._handleMouseMove({
target: tr.findOne('.top-left'),
clientX: 60,
clientY: 60 + top
});
assert.equal(tr.isTransforming(), true);
assert.equal(rect.x(), 60);
var transformend = 0;
rect.on('transformend', function() {
transformend += 1;
});
tr.stopTransform();
assert.equal(transformend, 1);
assert.equal(tr.isTransforming(), false);
assert.equal(rect.x(), 60);
// here is duplicate, because transformer is listening window events
stage.simulateMouseUp({
x: 100,
y: 100
});
});
}); });