UNPKG

p5.js-svg

Version:

The main goal of p5.SVG is to provide a SVG runtime for p5.js, so that we can draw using p5's powerful API in \<svg\>, save things to svg file and manipulating existing SVG file without rasterization.

132 lines (117 loc) 4.02 kB
import { P5SVG } from './types' /** * https://github.com/processing/p5.js/blob/main/src/core/p5.Element.js */ export default (p5: P5SVG) => { /** * Returns an Array of SVGElements of current SVG Graphics matching given selector * * @param selector CSS selector for query */ (p5.prototype as any).querySVG = function (selector: string) { const svg = this._renderer && this._renderer.svg if (!svg) { return null } return p5.SVGElement.prototype.query.call({ elt: svg }, selector) } p5.SVGElement = class SVGElement extends p5.Element { public elt: Element public isUserInstanciated: boolean /** * Returns an Array of children of current SVG Element matching given selector * * @param selector CSS selector for query */ query(selector: string) { const elements = this.elt.querySelectorAll(selector) const objects = [] for (let i = 0; i < elements.length; i++) { objects[i] = new SVGElement(elements[i] as any) } return objects } /** * Append a new child to current element. * @param element * @returns */ append(element: SVGElement | Element) { const elt = (element as SVGElement).elt || element as Element this.elt.appendChild(elt) return this } /** * Create SVGElement * */ static create(nodeName: string, attributes: { [key: string]: string }, isUserInstanciated?: boolean) { attributes = attributes || {} const elt = document.createElementNS('http://www.w3.org/2000/svg', nodeName) Object.keys(attributes).forEach(function (k) { elt.setAttribute(k, attributes[k]) }) const svgEl = new SVGElement(elt as any) svgEl.isUserInstanciated = isUserInstanciated return svgEl } /** * Check if any group above is user instanciated * Will also return true if oneself is user instanciated * */ isWithinUserInstanciated() : boolean { if (this.isUserInstanciated) { return true } if (!(this.parentNode() instanceof SVGElement)) { return false } return this.parentNode().isWithinUserInstanciated() } /** * Get parentNode. * If selector not given, returns parentNode. * Otherwise, will look up all ancestors, * and return closest element matching given selector, * or return null if not found. * */ parentNode(selector?: string) { if (!selector) { return new SVGElement(this.elt.parentNode as any) } let elt: SVGElement = this as SVGElement while (elt) { elt = this.parentNode() if (elt && elt.elt.matches(selector)) { return elt } } return null } /** * Apply different attribute operation based on arguments.length * <ul> * <li>setAttribute(name, value)</li> * <li>setAttributeNS(namespace, name, value)</li> * <li>getAttribute(name)</li> * </ul> * */ attribute = function (...args: any[]): any { if (args.length === 3) { this.elt.setAttributeNS(args[0], args[1], args[2]) return this } if (args.length === 2) { this.elt.setAttribute(args[0], args[1]) return this } if (args.length === 1) { return this.elt.getAttribute(args[0]) } return this } } }