(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "../Utils/CanvasUtils", "../Utils/Utils", "../Utils/ColorUtils", "./Utils/Constants"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Canvas = void 0; const CanvasUtils_1 = require("../Utils/CanvasUtils"); const Utils_1 = require("../Utils/Utils"); const ColorUtils_1 = require("../Utils/ColorUtils"); const Constants_1 = require("./Utils/Constants"); function setTransformValue(factor, newFactor, key) { var _a; const newValue = newFactor[key]; if (newValue !== undefined) { factor[key] = ((_a = factor[key]) !== null && _a !== void 0 ? _a : 1) * newValue; } } class Canvas { constructor(container) { this.container = container; this.size = { height: 0, width: 0, }; this._context = null; this._generated = false; this._preDrawUpdaters = []; this._postDrawUpdaters = []; this._resizePlugins = []; this._colorPlugins = []; this._mutationObserver = !(0, Utils_1.isSsr)() && typeof MutationObserver !== "undefined" ? new MutationObserver((records) => { for (const record of records) { if (record.type === "attributes" && record.attributeName === "style") { this._repairStyle(); } } }) : undefined; } get _fullScreen() { return this.container.actualOptions.fullScreen.enable; } clear() { const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = this._trailFill; if (options.backgroundMask.enable) { this.paint(); } else if (trail.enable && trail.length > 0 && trailFill) { if (trailFill.color) { this._paintBase((0, ColorUtils_1.getStyleFromRgb)(trailFill.color, trailFill.opacity)); } else if (trailFill.image) { this._paintImage(trailFill.image, trailFill.opacity); } } else { this.draw((ctx) => { (0, CanvasUtils_1.clear)(ctx, this.size); }); } } destroy() { var _a, _b; (_a = this._mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); if (this._generated) { (_b = this.element) === null || _b === void 0 ? void 0 : _b.remove(); } else { this._resetOriginalStyle(); } this.draw((ctx) => { (0, CanvasUtils_1.clear)(ctx, this.size); }); this._preDrawUpdaters = []; this._postDrawUpdaters = []; this._resizePlugins = []; this._colorPlugins = []; } draw(cb) { if (!this._context) { return; } return cb(this._context); } drawParticle(particle, delta) { var _a; if (particle.spawning || particle.destroyed) { return; } const radius = particle.getRadius(); if (radius <= 0) { return; } const pfColor = particle.getFillColor(), psColor = (_a = particle.getStrokeColor()) !== null && _a !== void 0 ? _a : pfColor; let [fColor, sColor] = this._getPluginParticleColors(particle); if (!fColor) { fColor = pfColor; } if (!sColor) { sColor = psColor; } if (!fColor && !sColor) { return; } this.draw((ctx) => { var _a, _b, _c, _d; const options = this.container.actualOptions, zIndexOptions = particle.options.zIndex, zOpacityFactor = (1 - particle.zIndexFactor) ** zIndexOptions.opacityRate, opacity = (_c = (_a = particle.bubble.opacity) !== null && _a !== void 0 ? _a : (_b = particle.opacity) === null || _b === void 0 ? void 0 : _b.value) !== null && _c !== void 0 ? _c : 1, strokeOpacity = (_d = particle.strokeOpacity) !== null && _d !== void 0 ? _d : opacity, zOpacity = opacity * zOpacityFactor, zStrokeOpacity = strokeOpacity * zOpacityFactor, transform = {}, colorStyles = { fill: fColor ? (0, ColorUtils_1.getStyleFromHsl)(fColor, zOpacity) : undefined, }; colorStyles.stroke = sColor ? (0, ColorUtils_1.getStyleFromHsl)(sColor, zStrokeOpacity) : colorStyles.fill; this._applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform); (0, CanvasUtils_1.drawParticle)({ container: this.container, context: ctx, particle, delta, colorStyles, backgroundMask: options.backgroundMask.enable, composite: options.backgroundMask.composite, radius: radius * (1 - particle.zIndexFactor) ** zIndexOptions.sizeRate, opacity: zOpacity, shadow: particle.options.shadow, transform, }); this._applyPostDrawUpdaters(particle); }); } drawParticlePlugin(plugin, particle, delta) { this.draw((ctx) => { (0, CanvasUtils_1.drawParticlePlugin)(ctx, plugin, particle, delta); }); } drawPlugin(plugin, delta) { this.draw((ctx) => { (0, CanvasUtils_1.drawPlugin)(ctx, plugin, delta); }); } async init() { var _a; this.resize(); this._initStyle(); this._initCover(); try { await this._initTrail(); } catch (e) { console.error(e); } this.initBackground(); if (this.element) { (_a = this._mutationObserver) === null || _a === void 0 ? void 0 : _a.observe(this.element, { attributes: true }); } this.initUpdaters(); this.initPlugins(); this.paint(); } initBackground() { const options = this.container.actualOptions, background = options.background, element = this.element, elementStyle = element === null || element === void 0 ? void 0 : element.style; if (!elementStyle) { return; } if (background.color) { const color = (0, ColorUtils_1.rangeColorToRgb)(background.color); elementStyle.backgroundColor = color ? (0, ColorUtils_1.getStyleFromRgb)(color, background.opacity) : ""; } else { elementStyle.backgroundColor = ""; } elementStyle.backgroundImage = background.image || ""; elementStyle.backgroundPosition = background.position || ""; elementStyle.backgroundRepeat = background.repeat || ""; elementStyle.backgroundSize = background.size || ""; } initPlugins() { this._resizePlugins = []; for (const [, plugin] of this.container.plugins) { if (plugin.resize) { this._resizePlugins.push(plugin); } if (plugin.particleFillColor || plugin.particleStrokeColor) { this._colorPlugins.push(plugin); } } } initUpdaters() { this._preDrawUpdaters = []; this._postDrawUpdaters = []; for (const updater of this.container.particles.updaters) { if (updater.afterDraw) { this._postDrawUpdaters.push(updater); } if (updater.getColorStyles || updater.getTransformValues || updater.beforeDraw) { this._preDrawUpdaters.push(updater); } } } loadCanvas(canvas) { var _a, _b; if (this._generated) { (_a = this.element) === null || _a === void 0 ? void 0 : _a.remove(); } this._generated = canvas.dataset && Constants_1.generatedAttribute in canvas.dataset ? canvas.dataset[Constants_1.generatedAttribute] === "true" : this._generated; this.element = canvas; this.element.ariaHidden = "true"; this._originalStyle = (0, Utils_1.deepExtend)({}, this.element.style); this.size.height = canvas.offsetHeight; this.size.width = canvas.offsetWidth; this._context = this.element.getContext("2d"); (_b = this._mutationObserver) === null || _b === void 0 ? void 0 : _b.observe(this.element, { attributes: true }); this.container.retina.init(); this.initBackground(); } paint() { const options = this.container.actualOptions; this.draw((ctx) => { if (options.backgroundMask.enable && options.backgroundMask.cover) { (0, CanvasUtils_1.clear)(ctx, this.size); this._paintBase(this._coverColorStyle); } else { this._paintBase(); } }); } resize() { if (!this.element) { return; } const container = this.container, pxRatio = container.retina.pixelRatio, size = container.canvas.size, newSize = { width: this.element.offsetWidth * pxRatio, height: this.element.offsetHeight * pxRatio, }; if (newSize.height === size.height && newSize.width === size.width && newSize.height === this.element.height && newSize.width === this.element.width) { return; } const oldSize = Object.assign({}, size); this.element.width = size.width = this.element.offsetWidth * pxRatio; this.element.height = size.height = this.element.offsetHeight * pxRatio; if (this.container.started) { this.resizeFactor = { width: size.width / oldSize.width, height: size.height / oldSize.height, }; } } async windowResize() { if (!this.element) { return; } this.resize(); const container = this.container, needsRefresh = container.updateActualOptions(); container.particles.setDensity(); this._applyResizePlugins(); if (needsRefresh) { await container.refresh(); } } _applyPostDrawUpdaters(particle) { var _a; for (const updater of this._postDrawUpdaters) { (_a = updater.afterDraw) === null || _a === void 0 ? void 0 : _a.call(updater, particle); } } _applyPreDrawUpdaters(ctx, particle, radius, zOpacity, colorStyles, transform) { var _a; for (const updater of this._preDrawUpdaters) { if (updater.getColorStyles) { const { fill, stroke } = updater.getColorStyles(particle, ctx, radius, zOpacity); if (fill) { colorStyles.fill = fill; } if (stroke) { colorStyles.stroke = stroke; } } if (updater.getTransformValues) { const updaterTransform = updater.getTransformValues(particle); for (const key in updaterTransform) { setTransformValue(transform, updaterTransform, key); } } (_a = updater.beforeDraw) === null || _a === void 0 ? void 0 : _a.call(updater, particle); } } _applyResizePlugins() { for (const plugin of this._resizePlugins) { if (plugin.resize) { plugin.resize(); } } } _getPluginParticleColors(particle) { let fColor, sColor; for (const plugin of this._colorPlugins) { if (!fColor && plugin.particleFillColor) { fColor = (0, ColorUtils_1.rangeColorToHsl)(plugin.particleFillColor(particle)); } if (!sColor && plugin.particleStrokeColor) { sColor = (0, ColorUtils_1.rangeColorToHsl)(plugin.particleStrokeColor(particle)); } if (fColor && sColor) { break; } } return [fColor, sColor]; } _initCover() { const options = this.container.actualOptions, cover = options.backgroundMask.cover, color = cover.color, coverRgb = (0, ColorUtils_1.rangeColorToRgb)(color); if (coverRgb) { const coverColor = { r: coverRgb.r, g: coverRgb.g, b: coverRgb.b, a: cover.opacity, }; this._coverColorStyle = (0, ColorUtils_1.getStyleFromRgb)(coverColor, coverColor.a); } } _initStyle() { const element = this.element, options = this.container.actualOptions; if (!element) { return; } if (this._fullScreen) { this._originalStyle = (0, Utils_1.deepExtend)({}, element.style); this._setFullScreenStyle(); } else { this._resetOriginalStyle(); } for (const key in options.style) { if (!key || !options.style) { continue; } const value = options.style[key]; if (!value) { continue; } element.style.setProperty(key, value, "important"); } } async _initTrail() { const options = this.container.actualOptions, trail = options.particles.move.trail, trailFill = trail.fill; if (!trail.enable) { return; } if (trailFill.color) { const fillColor = (0, ColorUtils_1.rangeColorToRgb)(trailFill.color); if (!fillColor) { return; } const trail = options.particles.move.trail; this._trailFill = { color: Object.assign({}, fillColor), opacity: 1 / trail.length, }; } else { await new Promise((resolve, reject) => { if (!trailFill.image) { return; } const img = document.createElement("img"); img.addEventListener("load", () => { this._trailFill = { image: img, opacity: 1 / trail.length, }; resolve(); }); img.addEventListener("error", (evt) => { reject(evt.error); }); img.src = trailFill.image; }); } } _paintBase(baseColor) { this.draw((ctx) => { (0, CanvasUtils_1.paintBase)(ctx, this.size, baseColor); }); } _paintImage(image, opacity) { this.draw((ctx) => { (0, CanvasUtils_1.paintImage)(ctx, this.size, image, opacity); }); } _repairStyle() { var _a, _b; const element = this.element; if (!element) { return; } (_a = this._mutationObserver) === null || _a === void 0 ? void 0 : _a.disconnect(); this._initStyle(); this.initBackground(); (_b = this._mutationObserver) === null || _b === void 0 ? void 0 : _b.observe(element, { attributes: true }); } _resetOriginalStyle() { const element = this.element, originalStyle = this._originalStyle; if (!(element && originalStyle)) { return; } element.style.position = originalStyle.position; element.style.zIndex = originalStyle.zIndex; element.style.top = originalStyle.top; element.style.left = originalStyle.left; element.style.width = originalStyle.width; element.style.height = originalStyle.height; } _setFullScreenStyle() { const element = this.element; if (!element) { return; } const priority = "important"; element.style.setProperty("position", "fixed", priority); element.style.setProperty("z-index", this.container.actualOptions.fullScreen.zIndex.toString(10), priority); element.style.setProperty("top", "0", priority); element.style.setProperty("left", "0", priority); element.style.setProperty("width", "100%", priority); element.style.setProperty("height", "100%", priority); } } exports.Canvas = Canvas; });