This commit is contained in:
Anton Lavrenov
2021-05-08 20:22:20 -05:00
parent fcd7cf62b0
commit f8e71d608a
12 changed files with 162 additions and 186 deletions

View File

@@ -22,6 +22,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- new `node.isClientRectOnScreen()` method
- argument `selector` is removed from `node.getIntersection(pos)` API
- `Konva.captureTouchEventsEnabled` is renamed to `Konva.capturePointerEventsEnabled`
- Full event system rewrite. Much better `pointer` evens support.
- `Konva.Util.extend` is removed
- Added `Konva.Util.degToRad` and `Konva.Util.radToDeg`
## 7.2.5

View File

@@ -3,6 +3,27 @@ import { Konva } from './Global';
import { Canvas } from './Canvas';
import { Shape } from './Shape';
function simplifyArray(arr: Array<any>) {
var retArr = [],
len = arr.length,
util = Util,
n,
val;
for (n = 0; n < len; n++) {
val = arr[n];
if (util._isNumber(val)) {
val = Math.round(val * 1000) / 1000;
} else if (!util._isString(val)) {
val = val + '';
}
retArr.push(val);
}
return retArr;
}
var COMMA = ',',
OPEN_PAREN = '(',
CLOSE_PAREN = ')',
@@ -638,7 +659,7 @@ export class Context {
ret;
that[methodName] = function () {
args = Util._simplifyArray(Array.prototype.slice.call(arguments, 0));
args = simplifyArray(Array.prototype.slice.call(arguments, 0));
ret = origMethod.apply(that, arguments);
that._trace({
@@ -810,13 +831,12 @@ export class SceneContext extends Context {
}
}
_applyShadow(shape) {
var util = Util,
color = util.get(shape.getShadowRGBA(), 'black'),
blur = util.get(shape.getShadowBlur(), 5),
offset = util.get(shape.getShadowOffset(), {
var color = shape.getShadowRGBA() ?? 'black',
blur = shape.getShadowBlur() ?? 5,
offset = shape.getShadowOffset() ?? {
x: 0,
y: 0,
}),
},
scale = shape.getAbsoluteScale(),
ratio = this.canvas.getPixelRatio(),
scaleX = scale.x * ratio,

View File

@@ -115,7 +115,9 @@ export const DD = {
if (elem.dragStatus === 'dragging' || elem.dragStatus === 'stopped') {
// if a node is stopped manually we still need to reset events:
DD.justDragged = true;
Konva.listenClickTap = false;
Konva._mouseListenClick = false;
Konva._touchListenClick = false;
Konva._pointerListenClick = false;
elem.dragStatus = 'stopped';
}

View File

@@ -45,7 +45,7 @@ export const Konva = {
return Konva.angleDeg ? angle * PI_OVER_180 : angle;
},
enableTrace: false,
pointerEventsEnabled: false,
pointerEventsEnabled: true,
/**
* Should Konva automatically update canvas on any changes. Default is true.
* @property autoDrawEnabled
@@ -81,8 +81,12 @@ export const Konva = {
*/
capturePointerEventsEnabled: false,
listenClickTap: false,
inDblClickWindow: false,
_mouseListenClick: false,
_touchListenClick: false,
_pointerListenClick: false,
_mouseInDblClickWindow: false,
_touchInDblClickWindow: false,
_pointerInDblClickWindow: false,
/**
* Global pixel ratio configuration. KonvaJS automatically detect pixel ratio of current device.

View File

@@ -2142,7 +2142,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
drawNode?.batchDraw();
}
}
_setAttr(key, val, skipFire = false) {
_setAttr(key, val) {
var oldVal = this.attrs[key];
if (oldVal === val && !Util.isObject(val)) {
return;

View File

@@ -31,36 +31,17 @@ var STAGE = 'Stage',
POINTERUP = 'pointerup',
POINTERCANCEL = 'pointercancel',
LOSTPOINTERCAPTURE = 'lostpointercapture',
POINTEROUT = 'pointerout',
POINTERLEAVE = 'pointerleave',
POINTEROVER = 'pointerover',
POINTERENTER = 'pointerenter',
CONTEXTMENU = 'contextmenu',
CLICK = 'click',
DBL_CLICK = 'dblclick',
TOUCHSTART = 'touchstart',
TOUCHEND = 'touchend',
TAP = 'tap',
DBL_TAP = 'dbltap',
TOUCHMOVE = 'touchmove',
TOUCHCANCEL = 'touchcancel',
WHEEL = 'wheel',
CONTENT_MOUSEOUT = 'contentMouseout',
CONTENT_MOUSEOVER = 'contentMouseover',
CONTENT_MOUSEMOVE = 'contentMousemove',
CONTENT_MOUSEDOWN = 'contentMousedown',
CONTENT_MOUSEUP = 'contentMouseup',
CONTENT_CONTEXTMENU = 'contentContextmenu',
CONTENT_CLICK = 'contentClick',
CONTENT_DBL_CLICK = 'contentDblclick',
CONTENT_TOUCHSTART = 'contentTouchstart',
CONTENT_TOUCHEND = 'contentTouchend',
CONTENT_DBL_TAP = 'contentDbltap',
CONTENT_TAP = 'contentTap',
CONTENT_TOUCHMOVE = 'contentTouchmove',
CONTENT_WHEEL = 'contentWheel',
RELATIVE = 'relative',
KONVA_CONTENT = 'konvajs-content',
UNDERSCORE = '_',
CONTAINER = 'container',
MAX_LAYERS_NUMBER = 5,
EMPTY_STRING = '',
EVENTS = [
[MOUSEENTER, '_pointerenter'],
[MOUSEDOWN, '_pointerdown'],
@@ -81,42 +62,40 @@ var STAGE = 'Stage',
[LOSTPOINTERCAPTURE, '_lostpointercapture'],
];
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[] = [];
const EVENTS_MAP = {
mouse: {
pointerout: 'mouseout',
pointerleave: 'mouseleave',
pointerover: 'mouseover',
pointerenter: 'mouseenter',
pointermove: 'mousemove',
pointerdown: 'mousedown',
pointerup: 'mouseup',
pointercancel: 'mousecancel',
[POINTEROUT]: MOUSEOUT,
[POINTERLEAVE]: MOUSELEAVE,
[POINTEROVER]: MOUSEOVER,
[POINTERENTER]: MOUSEENTER,
[POINTERMOVE]: MOUSEMOVE,
[POINTERDOWN]: MOUSEDOWN,
[POINTERUP]: MOUSEUP,
[POINTERCANCEL]: 'mousecancel',
pointerclick: 'click',
pointerdblclick: 'dblclick',
},
touch: {
pointerout: 'touchout',
pointerleave: 'touchleave',
pointerover: 'touchover',
pointerenter: 'touchenter',
pointermove: 'touchmove',
pointerdown: 'touchstart',
pointerup: 'touchend',
[POINTEROUT]: 'touchout',
[POINTERLEAVE]: 'touchleave',
[POINTEROVER]: 'touchover',
[POINTERENTER]: 'touchenter',
[POINTERMOVE]: TOUCHMOVE,
[POINTERDOWN]: TOUCHSTART,
[POINTERUP]: TOUCHEND,
[POINTERCANCEL]: TOUCHCANCEL,
pointerclick: 'tap',
pointerdblclick: 'dbltap',
},
pointer: {
pointerout: 'pointerout',
pointerleave: 'pointerleave',
pointerover: 'pointerover',
pointerenter: 'pointerenter',
pointermove: 'pointermove',
pointerdown: 'pointerdown',
pointerup: 'pointerup',
[POINTEROUT]: POINTEROUT,
[POINTERLEAVE]: POINTERLEAVE,
[POINTEROVER]: POINTEROVER,
[POINTERENTER]: POINTERENTER,
[POINTERMOVE]: POINTERMOVE,
[POINTERDOWN]: POINTERDOWN,
[POINTERUP]: POINTERUP,
[POINTERCANCEL]: POINTERCANCEL,
pointerclick: 'pointerclick',
pointerdblclick: 'pointerdblclick',
},
@@ -154,6 +133,10 @@ 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
@@ -248,7 +231,7 @@ export class Stage extends Container<Layer> {
throw 'Can not find container in document with id ' + id;
}
}
this._setAttr(CONTAINER, container);
this._setAttr('container', container);
if (this.content) {
if (this.content.parentElement) {
this.content.parentElement.removeChild(this.content);
@@ -553,7 +536,7 @@ export class Stage extends Container<Layer> {
var shape = this.getIntersection(pos);
DD.justDragged = false;
// probably we are staring a click
Konva.listenClickTap = true;
Konva['_' + eventType + 'ListenClick'] = true;
// no shape detected? do nothing
const hasShape = shape && shape.isListening();
@@ -660,9 +643,6 @@ export class Stage extends Container<Layer> {
pointerId: this._changedPointerPositions[0].id,
});
}
// content event
this._fire(CONTENT_MOUSEMOVE, { evt: evt });
}
_pointerup(evt) {
const events = getEventsMap(evt.type);
@@ -692,17 +672,17 @@ export class Stage extends Container<Layer> {
const event = { evt: evt, pointerId };
let fireDblClick = false;
if (Konva.inDblClickWindow) {
if (Konva['_' + eventType + 'InDblClickWindow']) {
fireDblClick = true;
clearTimeout(this[eventType + 'DblTimeout']);
} else if (!DD.justDragged) {
// don't set inDblClickWindow after dragging
Konva.inDblClickWindow = true;
Konva['_' + eventType + 'InDblClickWindow'] = true;
clearTimeout(this[eventType + 'DblTimeout']);
}
this[eventType + 'DblTimeout'] = setTimeout(function () {
Konva.inDblClickWindow = false;
Konva['_' + eventType + 'InDblClickWindow'] = false;
}, Konva.dblClickWindow);
if (shape && shape.isListening()) {
@@ -712,7 +692,7 @@ export class Stage extends Container<Layer> {
// detect if click or double click occurred
if (
Konva.listenClickTap &&
Konva['_' + eventType + 'ListenClick'] &&
clickStartShape &&
clickStartShape === shape
) {
@@ -725,7 +705,7 @@ export class Stage extends Container<Layer> {
} else {
this[eventType + 'ClickEndShape'] = null;
if (Konva.listenClickTap) {
if (Konva['_' + eventType + 'ListenClick']) {
this._fire(events.pointerclick, {
evt: evt,
target: this,
@@ -754,7 +734,7 @@ export class Stage extends Container<Layer> {
});
}
Konva.listenClickTap = false;
Konva['_' + eventType + 'ListenClick'] = false;
// always call preventDefault for desktop events because some browsers
// try to drag and drop the canvas element
@@ -913,13 +893,13 @@ export class Stage extends Container<Layer> {
throw 'Stage has no container. A container is required.';
}
// clear content inside container
container.innerHTML = EMPTY_STRING;
container.innerHTML = '';
// content
this.content = document.createElement('div');
this.content.style.position = RELATIVE;
this.content.style.position = 'relative';
this.content.style.userSelect = 'none';
this.content.className = KONVA_CONTENT;
this.content.className = 'konvajs-content';
this.content.setAttribute('role', 'presentation');

View File

@@ -444,6 +444,11 @@ 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) {
setTimeout(f, 60);
};
/**
* @namespace Util
* @memberof Konva
@@ -507,11 +512,6 @@ export const Util = {
requestAnimFrame(callback: Function) {
animQueue.push(callback);
const req =
(typeof requestAnimationFrame !== 'undefined' && requestAnimationFrame) ||
function (f) {
setTimeout(f, 60);
};
if (animQueue.length === 1) {
req(function () {
const queue = animQueue;
@@ -541,26 +541,7 @@ export const Util = {
}
return false;
},
_simplifyArray(arr: Array<any>) {
var retArr = [],
len = arr.length,
util = Util,
n,
val;
for (n = 0; n < len; n++) {
val = arr[n];
if (util._isNumber(val)) {
val = Math.round(val * 1000) / 1000;
} else if (!util._isString(val)) {
val = val + '';
}
retArr.push(val);
}
return retArr;
},
/*
* arg can be an image object or image data
*/
@@ -599,13 +580,6 @@ export const Util = {
return HASH + randColor;
},
get(val: any, def: any) {
if (val === undefined) {
return def;
} else {
return val;
}
},
/**
* get RGB components of a color
* @method
@@ -819,14 +793,26 @@ export const Util = {
cloneArray(arr: Array<any>) {
return arr.slice(0);
},
_degToRad(deg: number) {
degToRad(deg: number) {
return deg * PI_OVER_DEG180;
},
_radToDeg(rad: number) {
radToDeg(rad: number) {
return rad * DEG180_OVER_PI;
},
_degToRad(deg: number) {
Util.warn(
'Util._degToRad is removed. Please use public Util.degToRad instead.'
);
return Util._degToRad(deg);
},
_radToDeg(rad: number) {
Util.warn(
'Util._radToDeg is removed. Please use public Util.radToDeg instead.'
);
return Util._radToDeg(rad);
},
_getRotation(radians) {
return Konva.angleDeg ? Util._radToDeg(radians) : radians;
return Konva.angleDeg ? Util.radToDeg(radians) : radians;
},
_capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
@@ -843,64 +829,6 @@ export const Util = {
}
console.warn(KONVA_WARNING + str);
},
extend(child: any, parent: any) {
function Ctor() {
this.constructor = child;
}
Ctor.prototype = parent.prototype;
var oldProto = child.prototype;
child.prototype = new Ctor();
for (var key in oldProto) {
if (oldProto.hasOwnProperty(key)) {
child.prototype[key] = oldProto[key];
}
}
child.__super__ = parent.prototype;
// create reference to parent
child.super = parent;
},
_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)),
fa = (t * d01) / (d01 + d12),
fb = (t * d12) / (d01 + d12),
p1x = x1 - fa * (x2 - x0),
p1y = y1 - fa * (y2 - y0),
p2x = x1 + fb * (x2 - x0),
p2y = y1 + fb * (y2 - y0);
return [p1x, p1y, p2x, p2y];
},
_expandPoints(p, tension) {
var len = p.length,
allPoints = [],
n,
cp;
for (n = 2; n < len - 2; n += 2) {
cp = Util._getControlPoints(
p[n - 2],
p[n - 1],
p[n],
p[n + 1],
p[n + 2],
p[n + 3],
tension
);
if (isNaN(cp[0])) {
continue;
}
allPoints.push(cp[0]);
allPoints.push(cp[1]);
allPoints.push(p[n]);
allPoints.push(p[n + 1]);
allPoints.push(cp[2]);
allPoints.push(cp[3]);
}
return allPoints;
},
each(obj, func) {
for (var key in obj) {
func(key, obj[key]);

View File

@@ -7,6 +7,49 @@ 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)),
fa = (t * d01) / (d01 + d12),
fb = (t * d12) / (d01 + d12),
p1x = x1 - fa * (x2 - x0),
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 = [],
n,
cp;
for (n = 2; n < len - 2; n += 2) {
cp = getControlPoints(
p[n - 2],
p[n - 1],
p[n],
p[n + 1],
p[n + 2],
p[n + 3],
tension
);
if (isNaN(cp[0])) {
continue;
}
allPoints.push(cp[0]);
allPoints.push(cp[1]);
allPoints.push(p[n]);
allPoints.push(p[n + 1]);
allPoints.push(cp[2]);
allPoints.push(cp[3]);
}
return allPoints;
}
export interface LineConfig extends ShapeConfig {
points?: number[];
tension?: number;
@@ -134,14 +177,14 @@ export class Line<
if (this.closed()) {
return this._getTensionPointsClosed();
} else {
return Util._expandPoints(this.points(), this.tension());
return expandPoints(this.points(), this.tension());
}
}
_getTensionPointsClosed() {
var p = this.points(),
len = p.length,
tension = this.tension(),
firstControlPoints = Util._getControlPoints(
firstControlPoints = getControlPoints(
p[len - 2],
p[len - 1],
p[0],
@@ -150,7 +193,7 @@ export class Line<
p[3],
tension
),
lastControlPoints = Util._getControlPoints(
lastControlPoints = getControlPoints(
p[len - 4],
p[len - 3],
p[len - 2],
@@ -159,7 +202,7 @@ export class Line<
p[1],
tension
),
middle = Util._expandPoints(p, tension),
middle = expandPoints(p, tension),
tp = [firstControlPoints[2], firstControlPoints[3]]
.concat(middle)
.concat([

View File

@@ -96,8 +96,8 @@ function getCursor(anchorName, rad) {
return 'crosshair';
}
rad += Util._degToRad(ANGLES[anchorName] || 0);
var angle = ((Util._radToDeg(rad) % 360) + 360) % 360;
rad += Util.degToRad(ANGLES[anchorName] || 0);
var angle = ((Util.radToDeg(rad) % 360) + 360) % 360;
if (Util._inRange(angle, 315 + 22.5, 360) || Util._inRange(angle, 0, 22.5)) {
// TOP

View File

@@ -63,7 +63,7 @@ describe('TouchEvents', function () {
stage.add(layer);
// reset inDoubleClickWindow
Konva.inDblClickWindow = false;
Konva._touchInDblClickWindow = false;
// touchstart circle
simulateTouchStart(stage, [{ x: 289, y: 100, id: 0 }]);

View File

@@ -2,12 +2,6 @@ import { assert } from 'chai';
import { Konva } from './test-utils';
describe('Util', function () {
it('get()', function () {
assert.equal(Konva.Util.get(1, 2), 1);
assert.equal(Konva.Util.get(undefined, 2), 2);
assert.equal(Konva.Util.get(undefined, { foo: 'bar' }).foo, 'bar');
});
it('test _prepareToStringify', function () {
var o: any = {
a: 1,

View File

@@ -15,7 +15,9 @@ import { Stage } from '../../src/Stage.js';
// reset some data
beforeEach(function () {
Konva['inDblClickWindow'] = false;
Konva._mouseInDblClickWindow = false;
Konva._touchInDblClickWindow = false;
Konva._pointerInDblClickWindow = false;
});
// clear after test
@@ -179,7 +181,7 @@ export function showHit(layer) {
}
export function simulateMouseDown(stage, pos) {
// simulatePointerDown(stage, pos);
simulatePointerDown(stage, pos);
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
stage._pointerdown({
@@ -191,7 +193,7 @@ export function simulateMouseDown(stage, pos) {
}
export function simulateMouseMove(stage, pos) {
// simulatePointerMove(stage, pos);
simulatePointerMove(stage, pos);
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
var evt = {
clientX: pos.x,
@@ -205,7 +207,7 @@ export function simulateMouseMove(stage, pos) {
}
export function simulateMouseUp(stage, pos) {
// simulatePointerUp(stage, pos);
simulatePointerUp(stage, pos);
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
var evt = {
clientX: pos.x,
@@ -355,7 +357,7 @@ export function simulatePointerMove(stage: Stage, pos) {
};
stage._pointermove(evt as any);
Konva.DD._drag(evt);
// Konva.DD._drag(evt);
}
export function simulatePointerUp(stage: Stage, pos) {
@@ -368,9 +370,9 @@ export function simulatePointerUp(stage: Stage, pos) {
type: 'pointerup',
};
Konva.DD._endDragBefore(evt);
// Konva.DD._endDragBefore(evt);
stage._pointerup(evt as any);
Konva.DD._endDragAfter(evt);
// Konva.DD._endDragAfter(evt);
}
function isClose(a, b) {