123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- 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
- );
- }
|