UNPKG

zrender

Version:

A lightweight graphic library providing 2d draw for Apache ECharts

206 lines (181 loc) 5.53 kB
import { keys, map } from '../core/util'; import { encodeHTML } from '../core/dom'; export type CSSSelectorVNode = Record<string, string> export type CSSAnimationVNode = Record<string, Record<string, string>> export const SVGNS = 'http://www.w3.org/2000/svg'; export const XLINKNS = 'http://www.w3.org/1999/xlink'; export const XMLNS = 'http://www.w3.org/2000/xmlns/'; export const XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'; export const META_DATA_PREFIX = 'ecmeta_'; export function createElement(name: string) { return document.createElementNS(SVGNS, name); } export type SVGVNodeAttrs = Record<string, string | number | undefined | boolean> export interface SVGVNode { tag: string, attrs: SVGVNodeAttrs, children?: SVGVNode[], text?: string // For patching elm?: Node key: string }; export function createVNode( tag: string, key: string, attrs?: SVGVNodeAttrs, children?: SVGVNode[], text?: string ): SVGVNode { return { tag, attrs: attrs || {}, children, text, key }; } function createElementOpen(name: string, attrs?: SVGVNodeAttrs) { const attrsStr: string[] = []; if (attrs) { // eslint-disable-next-line for (let key in attrs) { const val = attrs[key]; let part = key; // Same with the logic in patch. if (val === false) { continue; } else if (val !== true && val != null) { part += `="${val}"`; } attrsStr.push(part); } } return `<${name} ${attrsStr.join(' ')}>`; } function createElementClose(name: string) { return `</${name}>`; } export function vNodeToString(el: SVGVNode, opts?: { newline?: boolean }) { opts = opts || {}; const S = opts.newline ? '\n' : ''; function convertElToString(el: SVGVNode): string { const {children, tag, attrs, text} = el; return createElementOpen(tag, attrs) + (tag !== 'style' ? encodeHTML(text) : text || '') + (children ? `${S}${map(children, child => convertElToString(child)).join(S)}${S}` : '') + createElementClose(tag); } return convertElToString(el); } export function getCssString( selectorNodes: Record<string, CSSSelectorVNode>, animationNodes: Record<string, CSSAnimationVNode>, opts?: { newline?: boolean } ) { opts = opts || {}; const S = opts.newline ? '\n' : ''; const bracketBegin = ` {${S}`; const bracketEnd = `${S}}`; const selectors = map(keys(selectorNodes), className => { return className + bracketBegin + map(keys(selectorNodes[className]), attrName => { return `${attrName}:${selectorNodes[className][attrName]};`; }).join(S) + bracketEnd; }).join(S); const animations = map(keys(animationNodes), (animationName) => { return `@keyframes ${animationName}${bracketBegin}` + map(keys(animationNodes[animationName]), percent => { return percent + bracketBegin + map(keys(animationNodes[animationName][percent]), attrName => { let val = animationNodes[animationName][percent][attrName]; // postprocess if (attrName === 'd') { val = `path("${val}")`; } return `${attrName}:${val};`; }).join(S) + bracketEnd; }).join(S) + bracketEnd; }).join(S); if (!selectors && !animations) { return ''; } return ['<![CDATA[', selectors, animations, ']]>'].join(S); } export interface BrushScope { zrId: string shadowCache: Record<string, string> gradientCache: Record<string, string> patternCache: Record<string, string> clipPathCache: Record<string, string> defs: Record<string, SVGVNode> cssNodes: Record<string, CSSSelectorVNode> cssAnims: Record<string, Record<string, Record<string, string>>> /** * Cache for css style string, mapping from style string to class name. */ cssStyleCache: Record<string, string> cssAnimIdx: number shadowIdx: number gradientIdx: number patternIdx: number clipPathIdx: number // configs /** * If create animates nodes. */ animation?: boolean, /** * If create emphasis styles. */ emphasis?: boolean, /** * If will update. Some optimization for string generation can't be applied. */ willUpdate?: boolean /** * If compress the output string. */ compress?: boolean } export function createBrushScope(zrId: string): BrushScope { return { zrId, shadowCache: {}, patternCache: {}, gradientCache: {}, clipPathCache: {}, defs: {}, cssNodes: {}, cssAnims: {}, cssStyleCache: {}, cssAnimIdx: 0, shadowIdx: 0, gradientIdx: 0, patternIdx: 0, clipPathIdx: 0 }; } export function createSVGVNode( width: number | string, height: number | string, children?: SVGVNode[], useViewBox?: boolean ) { return createVNode( 'svg', 'root', { 'width': width, 'height': height, 'xmlns': SVGNS, 'xmlns:xlink': XLINKNS, 'version': '1.1', 'baseProfile': 'full', 'viewBox': useViewBox ? `0 0 ${width} ${height}` : false }, children ); }