UNPKG

zrender

Version:

A lightweight graphic library providing 2d draw for Apache ECharts

192 lines (172 loc) 5.87 kB
// Shared methods of svg and svg-ssr import { MatrixArray } from '../core/matrix'; import Transformable, { TransformProp } from '../core/Transformable'; import { RADIAN_TO_DEGREE, retrieve2, logError, isFunction } from '../core/util'; import Displayable from '../graphic/Displayable'; import { GradientObject } from '../graphic/Gradient'; import { LinearGradientObject } from '../graphic/LinearGradient'; import Path from '../graphic/Path'; import { ImagePatternObject, PatternObject, SVGPatternObject } from '../graphic/Pattern'; import { RadialGradientObject } from '../graphic/RadialGradient'; import { parse } from '../tool/color'; import env from '../core/env'; const mathRound = Math.round; export function normalizeColor(color: string): { color: string; opacity: number; } { let opacity; if (!color || color === 'transparent') { color = 'none'; } else if (typeof color === 'string' && color.indexOf('rgba') > -1) { const arr = parse(color); if (arr) { // TODO use hex? color = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')'; opacity = arr[3]; } } return { color, opacity: opacity == null ? 1 : opacity }; } const EPSILON = 1e-4; export function isAroundZero(transform: number) { return transform < EPSILON && transform > -EPSILON; } export function round3(transform: number) { return mathRound(transform * 1e3) / 1e3; } export function round4(transform: number) { return mathRound(transform * 1e4) / 1e4; } export function round1(transform: number) { return mathRound(transform * 10) / 10; } export function getMatrixStr(m: MatrixArray) { return 'matrix(' // Avoid large string of matrix // PENDING If have precision issue when scaled + round3(m[0]) + ',' + round3(m[1]) + ',' + round3(m[2]) + ',' + round3(m[3]) + ',' + round4(m[4]) + ',' + round4(m[5]) + ')'; } export const TEXT_ALIGN_TO_ANCHOR = { left: 'start', right: 'end', center: 'middle', middle: 'middle' }; export function adjustTextY(y: number, lineHeight: number, textBaseline: CanvasTextBaseline): number { // TODO Other baselines. if (textBaseline === 'top') { y += lineHeight / 2; } else if (textBaseline === 'bottom') { y -= lineHeight / 2; } return y; } export function hasShadow(style: Displayable['style']) { // TODO: textBoxShadowBlur is not supported yet return style && (style.shadowBlur || style.shadowOffsetX || style.shadowOffsetY); } export function getShadowKey(displayable: Displayable) { const style = displayable.style; const globalScale = displayable.getGlobalScale(); return [ style.shadowColor, (style.shadowBlur || 0).toFixed(2), // Reduce the precision (style.shadowOffsetX || 0).toFixed(2), (style.shadowOffsetY || 0).toFixed(2), globalScale[0], globalScale[1] ].join(','); } export function getClipPathsKey(clipPaths: Path[]) { let key: number[] = []; if (clipPaths) { for (let i = 0; i < clipPaths.length; i++) { const clipPath = clipPaths[i]; key.push(clipPath.id); } } return key.join(','); } export function isImagePattern(val: any): val is ImagePatternObject { return val && (!!(val as ImagePatternObject).image); } export function isSVGPattern(val: any): val is SVGPatternObject { return val && (!!(val as SVGPatternObject).svgElement); } export function isPattern(val: any): val is PatternObject { return isImagePattern(val) || isSVGPattern(val); } export function isLinearGradient(val: GradientObject): val is LinearGradientObject { return val.type === 'linear'; } export function isRadialGradient(val: GradientObject): val is RadialGradientObject { return val.type === 'radial'; } export function isGradient(val: any): val is GradientObject { return val && ( (val as GradientObject).type === 'linear' || (val as GradientObject).type === 'radial' ); } export function getIdURL(id: string) { return `url(#${id})`; } export function getPathPrecision(el: Path) { const scale = el.getGlobalScale(); const size = Math.max(scale[0], scale[1]); return Math.max(Math.ceil(Math.log(size) / Math.log(10)), 1); } export function getSRTTransformString( transform: Partial<Pick<Transformable, TransformProp>> ) { const x = transform.x || 0; const y = transform.y || 0; const rotation = (transform.rotation || 0) * RADIAN_TO_DEGREE; const scaleX = retrieve2(transform.scaleX, 1); const scaleY = retrieve2(transform.scaleY, 1); const skewX = transform.skewX || 0; const skewY = transform.skewY || 0; const res = []; if (x || y) { // TODO not using px unit? res.push(`translate(${x}px,${y}px)`); } if (rotation) { res.push(`rotate(${rotation})`); } if (scaleX !== 1 || scaleY !== 1) { res.push(`scale(${scaleX},${scaleY})`); } if (skewX || skewY) { res.push(`skew(${mathRound(skewX * RADIAN_TO_DEGREE)}deg, ${mathRound(skewY * RADIAN_TO_DEGREE)}deg)`); } return res.join(' '); } export const encodeBase64 = (function () { if (env.hasGlobalWindow && isFunction(window.btoa)) { return function (str: string) { return window.btoa(unescape(encodeURIComponent(str))); }; } if (typeof Buffer !== 'undefined') { return function (str: string) { return Buffer.from(str).toString('base64'); }; } return function (str: string): string { if (process.env.NODE_ENV !== 'production') { logError('Base64 isn\'t natively supported in the current environment.'); } return null; }; })();