mirror of
https://github.com/konvajs/konva.git
synced 2025-06-28 15:23:44 +08:00
Merge branch 'master' into fix-unscalable-strokes
This commit is contained in:
commit
1bcea51047
@ -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
2
konva.d.ts
vendored
@ -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
125
konva.js
@ -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
6
konva.min.js
vendored
File diff suppressed because one or more lines are too long
21
package.json
21
package.json
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
10
src/Stage.js
10
src/Stage.js
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
@ -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);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -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');
|
||||||
});
|
});
|
||||||
|
|
||||||
// ======================================================
|
// ======================================================
|
||||||
|
@ -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();'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -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'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -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
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user