UNPKG

tsparticles

Version:

Easily create highly customizable particle, confetti and fireworks animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.

65 lines (64 loc) 3.35 kB
import { Circle, Constants, ExternalInteractorBase, Rectangle, Vector } from "../../../Core"; import { calculateBounds, circleBounce, circleBounceDataFromParticle, divModeExecute, isDivModeEnabled, isInArray, rectBounce, } from "../../../Utils"; export class Bouncer extends ExternalInteractorBase { constructor(container) { super(container); } isEnabled() { const container = this.container, options = container.actualOptions, mouse = container.interactivity.mouse, events = options.interactivity.events, divs = events.onDiv; return ((mouse.position && events.onHover.enable && isInArray("bounce" /* bounce */, events.onHover.mode)) || isDivModeEnabled("bounce" /* bounce */, divs)); } async interact() { const container = this.container, options = container.actualOptions, events = options.interactivity.events, mouseMoveStatus = container.interactivity.status === Constants.mouseMoveEvent, hoverEnabled = events.onHover.enable, hoverMode = events.onHover.mode, divs = events.onDiv; if (mouseMoveStatus && hoverEnabled && isInArray("bounce" /* bounce */, hoverMode)) { this.processMouseBounce(); } else { divModeExecute("bounce" /* bounce */, divs, (selector, div) => this.singleSelectorBounce(selector, div)); } } reset() { // do nothing } processMouseBounce() { const container = this.container, pxRatio = container.retina.pixelRatio, tolerance = 10 * pxRatio, mousePos = container.interactivity.mouse.position, radius = container.retina.bounceModeDistance; if (mousePos) { this.processBounce(mousePos, radius, new Circle(mousePos.x, mousePos.y, radius + tolerance)); } } singleSelectorBounce(selector, div) { const container = this.container; const query = document.querySelectorAll(selector); if (!query.length) { return; } query.forEach((item) => { const elem = item, pxRatio = container.retina.pixelRatio, pos = { x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio, y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio, }, radius = (elem.offsetWidth / 2) * pxRatio, tolerance = 10 * pxRatio; const area = div.type === "circle" /* circle */ ? new Circle(pos.x, pos.y, radius + tolerance) : new Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * 2, elem.offsetHeight * pxRatio + tolerance * 2); this.processBounce(pos, radius, area); }); } processBounce(position, radius, area) { const query = this.container.particles.quadTree.query(area); for (const particle of query) { if (area instanceof Circle) { circleBounce(circleBounceDataFromParticle(particle), { position, radius, mass: (radius ** 2 * Math.PI) / 2, velocity: Vector.origin, factor: Vector.origin, }); } else if (area instanceof Rectangle) { rectBounce(particle, calculateBounds(position, radius)); } } } }