import { ExternalInteractorBase, colorMix, drawLine, getStyleFromHsl, getStyleFromRgb, isInArray, } from "tsparticles-engine"; import { Connect } from "./Options/Classes/Connect"; function gradient(context, p1, p2, opacity) { const gradStop = Math.floor(p2.getRadius() / p1.getRadius()), color1 = p1.getFillColor(), color2 = p2.getFillColor(); if (!color1 || !color2) { return; } const sourcePos = p1.getPosition(), destPos = p2.getPosition(), midRgb = colorMix(color1, color2, p1.getRadius(), p2.getRadius()), grad = context.createLinearGradient(sourcePos.x, sourcePos.y, destPos.x, destPos.y); grad.addColorStop(0, getStyleFromHsl(color1, opacity)); grad.addColorStop(gradStop > 1 ? 1 : gradStop, getStyleFromRgb(midRgb, opacity)); grad.addColorStop(1, getStyleFromHsl(color2, opacity)); return grad; } function drawConnectLine(context, width, lineStyle, begin, end) { drawLine(context, begin, end); context.lineWidth = width; context.strokeStyle = lineStyle; context.stroke(); } function lineStyle(container, ctx, p1, p2) { const options = container.actualOptions, connectOptions = options.interactivity.modes.connect; if (!connectOptions) { return; } return gradient(ctx, p1, p2, connectOptions.links.opacity); } function drawConnection(container, p1, p2) { container.canvas.draw((ctx) => { var _a; const ls = lineStyle(container, ctx, p1, p2); if (!ls) { return; } const pos1 = p1.getPosition(), pos2 = p2.getPosition(); drawConnectLine(ctx, (_a = p1.retina.linksWidth) !== null && _a !== void 0 ? _a : 0, ls, pos1, pos2); }); } export class Connector extends ExternalInteractorBase { constructor(container) { super(container); } clear() { } init() { const container = this.container, connect = container.actualOptions.interactivity.modes.connect; if (!connect) { return; } container.retina.connectModeDistance = connect.distance * container.retina.pixelRatio; container.retina.connectModeRadius = connect.radius * container.retina.pixelRatio; } async interact() { const container = this.container, options = container.actualOptions; if (options.interactivity.events.onHover.enable && container.interactivity.status === "pointermove") { const mousePos = container.interactivity.mouse.position; if (!container.retina.connectModeDistance || container.retina.connectModeDistance < 0 || !container.retina.connectModeRadius || container.retina.connectModeRadius < 0 || !mousePos) { return; } const distance = Math.abs(container.retina.connectModeRadius), query = container.particles.quadTree.queryCircle(mousePos, distance, (p) => this.isEnabled(p)); let i = 0; for (const p1 of query) { const pos1 = p1.getPosition(); for (const p2 of query.slice(i + 1)) { const pos2 = p2.getPosition(), distMax = Math.abs(container.retina.connectModeDistance), xDiff = Math.abs(pos1.x - pos2.x), yDiff = Math.abs(pos1.y - pos2.y); if (xDiff < distMax && yDiff < distMax) { drawConnection(container, p1, p2); } } ++i; } } } isEnabled(particle) { var _a; const container = this.container, mouse = container.interactivity.mouse, events = ((_a = particle === null || particle === void 0 ? void 0 : particle.interactivity) !== null && _a !== void 0 ? _a : container.actualOptions.interactivity).events; if (!(events.onHover.enable && mouse.position)) { return false; } return isInArray("connect", events.onHover.mode); } loadModeOptions(options, ...sources) { if (!options.connect) { options.connect = new Connect(); } for (const source of sources) { options.connect.load(source === null || source === void 0 ? void 0 : source.connect); } } reset() { } }