events rewrite, fix types

This commit is contained in:
Anton Lavrenov
2021-05-07 07:48:13 -05:00
parent e5d86c9981
commit fcd7cf62b0
13 changed files with 450 additions and 851 deletions

View File

@@ -459,8 +459,12 @@ export class Context {
* @method
* @name Konva.Context#fillText
*/
fillText(a0, a1, a2) {
this._context.fillText(a0, a1, a2);
fillText(text: string, x: number, y: number, maxWidth?: number) {
if (maxWidth) {
this._context.fillText(text, x, y, maxWidth);
} else {
this._context.fillText(text, x, y);
}
}
/**
* measureText function.
@@ -696,30 +700,6 @@ export class SceneContext extends Context {
shape._fillFunc(this);
}
_fillPattern(shape) {
var fillPatternX = shape.getFillPatternX(),
fillPatternY = shape.getFillPatternY(),
fillPatternRotation = Konva.getAngle(shape.getFillPatternRotation()),
fillPatternOffsetX = shape.getFillPatternOffsetX(),
fillPatternOffsetY = shape.getFillPatternOffsetY(),
fillPatternScaleX = shape.getFillPatternScaleX(),
fillPatternScaleY = shape.getFillPatternScaleY();
// if (fillPatternX || fillPatternY) {
// this.translate(fillPatternX || 0, fillPatternY || 0);
// }
// if (fillPatternRotation) {
// this.rotate(fillPatternRotation);
// }
if (fillPatternScaleX || fillPatternScaleY) {
// this.scale(fillPatternScaleX, fillPatternScaleY);
}
// if (fillPatternOffsetX || fillPatternOffsetY) {
// this.translate(-1 * fillPatternOffsetX, -1 * fillPatternOffsetY);
// }
this.setAttr('fillStyle', shape._getFillPattern());
shape._fillFunc(this);
}

View File

@@ -95,7 +95,7 @@ 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?) {
DD._dragElements.forEach((elem, key) => {
DD._dragElements.forEach((elem) => {
const { node } = elem;
// we need to find pointer relative to that node
const stage = node.getStage();
@@ -113,7 +113,7 @@ export const DD = {
}
if (elem.dragStatus === 'dragging' || elem.dragStatus === 'stopped') {
// if a node is stopped manully we still need to reset events:
// if a node is stopped manually we still need to reset events:
DD.justDragged = true;
Konva.listenClickTap = 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: false,
/**
* Should Konva automatically update canvas on any changes. Default is true.
* @property autoDrawEnabled
@@ -72,16 +72,15 @@ export const Konva = {
* The case: we touchstart on div1, then touchmove out of that element into another element div2.
* DOM will continue trigger touchmove events on div1 (not div2). Because events are "captured" into initial target.
* By default Konva do not do that and will trigger touchmove on another element, while pointer is moving.
* @property captureTouchEventsEnabled
* @property capturePointerEventsEnabled
* @default false
* @name captureTouchEventsEnabled
* @name capturePointerEventsEnabled
* @memberof Konva
* @example
* Konva.captureTouchEventsEnabled = true;
* Konva.capturePointerEventsEnabled = true;
*/
captureTouchEventsEnabled: false,
capturePointerEventsEnabled: false,
// TODO: move that to stage?
listenClickTap: false,
inDblClickWindow: false,

View File

@@ -331,14 +331,11 @@ export class Layer extends Container<Group | Shape> {
* @param {Object} pos
* @param {Number} pos.x
* @param {Number} pos.y
* @param {String} [selector]
* @returns {Konva.Node}
* @example
* var shape = layer.getIntersection({x: 50, y: 50});
* // or if you interested in shape parent:
* var group = layer.getIntersection({x: 50, y: 50}, 'Group');
*/
getIntersection(pos: Vector2d, selector?: string): Node | null {
getIntersection(pos: Vector2d) {
if (!this.isListening() || !this.isVisible()) {
return null;
}
@@ -354,9 +351,7 @@ export class Layer extends Container<Group | Shape> {
y: pos.y + intersectionOffset.y * spiralSearchDistance,
});
const shape = obj.shape;
if (shape && selector) {
return shape.findAncestor(selector, true);
} else if (shape) {
if (shape) {
return shape;
}
// we should continue search if we found antialiased pixel

View File

@@ -39,6 +39,7 @@ var STAGE = 'Stage',
TAP = 'tap',
DBL_TAP = 'dbltap',
TOUCHMOVE = 'touchmove',
TOUCHCANCEL = 'touchcancel',
WHEEL = 'wheel',
CONTENT_MOUSEOUT = 'contentMouseout',
CONTENT_MOUSEOVER = 'contentMouseover',
@@ -53,52 +54,97 @@ var STAGE = 'Stage',
CONTENT_DBL_TAP = 'contentDbltap',
CONTENT_TAP = 'contentTap',
CONTENT_TOUCHMOVE = 'contentTouchmove',
CONTENT_POINTERMOVE = 'contentPointermove',
CONTENT_POINTERDOWN = 'contentPointerdown',
CONTENT_POINTERUP = 'contentPointerup',
CONTENT_WHEEL = 'contentWheel',
RELATIVE = 'relative',
KONVA_CONTENT = 'konvajs-content',
SPACE = ' ',
UNDERSCORE = '_',
CONTAINER = 'container',
MAX_LAYERS_NUMBER = 5,
EMPTY_STRING = '',
EVENTS = [
MOUSEENTER,
MOUSEDOWN,
MOUSEMOVE,
MOUSEUP,
MOUSELEAVE,
TOUCHSTART,
TOUCHMOVE,
TOUCHEND,
MOUSEOVER,
WHEEL,
CONTEXTMENU,
POINTERDOWN,
POINTERMOVE,
POINTERUP,
POINTERCANCEL,
LOSTPOINTERCAPTURE,
],
// cached variables
eventsLength = EVENTS.length;
function addEvent(ctx, eventName) {
ctx.content.addEventListener(
eventName,
function (evt) {
ctx[UNDERSCORE + eventName](evt);
},
false
);
}
[MOUSEENTER, '_pointerenter'],
[MOUSEDOWN, '_pointerdown'],
[MOUSEMOVE, '_pointermove'],
[MOUSEUP, '_pointerup'],
[MOUSELEAVE, '_pointerleave'],
[TOUCHSTART, '_pointerdown'],
[TOUCHMOVE, '_pointermove'],
[TOUCHEND, '_pointerup'],
[TOUCHCANCEL, '_pointercancel'],
[MOUSEOVER, '_pointerover'],
[WHEEL, '_wheel'],
[CONTEXTMENU, '_contextmenu'],
[POINTERDOWN, '_pointerdown'],
[POINTERMOVE, '_pointermove'],
[POINTERUP, '_pointerup'],
[POINTERCANCEL, '_pointercancel'],
[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',
pointerclick: 'click',
pointerdblclick: 'dblclick',
},
touch: {
pointerout: 'touchout',
pointerleave: 'touchleave',
pointerover: 'touchover',
pointerenter: 'touchenter',
pointermove: 'touchmove',
pointerdown: 'touchstart',
pointerup: 'touchend',
pointerclick: 'tap',
pointerdblclick: 'dbltap',
},
pointer: {
pointerout: 'pointerout',
pointerleave: 'pointerleave',
pointerover: 'pointerover',
pointerenter: 'pointerenter',
pointermove: 'pointermove',
pointerdown: 'pointerdown',
pointerup: 'pointerup',
pointerclick: 'pointerclick',
pointerdblclick: 'pointerdblclick',
},
};
const getEventType = (type) => {
if (type.indexOf('pointer') >= 0) {
return 'pointer';
}
if (type.indexOf('touch') >= 0) {
return 'touch';
}
return 'mouse';
};
const getEventsMap = (eventType: string) => {
const type = getEventType(eventType);
if (type === 'pointer') {
return Konva.pointerEventsEnabled && EVENTS_MAP.pointer;
}
if (type === 'touch') {
return EVENTS_MAP.touch;
}
if (type === 'mouse') {
return EVENTS_MAP.mouse;
}
};
function checkNoClip(attrs: any = {}) {
if (attrs.clipFunc || attrs.clipWidth || attrs.clipHeight) {
Util.warn(
@@ -128,16 +174,23 @@ export class Stage extends Container<Layer> {
content: HTMLDivElement;
pointerPos: Vector2d | null;
_pointerPositions: (Vector2d & { id?: number })[] = [];
_changedPointerPositions: (Vector2d & { id?: number })[] = [];
_changedPointerPositions: (Vector2d & { id: number })[] = [];
bufferCanvas: SceneCanvas;
bufferHitCanvas: HitCanvas;
targetShape: Shape;
clickStartShape: Shape;
clickEndShape: Shape;
tapStartShape: Shape;
tapEndShape: Shape;
dblTimeout: any;
_mouseTargetShape: Shape;
_touchTargetShape: Shape;
_pointerTargetShape: Shape;
_mouseClickStartShape: Shape;
_touchClickStartShape: Shape;
_pointerClickStartShape: Shape;
_mouseClickEndShape: Shape;
_touchClickEndShape: Shape;
_pointerClickEndShape: Shape;
_mouseDblTimeout: any;
_touchDblTimeout: any;
_pointerDblTimeout: any;
constructor(config: StageConfig) {
super(checkNoClip(config));
@@ -320,14 +373,11 @@ export class Stage extends Container<Layer> {
* @param {Object} pos
* @param {Number} pos.x
* @param {Number} pos.y
* @param {String} [selector]
* @returns {Konva.Node}
* @example
* var shape = stage.getIntersection({x: 50, y: 50});
* // or if you interested in shape parent:
* var group = stage.getIntersection({x: 50, y: 50}, 'Group');
*/
getIntersection(pos: Vector2d | null, selector?: string) {
getIntersection(pos: Vector2d) {
if (!pos) {
return null;
}
@@ -337,7 +387,7 @@ export class Stage extends Container<Layer> {
n;
for (n = end; n >= 0; n--) {
const shape = layers[n].getIntersection(pos, selector);
const shape = layers[n].getIntersection(pos);
if (shape) {
return shape;
}
@@ -423,36 +473,64 @@ export class Stage extends Container<Layer> {
if (!Konva.isBrowser) {
return;
}
for (var n = 0; n < eventsLength; n++) {
addEvent(this, EVENTS[n]);
EVENTS.forEach(([event, methodName]) => {
this.content.addEventListener(event, (evt) => {
this[methodName](evt);
});
});
}
_pointerenter(evt) {
this.setPointersPositions(evt);
const events = getEventsMap(evt.type);
this._fire(events.pointerenter, {
evt: evt,
target: this,
currentTarget: this,
});
}
_pointerover(evt) {
this.setPointersPositions(evt);
const events = getEventsMap(evt.type);
this._fire(events.pointerover, {
evt: evt,
target: this,
currentTarget: this,
});
}
_getTargetShape(evenType) {
let shape: Shape | null = this[evenType + 'targetShape'];
if (shape && !shape.getStage()) {
shape = null;
}
return shape;
}
_mouseenter(evt) {
this.setPointersPositions(evt);
this._fire(MOUSEENTER, { evt: evt, target: this, currentTarget: this });
}
_mouseover(evt) {
this.setPointersPositions(evt);
this._fire(CONTENT_MOUSEOVER, { evt: evt });
this._fire(MOUSEOVER, { evt: evt, target: this, currentTarget: this });
}
_mouseleave(evt) {
this.setPointersPositions(evt);
var targetShape = this.targetShape?.getStage() ? this.targetShape : null;
_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) {
targetShape._fireAndBubble(MOUSEOUT, { evt: evt });
targetShape._fireAndBubble(MOUSELEAVE, { evt: evt });
this._fire(MOUSELEAVE, { evt: evt, target: this, currentTarget: this });
this.targetShape = null;
} else if (eventsEnabled) {
this._fire(MOUSELEAVE, {
targetShape._fireAndBubble(events.pointerout, { evt: evt });
targetShape._fireAndBubble(events.pointerleave, { evt: evt });
this._fire(events.pointerleave, {
evt: evt,
target: this,
currentTarget: this,
});
this._fire(MOUSEOUT, {
this[eventType + 'targetShape'] = null;
} else if (eventsEnabled) {
this._fire(events.pointerleave, {
evt: evt,
target: this,
currentTarget: this,
});
this._fire(events.pointerout, {
evt: evt,
target: this,
currentTarget: this,
@@ -460,177 +538,220 @@ export class Stage extends Container<Layer> {
}
this.pointerPos = undefined;
this._pointerPositions = [];
this._fire(CONTENT_MOUSEOUT, { evt: evt });
}
_mousemove(evt) {
_pointerdown(evt: TouchEvent | MouseEvent | PointerEvent) {
const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type);
if (!events) {
return;
}
this.setPointersPositions(evt);
var pointerId = Util._getFirstPointerId(evt);
var targetShape = this.targetShape?.getStage() ? this.targetShape : null;
var triggeredOnShape = false;
this._changedPointerPositions.forEach((pos) => {
var shape = this.getIntersection(pos);
DD.justDragged = false;
// probably we are staring a click
Konva.listenClickTap = true;
// no shape detected? do nothing
const hasShape = shape && shape.isListening();
if (!hasShape) {
return;
}
if (Konva.capturePointerEventsEnabled) {
shape.setPointerCapture(pos.id);
}
// save where we started the click
this[eventType + 'ClickStartShape'] = shape;
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) {
evt.preventDefault();
}
});
// trigger down on stage if not already
if (!triggeredOnShape) {
this._fire(events.pointerdown, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._pointerPositions[0].id,
});
}
}
_pointermove(evt: TouchEvent | MouseEvent | PointerEvent) {
const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type);
if (!events) {
return;
}
if (DD.isDragging && DD.node.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
this.setPointersPositions(evt);
var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled;
if (eventsEnabled) {
const shape = this.getIntersection(this.getPointerPosition()) as Shape;
if (shape && shape.isListening()) {
var differentTarget = targetShape !== shape;
if (eventsEnabled && differentTarget) {
if (targetShape) {
targetShape._fireAndBubble(
MOUSEOUT,
{ evt: evt, pointerId },
shape
);
targetShape._fireAndBubble(
MOUSELEAVE,
{ evt: evt, pointerId },
shape
);
}
shape._fireAndBubble(MOUSEOVER, { evt: evt, pointerId }, targetShape);
shape._fireAndBubble(
MOUSEENTER,
{ evt: evt, pointerId },
targetShape
);
shape._fireAndBubble(MOUSEMOVE, { evt: evt, pointerId });
this.targetShape = shape;
} else {
shape._fireAndBubble(MOUSEMOVE, { evt: evt, pointerId });
if (!eventsEnabled) {
return;
}
var processedShapesIds = {};
let triggeredOnShape = false;
var targetShape = this._getTargetShape(eventType);
this._changedPointerPositions.forEach((pos) => {
const shape = (PointerEvents.getCapturedShape(pos.id) ||
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) {
shape._fireAndBubble(events.pointerover, event, targetShape);
shape._fireAndBubble(events.pointerenter, event, targetShape);
this[eventType + 'targetShape'] = shape;
}
shape._fireAndBubble(events.pointermove, event);
} else {
/*
* if no shape was detected, clear target shape and try
* to run mouseout from previous target shape
*/
if (targetShape && eventsEnabled) {
targetShape._fireAndBubble(MOUSEOUT, { evt: evt, pointerId });
targetShape._fireAndBubble(MOUSELEAVE, { evt: evt, pointerId });
this._fire(MOUSEOVER, {
if (targetShape) {
this._fire(events.pointerover, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
this.targetShape = null;
this[eventType + 'targetShape'] = null;
}
this._fire(MOUSEMOVE, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
}
});
// content event
this._fire(CONTENT_MOUSEMOVE, { evt: evt });
}
// always call preventDefault for desktop events because some browsers
// try to drag and drop the canvas element
if (evt.cancelable) {
evt.preventDefault();
}
}
_mousedown(evt) {
this.setPointersPositions(evt);
var pointerId = Util._getFirstPointerId(evt);
var shape = this.getIntersection(this.getPointerPosition()) as Shape;
DD.justDragged = false;
Konva.listenClickTap = true;
if (shape && shape.isListening()) {
this.clickStartShape = shape;
shape._fireAndBubble(MOUSEDOWN, { evt: evt, pointerId });
} else {
this._fire(MOUSEDOWN, {
if (!triggeredOnShape) {
this._fire(events.pointermove, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
pointerId: this._changedPointerPositions[0].id,
});
}
// content event
this._fire(CONTENT_MOUSEDOWN, { evt: evt });
// Do not prevent default behavior, because it will prevent listening events outside of window iframe
// we used preventDefault for disabling native drag&drop
// but userSelect = none style will do the trick
// if (evt.cancelable) {
// evt.preventDefault();
// }
this._fire(CONTENT_MOUSEMOVE, { evt: evt });
}
_mouseup(evt) {
this.setPointersPositions(evt);
var pointerId = Util._getFirstPointerId(evt);
var shape = this.getIntersection(this.getPointerPosition()) as Shape,
clickStartShape = this.clickStartShape,
clickEndShape = this.clickEndShape,
fireDblClick = false;
_pointerup(evt) {
const events = getEventsMap(evt.type);
const eventType = getEventType(evt.type);
if (Konva.inDblClickWindow) {
fireDblClick = true;
clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else if (!DD.justDragged) {
// don't set inDblClickWindow after dragging
Konva.inDblClickWindow = true;
clearTimeout(this.dblTimeout);
if (!events) {
return;
}
this.setPointersPositions(evt);
const clickStartShape = this[eventType + 'ClickStartShape'];
const clickEndShape = this[eventType + 'ClickEndShape'];
var processedShapesIds = {};
let triggeredOnShape = false;
this._changedPointerPositions.forEach((pos) => {
const shape = (PointerEvents.getCapturedShape(pos.id) ||
this.getIntersection(pos)) as Shape;
this.dblTimeout = setTimeout(function () {
Konva.inDblClickWindow = false;
}, Konva.dblClickWindow);
if (shape) {
shape.releaseCapture(pos.id);
if (processedShapesIds[shape._id]) {
return;
}
processedShapesIds[shape._id] = true;
}
if (shape && shape.isListening()) {
this.clickEndShape = shape;
shape._fireAndBubble(MOUSEUP, { evt: evt, pointerId });
const pointerId = pos.id;
const event = { evt: evt, pointerId };
// detect if click or double click occurred
if (
Konva.listenClickTap &&
clickStartShape &&
clickStartShape._id === shape._id
) {
shape._fireAndBubble(CLICK, { evt: evt, pointerId });
let fireDblClick = false;
if (Konva.inDblClickWindow) {
fireDblClick = true;
clearTimeout(this[eventType + 'DblTimeout']);
} else if (!DD.justDragged) {
// don't set inDblClickWindow after dragging
Konva.inDblClickWindow = true;
clearTimeout(this[eventType + 'DblTimeout']);
}
if (fireDblClick && clickEndShape && clickEndShape === shape) {
shape._fireAndBubble(DBL_CLICK, { evt: evt, pointerId });
this[eventType + 'DblTimeout'] = setTimeout(function () {
Konva.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.listenClickTap &&
clickStartShape &&
clickStartShape === shape
) {
shape._fireAndBubble(events.pointerclick, event);
if (fireDblClick && clickEndShape && clickEndShape === shape) {
shape._fireAndBubble(events.pointerdblclick, event);
}
}
} else {
this[eventType + 'ClickEndShape'] = null;
if (Konva.listenClickTap) {
this._fire(events.pointerclick, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
}
if (fireDblClick) {
this._fire(events.pointerdblclick, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
}
}
} else {
this.clickEndShape = null;
this._fire(MOUSEUP, {
});
if (!triggeredOnShape) {
this._fire(events.pointerup, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
pointerId: this._changedPointerPositions[0].id,
});
if (Konva.listenClickTap) {
this._fire(CLICK, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
}
if (fireDblClick) {
this._fire(DBL_CLICK, {
evt: evt,
target: this,
currentTarget: this,
pointerId,
});
}
}
// content events
this._fire(CONTENT_MOUSEUP, { evt: evt });
if (Konva.listenClickTap) {
this._fire(CONTENT_CLICK, { evt: evt });
if (fireDblClick) {
this._fire(CONTENT_DBL_CLICK, { evt: evt });
}
}
Konva.listenClickTap = false;
@@ -654,190 +775,6 @@ export class Stage extends Container<Layer> {
currentTarget: this,
});
}
this._fire(CONTENT_CONTEXTMENU, { evt: evt });
}
_touchstart(evt) {
this.setPointersPositions(evt);
var triggeredOnShape = false;
this._changedPointerPositions.forEach((pos) => {
var shape = this.getIntersection(pos) as Shape;
Konva.listenClickTap = true;
DD.justDragged = false;
const hasShape = shape && shape.isListening();
if (!hasShape) {
return;
}
if (Konva.captureTouchEventsEnabled) {
shape.setPointerCapture(pos.id);
}
this.tapStartShape = shape;
shape._fireAndBubble(TOUCHSTART, { evt: evt, pointerId: pos.id }, this);
triggeredOnShape = true;
// only call preventDefault if the shape is listening for events
if (shape.isListening() && shape.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
});
if (!triggeredOnShape) {
this._fire(TOUCHSTART, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._changedPointerPositions[0].id,
});
}
// content event
this._fire(CONTENT_TOUCHSTART, { evt: evt });
}
_touchmove(evt) {
this.setPointersPositions(evt);
var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled;
if (eventsEnabled) {
var triggeredOnShape = false;
var processedShapesIds = {};
this._changedPointerPositions.forEach((pos) => {
const shape =
PointerEvents.getCapturedShape(pos.id) || this.getIntersection(pos);
const hasShape = shape && shape.isListening();
if (!hasShape) {
return;
}
if (processedShapesIds[shape._id]) {
return;
}
processedShapesIds[shape._id] = true;
shape._fireAndBubble(TOUCHMOVE, { evt: evt, pointerId: pos.id });
triggeredOnShape = true;
// only call preventDefault if the shape is listening for events
if (shape.isListening() && shape.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
});
if (!triggeredOnShape) {
this._fire(TOUCHMOVE, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._changedPointerPositions[0].id,
});
}
this._fire(CONTENT_TOUCHMOVE, { evt: evt });
}
if (DD.isDragging && DD.node.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
}
_touchend(evt) {
this.setPointersPositions(evt);
var tapEndShape = this.tapEndShape,
fireDblClick = false;
if (Konva.inDblClickWindow) {
fireDblClick = true;
clearTimeout(this.dblTimeout);
// Konva.inDblClickWindow = false;
} else if (!DD.justDragged) {
Konva.inDblClickWindow = true;
clearTimeout(this.dblTimeout);
}
this.dblTimeout = setTimeout(function () {
Konva.inDblClickWindow = false;
}, Konva.dblClickWindow);
var triggeredOnShape = false;
var processedShapesIds = {};
var tapTriggered = false;
var dblTapTriggered = false;
this._changedPointerPositions.forEach((pos) => {
var shape =
(PointerEvents.getCapturedShape(pos.id) as Shape) ||
(this.getIntersection(pos) as Shape);
if (shape) {
shape.releaseCapture(pos.id);
}
const hasShape = shape && shape.isListening();
if (!hasShape) {
return;
}
if (processedShapesIds[shape._id]) {
return;
}
processedShapesIds[shape._id] = true;
this.tapEndShape = shape;
shape._fireAndBubble(TOUCHEND, { evt: evt, pointerId: pos.id });
triggeredOnShape = true;
// detect if tap or double tap occurred
if (Konva.listenClickTap && shape === this.tapStartShape) {
tapTriggered = true;
shape._fireAndBubble(TAP, { evt: evt, pointerId: pos.id });
if (fireDblClick && tapEndShape && tapEndShape === shape) {
dblTapTriggered = true;
shape._fireAndBubble(DBL_TAP, { evt: evt, pointerId: pos.id });
}
}
// only call preventDefault if the shape is listening for events
if (shape.isListening() && shape.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
});
if (!triggeredOnShape) {
this._fire(TOUCHEND, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._changedPointerPositions[0].id,
});
}
if (Konva.listenClickTap && !tapTriggered) {
this.tapEndShape = null;
this._fire(TAP, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._changedPointerPositions[0].id,
});
}
if (fireDblClick && !dblTapTriggered) {
this._fire(DBL_TAP, {
evt: evt,
target: this,
currentTarget: this,
pointerId: this._changedPointerPositions[0].id,
});
}
// content events
this._fire(CONTENT_TOUCHEND, { evt: evt });
if (Konva.listenClickTap) {
this._fire(CONTENT_TAP, { evt: evt });
if (fireDblClick) {
this._fire(CONTENT_DBL_TAP, { evt: evt });
}
}
if (this.preventDefault() && evt.cancelable) {
evt.preventDefault();
}
Konva.listenClickTap = false;
}
_wheel(evt) {
@@ -853,59 +790,9 @@ export class Stage extends Container<Layer> {
currentTarget: this,
});
}
this._fire(CONTENT_WHEEL, { evt: evt });
}
_pointerdown(evt: PointerEvent) {
if (!Konva._pointerEventsEnabled) {
return;
}
this.setPointersPositions(evt);
const shape =
PointerEvents.getCapturedShape(evt.pointerId) ||
this.getIntersection(this.getPointerPosition());
if (shape) {
shape._fireAndBubble(POINTERDOWN, PointerEvents.createEvent(evt));
}
}
_pointermove(evt: PointerEvent) {
if (!Konva._pointerEventsEnabled) {
return;
}
this.setPointersPositions(evt);
const shape =
PointerEvents.getCapturedShape(evt.pointerId) ||
this.getIntersection(this.getPointerPosition());
if (shape) {
shape._fireAndBubble(POINTERMOVE, PointerEvents.createEvent(evt));
}
}
_pointerup(evt: PointerEvent) {
if (!Konva._pointerEventsEnabled) {
return;
}
this.setPointersPositions(evt);
const shape =
PointerEvents.getCapturedShape(evt.pointerId) ||
this.getIntersection(this.getPointerPosition());
if (shape) {
shape._fireAndBubble(POINTERUP, PointerEvents.createEvent(evt));
}
PointerEvents.releaseCapture(evt.pointerId);
}
_pointercancel(evt: PointerEvent) {
if (!Konva._pointerEventsEnabled) {
return;
}
this.setPointersPositions(evt);
const shape =
PointerEvents.getCapturedShape(evt.pointerId) ||

View File

@@ -33,7 +33,7 @@ declare namespace Konva {
export let dragDistance: number;
export let angleDeg: boolean;
export let showWarnings: boolean;
export let captureTouchEventsEnabled: boolean;
export let capturePointerEventsEnabled: boolean;
export let dragButtons: Array<number>;
export let hitOnDragEnabled: boolean;
export const isDragging: () => boolean;