UNPKG

zrender

Version:

A lightweight graphic library providing 2d draw for Apache ECharts

111 lines (97 loc) 3.97 kB
import Path, { DEFAULT_PATH_STYLE, PathStyleProps } from '../graphic/Path'; import ZRImage, { ImageStyleProps } from '../graphic/Image'; import TSpan, { TSpanStyleProps } from '../graphic/TSpan'; import { getLineDash } from '../canvas/dashStyle'; import { map } from '../core/util'; import { normalizeColor } from './helper'; type AllStyleOption = PathStyleProps | TSpanStyleProps | ImageStyleProps; const NONE = 'none'; const mathRound = Math.round; function pathHasFill(style: AllStyleOption): style is PathStyleProps { const fill = (style as PathStyleProps).fill; return fill != null && fill !== NONE; } function pathHasStroke(style: AllStyleOption): style is PathStyleProps { const stroke = (style as PathStyleProps).stroke; return stroke != null && stroke !== NONE; } const strokeProps = ['lineCap', 'miterLimit', 'lineJoin'] as const; const svgStrokeProps = map(strokeProps, prop => `stroke-${prop.toLowerCase()}`); export default function mapStyleToAttrs( updateAttr: (key: string, val: string | number) => void, style: AllStyleOption, el: Path | TSpan | ZRImage, /** * Will try not to set the attribute if it's using default value if not using forceUpdate. * Mainly for reduce the generated size in svg-ssr mode. */ forceUpdate: boolean ): void { const opacity = style.opacity == null ? 1 : style.opacity; // only set opacity. stroke and fill cannot be applied to svg image if (el instanceof ZRImage) { updateAttr('opacity', opacity); return; } if (pathHasFill(style)) { const fill = normalizeColor(style.fill as string); updateAttr('fill', fill.color); const fillOpacity = style.fillOpacity != null ? style.fillOpacity * fill.opacity * opacity : fill.opacity * opacity; if (forceUpdate || fillOpacity < 1) { updateAttr('fill-opacity', fillOpacity); } } else { updateAttr('fill', NONE); } if (pathHasStroke(style)) { const stroke = normalizeColor(style.stroke as string); updateAttr('stroke', stroke.color); const strokeScale = style.strokeNoScale ? (el as Path).getLineScale() : 1; const strokeWidth = (strokeScale ? (style.lineWidth || 0) / strokeScale : 0); const strokeOpacity = style.strokeOpacity != null ? style.strokeOpacity * stroke.opacity * opacity : stroke.opacity * opacity; const strokeFirst = style.strokeFirst; if (forceUpdate || strokeWidth !== 1) { updateAttr('stroke-width', strokeWidth); } // stroke then fill for text; fill then stroke for others if (forceUpdate || strokeFirst) { updateAttr('paint-order', strokeFirst ? 'stroke' : 'fill'); } if (forceUpdate || strokeOpacity < 1) { updateAttr('stroke-opacity', strokeOpacity); } if (style.lineDash) { let [lineDash, lineDashOffset] = getLineDash(el); if (lineDash) { lineDashOffset = mathRound(lineDashOffset || 0); updateAttr('stroke-dasharray', lineDash.join(',')); if (lineDashOffset || forceUpdate) { updateAttr('stroke-dashoffset', lineDashOffset); } } } else if (forceUpdate) { // Reset if force update. updateAttr('stroke-dasharray', NONE); } // PENDING reset for (let i = 0; i < strokeProps.length; i++) { const propName = strokeProps[i]; if (forceUpdate || style[propName] !== DEFAULT_PATH_STYLE[propName]) { const val = style[propName] || DEFAULT_PATH_STYLE[propName]; // TODO reset val && updateAttr(svgStrokeProps[i], val); } } } else if (forceUpdate) { updateAttr('stroke', NONE); } }