Added null checks and types

This commit is contained in:
razw22 2023-07-17 15:14:30 +00:00
parent 6abd79c861
commit 7a85356a2a
16 changed files with 155 additions and 393 deletions

View File

@ -112,7 +112,7 @@ export class Animation {
const len = animations.length const len = animations.length
for (let n = 0; n < len; n++) { for (let n = 0; n < len; n++) {
if (animations[n].id === this.id) { if (animations[n]['id'] === this.id) {
return true; return true;
} }
} }

View File

@ -25,7 +25,6 @@ export interface ContainerConfig extends NodeConfig {
* @constructor * @constructor
* @memberof Konva * @memberof Konva
* @augments Konva.Node * @augments Konva.Node
* @abstract
* @param {Object} config * @param {Object} config
* @@nodeParams * @@nodeParams
* @@containerParams * @@containerParams
@ -313,7 +312,7 @@ export abstract class Container<
* @returns {Array} array of shapes * @returns {Array} array of shapes
*/ */
getAllIntersections(pos) { getAllIntersections(pos) {
var arr = []; var arr: Array<any> = [];
this.find('Shape').forEach(function (shape: Shape) { this.find('Shape').forEach(function (shape: Shape) {
if (shape.isVisible() && shape.intersects(pos)) { if (shape.isVisible() && shape.intersects(pos)) {
@ -343,7 +342,7 @@ export abstract class Container<
drawScene(can?: SceneCanvas, top?: Node) { drawScene(can?: SceneCanvas, top?: Node) {
var layer = this.getLayer(), var layer = this.getLayer(),
canvas = can || (layer && layer.getCanvas()), canvas = can || (layer && layer.getCanvas()),
context = canvas && canvas.getContext(), context = canvas! && canvas.getContext()!,
cachedCanvas = this._getCanvasCache(), cachedCanvas = this._getCanvasCache(),
cachedSceneCanvas = cachedCanvas && cachedCanvas.scene; cachedSceneCanvas = cachedCanvas && cachedCanvas.scene;
@ -370,7 +369,7 @@ export abstract class Container<
var layer = this.getLayer(), var layer = this.getLayer(),
canvas = can || (layer && layer.hitCanvas), canvas = can || (layer && layer.hitCanvas),
context = canvas && canvas.getContext(), context = canvas! && canvas.getContext()!,
cachedCanvas = this._getCanvasCache(), cachedCanvas = this._getCanvasCache(),
cachedHitCanvas = cachedCanvas && cachedCanvas.hit; cachedHitCanvas = cachedCanvas && cachedCanvas.hit;
@ -461,8 +460,8 @@ export abstract class Container<
var rect = child.getClientRect({ var rect = child.getClientRect({
relativeTo: that, relativeTo: that,
skipShadow: config.skipShadow, skipShadow: config!.skipShadow,
skipStroke: config.skipStroke, skipStroke: config!.skipStroke,
}); });
// skip invisible children (like empty groups) // skip invisible children (like empty groups)
@ -511,7 +510,7 @@ export abstract class Container<
} }
if (!skipTransform) { if (!skipTransform) {
return this._transformedRect(selfRect, relativeTo); return this._transformedRect(selfRect, relativeTo!);
} }
return selfRect; return selfRect;
} }

View File

@ -6,7 +6,7 @@ import { IRect } from './types';
import type { Node } from './Node'; import type { Node } from './Node';
function simplifyArray(arr: Array<any>) { function simplifyArray(arr: Array<any>) {
var retArr = [], var retArr: Array<any> = [],
len = arr.length, len = arr.length,
util = Util, util = Util,
n, n,
@ -441,9 +441,9 @@ export class Context {
if (a.length === 3) { if (a.length === 3) {
_context.drawImage(a0, a1, a2); _context.drawImage(a0, a1, a2);
} else if (a.length === 5) { } else if (a.length === 5) {
_context.drawImage(a0, a1, a2, a3, a4); _context.drawImage(a0, a1, a2, a3!, a4!);
} else if (a.length === 9) { } else if (a.length === 9) {
_context.drawImage(a0, a1, a2, a3, a4, a5, a6, a7, a8); _context.drawImage(a0, a1, a2, a3!, a4!, a5!, a6!, a7!, a8!);
} }
} }
/** /**

View File

@ -44,7 +44,7 @@ export const DD = {
DD._dragElements.forEach((elem, key) => { DD._dragElements.forEach((elem, key) => {
const { node } = elem; const { node } = elem;
// we need to find pointer relative to that node // we need to find pointer relative to that node
const stage = node.getStage(); const stage = node.getStage()!;
stage.setPointersPositions(evt); stage.setPointersPositions(evt);
// it is possible that user call startDrag without any event // it is possible that user call startDrag without any event
@ -95,11 +95,11 @@ export const DD = {
// dragBefore and dragAfter allows us to set correct order of events // dragBefore and dragAfter allows us to set correct order of events
// setup all in dragbefore, and stop dragging only after pointerup triggered. // setup all in dragbefore, and stop dragging only after pointerup triggered.
_endDragBefore(evt?) { _endDragBefore(evt?) {
const drawNodes = []; const drawNodes: any[] = [];
DD._dragElements.forEach((elem) => { DD._dragElements.forEach((elem) => {
const { node } = elem; const { node } = elem;
// we need to find pointer relative to that node // we need to find pointer relative to that node
const stage = node.getStage(); const stage = node.getStage()!;
if (evt) { if (evt) {
stage.setPointersPositions(evt); stage.setPointersPositions(evt);
} }

View File

@ -120,10 +120,10 @@ export class Layer extends Container<Group | Shape> {
if (stage && stage.content) { if (stage && stage.content) {
stage.content.removeChild(this.getNativeCanvasElement()); stage.content.removeChild(this.getNativeCanvasElement());
if (index < stage.children.length - 1) { if (index < stage.children!.length - 1) {
stage.content.insertBefore( stage.content.insertBefore(
this.getNativeCanvasElement(), this.getNativeCanvasElement(),
stage.children[index + 1].getCanvas()._canvas stage.children?.[index + 1].getCanvas()._canvas!
); );
} else { } else {
stage.content.appendChild(this.getNativeCanvasElement()); stage.content.appendChild(this.getNativeCanvasElement());
@ -151,10 +151,10 @@ export class Layer extends Container<Group | Shape> {
} }
stage.content.removeChild(this.getNativeCanvasElement()); stage.content.removeChild(this.getNativeCanvasElement());
if (this.index < stage.children.length - 1) { if (this.index < stage.children!.length - 1) {
stage.content.insertBefore( stage.content.insertBefore(
this.getNativeCanvasElement(), this.getNativeCanvasElement(),
stage.children[this.index + 1].getCanvas()._canvas stage.children?.[this.index + 1].getCanvas()._canvas!
); );
} else { } else {
stage.content.appendChild(this.getNativeCanvasElement()); stage.content.appendChild(this.getNativeCanvasElement());
@ -171,7 +171,7 @@ export class Layer extends Container<Group | Shape> {
stage.content.removeChild(this.getNativeCanvasElement()); stage.content.removeChild(this.getNativeCanvasElement());
stage.content.insertBefore( stage.content.insertBefore(
this.getNativeCanvasElement(), this.getNativeCanvasElement(),
children[this.index + 1].getCanvas()._canvas children?.[this.index + 1].getCanvas()._canvas!
); );
} }
} }
@ -189,7 +189,7 @@ export class Layer extends Container<Group | Shape> {
stage.content.removeChild(this.getNativeCanvasElement()); stage.content.removeChild(this.getNativeCanvasElement());
stage.content.insertBefore( stage.content.insertBefore(
this.getNativeCanvasElement(), this.getNativeCanvasElement(),
children[1].getCanvas()._canvas children?.[1].getCanvas()._canvas!
); );
} }
} }

View File

@ -148,7 +148,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
parent: Container<Node> | null = null; parent: Container<Node> | null = null;
_cache: Map<string, any> = new Map<string, any>(); _cache: Map<string, any> = new Map<string, any>();
_attachedDepsListeners: Map<string, boolean> = new Map<string, boolean>(); _attachedDepsListeners: Map<string, boolean> = new Map<string, boolean>();
_lastPos: Vector2d = null; _lastPos: Vector2d = null!;
_attrsAffectingSize!: string[]; _attrsAffectingSize!: string[];
_batchingTransformChange = false; _batchingTransformChange = false;
_needClearTransformCache = false; _needClearTransformCache = false;
@ -322,7 +322,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
) { ) {
rect = this.getClientRect({ rect = this.getClientRect({
skipTransform: true, skipTransform: true,
relativeTo: this.getParent(), relativeTo: this.getParent()!,
}); });
} }
var width = Math.ceil(conf.width || rect.width), var width = Math.ceil(conf.width || rect.width),
@ -513,10 +513,10 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
maxY = Math.max(maxY, transformed.y); maxY = Math.max(maxY, transformed.y);
}); });
return { return {
x: minX, x: minX!,
y: minY, y: minY!,
width: maxX - minX, width: maxX! - minX!,
height: maxY - minY, height: maxY! - minY!,
}; };
} }
_drawCachedSceneCanvas(context: Context) { _drawCachedSceneCanvas(context: Context) {
@ -1085,7 +1085,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
} }
} }
if (that.nodeType !== UPPER_STAGE) { if (that.nodeType !== UPPER_STAGE) {
addChildren(that.getStage().getChildren()); addChildren(that.getStage()!.getChildren());
} }
return index; return index;
@ -1154,7 +1154,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
return null; return null;
} }
// get pointer (say mouse or touch) position // get pointer (say mouse or touch) position
var pos = this.getStage().getPointerPosition(); var pos = this.getStage()!.getPointerPosition();
if (!pos) { if (!pos) {
return null; return null;
} }
@ -1210,8 +1210,6 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
// don't clear translation // don't clear translation
this.attrs.x = origTrans.x; this.attrs.x = origTrans.x;
this.attrs.y = origTrans.y; this.attrs.y = origTrans.y;
delete origTrans.x;
delete origTrans.y;
// important, use non cached value // important, use non cached value
this._clearCache(TRANSFORM); this._clearCache(TRANSFORM);
@ -1298,7 +1296,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
return this; return this;
} }
_eachAncestorReverse(func, top) { _eachAncestorReverse(func, top) {
var family = [], var family: any[] = [],
parent = this.getParent(), parent = this.getParent(),
len, len,
n; n;
@ -1348,8 +1346,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
var index = this.index, var index = this.index,
len = this.parent.getChildren().length; len = this.parent.getChildren().length;
if (index < len - 1) { if (index < len - 1) {
this.parent.children.splice(index, 1); this.parent.children!.splice(index, 1);
this.parent.children.push(this); this.parent.children!.push(this);
this.parent._setChildrenIndices(); this.parent._setChildrenIndices();
return true; return true;
} }
@ -1369,8 +1367,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
var index = this.index, var index = this.index,
len = this.parent.getChildren().length; len = this.parent.getChildren().length;
if (index < len - 1) { if (index < len - 1) {
this.parent.children.splice(index, 1); this.parent.children!.splice(index, 1);
this.parent.children.splice(index + 1, 0, this); this.parent.children!.splice(index + 1, 0, this);
this.parent._setChildrenIndices(); this.parent._setChildrenIndices();
return true; return true;
} }
@ -1389,8 +1387,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
} }
var index = this.index; var index = this.index;
if (index > 0) { if (index > 0) {
this.parent.children.splice(index, 1); this.parent.children!.splice(index, 1);
this.parent.children.splice(index - 1, 0, this); this.parent.children!.splice(index - 1, 0, this);
this.parent._setChildrenIndices(); this.parent._setChildrenIndices();
return true; return true;
} }
@ -1409,8 +1407,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
} }
var index = this.index; var index = this.index;
if (index > 0) { if (index > 0) {
this.parent.children.splice(index, 1); this.parent.children!.splice(index, 1);
this.parent.children.unshift(this); this.parent.children!.unshift(this);
this.parent._setChildrenIndices(); this.parent._setChildrenIndices();
return true; return true;
} }
@ -1421,18 +1419,18 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
Util.warn('Node has no parent. zIndex parameter is ignored.'); Util.warn('Node has no parent. zIndex parameter is ignored.');
return this; return this;
} }
if (zIndex < 0 || zIndex >= this.parent.children.length) { if (zIndex < 0 || zIndex >= this.parent.children!.length) {
Util.warn( Util.warn(
'Unexpected value ' + 'Unexpected value ' +
zIndex + zIndex +
' for zIndex property. zIndex is just index of a node in children of its parent. Expected value is from 0 to ' + ' for zIndex property. zIndex is just index of a node in children of its parent. Expected value is from 0 to ' +
(this.parent.children.length - 1) + (this.parent.children!.length - 1) +
'.' '.'
); );
} }
var index = this.index; var index = this.index;
this.parent.children.splice(index, 1); this.parent.children!.splice(index, 1);
this.parent.children.splice(zIndex, 0, this); this.parent.children!.splice(zIndex, 0, this);
this.parent._setChildrenIndices(); this.parent._setChildrenIndices();
return this; return this;
} }
@ -1575,7 +1573,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
* var group = node.findAncestors('.mygroup'); * var group = node.findAncestors('.mygroup');
*/ */
findAncestor(selector?: string, includeSelf?: boolean, stopNode?: Container) { findAncestor(selector?: string, includeSelf?: boolean, stopNode?: Container) {
return this.findAncestors(selector, includeSelf, stopNode)[0]; return this.findAncestors(selector!, includeSelf, stopNode)[0];
} }
// is current node match passed selector? // is current node match passed selector?
_isMatch(selector: string | Function) { _isMatch(selector: string | Function) {
@ -1642,7 +1640,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
_getStage(): Stage | undefined { _getStage(): Stage | undefined {
var parent = this.getParent(); var parent = this.getParent();
if (parent) { if (parent) {
return parent.getStage(); return parent.getStage()!;
} else { } else {
return undefined; return undefined;
} }
@ -1761,7 +1759,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
if (parent._isUnderCache) { if (parent._isUnderCache) {
top = parent; top = parent;
} }
parent = parent.getParent(); parent = parent.getParent()!;
} }
const transform = this.getAbsoluteTransform(top); const transform = this.getAbsoluteTransform(top);
@ -2079,7 +2077,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
if (callback) delete config.callback; if (callback) delete config.callback;
this.toCanvas(config).toBlob((blob) => { this.toCanvas(config).toBlob((blob) => {
resolve(blob); resolve(blob);
callback?.(blob); callback?.(blob!);
}); });
} catch (err) { } catch (err) {
reject(err); reject(err);
@ -2371,7 +2369,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
// drag & drop // drag & drop
_createDragElement(evt) { _createDragElement(evt) {
var pointerId = evt ? evt.pointerId : undefined; var pointerId = evt ? evt.pointerId : undefined;
var stage = this.getStage(); var stage = this.getStage()!;
var ap = this.getAbsolutePosition(); var ap = this.getAbsolutePosition();
var pos = var pos =
stage._getPointerById(pointerId) || stage._getPointerById(pointerId) ||
@ -2399,7 +2397,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
this._createDragElement(evt); this._createDragElement(evt);
} }
const elem = DD._dragElements.get(this._id); const elem = DD._dragElements.get(this._id)!;
elem.dragStatus = 'dragging'; elem.dragStatus = 'dragging';
this.fire( this.fire(
'dragstart', 'dragstart',
@ -2415,7 +2413,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
_setDragPosition(evt, elem) { _setDragPosition(evt, elem) {
// const pointers = this.getStage().getPointersPositions(); // const pointers = this.getStage().getPointersPositions();
// const pos = pointers.find(p => p.id === this._dragEventId); // const pos = pointers.find(p => p.id === this._dragEventId);
const pos = this.getStage()._getPointerById(elem.pointerId); const pos = this.getStage()!._getPointerById(elem.pointerId);
if (!pos) { if (!pos) {
return; return;

View File

@ -105,7 +105,7 @@ function getDummyContext(): CanvasRenderingContext2D {
if (dummyContext) { if (dummyContext) {
return dummyContext; return dummyContext;
} }
dummyContext = Util.createCanvasElement().getContext('2d'); dummyContext = Util.createCanvasElement().getContext('2d')!;
return dummyContext; return dummyContext;
} }
@ -210,11 +210,11 @@ export class Shape<
getContext() { getContext() {
Util.warn('shape.getContext() method is deprecated. Please do not use it.'); Util.warn('shape.getContext() method is deprecated. Please do not use it.');
return this.getLayer().getContext(); return this.getLayer()!.getContext();
} }
getCanvas() { getCanvas() {
Util.warn('shape.getCanvas() method is deprecated. Please do not use it.'); Util.warn('shape.getCanvas() method is deprecated. Please do not use it.');
return this.getLayer().getCanvas(); return this.getLayer()!.getCanvas();
} }
getSceneFunc() { getSceneFunc() {
@ -438,12 +438,12 @@ export class Shape<
* @returns {Boolean} * @returns {Boolean}
*/ */
intersects(point) { intersects(point) {
var stage = this.getStage(), var stage = this.getStage()!,
bufferHitCanvas = stage.bufferHitCanvas, bufferHitCanvas = stage.bufferHitCanvas,
p; p;
bufferHitCanvas.getContext().clear(); bufferHitCanvas.getContext().clear();
this.drawHit(bufferHitCanvas, null, true); this.drawHit(bufferHitCanvas, null!, true);
p = bufferHitCanvas.context.getImageData( p = bufferHitCanvas.context.getImageData(
Math.round(point.x), Math.round(point.x),
Math.round(point.y), Math.round(point.y),
@ -456,7 +456,6 @@ export class Shape<
destroy() { destroy() {
Node.prototype.destroy.call(this); Node.prototype.destroy.call(this);
delete shapes[this.colorKey]; delete shapes[this.colorKey];
delete this.colorKey;
return this; return this;
} }
// why do we need buffer canvas? // why do we need buffer canvas?
@ -567,7 +566,7 @@ export class Shape<
fillRect.y, fillRect.y,
}; };
if (!skipTransform) { if (!skipTransform) {
return this._transformedRect(rect, relativeTo); return this._transformedRect(rect, relativeTo!);
} }
return rect; return rect;
} }
@ -577,7 +576,7 @@ export class Shape<
// 2 - when we are caching current // 2 - when we are caching current
// 3 - when node is cached and we need to draw it into layer // 3 - when node is cached and we need to draw it into layer
var layer = this.getLayer(), var layer = this.getLayer()!,
canvas = can || layer.getCanvas(), canvas = can || layer.getCanvas(),
context = canvas.getContext() as SceneContext, context = canvas.getContext() as SceneContext,
cachedCanvas = this._getCanvasCache(), cachedCanvas = this._getCanvasCache(),
@ -662,7 +661,7 @@ export class Shape<
return this; return this;
} }
var layer = this.getLayer(), var layer = this.getLayer()!,
canvas = can || layer.hitCanvas, canvas = can || layer.hitCanvas,
context = canvas && canvas.getContext(), context = canvas && canvas.getContext(),
drawFunc = this.hitFunc() || this.sceneFunc(), drawFunc = this.hitFunc() || this.sceneFunc(),

View File

@ -9,11 +9,9 @@ import { Layer } from './Layer';
import { DD } from './DragAndDrop'; import { DD } from './DragAndDrop';
import { _registerNode } from './Global'; import { _registerNode } from './Global';
import * as PointerEvents from './PointerEvents'; import * as PointerEvents from './PointerEvents';
export interface StageConfig extends ContainerConfig { export interface StageConfig extends ContainerConfig {
container: HTMLDivElement | string; container: HTMLDivElement | string;
} }
// CONSTANTS // CONSTANTS
var STAGE = 'Stage', var STAGE = 'Stage',
STRING = 'string', STRING = 'string',
@ -60,7 +58,6 @@ var STAGE = 'Stage',
[POINTERCANCEL, '_pointercancel'], [POINTERCANCEL, '_pointercancel'],
[LOSTPOINTERCAPTURE, '_lostpointercapture'], [LOSTPOINTERCAPTURE, '_lostpointercapture'],
]; ];
const EVENTS_MAP = { const EVENTS_MAP = {
mouse: { mouse: {
[POINTEROUT]: MOUSEOUT, [POINTEROUT]: MOUSEOUT,
@ -99,7 +96,6 @@ const EVENTS_MAP = {
pointerdblclick: 'pointerdblclick', pointerdblclick: 'pointerdblclick',
}, },
}; };
const getEventType = (type) => { const getEventType = (type) => {
if (type.indexOf('pointer') >= 0) { if (type.indexOf('pointer') >= 0) {
return 'pointer'; return 'pointer';
@ -109,11 +105,10 @@ const getEventType = (type) => {
} }
return 'mouse'; return 'mouse';
}; };
const getEventsMap = (eventType: string) => { const getEventsMap = (eventType: string) => {
const type = getEventType(eventType); const type = getEventType(eventType);
if (type === 'pointer') { if (type === 'pointer' && Konva.pointerEventsEnabled) {
return Konva.pointerEventsEnabled && EVENTS_MAP.pointer; return EVENTS_MAP.pointer;
} }
if (type === 'touch') { if (type === 'touch') {
return EVENTS_MAP.touch; return EVENTS_MAP.touch;
@ -122,7 +117,6 @@ const getEventsMap = (eventType: string) => {
return EVENTS_MAP.mouse; return EVENTS_MAP.mouse;
} }
}; };
function checkNoClip(attrs: any = {}) { function checkNoClip(attrs: any = {}) {
if (attrs.clipFunc || attrs.clipWidth || attrs.clipHeight) { if (attrs.clipFunc || attrs.clipWidth || attrs.clipHeight) {
Util.warn( Util.warn(
@ -131,11 +125,8 @@ function checkNoClip(attrs: any = {}) {
} }
return attrs; return attrs;
} }
const NO_POINTERS_MESSAGE = `Pointer position is missing and not registered by the stage. Looks like it is outside of the stage container. You can set it manually from event: stage.setPointersPositions(event);`; const NO_POINTERS_MESSAGE = `Pointer position is missing and not registered by the stage. Looks like it is outside of the stage container. You can set it manually from event: stage.setPointersPositions(event);`;
export const stages: Stage[] = []; export const stages: Stage[] = [];
/** /**
* Stage constructor. A stage is used to contain multiple layers * Stage constructor. A stage is used to contain multiple layers
* @constructor * @constructor
@ -151,13 +142,11 @@ export const stages: Stage[] = [];
* container: 'containerId' // or "#containerId" or ".containerClass" * container: 'containerId' // or "#containerId" or ".containerClass"
* }); * });
*/ */
export class Stage extends Container<Layer> { export class Stage extends Container<Layer> {
content: HTMLDivElement; content: HTMLDivElement;
pointerPos: Vector2d | null; pointerPos: Vector2d | null;
_pointerPositions: (Vector2d & { id?: number })[] = []; _pointerPositions: (Vector2d & { id?: number })[] = [];
_changedPointerPositions: (Vector2d & { id: number })[] = []; _changedPointerPositions: (Vector2d & { id: number })[] = [];
bufferCanvas: SceneCanvas; bufferCanvas: SceneCanvas;
bufferHitCanvas: HitCanvas; bufferHitCanvas: HitCanvas;
_mouseTargetShape: Shape; _mouseTargetShape: Shape;
@ -169,11 +158,9 @@ export class Stage extends Container<Layer> {
_mouseClickEndShape: Shape; _mouseClickEndShape: Shape;
_touchClickEndShape: Shape; _touchClickEndShape: Shape;
_pointerClickEndShape: Shape; _pointerClickEndShape: Shape;
_mouseDblTimeout: any; _mouseDblTimeout: any;
_touchDblTimeout: any; _touchDblTimeout: any;
_pointerDblTimeout: any; _pointerDblTimeout: any;
constructor(config: StageConfig) { constructor(config: StageConfig) {
super(checkNoClip(config)); super(checkNoClip(config));
this._buildDOM(); this._buildDOM();
@ -189,7 +176,6 @@ export class Stage extends Container<Layer> {
); );
this._checkVisibility(); this._checkVisibility();
} }
_validateAdd(child) { _validateAdd(child) {
const isLayer = child.getType() === 'Layer'; const isLayer = child.getType() === 'Layer';
const isFastLayer = child.getType() === 'FastLayer'; const isFastLayer = child.getType() === 'FastLayer';
@ -198,7 +184,6 @@ export class Stage extends Container<Layer> {
Util.throw('You may only add layers to the stage.'); Util.throw('You may only add layers to the stage.');
} }
} }
_checkVisibility() { _checkVisibility() {
if (!this.content) { if (!this.content) {
return; return;
@ -242,7 +227,6 @@ export class Stage extends Container<Layer> {
shouldDrawHit() { shouldDrawHit() {
return true; return true;
} }
/** /**
* clear all layers * clear all layers
* @method * @method
@ -250,11 +234,10 @@ export class Stage extends Container<Layer> {
*/ */
clear() { clear() {
var layers = this.children, var layers = this.children,
len = layers.length, len = layers!.length,
n; n;
for (n = 0; n < len; n++) { for (n = 0; n < len; n++) {
layers[n].clear(); layers?.[n].clear();
} }
return this; return this;
} }
@ -266,10 +249,8 @@ export class Stage extends Container<Layer> {
typeof document !== 'undefined' && document.createElement('div'); typeof document !== 'undefined' && document.createElement('div');
return Container.prototype.clone.call(this, obj); return Container.prototype.clone.call(this, obj);
} }
destroy() { destroy() {
super.destroy(); super.destroy();
var content = this.content; var content = this.content;
if (content && Util._isInDocument(content)) { if (content && Util._isInDocument(content)) {
this.container().removeChild(content); this.container().removeChild(content);
@ -278,9 +259,7 @@ export class Stage extends Container<Layer> {
if (index > -1) { if (index > -1) {
stages.splice(index, 1); stages.splice(index, 1);
} }
Util.releaseCanvas(this.bufferCanvas._canvas, this.bufferHitCanvas._canvas) Util.releaseCanvas(this.bufferCanvas._canvas, this.bufferHitCanvas._canvas)
return this; return this;
} }
/** /**
@ -316,12 +295,10 @@ export class Stage extends Container<Layer> {
} }
_toKonvaCanvas(config) { _toKonvaCanvas(config) {
config = config || {}; config = config || {};
config.x = config.x || 0; config.x = config.x || 0;
config.y = config.y || 0; config.y = config.y || 0;
config.width = config.width || this.width(); config.width = config.width || this.width();
config.height = config.height || this.height(); config.height = config.height || this.height();
var canvas = new SceneCanvas({ var canvas = new SceneCanvas({
width: config.width, width: config.width,
height: config.height, height: config.height,
@ -329,12 +306,10 @@ export class Stage extends Container<Layer> {
}); });
var _context = canvas.getContext()._context; var _context = canvas.getContext()._context;
var layers = this.children; var layers = this.children;
if (config.x || config.y) { if (config.x || config.y) {
_context.translate(-1 * config.x, -1 * config.y); _context.translate(-1 * config.x, -1 * config.y);
} }
layers?.forEach(function (layer) {
layers.forEach(function (layer) {
if (!layer.isVisible()) { if (!layer.isVisible()) {
return; return;
} }
@ -349,7 +324,6 @@ export class Stage extends Container<Layer> {
}); });
return canvas; return canvas;
} }
/** /**
* get visible intersection shape. This is the preferred * get visible intersection shape. This is the preferred
* method for determining if a point intersects a shape or not * method for determining if a point intersects a shape or not
@ -366,18 +340,16 @@ export class Stage extends Container<Layer> {
if (!pos) { if (!pos) {
return null; return null;
} }
var layers = this.children, var layers = this.children!,
len = layers.length, len = layers.length,
end = len - 1, end = len - 1,
n; n;
for (n = end; n >= 0; n--) { for (n = end; n >= 0; n--) {
const shape = layers[n].getIntersection(pos); const shape = layers[n].getIntersection(pos);
if (shape) { if (shape) {
return shape; return shape;
} }
} }
return null; return null;
} }
_resizeDOM() { _resizeDOM() {
@ -388,12 +360,10 @@ export class Stage extends Container<Layer> {
this.content.style.width = width + PX; this.content.style.width = width + PX;
this.content.style.height = height + PX; this.content.style.height = height + PX;
} }
this.bufferCanvas.setSize(width, height); this.bufferCanvas.setSize(width, height);
this.bufferHitCanvas.setSize(width, height); this.bufferHitCanvas.setSize(width, height);
// set layer dimensions // set layer dimensions
this.children.forEach((layer) => { this.children!.forEach((layer) => {
layer.setSize({ width, height }); layer.setSize({ width, height });
layer.draw(); layer.draw();
}); });
@ -406,8 +376,7 @@ export class Stage extends Container<Layer> {
return this; return this;
} }
super.add(layer); super.add(layer);
var length = this.children!.length;
var length = this.children.length;
if (length > MAX_LAYERS_NUMBER) { if (length > MAX_LAYERS_NUMBER) {
Util.warn( Util.warn(
'The stage has ' + 'The stage has ' +
@ -416,14 +385,11 @@ export class Stage extends Container<Layer> {
); );
} }
layer.setSize({ width: this.width(), height: this.height() }); layer.setSize({ width: this.width(), height: this.height() });
// draw layer and append canvas to container // draw layer and append canvas to container
layer.draw(); layer.draw();
if (Konva.isBrowser) { if (Konva.isBrowser) {
this.content.appendChild(layer.canvas._canvas); this.content.appendChild(layer.canvas._canvas);
} }
// chainable // chainable
return this; return this;
} }
@ -433,19 +399,15 @@ export class Stage extends Container<Layer> {
getLayer() { getLayer() {
return null; return null;
} }
hasPointerCapture(pointerId: number): boolean { hasPointerCapture(pointerId: number): boolean {
return PointerEvents.hasPointerCapture(pointerId, this); return PointerEvents.hasPointerCapture(pointerId, this);
} }
setPointerCapture(pointerId: number) { setPointerCapture(pointerId: number) {
PointerEvents.setPointerCapture(pointerId, this); PointerEvents.setPointerCapture(pointerId, this);
} }
releaseCapture(pointerId: number) { releaseCapture(pointerId: number) {
PointerEvents.releaseCapture(pointerId, this); PointerEvents.releaseCapture(pointerId, this);
} }
/** /**
* returns an array of layers * returns an array of layers
* @method * @method
@ -470,7 +432,7 @@ export class Stage extends Container<Layer> {
} }
_pointerenter(evt) { _pointerenter(evt) {
this.setPointersPositions(evt); this.setPointersPositions(evt);
const events = getEventsMap(evt.type); const events = getEventsMap(evt.type)!;
this._fire(events.pointerenter, { this._fire(events.pointerenter, {
evt: evt, evt: evt,
target: this, target: this,
@ -479,7 +441,7 @@ export class Stage extends Container<Layer> {
} }
_pointerover(evt) { _pointerover(evt) {
this.setPointersPositions(evt); this.setPointersPositions(evt);
const events = getEventsMap(evt.type); const events = getEventsMap(evt.type)!;
this._fire(events.pointerover, { this._fire(events.pointerover, {
evt: evt, evt: evt,
target: this, target: this,
@ -496,12 +458,10 @@ export class Stage extends Container<Layer> {
_pointerleave(evt) { _pointerleave(evt) {
const events = getEventsMap(evt.type); const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type); const eventType = getEventType(evt.type);
if (!events) { if (!events) {
return; return;
} }
this.setPointersPositions(evt); this.setPointersPositions(evt);
var targetShape = this._getTargetShape(eventType); var targetShape = this._getTargetShape(eventType);
var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled; var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled;
if (targetShape && eventsEnabled) { if (targetShape && eventsEnabled) {
@ -525,52 +485,44 @@ export class Stage extends Container<Layer> {
currentTarget: this, currentTarget: this,
}); });
} }
this.pointerPos = undefined; this.pointerPos = undefined!;
this._pointerPositions = []; this._pointerPositions = [];
} }
_pointerdown(evt: TouchEvent | MouseEvent | PointerEvent) { _pointerdown(evt: TouchEvent | MouseEvent | PointerEvent) {
const events = getEventsMap(evt.type); const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type); const eventType = getEventType(evt.type);
if (!events) { if (!events) {
return; return;
} }
this.setPointersPositions(evt); this.setPointersPositions(evt);
var triggeredOnShape = false; var triggeredOnShape = false;
this._changedPointerPositions.forEach((pos) => { this._changedPointerPositions.forEach((pos) => {
var shape = this.getIntersection(pos); var shape = this.getIntersection(pos);
DD.justDragged = false; DD.justDragged = false;
// probably we are staring a click // probably we are staring a click
Konva['_' + eventType + 'ListenClick'] = true; Konva['_' + eventType + 'ListenClick'] = true;
// no shape detected? do nothing // no shape detected? do nothing
const hasShape = shape && shape.isListening(); const hasShape = shape && shape.isListening();
if (!hasShape) { if (!hasShape) {
return; return;
} }
if (Konva.capturePointerEventsEnabled) { if (Konva.capturePointerEventsEnabled) {
shape.setPointerCapture(pos.id); shape!.setPointerCapture(pos.id);
} }
// save where we started the click // save where we started the click
this[eventType + 'ClickStartShape'] = shape; this[eventType + 'ClickStartShape'] = shape;
shape!._fireAndBubble(events.pointerdown, {
shape._fireAndBubble(events.pointerdown, {
evt: evt, evt: evt,
pointerId: pos.id, pointerId: pos.id,
}); });
triggeredOnShape = true; triggeredOnShape = true;
// TODO: test in iframe // TODO: test in iframe
// only call preventDefault if the shape is listening for events // only call preventDefault if the shape is listening for events
const isTouch = evt.type.indexOf('touch') >= 0; const isTouch = evt.type.indexOf('touch') >= 0;
if (shape.preventDefault() && evt.cancelable && isTouch) { if (shape!.preventDefault() && evt.cancelable && isTouch) {
evt.preventDefault(); evt.preventDefault();
} }
}); });
// trigger down on stage if not already // trigger down on stage if not already
if (!triggeredOnShape) { if (!triggeredOnShape) {
this._fire(events.pointerdown, { this._fire(events.pointerdown, {
@ -587,16 +539,14 @@ export class Stage extends Container<Layer> {
if (!events) { if (!events) {
return; return;
} }
if (DD.isDragging && DD.node.preventDefault() && evt.cancelable) { if (DD.isDragging && DD.node!.preventDefault() && evt.cancelable) {
evt.preventDefault(); evt.preventDefault();
} }
this.setPointersPositions(evt); this.setPointersPositions(evt);
var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled; var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled;
if (!eventsEnabled) { if (!eventsEnabled) {
return; return;
} }
var processedShapesIds = {}; var processedShapesIds = {};
let triggeredOnShape = false; let triggeredOnShape = false;
var targetShape = this._getTargetShape(eventType); var targetShape = this._getTargetShape(eventType);
@ -605,21 +555,17 @@ export class Stage extends Container<Layer> {
this.getIntersection(pos)) as Shape; this.getIntersection(pos)) as Shape;
const pointerId = pos.id; const pointerId = pos.id;
const event = { evt: evt, pointerId }; const event = { evt: evt, pointerId };
var differentTarget = targetShape !== shape; var differentTarget = targetShape !== shape;
if (differentTarget && targetShape) { if (differentTarget && targetShape) {
targetShape._fireAndBubble(events.pointerout, { ...event }, shape); targetShape._fireAndBubble(events.pointerout, { ...event }, shape);
targetShape._fireAndBubble(events.pointerleave, { ...event }, shape); targetShape._fireAndBubble(events.pointerleave, { ...event }, shape);
} }
if (shape) { if (shape) {
if (processedShapesIds[shape._id]) { if (processedShapesIds[shape._id]) {
return; return;
} }
processedShapesIds[shape._id] = true; processedShapesIds[shape._id] = true;
} }
if (shape && shape.isListening()) { if (shape && shape.isListening()) {
triggeredOnShape = true; triggeredOnShape = true;
if (differentTarget) { if (differentTarget) {
@ -640,7 +586,6 @@ export class Stage extends Container<Layer> {
} }
} }
}); });
if (!triggeredOnShape) { if (!triggeredOnShape) {
this._fire(events.pointermove, { this._fire(events.pointermove, {
evt: evt, evt: evt,
@ -653,7 +598,6 @@ export class Stage extends Container<Layer> {
_pointerup(evt) { _pointerup(evt) {
const events = getEventsMap(evt.type); const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type); const eventType = getEventType(evt.type);
if (!events) { if (!events) {
return; return;
} }
@ -665,7 +609,6 @@ export class Stage extends Container<Layer> {
this._changedPointerPositions.forEach((pos) => { this._changedPointerPositions.forEach((pos) => {
const shape = (PointerEvents.getCapturedShape(pos.id) || const shape = (PointerEvents.getCapturedShape(pos.id) ||
this.getIntersection(pos)) as Shape; this.getIntersection(pos)) as Shape;
if (shape) { if (shape) {
shape.releaseCapture(pos.id); shape.releaseCapture(pos.id);
if (processedShapesIds[shape._id]) { if (processedShapesIds[shape._id]) {
@ -673,10 +616,8 @@ export class Stage extends Container<Layer> {
} }
processedShapesIds[shape._id] = true; processedShapesIds[shape._id] = true;
} }
const pointerId = pos.id; const pointerId = pos.id;
const event = { evt: evt, pointerId }; const event = { evt: evt, pointerId };
let fireDblClick = false; let fireDblClick = false;
if (Konva['_' + eventType + 'InDblClickWindow']) { if (Konva['_' + eventType + 'InDblClickWindow']) {
fireDblClick = true; fireDblClick = true;
@ -686,16 +627,13 @@ export class Stage extends Container<Layer> {
Konva['_' + eventType + 'InDblClickWindow'] = true; Konva['_' + eventType + 'InDblClickWindow'] = true;
clearTimeout(this[eventType + 'DblTimeout']); clearTimeout(this[eventType + 'DblTimeout']);
} }
this[eventType + 'DblTimeout'] = setTimeout(function () { this[eventType + 'DblTimeout'] = setTimeout(function () {
Konva['_' + eventType + 'InDblClickWindow'] = false; Konva['_' + eventType + 'InDblClickWindow'] = false;
}, Konva.dblClickWindow); }, Konva.dblClickWindow);
if (shape && shape.isListening()) { if (shape && shape.isListening()) {
triggeredOnShape = true; triggeredOnShape = true;
this[eventType + 'ClickEndShape'] = shape; this[eventType + 'ClickEndShape'] = shape;
shape._fireAndBubble(events.pointerup, { ...event }); shape._fireAndBubble(events.pointerup, { ...event });
// detect if click or double click occurred // detect if click or double click occurred
if ( if (
Konva['_' + eventType + 'ListenClick'] && Konva['_' + eventType + 'ListenClick'] &&
@ -703,14 +641,12 @@ export class Stage extends Container<Layer> {
clickStartShape === shape clickStartShape === shape
) { ) {
shape._fireAndBubble(events.pointerclick, { ...event }); shape._fireAndBubble(events.pointerclick, { ...event });
if (fireDblClick && clickEndShape && clickEndShape === shape) { if (fireDblClick && clickEndShape && clickEndShape === shape) {
shape._fireAndBubble(events.pointerdblclick, { ...event }); shape._fireAndBubble(events.pointerdblclick, { ...event });
} }
} }
} else { } else {
this[eventType + 'ClickEndShape'] = null; this[eventType + 'ClickEndShape'] = null;
if (Konva['_' + eventType + 'ListenClick']) { if (Konva['_' + eventType + 'ListenClick']) {
this._fire(events.pointerclick, { this._fire(events.pointerclick, {
evt: evt, evt: evt,
@ -719,7 +655,6 @@ export class Stage extends Container<Layer> {
pointerId, pointerId,
}); });
} }
if (fireDblClick) { if (fireDblClick) {
this._fire(events.pointerdblclick, { this._fire(events.pointerdblclick, {
evt: evt, evt: evt,
@ -730,7 +665,6 @@ export class Stage extends Container<Layer> {
} }
} }
}); });
if (!triggeredOnShape) { if (!triggeredOnShape) {
this._fire(events.pointerup, { this._fire(events.pointerup, {
evt: evt, evt: evt,
@ -739,9 +673,7 @@ export class Stage extends Container<Layer> {
pointerId: this._changedPointerPositions[0].id, pointerId: this._changedPointerPositions[0].id,
}); });
} }
Konva['_' + eventType + 'ListenClick'] = false; Konva['_' + eventType + 'ListenClick'] = false;
// always call preventDefault for desktop events because some browsers // always call preventDefault for desktop events because some browsers
// try to drag and drop the canvas element // try to drag and drop the canvas element
// TODO: are we sure we need to prevent default at all? // TODO: are we sure we need to prevent default at all?
@ -753,8 +685,7 @@ export class Stage extends Container<Layer> {
} }
_contextmenu(evt) { _contextmenu(evt) {
this.setPointersPositions(evt); this.setPointersPositions(evt);
var shape = this.getIntersection(this.getPointerPosition()); var shape = this.getIntersection(this.getPointerPosition()!);
if (shape && shape.isListening()) { if (shape && shape.isListening()) {
shape._fireAndBubble(CONTEXTMENU, { evt: evt }); shape._fireAndBubble(CONTEXTMENU, { evt: evt });
} else { } else {
@ -765,11 +696,9 @@ export class Stage extends Container<Layer> {
}); });
} }
} }
_wheel(evt) { _wheel(evt) {
this.setPointersPositions(evt); this.setPointersPositions(evt);
var shape = this.getIntersection(this.getPointerPosition()); var shape = this.getIntersection(this.getPointerPosition()!);
if (shape && shape.isListening()) { if (shape && shape.isListening()) {
shape._fireAndBubble(WHEEL, { evt: evt }); shape._fireAndBubble(WHEEL, { evt: evt });
} else { } else {
@ -780,24 +709,19 @@ export class Stage extends Container<Layer> {
}); });
} }
} }
_pointercancel(evt: PointerEvent) { _pointercancel(evt: PointerEvent) {
this.setPointersPositions(evt); this.setPointersPositions(evt);
const shape = const shape =
PointerEvents.getCapturedShape(evt.pointerId) || PointerEvents.getCapturedShape(evt.pointerId) ||
this.getIntersection(this.getPointerPosition()); this.getIntersection(this.getPointerPosition()!);
if (shape) { if (shape) {
shape._fireAndBubble(POINTERUP, PointerEvents.createEvent(evt)); shape._fireAndBubble(POINTERUP, PointerEvents.createEvent(evt));
} }
PointerEvents.releaseCapture(evt.pointerId); PointerEvents.releaseCapture(evt.pointerId);
} }
_lostpointercapture(evt: PointerEvent) { _lostpointercapture(evt: PointerEvent) {
PointerEvents.releaseCapture(evt.pointerId); PointerEvents.releaseCapture(evt.pointerId);
} }
/** /**
* manually register pointers positions (mouse/touch) in the stage. * manually register pointers positions (mouse/touch) in the stage.
* So you can use stage.getPointerPosition(). Usually you don't need to use that method * So you can use stage.getPointerPosition(). Usually you don't need to use that method
@ -814,10 +738,9 @@ export class Stage extends Container<Layer> {
*/ */
setPointersPositions(evt) { setPointersPositions(evt) {
var contentPosition = this._getContentPosition(), var contentPosition = this._getContentPosition(),
x = null, x: number = null!,
y = null; y: number = null!;
evt = evt ? evt : window.event; evt = evt ? evt : window.event;
// touch events // touch events
if (evt.touches !== undefined) { if (evt.touches !== undefined) {
// touchlist has not support for map method // touchlist has not support for map method
@ -831,7 +754,6 @@ export class Stage extends Container<Layer> {
y: (touch.clientY - contentPosition.top) / contentPosition.scaleY, y: (touch.clientY - contentPosition.top) / contentPosition.scaleY,
}); });
}); });
Array.prototype.forEach.call( Array.prototype.forEach.call(
evt.changedTouches || evt.touches, evt.changedTouches || evt.touches,
(touch: any) => { (touch: any) => {
@ -871,9 +793,7 @@ export class Stage extends Container<Layer> {
scaleY: 1, scaleY: 1,
}; };
} }
var rect = this.content.getBoundingClientRect(); var rect = this.content.getBoundingClientRect();
return { return {
top: rect.top, top: rect.top,
left: rect.left, left: rect.left,
@ -893,7 +813,6 @@ export class Stage extends Container<Layer> {
width: this.width(), width: this.width(),
height: this.height(), height: this.height(),
}); });
if (!Konva.isBrowser) { if (!Konva.isBrowser) {
return; return;
} }
@ -902,18 +821,14 @@ export class Stage extends Container<Layer> {
throw 'Stage has no container. A container is required.'; throw 'Stage has no container. A container is required.';
} }
// clear content inside container // clear content inside container
container.innerHTML = ''; while (container.hasChildNodes()) container.removeChild(container.firstChild!);
// content // content
this.content = document.createElement('div'); this.content = document.createElement('div');
this.content.style.position = 'relative'; this.content.style.position = 'relative';
this.content.style.userSelect = 'none'; this.content.style.userSelect = 'none';
this.content.className = 'konvajs-content'; this.content.className = 'konvajs-content';
this.content.setAttribute('role', 'presentation'); this.content.setAttribute('role', 'presentation');
container.appendChild(this.content); container.appendChild(this.content);
this._resizeDOM(); this._resizeDOM();
} }
// currently cache function is now working for stage, because stage has no its own canvas element // currently cache function is now working for stage, because stage has no its own canvas element
@ -938,13 +853,10 @@ export class Stage extends Container<Layer> {
}); });
return this; return this;
} }
container: GetSet<HTMLDivElement, this>; container: GetSet<HTMLDivElement, this>;
} }
Stage.prototype.nodeType = STAGE; Stage.prototype.nodeType = STAGE;
_registerNode(Stage); _registerNode(Stage);
/** /**
* get/set container DOM element * get/set container DOM element
* @method * @method

View File

@ -1,7 +1,6 @@
import { Konva } from './Global'; import { Konva } from './Global';
import { Context } from './Context'; import { Context } from './Context';
import { IRect, RGB, RGBA, Vector2d } from './types'; import { IRect, RGB, RGBA, Vector2d } from './types';
/* /*
* Last updated November 2011 * Last updated November 2011
* By Simon Sarris * By Simon Sarris
@ -16,7 +15,6 @@ import { IRect, RGB, RGBA, Vector2d } from './types';
* project, KineticJS-Ext by Wappworks, which is based on Simon's Transform * project, KineticJS-Ext by Wappworks, which is based on Simon's Transform
* class. Modified by Eric Rowell * class. Modified by Eric Rowell
*/ */
/** /**
* Transform constructor. * Transform constructor.
* In most of the cases you don't need to use it in your app. Because it is for internal usage in Konva core. * In most of the cases you don't need to use it in your app. Because it is for internal usage in Konva core.
@ -162,13 +160,10 @@ export class Transform {
multiply(matrix: Transform) { multiply(matrix: Transform) {
var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1]; var m11 = this.m[0] * matrix.m[0] + this.m[2] * matrix.m[1];
var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1]; var m12 = this.m[1] * matrix.m[0] + this.m[3] * matrix.m[1];
var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3]; var m21 = this.m[0] * matrix.m[2] + this.m[2] * matrix.m[3];
var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3]; var m22 = this.m[1] * matrix.m[2] + this.m[3] * matrix.m[3];
var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4]; var dx = this.m[0] * matrix.m[4] + this.m[2] * matrix.m[5] + this.m[4];
var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5]; var dy = this.m[1] * matrix.m[4] + this.m[3] * matrix.m[5] + this.m[5];
this.m[0] = m11; this.m[0] = m11;
this.m[1] = m12; this.m[1] = m12;
this.m[2] = m21; this.m[2] = m21;
@ -220,9 +215,7 @@ export class Transform {
var d = this.m[3]; var d = this.m[3];
var e = this.m[4]; var e = this.m[4];
var f = this.m[5]; var f = this.m[5];
var delta = a * d - b * c; var delta = a * d - b * c;
let result = { let result = {
x: e, x: e,
y: f, y: f,
@ -232,7 +225,6 @@ export class Transform {
skewX: 0, skewX: 0,
skewY: 0, skewY: 0,
}; };
// Apply the QR-like decomposition. // Apply the QR-like decomposition.
if (a != 0 || b != 0) { if (a != 0 || b != 0) {
var r = Math.sqrt(a * a + b * b); var r = Math.sqrt(a * a + b * b);
@ -252,13 +244,10 @@ export class Transform {
} else { } else {
// a = b = c = d = 0 // a = b = c = d = 0
} }
result.rotation = Util._getRotation(result.rotation); result.rotation = Util._getRotation(result.rotation);
return result; return result;
} }
} }
// CONSTANTS // CONSTANTS
var OBJECT_ARRAY = '[object Array]', var OBJECT_ARRAY = '[object Array]',
OBJECT_NUMBER = '[object Number]', OBJECT_NUMBER = '[object Number]',
@ -425,7 +414,6 @@ var OBJECT_ARRAY = '[object Array]',
}, },
RGB_REGEX = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/, RGB_REGEX = /rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)/,
animQueue: Array<Function> = []; animQueue: Array<Function> = [];
const req = const req =
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame) || (typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame) ||
function (f) { function (f) {
@ -491,7 +479,6 @@ export const Util = {
return -1; return -1;
} }
}, },
requestAnimFrame(callback: Function) { requestAnimFrame(callback: Function) {
animQueue.push(callback); animQueue.push(callback);
if (animQueue.length === 1) { if (animQueue.length === 1) {
@ -523,13 +510,12 @@ export const Util = {
} }
return false; return false;
}, },
/* /*
* arg can be an image object or image data * arg can be an image object or image data
*/ */
_urlToImage(url: string, callback: Function) { _urlToImage(url: string, callback: Function) {
// if arg is a string, then it's a data url // if arg is a string, then it's a data url
var imageObj = Util.createImageElement(); var imageObj = new window.Image();
imageObj.onload = function () { imageObj.onload = function () {
callback(imageObj); callback(imageObj);
}; };
@ -561,7 +547,6 @@ export const Util = {
} }
return HASH + randColor; return HASH + randColor;
}, },
/** /**
* get RGB components of a color * get RGB components of a color
* @method * @method
@ -615,7 +600,7 @@ export const Util = {
Util._hex8ColorToRGBA(str) || Util._hex8ColorToRGBA(str) ||
Util._rgbColorToRGBA(str) || Util._rgbColorToRGBA(str) ||
Util._rgbaColorToRGBA(str) || Util._rgbaColorToRGBA(str) ||
Util._hslColorToRGBA(str) Util._hslColorToRGBA(str)!
); );
}, },
// Parse named css color. Like "green" // Parse named css color. Like "green"
@ -632,9 +617,9 @@ export const Util = {
}; };
}, },
// Parse rgb(n, n, n) // Parse rgb(n, n, n)
_rgbColorToRGBA(str: string): RGBA { _rgbColorToRGBA(str: string): RGBA | undefined {
if (str.indexOf('rgb(') === 0) { if (str.indexOf('rgb(') === 0) {
str = str.match(/rgb\(([^)]+)\)/)[1]; str = str.match(/rgb\(([^)]+)\)/)?.[1]!;
var parts = str.split(/ *, */).map(Number); var parts = str.split(/ *, */).map(Number);
return { return {
r: parts[0], r: parts[0],
@ -645,9 +630,9 @@ export const Util = {
} }
}, },
// Parse rgba(n, n, n, n) // Parse rgba(n, n, n, n)
_rgbaColorToRGBA(str: string): RGBA { _rgbaColorToRGBA(str: string): RGBA | undefined {
if (str.indexOf('rgba(') === 0) { if (str.indexOf('rgba(') === 0) {
str = str.match(/rgba\(([^)]+)\)/)[1]; str = str.match(/rgba\(([^)]+)\)/)?.[1]!;
var parts = str.split(/ *, */).map((n, index) => { var parts = str.split(/ *, */).map((n, index) => {
if (n.slice(-1) === '%') { if (n.slice(-1) === '%') {
return index === 3 ? parseInt(n) / 100 : (parseInt(n) / 100) * 255; return index === 3 ? parseInt(n) / 100 : (parseInt(n) / 100) * 255;
@ -663,7 +648,7 @@ export const Util = {
} }
}, },
// Parse #nnnnnnnn // Parse #nnnnnnnn
_hex8ColorToRGBA(str: string): RGBA { _hex8ColorToRGBA(str: string): RGBA | undefined{
if (str[0] === '#' && str.length === 9) { if (str[0] === '#' && str.length === 9) {
return { return {
r: parseInt(str.slice(1, 3), 16), r: parseInt(str.slice(1, 3), 16),
@ -674,7 +659,7 @@ export const Util = {
} }
}, },
// Parse #nnnnnn // Parse #nnnnnn
_hex6ColorToRGBA(str: string): RGBA { _hex6ColorToRGBA(str: string): RGBA | undefined {
if (str[0] === '#' && str.length === 7) { if (str[0] === '#' && str.length === 7) {
return { return {
r: parseInt(str.slice(1, 3), 16), r: parseInt(str.slice(1, 3), 16),
@ -685,7 +670,7 @@ export const Util = {
} }
}, },
// Parse #nnnn // Parse #nnnn
_hex4ColorToRGBA(str: string): RGBA { _hex4ColorToRGBA(str: string): RGBA | undefined {
if (str[0] === '#' && str.length === 5) { if (str[0] === '#' && str.length === 5) {
return { return {
r: parseInt(str[1] + str[1], 16), r: parseInt(str[1] + str[1], 16),
@ -696,7 +681,7 @@ export const Util = {
} }
}, },
// Parse #nnn // Parse #nnn
_hex3ColorToRGBA(str: string): RGBA { _hex3ColorToRGBA(str: string): RGBA | undefined {
if (str[0] === '#' && str.length === 4) { if (str[0] === '#' && str.length === 4) {
return { return {
r: parseInt(str[1] + str[1], 16), r: parseInt(str[1] + str[1], 16),
@ -707,20 +692,17 @@ export const Util = {
} }
}, },
// Code adapted from https://github.com/Qix-/color-convert/blob/master/conversions.js#L244 // Code adapted from https://github.com/Qix-/color-convert/blob/master/conversions.js#L244
_hslColorToRGBA(str: string): RGBA { _hslColorToRGBA(str: string): RGBA | undefined {
// Check hsl() format // Check hsl() format
if (/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.test(str)) { if (/hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.test(str)) {
// Extract h, s, l // Extract h, s, l
const [_, ...hsl] = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(str); const [_, ...hsl] = /hsl\((\d+),\s*([\d.]+)%,\s*([\d.]+)%\)/g.exec(str)!;
const h = Number(hsl[0]) / 360; const h = Number(hsl[0]) / 360;
const s = Number(hsl[1]) / 100; const s = Number(hsl[1]) / 100;
const l = Number(hsl[2]) / 100; const l = Number(hsl[2]) / 100;
let t2; let t2;
let t3; let t3;
let val; let val;
if (s === 0) { if (s === 0) {
val = l * 255; val = l * 255;
return { return {
@ -730,26 +712,21 @@ export const Util = {
a: 1, a: 1,
}; };
} }
if (l < 0.5) { if (l < 0.5) {
t2 = l * (1 + s); t2 = l * (1 + s);
} else { } else {
t2 = l + s - l * s; t2 = l + s - l * s;
} }
const t1 = 2 * l - t2; const t1 = 2 * l - t2;
const rgb = [0, 0, 0]; const rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) { for (let i = 0; i < 3; i++) {
t3 = h + (1 / 3) * -(i - 1); t3 = h + (1 / 3) * -(i - 1);
if (t3 < 0) { if (t3 < 0) {
t3++; t3++;
} }
if (t3 > 1) { if (t3 > 1) {
t3--; t3--;
} }
if (6 * t3 < 1) { if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3; val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) { } else if (2 * t3 < 1) {
@ -759,10 +736,8 @@ export const Util = {
} else { } else {
val = t1; val = t1;
} }
rgb[i] = val * 255; rgb[i] = val * 255;
} }
return { return {
r: Math.round(rgb[0]), r: Math.round(rgb[0]),
g: Math.round(rgb[1]), g: Math.round(rgb[1]),
@ -850,7 +825,6 @@ export const Util = {
}, },
_getProjectionToSegment(x1, y1, x2, y2, x3, y3) { _getProjectionToSegment(x1, y1, x2, y2, x3, y3) {
var x, y, dist; var x, y, dist;
var pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); var pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
if (pd2 == 0) { if (pd2 == 0) {
x = x1; x = x1;
@ -905,8 +879,8 @@ export const Util = {
}, },
_prepareArrayForTween(startArray, endArray, isClosed) { _prepareArrayForTween(startArray, endArray, isClosed) {
var n, var n,
start = [], start: any[] = [],
end = []; end: any[] = [];
if (startArray.length > endArray.length) { if (startArray.length > endArray.length) {
var temp = endArray; var temp = endArray;
endArray = startArray; endArray = startArray;
@ -924,8 +898,7 @@ export const Util = {
y: endArray[n + 1], y: endArray[n + 1],
}); });
} }
var newStart: number[] = [];
var newStart = [];
end.forEach(function (point) { end.forEach(function (point) {
var pr = Util._getProjectionToLine(point, start, isClosed); var pr = Util._getProjectionToLine(point, start, isClosed);
newStart.push(pr.x); newStart.push(pr.x);
@ -935,9 +908,7 @@ export const Util = {
}, },
_prepareToStringify(obj) { _prepareToStringify(obj) {
var desc; var desc;
obj.visitedByCircularReferenceRemoval = true; obj.visitedByCircularReferenceRemoval = true;
for (var key in obj) { for (var key in obj) {
if ( if (
!(obj.hasOwnProperty(key) && obj[key] && typeof obj[key] == 'object') !(obj.hasOwnProperty(key) && obj[key] && typeof obj[key] == 'object')
@ -962,9 +933,7 @@ export const Util = {
} }
} }
} }
delete obj.visitedByCircularReferenceRemoval; delete obj.visitedByCircularReferenceRemoval;
return obj; return obj;
}, },
// very simplified version of Object.assign // very simplified version of Object.assign
@ -984,7 +953,6 @@ export const Util = {
}, },
releaseCanvas(...canvases: HTMLCanvasElement[]) { releaseCanvas(...canvases: HTMLCanvasElement[]) {
if (!Konva.releaseCanvasOnDestroy) return; if (!Konva.releaseCanvasOnDestroy) return;
canvases.forEach(c => { canvases.forEach(c => {
c.width = 0; c.width = 0;
c.height = 0; c.height = 0;

View File

@ -2,7 +2,6 @@ import { Factory } from '../Factory';
import { Node, Filter } from '../Node'; import { Node, Filter } from '../Node';
import { Util } from '../Util'; import { Util } from '../Util';
import { getNumberValidator } from '../Validators'; import { getNumberValidator } from '../Validators';
/* /*
* ToPolar Filter. Converts image data to polar coordinates. Performs * ToPolar Filter. Converts image data to polar coordinates. Performs
* w*h*4 pixel reads and w*h pixel writes. The r axis is placed along * w*h*4 pixel reads and w*h pixel writes. The r axis is placed along
@ -18,7 +17,6 @@ import { getNumberValidator } from '../Validators';
* @param {Number} [opt.polarCenterY] vertical location for the center of the circle, * @param {Number} [opt.polarCenterY] vertical location for the center of the circle,
* default is in the middle * default is in the middle
*/ */
var ToPolar = function (src, dst, opt) { var ToPolar = function (src, dst, opt) {
var srcPixels = src.data, var srcPixels = src.data,
dstPixels = dst.data, dstPixels = dst.data,
@ -33,7 +31,6 @@ var ToPolar = function (src, dst, opt) {
g = 0, g = 0,
b = 0, b = 0,
a = 0; a = 0;
// Find the largest radius // Find the largest radius
var rad, var rad,
rMax = Math.sqrt(xMid * xMid + yMid * yMid); rMax = Math.sqrt(xMid * xMid + yMid * yMid);
@ -41,21 +38,17 @@ var ToPolar = function (src, dst, opt) {
y = ySize - yMid; y = ySize - yMid;
rad = Math.sqrt(x * x + y * y); rad = Math.sqrt(x * x + y * y);
rMax = rad > rMax ? rad : rMax; rMax = rad > rMax ? rad : rMax;
// We'll be uisng y as the radius, and x as the angle (theta=t) // We'll be uisng y as the radius, and x as the angle (theta=t)
var rSize = ySize, var rSize = ySize,
tSize = xSize, tSize = xSize,
radius, radius,
theta; theta;
// We want to cover all angles (0-360) and we need to convert to // We want to cover all angles (0-360) and we need to convert to
// radians (*PI/180) // radians (*PI/180)
var conversion = ((360 / tSize) * Math.PI) / 180, var conversion = ((360 / tSize) * Math.PI) / 180,
sin, sin,
cos; cos;
// var x1, x2, x1i, x2i, y1, y2, y1i, y2i, scale; // var x1, x2, x1i, x2i, y1, y2, y1i, y2i, scale;
for (theta = 0; theta < tSize; theta += 1) { for (theta = 0; theta < tSize; theta += 1) {
sin = Math.sin(theta * conversion); sin = Math.sin(theta * conversion);
cos = Math.cos(theta * conversion); cos = Math.cos(theta * conversion);
@ -67,7 +60,6 @@ var ToPolar = function (src, dst, opt) {
g = srcPixels[i + 1]; g = srcPixels[i + 1];
b = srcPixels[i + 2]; b = srcPixels[i + 2];
a = srcPixels[i + 3]; a = srcPixels[i + 3];
// Store it // Store it
//i = (theta * xSize + radius) * 4; //i = (theta * xSize + radius) * 4;
i = (theta + radius * xSize) * 4; i = (theta + radius * xSize) * 4;
@ -78,7 +70,6 @@ var ToPolar = function (src, dst, opt) {
} }
} }
}; };
/* /*
* FromPolar Filter. Converts image data from polar coordinates back to rectangular. * FromPolar Filter. Converts image data from polar coordinates back to rectangular.
* Performs w*h*4 pixel reads and w*h pixel writes. * Performs w*h*4 pixel reads and w*h pixel writes.
@ -95,7 +86,6 @@ var ToPolar = function (src, dst, opt) {
* @param {Number} [opt.polarRotation] amount to rotate the image counterclockwis, * @param {Number} [opt.polarRotation] amount to rotate the image counterclockwis,
* 0 is no rotation, 360 degrees is a full rotation * 0 is no rotation, 360 degrees is a full rotation
*/ */
var FromPolar = function (src, dst, opt) { var FromPolar = function (src, dst, opt) {
var srcPixels = src.data, var srcPixels = src.data,
dstPixels = dst.data, dstPixels = dst.data,
@ -112,7 +102,6 @@ var FromPolar = function (src, dst, opt) {
g = 0, g = 0,
b = 0, b = 0,
a = 0; a = 0;
// Find the largest radius // Find the largest radius
var rad, var rad,
rMax = Math.sqrt(xMid * xMid + yMid * yMid); rMax = Math.sqrt(xMid * xMid + yMid * yMid);
@ -120,21 +109,17 @@ var FromPolar = function (src, dst, opt) {
y = ySize - yMid; y = ySize - yMid;
rad = Math.sqrt(x * x + y * y); rad = Math.sqrt(x * x + y * y);
rMax = rad > rMax ? rad : rMax; rMax = rad > rMax ? rad : rMax;
// We'll be uisng x as the radius, and y as the angle (theta=t) // We'll be uisng x as the radius, and y as the angle (theta=t)
var rSize = ySize, var rSize = ySize,
tSize = xSize, tSize = xSize,
radius, radius,
theta, theta,
phaseShift = opt.polarRotation || 0; phaseShift = opt.polarRotation || 0;
// We need to convert to degrees and we need to make sure // We need to convert to degrees and we need to make sure
// it's between (0-360) // it's between (0-360)
// var conversion = tSize/360*180/Math.PI; // var conversion = tSize/360*180/Math.PI;
//var conversion = tSize/360*180/Math.PI; //var conversion = tSize/360*180/Math.PI;
var x1, y1; var x1, y1;
for (x = 0; x < xSize; x += 1) { for (x = 0; x < xSize; x += 1) {
for (y = 0; y < ySize; y += 1) { for (y = 0; y < ySize; y += 1) {
dx = x - xMid; dx = x - xMid;
@ -149,7 +134,6 @@ var FromPolar = function (src, dst, opt) {
g = srcPixels[i + 1]; g = srcPixels[i + 1];
b = srcPixels[i + 2]; b = srcPixels[i + 2];
a = srcPixels[i + 3]; a = srcPixels[i + 3];
// Store it // Store it
i = (y * xSize + x) * 4; i = (y * xSize + x) * 4;
dstPixels[i + 0] = r; dstPixels[i + 0] = r;
@ -159,12 +143,9 @@ var FromPolar = function (src, dst, opt) {
} }
} }
}; };
//Konva.Filters.ToPolar = Util._FilterWrapDoubleBuffer(ToPolar); //Konva.Filters.ToPolar = Util._FilterWrapDoubleBuffer(ToPolar);
//Konva.Filters.FromPolar = Util._FilterWrapDoubleBuffer(FromPolar); //Konva.Filters.FromPolar = Util._FilterWrapDoubleBuffer(FromPolar);
// create a temporary canvas for working - shared between multiple calls // create a temporary canvas for working - shared between multiple calls
/* /*
* Kaleidoscope Filter. * Kaleidoscope Filter.
* @function * @function
@ -180,22 +161,19 @@ var FromPolar = function (src, dst, opt) {
export const Kaleidoscope: Filter = function (imageData) { export const Kaleidoscope: Filter = function (imageData) {
var xSize = imageData.width, var xSize = imageData.width,
ySize = imageData.height; ySize = imageData.height;
var x, y, xoff, i, r, g, b, a, srcPos, dstPos; var x, y, xoff, i, r, g, b, a, srcPos, dstPos;
var power = Math.round(this.kaleidoscopePower()); var power = Math.round(this.kaleidoscopePower());
var angle = Math.round(this.kaleidoscopeAngle()); var angle = Math.round(this.kaleidoscopeAngle());
var offset = Math.floor((xSize * (angle % 360)) / 360); var offset = Math.floor((xSize * (angle % 360)) / 360);
if (power < 1) { if (power < 1) {
return; return;
} }
// Work with our shared buffer canvas // Work with our shared buffer canvas
var tempCanvas = Util.createCanvasElement(); var tempCanvas = Util.createCanvasElement();
tempCanvas.width = xSize; tempCanvas.width = xSize;
tempCanvas.height = ySize; tempCanvas.height = ySize;
var scratchData = tempCanvas var scratchData = tempCanvas
.getContext('2d') .getContext('2d')!
.getImageData(0, 0, xSize, ySize); .getImageData(0, 0, xSize, ySize);
Util.releaseCanvas(tempCanvas); Util.releaseCanvas(tempCanvas);
// Convert thhe original to polar coordinates // Convert thhe original to polar coordinates
@ -203,7 +181,6 @@ export const Kaleidoscope: Filter = function (imageData) {
polarCenterX: xSize / 2, polarCenterX: xSize / 2,
polarCenterY: ySize / 2, polarCenterY: ySize / 2,
}); });
// Determine how big each section will be, if it's too small // Determine how big each section will be, if it's too small
// make it bigger // make it bigger
var minSectionSize = xSize / Math.pow(2, power); var minSectionSize = xSize / Math.pow(2, power);
@ -213,7 +190,6 @@ export const Kaleidoscope: Filter = function (imageData) {
} }
minSectionSize = Math.ceil(minSectionSize); minSectionSize = Math.ceil(minSectionSize);
var sectionSize = minSectionSize; var sectionSize = minSectionSize;
// Copy the offset region to 0 // Copy the offset region to 0
// Depending on the size of filter and location of the offset we may need // Depending on the size of filter and location of the offset we may need
// to copy the section backwards to prevent it from rewriting itself // to copy the section backwards to prevent it from rewriting itself
@ -240,7 +216,6 @@ export const Kaleidoscope: Filter = function (imageData) {
scratchData.data[dstPos + 3] = a; scratchData.data[dstPos + 3] = a;
} }
} }
// Perform the actual effect // Perform the actual effect
for (y = 0; y < ySize; y += 1) { for (y = 0; y < ySize; y += 1) {
sectionSize = Math.floor(minSectionSize); sectionSize = Math.floor(minSectionSize);
@ -260,11 +235,9 @@ export const Kaleidoscope: Filter = function (imageData) {
sectionSize *= 2; sectionSize *= 2;
} }
} }
// Convert back from polar coordinates // Convert back from polar coordinates
FromPolar(scratchData, imageData, { polarRotation: 0 }); FromPolar(scratchData, imageData, { polarRotation: 0 });
}; };
/** /**
* get/set kaleidoscope power. Use with {@link Konva.Filters.Kaleidoscope} filter. * get/set kaleidoscope power. Use with {@link Konva.Filters.Kaleidoscope} filter.
* @name Konva.Node#kaleidoscopePower * @name Konva.Node#kaleidoscopePower
@ -279,7 +252,6 @@ Factory.addGetterSetter(
getNumberValidator(), getNumberValidator(),
Factory.afterSetFilter Factory.afterSetFilter
); );
/** /**
* get/set kaleidoscope angle. Use with {@link Konva.Filters.Kaleidoscope} filter. * get/set kaleidoscope angle. Use with {@link Konva.Filters.Kaleidoscope} filter.
* @name Konva.Node#kaleidoscopeAngle * @name Konva.Node#kaleidoscopeAngle

View File

@ -3,10 +3,8 @@ import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape'; import { Shape, ShapeConfig } from '../Shape';
import { getNumberValidator, getNumberArrayValidator } from '../Validators'; import { getNumberValidator, getNumberArrayValidator } from '../Validators';
import { _registerNode } from '../Global'; import { _registerNode } from '../Global';
import { GetSet } from '../types'; import { GetSet } from '../types';
import { Context } from '../Context'; import { Context } from '../Context';
function getControlPoints(x0, y0, x1, y1, x2, y2, t) { function getControlPoints(x0, y0, x1, y1, x2, y2, t) {
var d01 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)), var d01 = Math.sqrt(Math.pow(x1 - x0, 2) + Math.pow(y1 - y0, 2)),
d12 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)), d12 = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)),
@ -16,16 +14,13 @@ function getControlPoints(x0, y0, x1, y1, x2, y2, t) {
p1y = y1 - fa * (y2 - y0), p1y = y1 - fa * (y2 - y0),
p2x = x1 + fb * (x2 - x0), p2x = x1 + fb * (x2 - x0),
p2y = y1 + fb * (y2 - y0); p2y = y1 + fb * (y2 - y0);
return [p1x, p1y, p2x, p2y]; return [p1x, p1y, p2x, p2y];
} }
function expandPoints(p, tension) { function expandPoints(p, tension) {
var len = p.length, var len = p.length,
allPoints = [], allPoints: any[] = [],
n, n,
cp; cp;
for (n = 2; n < len - 2; n += 2) { for (n = 2; n < len - 2; n += 2) {
cp = getControlPoints( cp = getControlPoints(
p[n - 2], p[n - 2],
@ -46,17 +41,14 @@ function expandPoints(p, tension) {
allPoints.push(cp[2]); allPoints.push(cp[2]);
allPoints.push(cp[3]); allPoints.push(cp[3]);
} }
return allPoints; return allPoints;
} }
export interface LineConfig extends ShapeConfig { export interface LineConfig extends ShapeConfig {
points?: number[] | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array; points?: number[] | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
tension?: number; tension?: number;
closed?: boolean; closed?: boolean;
bezier?: boolean; bezier?: boolean;
} }
/** /**
* Line constructor.&nbsp; Lines are defined by an array of points and * Line constructor.&nbsp; Lines are defined by an array of points and
* a tension * a tension
@ -80,7 +72,6 @@ export interface LineConfig extends ShapeConfig {
* tension: 1 * tension: 1
* }); * });
*/ */
export class Line< export class Line<
Config extends LineConfig = LineConfig Config extends LineConfig = LineConfig
> extends Shape<Config> { > extends Shape<Config> {
@ -93,7 +84,6 @@ export class Line<
} }
); );
} }
_sceneFunc(context: Context) { _sceneFunc(context: Context) {
var points = this.points(), var points = this.points(),
length = points.length, length = points.length,
@ -103,24 +93,19 @@ export class Line<
tp, tp,
len, len,
n; n;
if (!length) { if (!length) {
return; return;
} }
context.beginPath(); context.beginPath();
context.moveTo(points[0], points[1]); context.moveTo(points[0], points[1]);
// tension // tension
if (tension !== 0 && length > 4) { if (tension !== 0 && length > 4) {
tp = this.getTensionPoints(); tp = this.getTensionPoints();
len = tp.length; len = tp.length;
n = closed ? 0 : 4; n = closed ? 0 : 4;
if (!closed) { if (!closed) {
context.quadraticCurveTo(tp[0], tp[1], tp[2], tp[3]); context.quadraticCurveTo(tp[0], tp[1], tp[2], tp[3]);
} }
while (n < len - 2) { while (n < len - 2) {
context.bezierCurveTo( context.bezierCurveTo(
tp[n++], tp[n++],
@ -131,7 +116,6 @@ export class Line<
tp[n++] tp[n++]
); );
} }
if (!closed) { if (!closed) {
context.quadraticCurveTo( context.quadraticCurveTo(
tp[len - 2], tp[len - 2],
@ -143,7 +127,6 @@ export class Line<
} else if (bezier) { } else if (bezier) {
// no tension but bezier // no tension but bezier
n = 2; n = 2;
while (n < length) { while (n < length) {
context.bezierCurveTo( context.bezierCurveTo(
points[n++], points[n++],
@ -160,7 +143,6 @@ export class Line<
context.lineTo(points[n], points[n + 1]); context.lineTo(points[n], points[n + 1]);
} }
} }
// closed e.g. polygons and blobs // closed e.g. polygons and blobs
if (closed) { if (closed) {
context.closePath(); context.closePath();
@ -217,7 +199,6 @@ export class Line<
p[0], p[0],
p[1], p[1],
]); ]);
return tp; return tp;
} }
getWidth() { getWidth() {
@ -268,20 +249,16 @@ export class Line<
height: maxY - minY, height: maxY - minY,
}; };
} }
closed: GetSet<boolean, this>; closed: GetSet<boolean, this>;
bezier: GetSet<boolean, this>; bezier: GetSet<boolean, this>;
tension: GetSet<number, this>; tension: GetSet<number, this>;
points: GetSet<number[], this>; points: GetSet<number[], this>;
} }
Line.prototype.className = 'Line'; Line.prototype.className = 'Line';
Line.prototype._attrsAffectingSize = ['points', 'bezier', 'tension']; Line.prototype._attrsAffectingSize = ['points', 'bezier', 'tension'];
_registerNode(Line); _registerNode(Line);
// add getters setters // add getters setters
Factory.addGetterSetter(Line, 'closed', false); Factory.addGetterSetter(Line, 'closed', false);
/** /**
* get/set closed flag. The default is false * get/set closed flag. The default is false
* @name Konva.Line#closed * @name Konva.Line#closed
@ -298,9 +275,7 @@ Factory.addGetterSetter(Line, 'closed', false);
* // open the shape * // open the shape
* line.closed(false); * line.closed(false);
*/ */
Factory.addGetterSetter(Line, 'bezier', false); Factory.addGetterSetter(Line, 'bezier', false);
/** /**
* get/set bezier flag. The default is false * get/set bezier flag. The default is false
* @name Konva.Line#bezier * @name Konva.Line#bezier
@ -314,9 +289,7 @@ Factory.addGetterSetter(Line, 'bezier', false);
* // set whether the line is a bezier * // set whether the line is a bezier
* line.bezier(true); * line.bezier(true);
*/ */
Factory.addGetterSetter(Line, 'tension', 0, getNumberValidator()); Factory.addGetterSetter(Line, 'tension', 0, getNumberValidator());
/** /**
* get/set tension * get/set tension
* @name Konva.Line#tension * @name Konva.Line#tension
@ -330,7 +303,6 @@ Factory.addGetterSetter(Line, 'tension', 0, getNumberValidator());
* // set tension * // set tension
* line.tension(3); * line.tension(3);
*/ */
Factory.addGetterSetter(Line, 'points', [], getNumberArrayValidator()); Factory.addGetterSetter(Line, 'points', [], getNumberArrayValidator());
/** /**
* get/set points array. Points is a flat array [x1, y1, x2, y2]. It is flat for performance reasons. * get/set points array. Points is a flat array [x1, y1, x2, y2]. It is flat for performance reasons.

View File

@ -1,14 +1,12 @@
import { Factory } from '../Factory'; import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape'; import { Shape, ShapeConfig } from '../Shape';
import { _registerNode } from '../Global'; import { _registerNode } from '../Global';
import { GetSet, PathSegment } from '../types'; import { GetSet, PathSegment } from '../types';
import { import {
getCubicArcLength, getCubicArcLength,
getQuadraticArcLength, getQuadraticArcLength,
t2length, t2length,
} from '../BezierFunctions'; } from '../BezierFunctions';
export interface PathConfig extends ShapeConfig { export interface PathConfig extends ShapeConfig {
data?: string; data?: string;
} }
@ -33,26 +31,21 @@ export interface PathConfig extends ShapeConfig {
* }); * });
*/ */
export class Path extends Shape<PathConfig> { export class Path extends Shape<PathConfig> {
dataArray = []; dataArray: any[] = [];
pathLength = 0; pathLength = 0;
constructor(config?: PathConfig) { constructor(config?: PathConfig) {
super(config); super(config);
this._readDataAttribute(); this._readDataAttribute();
this.on('dataChange.konva', function () { this.on('dataChange.konva', function () {
this._readDataAttribute(); this._readDataAttribute();
}); });
} }
_readDataAttribute() { _readDataAttribute() {
this.dataArray = Path.parsePathData(this.data()); this.dataArray = Path.parsePathData(this.data());
this.pathLength = Path.getPathLength(this.dataArray); this.pathLength = Path.getPathLength(this.dataArray);
} }
_sceneFunc(context) { _sceneFunc(context) {
var ca = this.dataArray; var ca = this.dataArray;
// context position // context position
context.beginPath(); context.beginPath();
var isClosed = false; var isClosed = false;
@ -81,11 +74,9 @@ export class Path extends Shape<PathConfig> {
dTheta = p[5], dTheta = p[5],
psi = p[6], psi = p[6],
fs = p[7]; fs = p[7];
var r = rx > ry ? rx : ry; var r = rx > ry ? rx : ry;
var scaleX = rx > ry ? 1 : rx / ry; var scaleX = rx > ry ? 1 : rx / ry;
var scaleY = rx > ry ? ry / rx : 1; var scaleY = rx > ry ? ry / rx : 1;
context.translate(cx, cy); context.translate(cx, cy);
context.rotate(psi); context.rotate(psi);
context.scale(scaleX, scaleY); context.scale(scaleX, scaleY);
@ -93,7 +84,6 @@ export class Path extends Shape<PathConfig> {
context.scale(1 / scaleX, 1 / scaleY); context.scale(1 / scaleX, 1 / scaleY);
context.rotate(-psi); context.rotate(-psi);
context.translate(-cx, -cy); context.translate(-cx, -cy);
break; break;
case 'z': case 'z':
isClosed = true; isClosed = true;
@ -101,7 +91,6 @@ export class Path extends Shape<PathConfig> {
break; break;
} }
} }
if (!isClosed && !this.hasFill()) { if (!isClosed && !this.hasFill()) {
context.strokeShape(this); context.strokeShape(this);
} else { } else {
@ -109,7 +98,7 @@ export class Path extends Shape<PathConfig> {
} }
} }
getSelfRect() { getSelfRect() {
var points = []; var points: any[] = [];
this.dataArray.forEach(function (data) { this.dataArray.forEach(function (data) {
if (data.command === 'A') { if (data.command === 'A') {
// Approximates by breaking curve into line segments // Approximates by breaking curve into line segments
@ -179,7 +168,6 @@ export class Path extends Shape<PathConfig> {
for (var i = 0; i < points.length / 2; i++) { for (var i = 0; i < points.length / 2; i++) {
x = points[i * 2]; x = points[i * 2];
y = points[i * 2 + 1]; y = points[i * 2 + 1];
// skip bad values // skip bad values
if (!isNaN(x)) { if (!isNaN(x)) {
minX = Math.min(minX, x); minX = Math.min(minX, x);
@ -220,13 +208,10 @@ export class Path extends Shape<PathConfig> {
getPointAtLength(length) { getPointAtLength(length) {
return Path.getPointAtLengthOfDataArray(length, this.dataArray); return Path.getPointAtLengthOfDataArray(length, this.dataArray);
} }
data: GetSet<string, this>; data: GetSet<string, this>;
static getLineLength(x1, y1, x2, y2) { static getLineLength(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
} }
static getPathLength(dataArray: PathSegment[]) { static getPathLength(dataArray: PathSegment[]) {
let pathLength = 0; let pathLength = 0;
for (var i = 0; i < dataArray.length; ++i) { for (var i = 0; i < dataArray.length; ++i) {
@ -234,21 +219,17 @@ export class Path extends Shape<PathConfig> {
} }
return pathLength; return pathLength;
} }
static getPointAtLengthOfDataArray(length: number, dataArray) { static getPointAtLengthOfDataArray(length: number, dataArray) {
var point, var point,
i = 0, i = 0,
ii = dataArray.length; ii = dataArray.length;
if (!ii) { if (!ii) {
return null; return null;
} }
while (i < ii && length > dataArray[i].pathLength) { while (i < ii && length > dataArray[i].pathLength) {
length -= dataArray[i].pathLength; length -= dataArray[i].pathLength;
++i; ++i;
} }
if (i === ii) { if (i === ii) {
point = dataArray[i - 1].points.slice(-2); point = dataArray[i - 1].points.slice(-2);
return { return {
@ -256,7 +237,6 @@ export class Path extends Shape<PathConfig> {
y: point[1], y: point[1],
}; };
} }
if (length < 0.01) { if (length < 0.01) {
point = dataArray[i].points.slice(0, 2); point = dataArray[i].points.slice(0, 2);
return { return {
@ -264,7 +244,6 @@ export class Path extends Shape<PathConfig> {
y: point[1], y: point[1],
}; };
} }
var cp = dataArray[i]; var cp = dataArray[i];
var p = cp.points; var p = cp.points;
switch (cp.command) { switch (cp.command) {
@ -315,10 +294,8 @@ export class Path extends Shape<PathConfig> {
theta += (dTheta * length) / cp.pathLength; theta += (dTheta * length) / cp.pathLength;
return Path.getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi); return Path.getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi);
} }
return null; return null;
} }
static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) { static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) {
if (fromX === undefined) { if (fromX === undefined) {
fromX = P1x; fromX = P1x;
@ -326,7 +303,6 @@ export class Path extends Shape<PathConfig> {
if (fromY === undefined) { if (fromY === undefined) {
fromY = P1y; fromY = P1y;
} }
var m = (P2y - P1y) / (P2x - P1x + 0.00000001); var m = (P2y - P1y) / (P2x - P1x + 0.00000001);
var run = Math.sqrt((dist * dist) / (1 + m * m)); var run = Math.sqrt((dist * dist) / (1 + m * m));
if (P2x < P1x) { if (P2x < P1x) {
@ -334,7 +310,6 @@ export class Path extends Shape<PathConfig> {
} }
var rise = m * run; var rise = m * run;
var pt; var pt;
if (P2x === P1x) { if (P2x === P1x) {
// vertical line // vertical line
pt = { pt = {
@ -348,7 +323,6 @@ export class Path extends Shape<PathConfig> {
}; };
} else { } else {
var ix, iy; var ix, iy;
var len = this.getLineLength(P1x, P1y, P2x, P2y); var len = this.getLineLength(P1x, P1y, P2x, P2y);
// if (len < 0.00000001) { // if (len < 0.00000001) {
// return { // return {
@ -360,7 +334,6 @@ export class Path extends Shape<PathConfig> {
u = u / (len * len); u = u / (len * len);
ix = P1x + u * (P2x - P1x); ix = P1x + u * (P2x - P1x);
iy = P1y + u * (P2y - P1y); iy = P1y + u * (P2y - P1y);
var pRise = this.getLineLength(fromX, fromY, ix, iy); var pRise = this.getLineLength(fromX, fromY, ix, iy);
var pRun = Math.sqrt(dist * dist - pRise * pRise); var pRun = Math.sqrt(dist * dist - pRise * pRise);
run = Math.sqrt((pRun * pRun) / (1 + m * m)); run = Math.sqrt((pRun * pRun) / (1 + m * m));
@ -373,10 +346,8 @@ export class Path extends Shape<PathConfig> {
y: iy + rise, y: iy + rise,
}; };
} }
return pt; return pt;
} }
static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) { static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) {
function CB1(t) { function CB1(t) {
return t * t * t; return t * t * t;
@ -392,7 +363,6 @@ export class Path extends Shape<PathConfig> {
} }
var x = P4x * CB1(pct) + P3x * CB2(pct) + P2x * CB3(pct) + P1x * CB4(pct); var x = P4x * CB1(pct) + P3x * CB2(pct) + P2x * CB3(pct) + P1x * CB4(pct);
var y = P4y * CB1(pct) + P3y * CB2(pct) + P2y * CB3(pct) + P1y * CB4(pct); var y = P4y * CB1(pct) + P3y * CB2(pct) + P2y * CB3(pct) + P1y * CB4(pct);
return { return {
x: x, x: x,
y: y, y: y,
@ -410,7 +380,6 @@ export class Path extends Shape<PathConfig> {
} }
var x = P3x * QB1(pct) + P2x * QB2(pct) + P1x * QB3(pct); var x = P3x * QB1(pct) + P2x * QB2(pct) + P1x * QB3(pct);
var y = P3y * QB1(pct) + P2y * QB2(pct) + P1y * QB3(pct); var y = P3y * QB1(pct) + P2y * QB2(pct) + P1y * QB3(pct);
return { return {
x: x, x: x,
y: y, y: y,
@ -456,15 +425,12 @@ export class Path extends Shape<PathConfig> {
//S (x2 y2 x y)+ Shorthand/Smooth Absolute Bezier curve //S (x2 y2 x y)+ Shorthand/Smooth Absolute Bezier curve
//a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Relative Elliptical Arc //a (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Relative Elliptical Arc
//A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Absolute Elliptical Arc //A (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ Absolute Elliptical Arc
// return early if data is not defined // return early if data is not defined
if (!data) { if (!data) {
return []; return [];
} }
// command string // command string
var cs = data; var cs = data;
// command chars // command chars
var cc = [ var cc = [
'm', 'm',
@ -496,29 +462,25 @@ export class Path extends Shape<PathConfig> {
} }
// create array // create array
var arr = cs.split('|'); var arr = cs.split('|');
var ca = []; var ca: any[] = [];
var coords = []; var coords: any[] = [];
// init context point // init context point
var cpx = 0; var cpx = 0;
var cpy = 0; var cpy = 0;
var re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi; var re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi;
var match; var match;
for (n = 1; n < arr.length; n++) { for (n = 1; n < arr.length; n++) {
var str = arr[n]; var str = arr[n];
var c = str.charAt(0); var c = str.charAt(0);
str = str.slice(1); str = str.slice(1);
coords.length = 0; coords.length = 0;
while ((match = re.exec(str))) { while ((match = re.exec(str))) {
coords.push(match[0]); coords.push(match[0]);
} }
// while ((match = re.exec(str))) { // while ((match = re.exec(str))) {
// coords.push(match[0]); // coords.push(match[0]);
// } // }
var p = []; var p: any[] = [];
for (var j = 0, jlen = coords.length; j < jlen; j++) { for (var j = 0, jlen = coords.length; j < jlen; j++) {
// extra case for merged flags // extra case for merged flags
if (coords[j] === '00') { if (coords[j] === '00') {
@ -532,21 +494,18 @@ export class Path extends Shape<PathConfig> {
p.push(0); p.push(0);
} }
} }
while (p.length > 0) { while (p.length > 0) {
if (isNaN(p[0])) { if (isNaN(p[0])) {
// case for a trailing comma before next command // case for a trailing comma before next command
break; break;
} }
var cmd: any = null!;
var cmd = null; var points: any[] = [];
var points = [];
var startX = cpx, var startX = cpx,
startY = cpy; startY = cpy;
// Move var from within the switch to up here (jshint) // Move var from within the switch to up here (jshint)
var prevCmd, ctlPtx, ctlPty; // Ss, Tt var prevCmd, ctlPtx, ctlPty; // Ss, Tt
var rx, ry, psi, fa, fs, x1, y1; // Aa var rx, ry, psi, fa, fs, x1, y1; // Aa
// convert l, H, h, V, and v to L // convert l, H, h, V, and v to L
switch (c) { switch (c) {
// Note: Keep the lineTo's above the moveTo's in this switch // Note: Keep the lineTo's above the moveTo's in this switch
@ -591,7 +550,6 @@ export class Path extends Shape<PathConfig> {
c = 'L'; c = 'L';
// subsequent points are treated as absolute lineTo // subsequent points are treated as absolute lineTo
break; break;
case 'h': case 'h':
cpx += p.shift(); cpx += p.shift();
cmd = 'L'; cmd = 'L';
@ -744,7 +702,6 @@ export class Path extends Shape<PathConfig> {
); );
break; break;
} }
ca.push({ ca.push({
command: cmd || c, command: cmd || c,
points: points, points: points,
@ -755,7 +712,6 @@ export class Path extends Shape<PathConfig> {
pathLength: this.calcLength(startX, startY, cmd || c, points), pathLength: this.calcLength(startX, startY, cmd || c, points),
}); });
} }
if (c === 'z' || c === 'Z') { if (c === 'z' || c === 'Z') {
ca.push({ ca.push({
command: 'z', command: 'z',
@ -765,13 +721,11 @@ export class Path extends Shape<PathConfig> {
}); });
} }
} }
return ca; return ca;
} }
static calcLength(x, y, cmd, points) { static calcLength(x, y, cmd, points) {
var len, p1, p2, t; var len, p1, p2, t;
var path = Path; var path = Path;
switch (cmd) { switch (cmd) {
case 'L': case 'L':
return path.getLineLength(x, y, points[0], points[1]); return path.getLineLength(x, y, points[0], points[1]);
@ -847,10 +801,8 @@ export class Path extends Shape<PathConfig> {
0 0
); );
len += path.getLineLength(p1.x, p1.y, p2.x, p2.y); len += path.getLineLength(p1.x, p1.y, p2.x, p2.y);
return len; return len;
} }
return 0; return 0;
} }
static convertEndpointToCenterParameterization( static convertEndpointToCenterParameterization(
@ -871,32 +823,25 @@ export class Path extends Shape<PathConfig> {
var yp = var yp =
(-1 * Math.sin(psi) * (x1 - x2)) / 2.0 + (-1 * Math.sin(psi) * (x1 - x2)) / 2.0 +
(Math.cos(psi) * (y1 - y2)) / 2.0; (Math.cos(psi) * (y1 - y2)) / 2.0;
var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry); var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
if (lambda > 1) { if (lambda > 1) {
rx *= Math.sqrt(lambda); rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda); ry *= Math.sqrt(lambda);
} }
var f = Math.sqrt( var f = Math.sqrt(
(rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) / (rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) /
(rx * rx * (yp * yp) + ry * ry * (xp * xp)) (rx * rx * (yp * yp) + ry * ry * (xp * xp))
); );
if (fa === fs) { if (fa === fs) {
f *= -1; f *= -1;
} }
if (isNaN(f)) { if (isNaN(f)) {
f = 0; f = 0;
} }
var cxp = (f * rx * yp) / ry; var cxp = (f * rx * yp) / ry;
var cyp = (f * -ry * xp) / rx; var cyp = (f * -ry * xp) / rx;
var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp; var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp;
var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp; var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp;
var vMag = function (v) { var vMag = function (v) {
return Math.sqrt(v[0] * v[0] + v[1] * v[1]); return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
}; };
@ -910,7 +855,6 @@ export class Path extends Shape<PathConfig> {
var u = [(xp - cxp) / rx, (yp - cyp) / ry]; var u = [(xp - cxp) / rx, (yp - cyp) / ry];
var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry]; var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
var dTheta = vAngle(u, v); var dTheta = vAngle(u, v);
if (vRatio(u, v) <= -1) { if (vRatio(u, v) <= -1) {
dTheta = Math.PI; dTheta = Math.PI;
} }
@ -926,11 +870,9 @@ export class Path extends Shape<PathConfig> {
return [cx, cy, rx, ry, theta, dTheta, psi, fs]; return [cx, cy, rx, ry, theta, dTheta, psi, fs];
} }
} }
Path.prototype.className = 'Path'; Path.prototype.className = 'Path';
Path.prototype._attrsAffectingSize = ['data']; Path.prototype._attrsAffectingSize = ['data'];
_registerNode(Path); _registerNode(Path);
/** /**
* get/set SVG path data string. This method * get/set SVG path data string. This method
* also automatically parses the data string * also automatically parses the data string

View File

@ -47,7 +47,7 @@ export class RegularPolygon extends Shape<RegularPolygonConfig> {
_getPoints() { _getPoints() {
const sides = this.attrs.sides; const sides = this.attrs.sides;
const radius = this.attrs.radius || 0; const radius = this.attrs.radius || 0;
const points = []; const points: any[] = [];
for (var n = 0; n < sides; n++) { for (var n = 0; n < sides; n++) {
points.push({ points.push({
x: radius * Math.sin((n * 2 * Math.PI) / sides), x: radius * Math.sin((n * 2 * Math.PI) / sides),

View File

@ -112,7 +112,7 @@ function _strokeFunc(context: Context) {
context.strokeText(this._partialText, this._partialTextX, this._partialTextY); context.strokeText(this._partialText, this._partialTextX, this._partialTextY);
} }
function checkDefaultFill(config: TextConfig) { function checkDefaultFill(config: TextConfig | undefined) {
config = config || {}; config = config || {};
// set default color to black // set default color to black

View File

@ -74,7 +74,7 @@ function _strokeFunc(context) {
*/ */
export class TextPath extends Shape<TextPathConfig> { export class TextPath extends Shape<TextPathConfig> {
dummyCanvas = Util.createCanvasElement(); dummyCanvas = Util.createCanvasElement();
dataArray = []; dataArray: any[] = [];
glyphInfo: Array<{ glyphInfo: Array<{
transposeX: number; transposeX: number;
transposeY: number; transposeY: number;
@ -221,7 +221,7 @@ export class TextPath extends Shape<TextPathConfig> {
_getTextSize(text: string) { _getTextSize(text: string) {
var dummyCanvas = this.dummyCanvas; var dummyCanvas = this.dummyCanvas;
var _context = dummyCanvas.getContext('2d'); var _context = dummyCanvas.getContext('2d')!;
_context.save(); _context.save();
@ -338,7 +338,7 @@ export class TextPath extends Shape<TextPathConfig> {
height: 0, height: 0,
}; };
} }
var points = []; var points: number[] = [];
this.glyphInfo.forEach(function (info) { this.glyphInfo.forEach(function (info) {
points.push(info.p0.x); points.push(info.p0.x);

View File

@ -476,7 +476,7 @@ export class Transformer extends Group {
}; };
} }
const totalPoints = []; const totalPoints: Vector2d[] = [];
this.nodes().map((node) => { this.nodes().map((node) => {
const box = node.getClientRect({ const box = node.getClientRect({
skipTransform: true, skipTransform: true,
@ -513,12 +513,12 @@ export class Transformer extends Group {
}); });
tr.invert(); tr.invert();
const p = tr.point({ x: minX, y: minY }); const p = tr.point({ x: minX!, y: minY! });
return { return {
x: p.x, x: p.x,
y: p.y, y: p.y,
width: maxX - minX, width: maxX! - minX!,
height: maxY - minY, height: maxY! - minY!,
rotation: Konva.getAngle(this.rotation()), rotation: Konva.getAngle(this.rotation()),
}; };
// const shapes = this.nodes().map(node => { // const shapes = this.nodes().map(node => {
@ -582,13 +582,13 @@ export class Transformer extends Group {
anchor.on('mouseenter', () => { anchor.on('mouseenter', () => {
var rad = Konva.getAngle(this.rotation()); var rad = Konva.getAngle(this.rotation());
var cursor = getCursor(name, rad); var cursor = getCursor(name, rad);
anchor.getStage().content && anchor.getStage()!.content &&
(anchor.getStage().content.style.cursor = cursor); (anchor.getStage()!.content.style.cursor = cursor);
this._cursorChange = true; this._cursorChange = true;
}); });
anchor.on('mouseout', () => { anchor.on('mouseout', () => {
anchor.getStage().content && anchor.getStage()!.content &&
(anchor.getStage().content.style.cursor = ''); (anchor.getStage()!.content.style.cursor = '');
this._cursorChange = false; this._cursorChange = false;
}); });
this.add(anchor); this.add(anchor);
@ -685,12 +685,12 @@ export class Transformer extends Group {
} }
_handleMouseMove(e) { _handleMouseMove(e) {
var x, y, newHypotenuse; var x, y, newHypotenuse;
var anchorNode = this.findOne('.' + this._movingAnchorName); var anchorNode = this.findOne('.' + this._movingAnchorName)!;
var stage = anchorNode.getStage(); var stage = anchorNode?.getStage()!;
stage.setPointersPositions(e); stage.setPointersPositions(e);
const pp = stage.getPointerPosition(); const pp = stage.getPointerPosition()!;
let newNodePos = { let newNodePos = {
x: pp.x - this._anchorDragOffset.x, x: pp.x - this._anchorDragOffset.x,
y: pp.y - this._anchorDragOffset.y, y: pp.y - this._anchorDragOffset.y,
@ -756,26 +756,26 @@ export class Transformer extends Group {
y: this.height() / 2, y: this.height() / 2,
} }
: { : {
x: this.findOne('.bottom-right').x(), x: this.findOne('.bottom-right')!.x(),
y: this.findOne('.bottom-right').y(), y: this.findOne('.bottom-right')!.y(),
}; };
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
Math.pow(comparePoint.x - anchorNode.x(), 2) + Math.pow(comparePoint.x - anchorNode.x(), 2) +
Math.pow(comparePoint.y - anchorNode.y(), 2) Math.pow(comparePoint.y - anchorNode.y(), 2)
); );
var reverseX = this.findOne('.top-left').x() > comparePoint.x ? -1 : 1; var reverseX = this.findOne('.top-left')!.x() > comparePoint.x ? -1 : 1;
var reverseY = this.findOne('.top-left').y() > comparePoint.y ? -1 : 1; var reverseY = this.findOne('.top-left')!.y() > comparePoint.y ? -1 : 1;
x = newHypotenuse * this.cos * reverseX; x = newHypotenuse * this.cos * reverseX;
y = newHypotenuse * this.sin * reverseY; y = newHypotenuse * this.sin * reverseY;
this.findOne('.top-left').x(comparePoint.x - x); this.findOne('.top-left')!.x(comparePoint.x - x);
this.findOne('.top-left').y(comparePoint.y - y); this.findOne('.top-left')!.y(comparePoint.y - y);
} }
} else if (this._movingAnchorName === 'top-center') { } else if (this._movingAnchorName === 'top-center') {
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 (keepProportion) { if (keepProportion) {
var comparePoint = centeredScaling var comparePoint = centeredScaling
@ -784,8 +784,8 @@ export class Transformer extends Group {
y: this.height() / 2, y: this.height() / 2,
} }
: { : {
x: this.findOne('.bottom-left').x(), x: this.findOne('.bottom-left')!.x(),
y: this.findOne('.bottom-left').y(), y: this.findOne('.bottom-left')!.y(),
}; };
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
@ -793,23 +793,23 @@ export class Transformer extends Group {
Math.pow(comparePoint.y - anchorNode.y(), 2) Math.pow(comparePoint.y - anchorNode.y(), 2)
); );
var reverseX = this.findOne('.top-right').x() < comparePoint.x ? -1 : 1; var reverseX = this.findOne('.top-right')!.x() < comparePoint.x ? -1 : 1;
var reverseY = this.findOne('.top-right').y() > comparePoint.y ? -1 : 1; var reverseY = this.findOne('.top-right')!.y() > comparePoint.y ? -1 : 1;
x = newHypotenuse * this.cos * reverseX; x = newHypotenuse * this.cos * reverseX;
y = newHypotenuse * this.sin * reverseY; y = newHypotenuse * this.sin * reverseY;
this.findOne('.top-right').x(comparePoint.x + x); this.findOne('.top-right')!.x(comparePoint.x + x);
this.findOne('.top-right').y(comparePoint.y - y); this.findOne('.top-right')!.y(comparePoint.y - y);
} }
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') {
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') {
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 (keepProportion) { if (keepProportion) {
var comparePoint = centeredScaling var comparePoint = centeredScaling
@ -818,8 +818,8 @@ export class Transformer extends Group {
y: this.height() / 2, y: this.height() / 2,
} }
: { : {
x: this.findOne('.top-right').x(), x: this.findOne('.top-right')!.x(),
y: this.findOne('.top-right').y(), y: this.findOne('.top-right')!.y(),
}; };
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
@ -840,10 +840,10 @@ export class Transformer extends Group {
pos = anchorNode.position(); pos = anchorNode.position();
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') {
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 (keepProportion) { if (keepProportion) {
var comparePoint = centeredScaling var comparePoint = centeredScaling
@ -852,8 +852,8 @@ export class Transformer extends Group {
y: this.height() / 2, y: this.height() / 2,
} }
: { : {
x: this.findOne('.top-left').x(), x: this.findOne('.top-left')!.x(),
y: this.findOne('.top-left').y(), y: this.findOne('.top-left')!.y(),
}; };
newHypotenuse = Math.sqrt( newHypotenuse = Math.sqrt(
@ -862,16 +862,16 @@ export class Transformer extends Group {
); );
var reverseX = var reverseX =
this.findOne('.bottom-right').x() < comparePoint.x ? -1 : 1; this.findOne('.bottom-right')!.x() < comparePoint.x ? -1 : 1;
var reverseY = var reverseY =
this.findOne('.bottom-right').y() < comparePoint.y ? -1 : 1; this.findOne('.bottom-right')!.y() < comparePoint.y ? -1 : 1;
x = newHypotenuse * this.cos * reverseX; x = newHypotenuse * this.cos * reverseX;
y = newHypotenuse * this.sin * reverseY; y = newHypotenuse * this.sin * reverseY;
this.findOne('.bottom-right').x(comparePoint.x + x); this.findOne('.bottom-right')!.x(comparePoint.x + x);
this.findOne('.bottom-right').y(comparePoint.y + y); this.findOne('.bottom-right')!.y(comparePoint.y + y);
} }
} else { } else {
console.error( console.error(
@ -884,8 +884,8 @@ export class Transformer extends Group {
var centeredScaling = this.centeredScaling() || e.altKey; var centeredScaling = this.centeredScaling() || e.altKey;
if (centeredScaling) { if (centeredScaling) {
var topLeft = this.findOne('.top-left'); var topLeft = this.findOne('.top-left')!;
var bottomRight = this.findOne('.bottom-right'); var bottomRight = this.findOne('.bottom-right')!;
var topOffsetX = topLeft.x(); var topOffsetX = topLeft.x();
var topOffsetY = topLeft.y(); var topOffsetY = topLeft.y();
@ -903,16 +903,16 @@ export class Transformer extends Group {
}); });
} }
var absPos = this.findOne('.top-left').getAbsolutePosition(); var absPos = this.findOne('.top-left')!.getAbsolutePosition();
x = absPos.x; x = absPos.x;
y = absPos.y; y = absPos.y;
var width = var width =
this.findOne('.bottom-right').x() - this.findOne('.top-left').x(); this.findOne('.bottom-right')!.x() - this.findOne('.top-left')!.x();
var height = var height =
this.findOne('.bottom-right').y() - this.findOne('.top-left').y(); this.findOne('.bottom-right')!.y() - this.findOne('.top-left')!.y();
this._fitNodesInto( this._fitNodesInto(
{ {
@ -948,7 +948,7 @@ export class Transformer extends Group {
target._fire('transformend', { evt: e, target }); target._fire('transformend', { evt: e, target });
}); });
} }
this._movingAnchorName = null; this._movingAnchorName = null!;
} }
} }
_fitNodesInto(newAttrs, evt?) { _fitNodesInto(newAttrs, evt?) {
@ -1085,7 +1085,7 @@ export class Transformer extends Group {
// [delta transform] * [parent transform] * [old local transform] = [parent transform] * [new local transform] // [delta transform] * [parent transform] * [old local transform] = [parent transform] * [new local transform]
// and we need to find [new local transform] // and we need to find [new local transform]
// [new local] = [parent inverted] * [delta] * [parent] * [old local] // [new local] = [parent inverted] * [delta] * [parent] * [old local]
const parentTransform = node.getParent().getAbsoluteTransform(); const parentTransform = node.getParent()!.getAbsoluteTransform();
const localTransform = node.getTransform().copy(); const localTransform = node.getTransform().copy();
// skip offset: // skip offset:
localTransform.translate(node.offsetX(), node.offsetY()); localTransform.translate(node.offsetX(), node.offsetY());
@ -1106,7 +1106,7 @@ export class Transformer extends Group {
this.rotation(Util._getRotation(newAttrs.rotation)); this.rotation(Util._getRotation(newAttrs.rotation));
this._resetTransformCache(); this._resetTransformCache();
this.update(); this.update();
this.getLayer().batchDraw(); this.getLayer()?.batchDraw();
} }
/** /**
* force update of Konva.Transformer. * force update of Konva.Transformer.
@ -1120,7 +1120,7 @@ export class Transformer extends Group {
} }
_batchChangeChild(selector: string, attrs: any) { _batchChangeChild(selector: string, attrs: any) {
const anchor = this.findOne(selector); const anchor = this.findOne(selector)!;
anchor.setAttrs(attrs); anchor.setAttrs(attrs);
} }
@ -1253,7 +1253,7 @@ export class Transformer extends Group {
} }
destroy() { destroy() {
if (this.getStage() && this._cursorChange) { if (this.getStage() && this._cursorChange) {
this.getStage().content && (this.getStage().content.style.cursor = ''); this.getStage()?.content && (this.getStage()!.content.style.cursor = '');
} }
Group.prototype.destroy.call(this); Group.prototype.destroy.call(this);
this.detach(); this.detach();
@ -1810,4 +1810,4 @@ Factory.backCompat(Transformer, {
lineEnabled: 'borderEnabled', lineEnabled: 'borderEnabled',
rotateHandlerOffset: 'rotateAnchorOffset', rotateHandlerOffset: 'rotateAnchorOffset',
enabledHandlers: 'enabledAnchors', enabledHandlers: 'enabledAnchors',
}); })