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
for (let n = 0; n < len; n++) {
if (animations[n].id === this.id) {
if (animations[n]['id'] === this.id) {
return true;
}
}

View File

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

View File

@ -6,7 +6,7 @@ import { IRect } from './types';
import type { Node } from './Node';
function simplifyArray(arr: Array<any>) {
var retArr = [],
var retArr: Array<any> = [],
len = arr.length,
util = Util,
n,
@ -441,9 +441,9 @@ export class Context {
if (a.length === 3) {
_context.drawImage(a0, a1, a2);
} else if (a.length === 5) {
_context.drawImage(a0, a1, a2, a3, a4);
_context.drawImage(a0, a1, a2, a3!, a4!);
} 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) => {
const { node } = elem;
// we need to find pointer relative to that node
const stage = node.getStage();
const stage = node.getStage()!;
stage.setPointersPositions(evt);
// 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
// setup all in dragbefore, and stop dragging only after pointerup triggered.
_endDragBefore(evt?) {
const drawNodes = [];
const drawNodes: any[] = [];
DD._dragElements.forEach((elem) => {
const { node } = elem;
// we need to find pointer relative to that node
const stage = node.getStage();
const stage = node.getStage()!;
if (evt) {
stage.setPointersPositions(evt);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,10 +3,8 @@ import { Factory } from '../Factory';
import { Shape, ShapeConfig } from '../Shape';
import { getNumberValidator, getNumberArrayValidator } from '../Validators';
import { _registerNode } from '../Global';
import { GetSet } from '../types';
import { Context } from '../Context';
function getControlPoints(x0, y0, x1, y1, x2, y2, t) {
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)),
@ -16,16 +14,13 @@ function getControlPoints(x0, y0, x1, y1, x2, y2, t) {
p1y = y1 - fa * (y2 - y0),
p2x = x1 + fb * (x2 - x0),
p2y = y1 + fb * (y2 - y0);
return [p1x, p1y, p2x, p2y];
}
function expandPoints(p, tension) {
var len = p.length,
allPoints = [],
allPoints: any[] = [],
n,
cp;
for (n = 2; n < len - 2; n += 2) {
cp = getControlPoints(
p[n - 2],
@ -46,17 +41,14 @@ function expandPoints(p, tension) {
allPoints.push(cp[2]);
allPoints.push(cp[3]);
}
return allPoints;
}
export interface LineConfig extends ShapeConfig {
points?: number[] | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
tension?: number;
closed?: boolean;
bezier?: boolean;
}
/**
* Line constructor.&nbsp; Lines are defined by an array of points and
* a tension
@ -80,7 +72,6 @@ export interface LineConfig extends ShapeConfig {
* tension: 1
* });
*/
export class Line<
Config extends LineConfig = LineConfig
> extends Shape<Config> {
@ -93,7 +84,6 @@ export class Line<
}
);
}
_sceneFunc(context: Context) {
var points = this.points(),
length = points.length,
@ -103,24 +93,19 @@ export class Line<
tp,
len,
n;
if (!length) {
return;
}
context.beginPath();
context.moveTo(points[0], points[1]);
// tension
if (tension !== 0 && length > 4) {
tp = this.getTensionPoints();
len = tp.length;
n = closed ? 0 : 4;
if (!closed) {
context.quadraticCurveTo(tp[0], tp[1], tp[2], tp[3]);
}
while (n < len - 2) {
context.bezierCurveTo(
tp[n++],
@ -131,7 +116,6 @@ export class Line<
tp[n++]
);
}
if (!closed) {
context.quadraticCurveTo(
tp[len - 2],
@ -143,7 +127,6 @@ export class Line<
} else if (bezier) {
// no tension but bezier
n = 2;
while (n < length) {
context.bezierCurveTo(
points[n++],
@ -160,7 +143,6 @@ export class Line<
context.lineTo(points[n], points[n + 1]);
}
}
// closed e.g. polygons and blobs
if (closed) {
context.closePath();
@ -217,7 +199,6 @@ export class Line<
p[0],
p[1],
]);
return tp;
}
getWidth() {
@ -268,20 +249,16 @@ export class Line<
height: maxY - minY,
};
}
closed: GetSet<boolean, this>;
bezier: GetSet<boolean, this>;
tension: GetSet<number, this>;
points: GetSet<number[], this>;
}
Line.prototype.className = 'Line';
Line.prototype._attrsAffectingSize = ['points', 'bezier', 'tension'];
_registerNode(Line);
// add getters setters
Factory.addGetterSetter(Line, 'closed', false);
/**
* get/set closed flag. The default is false
* @name Konva.Line#closed
@ -298,9 +275,7 @@ Factory.addGetterSetter(Line, 'closed', false);
* // open the shape
* line.closed(false);
*/
Factory.addGetterSetter(Line, 'bezier', false);
/**
* get/set bezier flag. The default is false
* @name Konva.Line#bezier
@ -314,9 +289,7 @@ Factory.addGetterSetter(Line, 'bezier', false);
* // set whether the line is a bezier
* line.bezier(true);
*/
Factory.addGetterSetter(Line, 'tension', 0, getNumberValidator());
/**
* get/set tension
* @name Konva.Line#tension
@ -330,7 +303,6 @@ Factory.addGetterSetter(Line, 'tension', 0, getNumberValidator());
* // set tension
* line.tension(3);
*/
Factory.addGetterSetter(Line, 'points', [], getNumberArrayValidator());
/**
* 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 { Shape, ShapeConfig } from '../Shape';
import { _registerNode } from '../Global';
import { GetSet, PathSegment } from '../types';
import {
getCubicArcLength,
getQuadraticArcLength,
t2length,
} from '../BezierFunctions';
export interface PathConfig extends ShapeConfig {
data?: string;
}
@ -33,26 +31,21 @@ export interface PathConfig extends ShapeConfig {
* });
*/
export class Path extends Shape<PathConfig> {
dataArray = [];
dataArray: any[] = [];
pathLength = 0;
constructor(config?: PathConfig) {
super(config);
this._readDataAttribute();
this.on('dataChange.konva', function () {
this._readDataAttribute();
});
}
_readDataAttribute() {
this.dataArray = Path.parsePathData(this.data());
this.pathLength = Path.getPathLength(this.dataArray);
}
_sceneFunc(context) {
var ca = this.dataArray;
// context position
context.beginPath();
var isClosed = false;
@ -81,11 +74,9 @@ export class Path extends Shape<PathConfig> {
dTheta = p[5],
psi = p[6],
fs = p[7];
var r = rx > ry ? rx : ry;
var scaleX = rx > ry ? 1 : rx / ry;
var scaleY = rx > ry ? ry / rx : 1;
context.translate(cx, cy);
context.rotate(psi);
context.scale(scaleX, scaleY);
@ -93,7 +84,6 @@ export class Path extends Shape<PathConfig> {
context.scale(1 / scaleX, 1 / scaleY);
context.rotate(-psi);
context.translate(-cx, -cy);
break;
case 'z':
isClosed = true;
@ -101,7 +91,6 @@ export class Path extends Shape<PathConfig> {
break;
}
}
if (!isClosed && !this.hasFill()) {
context.strokeShape(this);
} else {
@ -109,7 +98,7 @@ export class Path extends Shape<PathConfig> {
}
}
getSelfRect() {
var points = [];
var points: any[] = [];
this.dataArray.forEach(function (data) {
if (data.command === 'A') {
// 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++) {
x = points[i * 2];
y = points[i * 2 + 1];
// skip bad values
if (!isNaN(x)) {
minX = Math.min(minX, x);
@ -220,13 +208,10 @@ export class Path extends Shape<PathConfig> {
getPointAtLength(length) {
return Path.getPointAtLengthOfDataArray(length, this.dataArray);
}
data: GetSet<string, this>;
static getLineLength(x1, y1, x2, y2) {
return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
static getPathLength(dataArray: PathSegment[]) {
let pathLength = 0;
for (var i = 0; i < dataArray.length; ++i) {
@ -234,21 +219,17 @@ export class Path extends Shape<PathConfig> {
}
return pathLength;
}
static getPointAtLengthOfDataArray(length: number, dataArray) {
var point,
i = 0,
ii = dataArray.length;
if (!ii) {
return null;
}
while (i < ii && length > dataArray[i].pathLength) {
length -= dataArray[i].pathLength;
++i;
}
if (i === ii) {
point = dataArray[i - 1].points.slice(-2);
return {
@ -256,7 +237,6 @@ export class Path extends Shape<PathConfig> {
y: point[1],
};
}
if (length < 0.01) {
point = dataArray[i].points.slice(0, 2);
return {
@ -264,7 +244,6 @@ export class Path extends Shape<PathConfig> {
y: point[1],
};
}
var cp = dataArray[i];
var p = cp.points;
switch (cp.command) {
@ -315,10 +294,8 @@ export class Path extends Shape<PathConfig> {
theta += (dTheta * length) / cp.pathLength;
return Path.getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi);
}
return null;
}
static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) {
if (fromX === undefined) {
fromX = P1x;
@ -326,7 +303,6 @@ export class Path extends Shape<PathConfig> {
if (fromY === undefined) {
fromY = P1y;
}
var m = (P2y - P1y) / (P2x - P1x + 0.00000001);
var run = Math.sqrt((dist * dist) / (1 + m * m));
if (P2x < P1x) {
@ -334,7 +310,6 @@ export class Path extends Shape<PathConfig> {
}
var rise = m * run;
var pt;
if (P2x === P1x) {
// vertical line
pt = {
@ -348,7 +323,6 @@ export class Path extends Shape<PathConfig> {
};
} else {
var ix, iy;
var len = this.getLineLength(P1x, P1y, P2x, P2y);
// if (len < 0.00000001) {
// return {
@ -360,7 +334,6 @@ export class Path extends Shape<PathConfig> {
u = u / (len * len);
ix = P1x + u * (P2x - P1x);
iy = P1y + u * (P2y - P1y);
var pRise = this.getLineLength(fromX, fromY, ix, iy);
var pRun = Math.sqrt(dist * dist - pRise * pRise);
run = Math.sqrt((pRun * pRun) / (1 + m * m));
@ -373,10 +346,8 @@ export class Path extends Shape<PathConfig> {
y: iy + rise,
};
}
return pt;
}
static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) {
function CB1(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 y = P4y * CB1(pct) + P3y * CB2(pct) + P2y * CB3(pct) + P1y * CB4(pct);
return {
x: x,
y: y,
@ -410,7 +380,6 @@ export class Path extends Shape<PathConfig> {
}
var x = P3x * QB1(pct) + P2x * QB2(pct) + P1x * QB3(pct);
var y = P3y * QB1(pct) + P2y * QB2(pct) + P1y * QB3(pct);
return {
x: x,
y: y,
@ -456,15 +425,12 @@ export class Path extends Shape<PathConfig> {
//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)+ Absolute Elliptical Arc
// return early if data is not defined
if (!data) {
return [];
}
// command string
var cs = data;
// command chars
var cc = [
'm',
@ -496,29 +462,25 @@ export class Path extends Shape<PathConfig> {
}
// create array
var arr = cs.split('|');
var ca = [];
var coords = [];
var ca: any[] = [];
var coords: any[] = [];
// init context point
var cpx = 0;
var cpy = 0;
var re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi;
var match;
for (n = 1; n < arr.length; n++) {
var str = arr[n];
var c = str.charAt(0);
str = str.slice(1);
coords.length = 0;
while ((match = re.exec(str))) {
coords.push(match[0]);
}
// while ((match = re.exec(str))) {
// coords.push(match[0]);
// }
var p = [];
var p: any[] = [];
for (var j = 0, jlen = coords.length; j < jlen; j++) {
// extra case for merged flags
if (coords[j] === '00') {
@ -532,21 +494,18 @@ export class Path extends Shape<PathConfig> {
p.push(0);
}
}
while (p.length > 0) {
if (isNaN(p[0])) {
// case for a trailing comma before next command
break;
}
var cmd = null;
var points = [];
var cmd: any = null!;
var points: any[] = [];
var startX = cpx,
startY = cpy;
// Move var from within the switch to up here (jshint)
var prevCmd, ctlPtx, ctlPty; // Ss, Tt
var rx, ry, psi, fa, fs, x1, y1; // Aa
// convert l, H, h, V, and v to L
switch (c) {
// Note: Keep the lineTo's above the moveTo's in this switch
@ -591,7 +550,6 @@ export class Path extends Shape<PathConfig> {
c = 'L';
// subsequent points are treated as absolute lineTo
break;
case 'h':
cpx += p.shift();
cmd = 'L';
@ -744,7 +702,6 @@ export class Path extends Shape<PathConfig> {
);
break;
}
ca.push({
command: cmd || c,
points: points,
@ -755,7 +712,6 @@ export class Path extends Shape<PathConfig> {
pathLength: this.calcLength(startX, startY, cmd || c, points),
});
}
if (c === 'z' || c === 'Z') {
ca.push({
command: 'z',
@ -765,13 +721,11 @@ export class Path extends Shape<PathConfig> {
});
}
}
return ca;
}
static calcLength(x, y, cmd, points) {
var len, p1, p2, t;
var path = Path;
switch (cmd) {
case 'L':
return path.getLineLength(x, y, points[0], points[1]);
@ -847,10 +801,8 @@ export class Path extends Shape<PathConfig> {
0
);
len += path.getLineLength(p1.x, p1.y, p2.x, p2.y);
return len;
}
return 0;
}
static convertEndpointToCenterParameterization(
@ -871,32 +823,25 @@ export class Path extends Shape<PathConfig> {
var yp =
(-1 * Math.sin(psi) * (x1 - x2)) / 2.0 +
(Math.cos(psi) * (y1 - y2)) / 2.0;
var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
if (lambda > 1) {
rx *= Math.sqrt(lambda);
ry *= Math.sqrt(lambda);
}
var f = Math.sqrt(
(rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) /
(rx * rx * (yp * yp) + ry * ry * (xp * xp))
);
if (fa === fs) {
f *= -1;
}
if (isNaN(f)) {
f = 0;
}
var cxp = (f * rx * yp) / ry;
var cyp = (f * -ry * xp) / rx;
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 vMag = function (v) {
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 v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
var dTheta = vAngle(u, v);
if (vRatio(u, v) <= -1) {
dTheta = Math.PI;
}
@ -926,11 +870,9 @@ export class Path extends Shape<PathConfig> {
return [cx, cy, rx, ry, theta, dTheta, psi, fs];
}
}
Path.prototype.className = 'Path';
Path.prototype._attrsAffectingSize = ['data'];
_registerNode(Path);
/**
* get/set SVG path data string. This method
* also automatically parses the data string

View File

@ -47,7 +47,7 @@ export class RegularPolygon extends Shape<RegularPolygonConfig> {
_getPoints() {
const sides = this.attrs.sides;
const radius = this.attrs.radius || 0;
const points = [];
const points: any[] = [];
for (var n = 0; n < sides; n++) {
points.push({
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);
}
function checkDefaultFill(config: TextConfig) {
function checkDefaultFill(config: TextConfig | undefined) {
config = config || {};
// set default color to black

View File

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