UNPKG

@tsparticles/plugin-emitters-shape-canvas

Version:

tsParticles emitters shape canvas plugin

92 lines (91 loc) 3.28 kB
import { EmitterShapeBase } from "@tsparticles/plugin-emitters"; import { getRandom, isFunction, isNull, isString, } from "@tsparticles/engine"; import { getCanvasImageData, getImageData, getTextData } from "./utils.js"; const maxRetries = 100, half = 0.5; export class EmittersCanvasShape extends EmitterShapeBase { constructor(position, size, fill, options) { super(position, size, fill, options); const filter = options.filter, minAlpha = 0; let filterFunc = (pixel) => pixel.a > minAlpha; if (filter !== undefined) { if (isString(filter)) { if (Object.hasOwn(window, filter)) { const wndFilter = window[filter]; if (isFunction(wndFilter)) { filterFunc = wndFilter; } } } else { filterFunc = filter; } } this.filter = filterFunc; this.scale = options.scale; this.pixelData = { pixels: [], height: 0, width: 0, }; } async init() { let pixelData; const options = this.options, selector = options.selector, pixels = options.pixels, image = options.image, element = options.element, text = options.text, offset = pixels.offset; if (image) { const url = image.src; if (!url) { return; } pixelData = await getImageData(url, offset); } else if (text) { const data = getTextData(text, offset, this.fill); if (isNull(data)) { return; } pixelData = data; } else if (element ?? selector) { const canvas = element ?? (selector && document.querySelector(selector)); if (!canvas) { return; } const context = canvas.getContext("2d"); if (!context) { return; } pixelData = getCanvasImageData(context, canvas, offset); } if (!pixelData) { return; } this.pixelData = pixelData; } randomPosition() { const { height, width } = this.pixelData, data = this.pixelData, position = this.position, scale = this.scale, positionOffset = { x: position.x - width * scale * half, y: position.y - height * scale * half, }; for (let i = 0; i < maxRetries; i++) { const nextIndex = Math.floor(getRandom() * width * height), pixelPos = { x: nextIndex % width, y: Math.floor(nextIndex / width), }, pixel = data.pixels[pixelPos.y][pixelPos.x], shouldCreateParticle = this.filter(pixel); if (!shouldCreateParticle) { continue; } return { position: { x: pixelPos.x * scale + positionOffset.x, y: pixelPos.y * scale + positionOffset.y, }, color: { ...pixel }, opacity: pixel.a, }; } return null; } resize(position, size) { super.resize(position, size); } }