1 | import { Circle, Constants, Rectangle, Utils } from "../../Utils";
|
2 | import { DivMode, DivType, HoverMode } from "../../Enums";
|
3 | import { Vector } from "../../Core/Particle/Vector";
|
4 | export class Bouncer {
|
5 | constructor(container) {
|
6 | this.container = container;
|
7 | }
|
8 | isEnabled() {
|
9 | const container = this.container;
|
10 | const options = container.actualOptions;
|
11 | const mouse = container.interactivity.mouse;
|
12 | const events = options.interactivity.events;
|
13 | const divs = events.onDiv;
|
14 | return ((mouse.position && events.onHover.enable && Utils.isInArray(HoverMode.bounce, events.onHover.mode)) ||
|
15 | Utils.isDivModeEnabled(DivMode.bounce, divs));
|
16 | }
|
17 | interact() {
|
18 | const container = this.container;
|
19 | const options = container.actualOptions;
|
20 | const events = options.interactivity.events;
|
21 | const mouseMoveStatus = container.interactivity.status === Constants.mouseMoveEvent;
|
22 | const hoverEnabled = events.onHover.enable;
|
23 | const hoverMode = events.onHover.mode;
|
24 | const divs = events.onDiv;
|
25 | if (mouseMoveStatus && hoverEnabled && Utils.isInArray(HoverMode.bounce, hoverMode)) {
|
26 | this.processMouseBounce();
|
27 | }
|
28 | else {
|
29 | Utils.divModeExecute(DivMode.bounce, divs, (selector, div) => this.singleSelectorBounce(selector, div));
|
30 | }
|
31 | }
|
32 | reset() {
|
33 | }
|
34 | processMouseBounce() {
|
35 | const container = this.container;
|
36 | const pxRatio = container.retina.pixelRatio;
|
37 | const tolerance = 10 * pxRatio;
|
38 | const mousePos = container.interactivity.mouse.position;
|
39 | const radius = container.retina.bounceModeDistance;
|
40 | if (mousePos) {
|
41 | this.processBounce(mousePos, radius, new Circle(mousePos.x, mousePos.y, radius + tolerance));
|
42 | }
|
43 | }
|
44 | singleSelectorBounce(selector, div) {
|
45 | const container = this.container;
|
46 | const query = document.querySelectorAll(selector);
|
47 | if (!query.length) {
|
48 | return;
|
49 | }
|
50 | query.forEach((item) => {
|
51 | const elem = item;
|
52 | const pxRatio = container.retina.pixelRatio;
|
53 | const pos = {
|
54 | x: (elem.offsetLeft + elem.offsetWidth / 2) * pxRatio,
|
55 | y: (elem.offsetTop + elem.offsetHeight / 2) * pxRatio,
|
56 | };
|
57 | const radius = (elem.offsetWidth / 2) * pxRatio;
|
58 | const tolerance = 10 * pxRatio;
|
59 | const area = div.type === DivType.circle
|
60 | ? new Circle(pos.x, pos.y, radius + tolerance)
|
61 | : new Rectangle(elem.offsetLeft * pxRatio - tolerance, elem.offsetTop * pxRatio - tolerance, elem.offsetWidth * pxRatio + tolerance * 2, elem.offsetHeight * pxRatio + tolerance * 2);
|
62 | this.processBounce(pos, radius, area);
|
63 | });
|
64 | }
|
65 | processBounce(position, radius, area) {
|
66 | const query = this.container.particles.quadTree.query(area);
|
67 | for (const particle of query) {
|
68 | if (area instanceof Circle) {
|
69 | Utils.circleBounce(Utils.circleBounceDataFromParticle(particle), {
|
70 | position,
|
71 | radius,
|
72 | mass: (Math.pow(radius, 2) * Math.PI) / 2,
|
73 | velocity: Vector.create(0, 0),
|
74 | factor: {
|
75 | horizontal: 0,
|
76 | vertical: 0,
|
77 | },
|
78 | });
|
79 | }
|
80 | else if (area instanceof Rectangle) {
|
81 | Utils.rectBounce(particle, Utils.calculateBounds(position, radius));
|
82 | }
|
83 | }
|
84 | }
|
85 | }
|