mirror of
https://github.com/konvajs/konva.git
synced 2025-04-05 20:48:28 +08:00
events rewrite, fix types
This commit is contained in:
parent
e5d86c9981
commit
fcd7cf62b0
@ -20,6 +20,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- `Konva.names` and `Konva.ids` are removed
|
||||
- new `flipEnabled` property for `Konva.Transformer`.
|
||||
- new `node.isClientRectOnScreen()` method
|
||||
- argument `selector` is removed from `node.getIntersection(pos)` API
|
||||
- `Konva.captureTouchEventsEnabled` is renamed to `Konva.capturePointerEventsEnabled`
|
||||
|
||||
## 7.2.5
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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';
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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
|
||||
|
763
src/Stage.ts
763
src/Stage.ts
@ -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) ||
|
||||
|
2
src/index-types.d.ts
vendored
2
src/index-types.d.ts
vendored
@ -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;
|
||||
|
@ -243,56 +243,6 @@ describe('Layer', function () {
|
||||
);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('layer getIntersection() with selector', function () {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer({
|
||||
name: 'layer',
|
||||
});
|
||||
|
||||
var group = new Konva.Group({
|
||||
name: 'group',
|
||||
});
|
||||
|
||||
var circle = new Konva.Circle({
|
||||
x: stage.width() / 2,
|
||||
y: stage.height() / 2,
|
||||
radius: 70,
|
||||
strokeWidth: 4,
|
||||
fill: 'red',
|
||||
stroke: 'black',
|
||||
});
|
||||
|
||||
group.add(circle);
|
||||
layer.add(group);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(
|
||||
layer.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'Circle'
|
||||
),
|
||||
circle,
|
||||
'intersection with shape selector'
|
||||
);
|
||||
assert.equal(
|
||||
layer.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'.group'
|
||||
),
|
||||
group,
|
||||
'intersection with group selector'
|
||||
);
|
||||
assert.equal(
|
||||
layer.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'Stage'
|
||||
),
|
||||
stage,
|
||||
'intersection with stage selector'
|
||||
);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('set layer visibility', function () {
|
||||
var stage = addStage();
|
||||
|
@ -12,139 +12,6 @@ import {
|
||||
} from './test-utils';
|
||||
|
||||
describe('MouseEvents', function () {
|
||||
// ======================================================
|
||||
it('stage content mouse events', function (done) {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
var circle = new Konva.Circle({
|
||||
x: 100,
|
||||
y: 100,
|
||||
radius: 70,
|
||||
fill: 'green',
|
||||
stroke: 'black',
|
||||
strokeWidth: 4,
|
||||
name: 'myCircle',
|
||||
});
|
||||
|
||||
layer.add(circle);
|
||||
stage.add(layer);
|
||||
|
||||
var circleMousedown = 0;
|
||||
var circleMouseup = 0;
|
||||
var stageContentMousedown = 0;
|
||||
var stageContentMouseup = 0;
|
||||
var stageContentMousemove = 0;
|
||||
var stageContentMouseout = 0;
|
||||
var stageContentMouseover = 0;
|
||||
var stageContentClick = 0;
|
||||
var stageContentDblClick = 0;
|
||||
|
||||
circle.on('mousedown', function () {
|
||||
circleMousedown++;
|
||||
});
|
||||
|
||||
circle.on('mouseup', function () {
|
||||
circleMouseup++;
|
||||
});
|
||||
|
||||
stage.on('contentMousedown', function () {
|
||||
stageContentMousedown++;
|
||||
});
|
||||
|
||||
stage.on('contentMouseup', function () {
|
||||
stageContentMouseup++;
|
||||
});
|
||||
|
||||
stage.on('contentMousemove', function () {
|
||||
stageContentMousemove++;
|
||||
});
|
||||
|
||||
stage.on('contentMouseout', function () {
|
||||
stageContentMouseout++;
|
||||
});
|
||||
|
||||
stage.on('contentMouseover', function () {
|
||||
stageContentMouseover++;
|
||||
});
|
||||
|
||||
stage.on('contentClick', function () {
|
||||
//console.log('click');
|
||||
stageContentClick++;
|
||||
});
|
||||
|
||||
stage.on('contentDblclick', function () {
|
||||
//console.log('dbl click');
|
||||
stageContentDblClick++;
|
||||
});
|
||||
|
||||
simulateMouseDown(stage, {
|
||||
x: 100,
|
||||
y: 100,
|
||||
});
|
||||
|
||||
simulateMouseUp(stage, {
|
||||
x: 100,
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert.equal(circleMousedown, 1);
|
||||
assert.equal(circleMouseup, 1);
|
||||
assert.equal(stageContentMousedown, 1);
|
||||
assert.equal(stageContentMouseup, 1);
|
||||
assert.equal(stageContentClick, 1);
|
||||
|
||||
simulateMouseDown(stage, {
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
simulateMouseUp(stage, {
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
|
||||
assert.equal(stageContentMousedown, 2);
|
||||
assert.equal(stageContentMouseup, 2);
|
||||
|
||||
// trigger double click
|
||||
simulateMouseDown(stage, {
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
simulateMouseUp(stage, {
|
||||
x: 1,
|
||||
y: 1,
|
||||
});
|
||||
|
||||
assert.equal(stageContentMousedown, 3);
|
||||
assert.equal(stageContentMouseup, 3);
|
||||
//assert.equal(stageContentDblClick, 1);
|
||||
|
||||
setTimeout(function () {
|
||||
simulateMouseMove(stage, {
|
||||
x: 200,
|
||||
y: 1,
|
||||
});
|
||||
|
||||
assert.equal(stageContentMousemove, 1);
|
||||
|
||||
stage._mouseleave({
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
});
|
||||
|
||||
assert.equal(stageContentMouseout, 1);
|
||||
|
||||
stage._mouseover({
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
});
|
||||
|
||||
assert.equal(stageContentMouseover, 1);
|
||||
|
||||
done();
|
||||
}, 20);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('remove shape with onclick', function () {
|
||||
var stage = addStage();
|
||||
@ -443,6 +310,54 @@ describe('MouseEvents', function () {
|
||||
}, 20);
|
||||
});
|
||||
|
||||
it.skip('mouseleave and mouseenter', function () {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer({
|
||||
throttle: 999,
|
||||
});
|
||||
var circle = new Konva.Circle({
|
||||
x: 100,
|
||||
y: 100,
|
||||
radius: 70,
|
||||
strokeWidth: 4,
|
||||
fill: 'red',
|
||||
stroke: 'black',
|
||||
});
|
||||
layer.add(circle);
|
||||
stage.add(layer);
|
||||
|
||||
var mouseenter = 0;
|
||||
circle.on('mouseenter', () => {
|
||||
mouseenter += 1;
|
||||
});
|
||||
|
||||
var mouseleave = 0;
|
||||
circle.on('mouseleave', () => {
|
||||
mouseleave += 1;
|
||||
});
|
||||
|
||||
simulateMouseMove(stage, {
|
||||
x: 10,
|
||||
y: 10,
|
||||
});
|
||||
simulateMouseMove(stage, {
|
||||
x: 100,
|
||||
y: 100,
|
||||
});
|
||||
simulateMouseMove(stage, {
|
||||
x: 100,
|
||||
y: 100,
|
||||
});
|
||||
assert.equal(mouseenter, 1);
|
||||
assert.equal(mouseleave, 0);
|
||||
simulateMouseMove(stage, {
|
||||
x: 10,
|
||||
y: 10,
|
||||
});
|
||||
assert.equal(mouseenter, 1);
|
||||
assert.equal(mouseleave, 1);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('mousedown mouseup mouseover mouseout mousemove click dblclick', function (done) {
|
||||
var stage = addStage();
|
||||
@ -2045,7 +1960,7 @@ describe('MouseEvents', function () {
|
||||
y: 15,
|
||||
});
|
||||
|
||||
assert.equal(bigClicks, 0, 'single click on big rect');
|
||||
assert.equal(bigClicks, 0, 'single click on big rect (1)');
|
||||
assert.equal(smallClicks, 0, 'no click on small rect');
|
||||
assert.equal(smallDblClicks, 0, 'no dblclick on small rect');
|
||||
|
||||
@ -2059,7 +1974,7 @@ describe('MouseEvents', function () {
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert.equal(bigClicks, 0, 'single click on big rect');
|
||||
assert.equal(bigClicks, 0, 'single click on big rect (2)');
|
||||
assert.equal(smallClicks, 1, 'single click on small rect');
|
||||
assert.equal(smallDblClicks, 0, 'no dblclick on small rect');
|
||||
|
||||
@ -2073,7 +1988,7 @@ describe('MouseEvents', function () {
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert.equal(bigClicks, 0, 'single click on big rect');
|
||||
assert.equal(bigClicks, 0, 'single click on big rect (3)');
|
||||
assert.equal(smallClicks, 2, 'second click on small rect');
|
||||
assert.equal(smallDblClicks, 1, 'single dblclick on small rect');
|
||||
|
||||
@ -2097,9 +2012,10 @@ describe('MouseEvents', function () {
|
||||
clientX: 10,
|
||||
clientY: 10 + top,
|
||||
button: 0,
|
||||
type: 'mouseenter',
|
||||
};
|
||||
|
||||
stage._mouseenter(evt);
|
||||
stage._pointerenter(evt);
|
||||
|
||||
assert.equal(mouseenterCount, 1, 'mouseenterCount should be 1');
|
||||
});
|
||||
@ -2119,9 +2035,10 @@ describe('MouseEvents', function () {
|
||||
clientX: 0,
|
||||
clientY: 0 + top,
|
||||
button: 0,
|
||||
type: 'mouseleave',
|
||||
};
|
||||
|
||||
stage._mouseleave(evt);
|
||||
stage._pointerleave(evt);
|
||||
|
||||
assert.equal(mouseleave, 1, 'mouseleave should be 1');
|
||||
});
|
||||
@ -2178,9 +2095,10 @@ describe('MouseEvents', function () {
|
||||
clientX: 200,
|
||||
clientY: -5 + top,
|
||||
button: 0,
|
||||
type: 'mouseleave',
|
||||
};
|
||||
|
||||
stage._mouseleave(evt);
|
||||
stage._pointerleave(evt);
|
||||
|
||||
assert.equal(circleMouseleave, 1, 'circleMouseleave should be 1');
|
||||
assert.equal(circleMouseout, 1, 'circleMouseout should be 1');
|
||||
@ -2294,16 +2212,20 @@ describe('MouseEvents', function () {
|
||||
clientX: 10,
|
||||
clientY: 10 + top,
|
||||
button: 0,
|
||||
type: 'mouseenter',
|
||||
};
|
||||
|
||||
stage._mouseenter(evt);
|
||||
stage._pointerenter(evt);
|
||||
|
||||
simulateMouseMove(stage, {
|
||||
x: 10,
|
||||
y: 10,
|
||||
});
|
||||
|
||||
stage._mouseleave(evt);
|
||||
stage._pointerleave({
|
||||
...evt,
|
||||
type: 'mouseleave',
|
||||
});
|
||||
|
||||
assert.equal(mouseenter, 1, 'mouseenter should be 1');
|
||||
});
|
||||
|
@ -8,9 +8,7 @@ import {
|
||||
simulatePointerUp,
|
||||
} from './test-utils';
|
||||
|
||||
// TODO: restore it!
|
||||
describe.skip('PointerEvents', function () {
|
||||
Konva._pointerEventsEnabled = true;
|
||||
// ======================================================
|
||||
it('pointerdown pointerup pointermove', function (done) {
|
||||
var stage = addStage();
|
||||
@ -51,8 +49,6 @@ describe.skip('PointerEvents', function () {
|
||||
simulatePointerDown(stage, {
|
||||
x: 289,
|
||||
y: 100,
|
||||
pointerId: 1,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
||||
assert(pointerdown, '1) pointerdown should be true');
|
||||
@ -61,8 +57,8 @@ describe.skip('PointerEvents', function () {
|
||||
|
||||
// pointerup circle
|
||||
simulatePointerUp(stage, {
|
||||
touches: [],
|
||||
preventDefault: function () {},
|
||||
x: 289,
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert(pointerdown, '2) pointerdown should be true');
|
||||
@ -71,13 +67,8 @@ describe.skip('PointerEvents', function () {
|
||||
|
||||
// pointerdown circle
|
||||
simulatePointerDown(stage, {
|
||||
touches: [
|
||||
{
|
||||
x: 289,
|
||||
y: 100,
|
||||
},
|
||||
],
|
||||
preventDefault: function () {},
|
||||
x: 289,
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert(pointerdown, '3) pointerdown should be true');
|
||||
@ -86,8 +77,8 @@ describe.skip('PointerEvents', function () {
|
||||
|
||||
// pointerup circle to triger dbltap
|
||||
simulatePointerUp(stage, {
|
||||
touches: [],
|
||||
preventDefault: function () {},
|
||||
x: 289,
|
||||
y: 100,
|
||||
});
|
||||
// end drag is tied to document mouseup and pointerup event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
@ -100,13 +91,8 @@ describe.skip('PointerEvents', function () {
|
||||
setTimeout(function () {
|
||||
// pointermove circle
|
||||
simulatePointerMove(stage, {
|
||||
touches: [
|
||||
{
|
||||
x: 290,
|
||||
y: 100,
|
||||
},
|
||||
],
|
||||
preventDefault: function () {},
|
||||
x: 290,
|
||||
y: 100,
|
||||
});
|
||||
|
||||
assert(pointerdown, '5) pointerdown should be true');
|
||||
@ -118,7 +104,7 @@ describe.skip('PointerEvents', function () {
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('pointer capture', function (done) {
|
||||
it.skip('pointer capture', function (done) {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
var circle = new Konva.Circle({
|
||||
@ -172,17 +158,15 @@ describe.skip('PointerEvents', function () {
|
||||
layer.add(circle2);
|
||||
stage.add(layer);
|
||||
|
||||
var top = stage.content.getBoundingClientRect().top;
|
||||
|
||||
// on circle 2 to confirm it works
|
||||
simulatePointerDown(stage, {
|
||||
x: 289,
|
||||
y: 10 + top,
|
||||
y: 10,
|
||||
pointerId: 0,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
||||
assert(otherDownCount === 1, '6) otherDownCount should be 1');
|
||||
assert.equal(otherDownCount, 1, '6) otherDownCount should be 1');
|
||||
assert(downCount === 0, '6) downCount should be 0');
|
||||
assert(!pointermove, '6) pointermove should be false');
|
||||
assert(!pointerup, '6) pointerup should be false');
|
||||
@ -190,12 +174,12 @@ describe.skip('PointerEvents', function () {
|
||||
// on circle with capture
|
||||
simulatePointerDown(stage, {
|
||||
x: 289,
|
||||
y: 100 + top,
|
||||
y: 100,
|
||||
pointerId: 1,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
||||
assert(otherDownCount === 1, '7) otherDownCount should be 1');
|
||||
assert.equal(otherDownCount, 1, '7) otherDownCount should be 1');
|
||||
assert(downCount === 1, '7) downCount should be 1');
|
||||
assert(!pointermove, '7) pointermove should be false');
|
||||
assert(!pointerup, '7) pointerup should be true');
|
||||
@ -203,12 +187,12 @@ describe.skip('PointerEvents', function () {
|
||||
// second pointerdown
|
||||
simulatePointerDown(stage, {
|
||||
x: 289,
|
||||
y: 10 + top,
|
||||
pointerId: 1,
|
||||
y: 10,
|
||||
pointerId: 2,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
||||
assert(otherDownCount === 1, '8) otherDownCount should be 1');
|
||||
assert.equal(otherDownCount, 1, '8) otherDownCount should be 1');
|
||||
assert(downCount === 2, '8) pointerdown should be 2');
|
||||
assert(!pointermove, '8) pointermove should be false');
|
||||
assert(!pointerup, '8) pointerup should be true');
|
||||
@ -217,9 +201,8 @@ describe.skip('PointerEvents', function () {
|
||||
// pointermove over circle 2
|
||||
simulatePointerMove(stage, {
|
||||
x: 290,
|
||||
y: 10 + top,
|
||||
y: 10,
|
||||
pointerId: 1,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
||||
assert(otherDownCount === 1, '9) otherDownCount should be 1');
|
||||
@ -232,7 +215,7 @@ describe.skip('PointerEvents', function () {
|
||||
|
||||
simulatePointerDown(stage, {
|
||||
x: 289,
|
||||
y: 10 + top,
|
||||
y: 10,
|
||||
pointerId: 1,
|
||||
preventDefault: function () {},
|
||||
});
|
||||
|
@ -309,56 +309,6 @@ describe('Stage', function () {
|
||||
);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('layer getIntersection() with selector', function () {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer({
|
||||
name: 'layer',
|
||||
});
|
||||
|
||||
var group = new Konva.Group({
|
||||
name: 'group',
|
||||
});
|
||||
|
||||
var circle = new Konva.Circle({
|
||||
x: stage.width() / 2,
|
||||
y: stage.height() / 2,
|
||||
radius: 70,
|
||||
strokeWidth: 4,
|
||||
fill: 'red',
|
||||
stroke: 'black',
|
||||
});
|
||||
|
||||
group.add(circle);
|
||||
layer.add(group);
|
||||
stage.add(layer);
|
||||
|
||||
assert.equal(
|
||||
stage.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'Circle'
|
||||
),
|
||||
circle,
|
||||
'intersection with shape selector'
|
||||
);
|
||||
assert.equal(
|
||||
stage.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'.group'
|
||||
),
|
||||
group,
|
||||
'intersection with group selector'
|
||||
);
|
||||
assert.equal(
|
||||
stage.getIntersection(
|
||||
{ x: stage.width() / 2, y: stage.height() / 2 },
|
||||
'Stage'
|
||||
),
|
||||
stage,
|
||||
'intersection with stage selector'
|
||||
);
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('stage getIntersection() edge detection', function () {
|
||||
var stage = addStage();
|
||||
@ -1190,9 +1140,10 @@ describe('Stage', function () {
|
||||
}
|
||||
});
|
||||
|
||||
stage._mouseover({
|
||||
stage._pointerover({
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
type: 'mouseover',
|
||||
});
|
||||
|
||||
assert.equal(mouseover, 1, 'initial over');
|
||||
@ -1267,7 +1218,7 @@ describe('Stage', function () {
|
||||
stage.on('mouseout', function () {
|
||||
count += 1;
|
||||
});
|
||||
stage._mouseleave({});
|
||||
stage._pointerleave({ type: 'mouseleave' });
|
||||
assert.equal(count, 2);
|
||||
});
|
||||
|
||||
|
@ -9,77 +9,6 @@ import {
|
||||
} from './test-utils';
|
||||
|
||||
describe('TouchEvents', function () {
|
||||
// ======================================================
|
||||
it('stage content touch events', function () {
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
var circle = new Konva.Circle({
|
||||
x: 100,
|
||||
y: 100,
|
||||
radius: 70,
|
||||
fill: 'green',
|
||||
stroke: 'black',
|
||||
strokeWidth: 4,
|
||||
name: 'myCircle',
|
||||
});
|
||||
|
||||
layer.add(circle);
|
||||
stage.add(layer);
|
||||
|
||||
var circleTouchstart = 0;
|
||||
var circleTouchend = 0;
|
||||
var stageContentTouchstart = 0;
|
||||
var stageContentTouchend = 0;
|
||||
var stageContentTouchmove = 0;
|
||||
var stageContentTap = 0;
|
||||
var stageContentDbltap = 0;
|
||||
|
||||
circle.on('touchstart', function () {
|
||||
circleTouchstart++;
|
||||
});
|
||||
|
||||
circle.on('touchend', function () {
|
||||
circleTouchend++;
|
||||
});
|
||||
|
||||
stage.on('contentTouchstart', function () {
|
||||
stageContentTouchstart++;
|
||||
});
|
||||
|
||||
stage.on('contentTouchend', function () {
|
||||
stageContentTouchend++;
|
||||
});
|
||||
|
||||
stage.on('contentTouchmove', function () {
|
||||
stageContentTouchmove++;
|
||||
});
|
||||
|
||||
stage.on('contentTap', function () {
|
||||
stageContentTap++;
|
||||
});
|
||||
|
||||
stage.on('contentDbltap', function () {
|
||||
stageContentDbltap++;
|
||||
});
|
||||
|
||||
simulateTouchStart(stage, [{ x: 100, y: 100, id: 0 }]);
|
||||
|
||||
simulateTouchEnd(stage, [], [{ x: 100, y: 100, id: 0 }]);
|
||||
assert.equal(circleTouchstart, 1, '1');
|
||||
assert.equal(circleTouchend, 1, '2');
|
||||
assert.equal(stageContentTouchstart, 1, '3');
|
||||
assert.equal(stageContentTouchend, 1, '4');
|
||||
assert.equal(stageContentDbltap, 0, '5');
|
||||
|
||||
simulateTouchStart(stage, [{ x: 1, y: 1, id: 0 }]);
|
||||
|
||||
simulateTouchEnd(stage, [], [{ x: 1, y: 1, id: 0 }]);
|
||||
|
||||
assert.equal(stageContentTouchstart, 2, '6');
|
||||
assert.equal(stageContentTouchend, 2, '7');
|
||||
assert.equal(stageContentDbltap, 1, '8');
|
||||
});
|
||||
|
||||
// ======================================================
|
||||
it('touchstart touchend touchmove tap dbltap', function (done) {
|
||||
var stage = addStage();
|
||||
@ -282,26 +211,14 @@ describe('TouchEvents', function () {
|
||||
stage.add(layer);
|
||||
|
||||
var circleTouchend = 0;
|
||||
var stageContentTouchstart = 0;
|
||||
var stageContentTouchend = 0;
|
||||
|
||||
circle.on('touchend', function () {
|
||||
circleTouchend++;
|
||||
});
|
||||
|
||||
stage.on('contentTouchstart', function () {
|
||||
stageContentTouchstart++;
|
||||
});
|
||||
|
||||
stage.on('contentTouchend', function () {
|
||||
stageContentTouchend++;
|
||||
});
|
||||
|
||||
simulateTouchStart(stage, [{ x: 1, y: 1, id: 0 }]);
|
||||
simulateTouchEnd(stage, [], [{ x: 100, y: 100, id: 0 }]);
|
||||
|
||||
assert.equal(stageContentTouchstart, 1);
|
||||
assert.equal(stageContentTouchend, 1);
|
||||
assert.equal(circleTouchend, 1);
|
||||
});
|
||||
|
||||
@ -554,7 +471,7 @@ describe('TouchEvents', function () {
|
||||
});
|
||||
|
||||
it('can capture touch events', function () {
|
||||
Konva.captureTouchEventsEnabled = true;
|
||||
Konva.capturePointerEventsEnabled = true;
|
||||
var stage = addStage();
|
||||
var layer = new Konva.Layer();
|
||||
stage.add(layer);
|
||||
@ -641,7 +558,7 @@ describe('TouchEvents', function () {
|
||||
assert.equal(circle1.hasPointerCapture(0), false);
|
||||
assert.equal(circle1.hasPointerCapture(1), false);
|
||||
|
||||
Konva.captureTouchEventsEnabled = false;
|
||||
Konva.capturePointerEventsEnabled = false;
|
||||
});
|
||||
|
||||
it('tap and double tap should trigger just once on stage', function () {
|
||||
|
@ -24,7 +24,9 @@ afterEach(function () {
|
||||
var isManual = this.currentTest.parent.title === 'Manual';
|
||||
|
||||
Konva.stages.forEach(function (stage) {
|
||||
clearTimeout(stage.dblTimeout);
|
||||
clearTimeout(stage._mouseDblTimeout);
|
||||
clearTimeout(stage._touchDblTimeout);
|
||||
clearTimeout(stage._pointerDblTimeout);
|
||||
});
|
||||
|
||||
if (!isFailed && !isManual) {
|
||||
@ -177,37 +179,43 @@ export function showHit(layer) {
|
||||
}
|
||||
|
||||
export function simulateMouseDown(stage, pos) {
|
||||
// simulatePointerDown(stage, pos);
|
||||
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
|
||||
|
||||
stage._mousedown({
|
||||
stage._pointerdown({
|
||||
clientX: pos.x,
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
type: 'mousedown',
|
||||
});
|
||||
}
|
||||
|
||||
export function simulateMouseMove(stage, pos) {
|
||||
// simulatePointerMove(stage, pos);
|
||||
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
|
||||
var evt = {
|
||||
clientX: pos.x,
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
type: 'mousemove',
|
||||
};
|
||||
|
||||
stage._mousemove(evt);
|
||||
stage._pointermove(evt);
|
||||
Konva.DD._drag(evt);
|
||||
}
|
||||
|
||||
export function simulateMouseUp(stage, pos) {
|
||||
// simulatePointerUp(stage, pos);
|
||||
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
|
||||
var evt = {
|
||||
clientX: pos.x,
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
type: 'mouseup',
|
||||
};
|
||||
|
||||
Konva.DD._endDragBefore(evt);
|
||||
stage._mouseup(evt);
|
||||
stage._pointerup(evt);
|
||||
Konva.DD._endDragAfter(evt);
|
||||
}
|
||||
|
||||
@ -242,9 +250,10 @@ export function simulateTouchStart(stage, pos, changed?) {
|
||||
var evt = {
|
||||
touches: touches,
|
||||
changedTouches: changedTouches,
|
||||
type: 'touchstart',
|
||||
};
|
||||
|
||||
stage._touchstart(evt);
|
||||
stage._pointerdown(evt);
|
||||
}
|
||||
|
||||
export function simulateTouchMove(stage, pos, changed?) {
|
||||
@ -278,9 +287,10 @@ export function simulateTouchMove(stage, pos, changed?) {
|
||||
var evt = {
|
||||
touches: touches,
|
||||
changedTouches: changedTouches,
|
||||
type: 'touchmove',
|
||||
};
|
||||
|
||||
stage._touchmove(evt);
|
||||
stage._pointermove(evt);
|
||||
Konva.DD._drag(evt);
|
||||
}
|
||||
|
||||
@ -315,10 +325,11 @@ export function simulateTouchEnd(stage, pos, changed?) {
|
||||
var evt = {
|
||||
touches: touches,
|
||||
changedTouches: changedTouches,
|
||||
type: 'touchend',
|
||||
};
|
||||
|
||||
Konva.DD._endDragBefore(evt);
|
||||
stage._touchend(evt);
|
||||
stage._pointerup(evt);
|
||||
Konva.DD._endDragAfter(evt);
|
||||
}
|
||||
|
||||
@ -329,6 +340,7 @@ export function simulatePointerDown(stage: Stage, pos) {
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
pointerId: pos.pointerId || 1,
|
||||
type: 'pointerdown',
|
||||
} as any);
|
||||
}
|
||||
|
||||
@ -339,6 +351,7 @@ export function simulatePointerMove(stage: Stage, pos) {
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
pointerId: pos.pointerId || 1,
|
||||
type: 'pointermove',
|
||||
};
|
||||
|
||||
stage._pointermove(evt as any);
|
||||
@ -346,13 +359,13 @@ export function simulatePointerMove(stage: Stage, pos) {
|
||||
}
|
||||
|
||||
export function simulatePointerUp(stage: Stage, pos) {
|
||||
debugger;
|
||||
var top = isNode ? 0 : stage.content.getBoundingClientRect().top;
|
||||
var evt = {
|
||||
clientX: pos.x,
|
||||
clientY: pos.y + top,
|
||||
button: pos.button || 0,
|
||||
pointerId: pos.pointerId || 1,
|
||||
type: 'pointerup',
|
||||
};
|
||||
|
||||
Konva.DD._endDragBefore(evt);
|
||||
|
Loading…
Reference in New Issue
Block a user