tsparticles
Version:
Porting of the abandoned Vincent Garreau's particles.js, converted in TypeScript. Added many new cool features and various bug fixes.
237 lines (236 loc) • 10.7 kB
JavaScript
import { ClickMode } from "../../Enums/Modes/ClickMode";
import { InteractivityDetect } from "../../Enums/InteractivityDetect";
import { PolygonMaskType } from "../../Enums/PolygonMaskType";
import { Constants } from "./Constants";
export class EventListeners {
constructor(container) {
this.container = container;
this.canPush = true;
this.mouseMoveHandler = (e) => this.mouseTouchMove(e);
this.touchStartHandler = (e) => this.mouseTouchMove(e);
this.touchMoveHandler = (e) => this.mouseTouchMove(e);
this.touchEndHandler = () => this.mouseTouchFinish();
this.mouseLeaveHandler = () => this.mouseTouchFinish();
this.touchCancelHandler = () => this.mouseTouchFinish();
this.touchEndClickHandler = (e) => this.mouseTouchClick(e);
this.mouseUpHandler = (e) => this.mouseTouchClick(e);
this.visibilityChangeHandler = () => this.handleVisibilityChange();
this.resizeHandler = () => this.handleWindowResize();
}
addListeners() {
this.manageListeners(true);
}
removeListeners() {
this.manageListeners(false);
}
manageListeners(add) {
const container = this.container;
const options = container.options;
if (options.interactivity.detectsOn === InteractivityDetect.window) {
container.interactivity.element = window;
}
else if (options.interactivity.detectsOn === InteractivityDetect.parent && container.canvas.element) {
container.interactivity.element = container.canvas.element.parentNode;
}
else {
container.interactivity.element = container.canvas.element;
}
const interactivityEl = container.interactivity.element;
if (interactivityEl && (options.interactivity.events.onHover.enable ||
options.interactivity.events.onClick.enable)) {
this.manageListener(interactivityEl, Constants.mouseMoveEvent, this.mouseMoveHandler, add);
this.manageListener(interactivityEl, Constants.touchStartEvent, this.touchStartHandler, add);
this.manageListener(interactivityEl, Constants.touchMoveEvent, this.touchMoveHandler, add);
if (!options.interactivity.events.onClick.enable) {
this.manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndHandler, add);
}
this.manageListener(interactivityEl, Constants.mouseLeaveEvent, this.mouseLeaveHandler, add);
this.manageListener(interactivityEl, Constants.touchCancelEvent, this.touchCancelHandler, add);
}
if (options.interactivity.events.onClick.enable && interactivityEl) {
this.manageListener(interactivityEl, Constants.touchEndEvent, this.touchEndClickHandler, add);
this.manageListener(interactivityEl, Constants.mouseUpEvent, this.mouseUpHandler, add);
}
if (options.interactivity.events.resize) {
this.manageListener(window, Constants.resizeEvent, this.resizeHandler, add);
}
if (document) {
this.manageListener(document, Constants.visibilityChangeEvent, this.visibilityChangeHandler, add, false);
}
}
manageListener(element, event, handler, add, options) {
if (add) {
this.addListener(element, event, handler, options);
}
else {
this.removeListener(element, event, handler, options);
}
}
addListener(element, event, handler, options) {
element.addEventListener(event, handler, options);
}
removeListener(element, event, handler, options) {
element.removeEventListener(event, handler, options);
}
handleWindowResize() {
const container = this.container;
const options = container.options;
if (!container.canvas.element) {
return;
}
container.canvas.dimension.width = container.canvas.element.offsetWidth;
container.canvas.dimension.height = container.canvas.element.offsetHeight;
if (container.retina.isRetina) {
container.canvas.dimension.width *= container.retina.pxRatio;
container.canvas.dimension.height *= container.retina.pxRatio;
}
container.canvas.element.width = container.canvas.dimension.width;
container.canvas.element.height = container.canvas.dimension.height;
if (!options.particles.move.enable) {
container.particles.redraw();
}
container.densityAutoParticles();
container.polygon.redraw();
}
handleVisibilityChange() {
const container = this.container;
const options = container.options;
if (!options.pauseOnBlur) {
return;
}
if (document === null || document === void 0 ? void 0 : document.hidden) {
container.pageHidden = true;
container.pause();
}
else {
container.pageHidden = false;
container.play();
}
}
mouseTouchMove(e) {
var _a, _b, _c;
const container = this.container;
const options = container.options;
let pos;
if (e.type.startsWith("mouse")) {
this.canPush = true;
const mouseEvent = e;
if (container.interactivity.element === window && container.canvas.element) {
const clientRect = container.canvas.element.getBoundingClientRect();
pos = {
x: mouseEvent.clientX - clientRect.left,
y: mouseEvent.clientY - clientRect.top,
};
}
else if (options.interactivity.detectsOn === InteractivityDetect.parent) {
const source = mouseEvent.target;
const target = mouseEvent.currentTarget;
if (source && target) {
const sourceRect = source.getBoundingClientRect();
const targetRect = target.getBoundingClientRect();
pos = {
x: mouseEvent.offsetX + sourceRect.left - targetRect.left,
y: mouseEvent.offsetY + sourceRect.top - targetRect.top,
};
}
else {
pos = {
x: mouseEvent.offsetX || mouseEvent.clientX,
y: mouseEvent.offsetY || mouseEvent.clientY,
};
}
}
else {
pos = {
x: mouseEvent.offsetX || mouseEvent.clientX,
y: mouseEvent.offsetY || mouseEvent.clientY,
};
}
}
else {
this.canPush = e.type !== "touchmove";
const touchEvent = e;
const lastTouch = touchEvent.touches[touchEvent.touches.length - 1];
const canvasRect = (_a = container.canvas.element) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
pos = {
x: lastTouch.clientX - ((_b = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.left) !== null && _b !== void 0 ? _b : 0),
y: lastTouch.clientY - ((_c = canvasRect === null || canvasRect === void 0 ? void 0 : canvasRect.top) !== null && _c !== void 0 ? _c : 0),
};
}
container.interactivity.mouse.position = pos;
if (container.retina.isRetina) {
container.interactivity.mouse.position.x *= container.retina.pxRatio;
container.interactivity.mouse.position.y *= container.retina.pxRatio;
}
container.interactivity.status = Constants.mouseMoveEvent;
}
mouseTouchFinish() {
const container = this.container;
delete container.interactivity.mouse.position;
container.interactivity.status = Constants.mouseLeaveEvent;
}
mouseTouchClick(e) {
const container = this.container;
const options = container.options;
if (options.polygon.enable && options.polygon.type !== PolygonMaskType.none &&
options.polygon.type !== PolygonMaskType.inline) {
if (container.polygon.checkInsidePolygon(container.interactivity.mouse.position)) {
this.doMouseTouchClick(e);
}
}
else {
this.doMouseTouchClick(e);
}
}
doMouseTouchClick(e) {
const container = this.container;
const options = container.options;
if (this.canPush) {
if (container.interactivity.mouse.position) {
container.interactivity.mouse.clickPosition = {
x: container.interactivity.mouse.position.x,
y: container.interactivity.mouse.position.y,
};
}
container.interactivity.mouse.clickTime = new Date().getTime();
const pushNb = options.interactivity.modes.push.quantity;
const removeNb = options.interactivity.modes.remove.quantity;
switch (options.interactivity.events.onClick.mode) {
case ClickMode.push:
if (options.particles.move.enable) {
container.particles.push(pushNb, container.interactivity.mouse);
}
else {
if (options.interactivity.modes.push.quantity === 1) {
container.particles.push(pushNb, container.interactivity.mouse);
}
else if (options.interactivity.modes.push.quantity > 1) {
container.particles.push(pushNb);
}
}
break;
case ClickMode.remove:
container.particles.removeQuantity(removeNb);
break;
case ClickMode.bubble:
container.bubble.clicking = true;
break;
case ClickMode.repulse:
container.repulse.clicking = true;
container.repulse.count = 0;
container.repulse.finish = false;
setTimeout(() => {
if (!container.destroyed) {
container.repulse.clicking = false;
}
}, options.interactivity.modes.repulse.duration * 1000);
break;
}
}
e.preventDefault();
if (e.type === "touchend") {
setTimeout(() => this.mouseTouchFinish(), 500);
}
e.preventDefault();
}
}