CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-zrender

A lightweight 2D graphics library providing canvas and SVG rendering for Apache ECharts

Overview
Eval results
Files

utilities.mddocs/

Utility Libraries

ZRender provides comprehensive utility libraries for mathematical operations, color manipulation, path processing, and platform abstractions. These utilities are essential for graphics programming and provide cross-platform compatibility.

Core Utilities (util namespace)

The util namespace provides fundamental utility functions:

Object and Array Utilities

namespace util {
  // Object utilities
  function clone<T>(obj: T): T;
  function merge<T, S>(target: T, source: S, overwrite?: boolean): T & S;
  function extend<T, S>(target: T, source: S): T & S;
  function defaults<T>(target: T, ...sources: Partial<T>[]): T;
  
  // Array utilities
  function map<T, R>(arr: T[], cb: (item: T, index: number) => R): R[];
  function reduce<T, R>(arr: T[], cb: (prev: R, item: T, index: number) => R, memo?: R): R;
  function filter<T>(arr: T[], cb: (item: T, index: number) => boolean): T[];
  function find<T>(arr: T[], cb: (item: T, index: number) => boolean): T | undefined;
  function indexOf<T>(arr: T[], item: T): number;
  
  // Type checking
  function isArray(value: any): value is any[];
  function isFunction(value: any): value is Function;
  function isString(value: any): value is string;
  function isObject(value: any): value is object;
  function isNumber(value: any): value is number;
  function isBoolean(value: any): value is boolean;
  function isDom(value: any): value is Element;
  
  // Value utilities
  function retrieve<T>(...args: T[]): T;
  function retrieve2<T>(value0: T, value1: T): T;
  function retrieve3<T>(value0: T, value1: T, value2: T): T;
  function slice<T>(arr: ArrayLike<T>, start?: number, end?: number): T[];
  function normalizeCssArray(val: number | number[]): number[];
  
  // String utilities
  function trim(str: string): string;
  function toCamelCase(str: string): string;
  function toHyphenCase(str: string): string;
  
  // Unique ID generation
  function guid(): number;
  
  // Performance utilities
  function createHashMap<T>(obj?: Record<string, T>): HashMap<T>;
  function concatArray<T>(a: T[], b: T[]): T[];
  function each<T>(obj: T[] | Record<string, T>, cb: (value: T, key: string | number) => void): void;
}

interface HashMap<T> {
  data: Record<string, T>;
  get(key: string): T;
  set(key: string, value: T): T;
  has(key: string): boolean;
  removeKey(key: string): void;
}

Matrix Operations (matrix namespace)

2D transformation matrix utilities:

namespace matrix {
  // Matrix creation and manipulation
  function create(): number[];
  function identity(): number[];
  function copy(out: number[], m: number[]): number[];
  
  // Basic transformations
  function translate(out: number[], a: number[], v: number[]): number[];
  function rotate(out: number[], a: number[], rad: number): number[];
  function scale(out: number[], a: number[], v: number[]): number[];
  
  // Matrix operations
  function mul(out: number[], a: number[], b: number[]): number[];
  function invert(out: number[], a: number[]): number[] | null;
  
  // Point transformations
  function applyTransform(out: number[], v: number[], m: number[]): number[];
  
  // Decomposition
  function decompose(m: number[], a: number[], translate: number[], rotate: number[], scale: number[]): boolean;
}

Vector Operations (vector namespace)

2D vector mathematics:

namespace vector {
  // Vector creation
  function create(x?: number, y?: number): number[];
  function copy(out: number[], v: number[]): number[];
  function clone(v: number[]): number[];
  function set(out: number[], a: number, b: number): number[];
  
  // Arithmetic operations
  function add(out: number[], a: number[], b: number[]): number[];
  function scaleAndAdd(out: number[], a: number[], b: number[], scale: number): number[];
  function sub(out: number[], a: number[], b: number[]): number[];
  function len(v: number[]): number;
  function lenSquare(v: number[]): number;
  function mul(out: number[], a: number[], b: number[]): number[];
  function div(out: number[], a: number[], b: number[]): number[];
  function dot(a: number[], b: number[]): number;
  function scale(out: number[], a: number[], b: number): number[];
  function normalize(out: number[], a: number[]): number[];
  
  // Distance and angle calculations
  function distance(a: number[], b: number[]): number;
  function distanceSquare(a: number[], b: number[]): number;
  function negate(out: number[], a: number[]): number[];
  function lerp(out: number[], a: number[], b: number[], t: number): number[];
  
  // Geometric utilities
  function applyTransform(out: number[], v: number[], m: number[]): number[];
  function min(out: number[], a: number[], b: number[]): number[];
  function max(out: number[], a: number[], b: number[]): number[];
}

Color Manipulation (color namespace)

Color parsing, conversion, and manipulation:

namespace color {
  // Color parsing
  function parse(colorStr: string): number[] | null;
  function rgba2String(rgba: number[]): string;
  
  // Color format conversion
  function toHex(color: string): string;
  function toRGB(color: string): string;
  function toHSL(color: string): string;
  function toHSV(color: string): string;
  
  // Color space conversions
  function rgb2hsv(r: number, g: number, b: number): number[];
  function hsv2rgb(h: number, s: number, v: number): number[];
  function rgb2hsl(r: number, g: number, b: number): number[];
  function hsl2rgb(h: number, s: number, l: number): number[];
  
  // Color interpolation
  function lerp(t: number, a: string, b: string, out?: number[]): string;
  function lerpArray(t: number, a: number[], b: number[], out?: number[]): number[];
  
  // Color analysis
  function lum(color: string, backgroundLum?: number): number;
  function random(): string;
  
  // Color modification
  function modifyHSL(color: string, h?: number, s?: number, l?: number): string;
  function modifyAlpha(color: string, alpha: number): string;
  
  // Palette generation
  function stringify(arrColor: number[], type: 'rgba' | 'rgb'): string;
}

Path Processing (path namespace)

SVG path manipulation and processing:

namespace path {
  // Path parsing and creation
  function createFromString(str: string): PathProxy;
  function extendFromString(path: PathProxy, str: string): void;
  function mergePath(path1: PathProxy, path2: PathProxy): PathProxy;
  
  // Path transformation
  function transformPath(path: PathProxy, m: number[]): void;
  
  // Path analysis
  function getPathBoundingRect(path: PathProxy): BoundingRect;
  function getPathLength(path: PathProxy): number;
  function getPointAtPath(path: PathProxy, percent: number): number[];
  
  // Path utilities
  function clone(path: PathProxy): PathProxy;
  function parseSVGPath(str: string): PathProxy;
  function normalizeArcPath(path: PathProxy): void;
}

interface PathProxy {
  data: number[];
  len(): number;
  setData(data: ArrayLike<number>): void;
  appendPath(path: PathProxy): void;
  addData(cmd: number, ...args: number[]): void;
  moveTo(x: number, y: number): void;
  lineTo(x: number, y: number): void;
  bezierCurveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): void;
  quadraticCurveTo(x1: number, y1: number, x: number, y: number): void;
  arc(cx: number, cy: number, r: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void;
  arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void;
  rect(x: number, y: number, w: number, h: number): void;
  closePath(): void;
}

Path Morphing (morph namespace)

Advanced path morphing and interpolation:

namespace morph {
  // Path morphing
  function morphPath(from: string, to: string, animationOpts?: any): string;
  function getPathKey(path: string): string;
  function morphingPathKey(path: string): string;
  
  // Combined morphing
  function combineMorphing(morphList: any[]): any;
  function isCombineMorphing(obj: any): boolean;
  
  // Morphing utilities
  function pathToAbsolute(path: string): string;
  function pathToBezier(path: string): number[][];
}

Platform Abstraction

Platform-specific API configuration:

function setPlatformAPI(platformAPI: PlatformAPI): void;

interface PlatformAPI {
  createCanvas?: () => HTMLCanvasElement;
  measureText?: (text: string, font: string) => { width: number };
  loadImage?: (src: string, onload: () => void, onerror: () => void) => HTMLImageElement;
  
  // Platform detection
  $override?: {
    createCanvas?: () => HTMLCanvasElement;
    measureText?: (text: string, font: string) => { width: number };
    loadImage?: (src: string, onload: () => void, onerror: () => void) => HTMLImageElement;
  };
}

Geometry Utilities

Additional geometric calculations and utilities:

// Point and rectangle utilities
interface Point {
  x: number;
  y: number;
}

interface PointLike {
  x: number;
  y: number;
}

interface RectLike {
  x: number;
  y: number;
  width: number;
  height: number;
}

class BoundingRect {
  x: number;
  y: number;
  width: number;
  height: number;
  
  constructor(x: number, y: number, width: number, height: number);
  
  // Geometric operations
  union(other: BoundingRect): void;
  intersect(other: BoundingRect): void;
  contain(x: number, y: number): boolean;
  clone(): BoundingRect;
  copy(other: BoundingRect): void;
  plain(): RectLike;
  
  // Static utilities
  static create(rect: RectLike): BoundingRect;
  static copy(target: BoundingRect, source: BoundingRect): void;
  static applyTransform(target: BoundingRect, source: BoundingRect, m: number[]): void;
}

class OrientedBoundingRect {
  cx: number;
  cy: number;
  width: number;
  height: number;
  rotation: number;
  
  constructor();
  
  // Geometric operations
  intersect(other: OrientedBoundingRect): boolean;
  contain(x: number, y: number): boolean;
  clone(): OrientedBoundingRect;
  
  // Static utilities
  static fromPoints(points: number[][]): OrientedBoundingRect;
}

Usage Examples

Utility Functions

import { util, matrix, vector, color } from "zrender";

// Object manipulation
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = util.merge({}, obj1, obj2); // { a: 1, b: 3, c: 4 }

// Array operations
const numbers = [1, 2, 3, 4, 5];
const doubled = util.map(numbers, x => x * 2); // [2, 4, 6, 8, 10]
const evens = util.filter(numbers, x => x % 2 === 0); // [2, 4]

// Type checking
if (util.isArray(someValue)) {
  console.log('It is an array');
}

// Unique IDs
const uniqueId = util.guid(); // Returns unique number

Matrix Operations

import { matrix } from "zrender";

// Create transformation matrix
const m = matrix.identity();

// Apply transformations
matrix.translate(m, m, [100, 50]);  // Translate by (100, 50)
matrix.rotate(m, m, Math.PI / 4);   // Rotate 45 degrees
matrix.scale(m, m, [1.5, 1.5]);    // Scale by 1.5x

// Transform a point
const point = [0, 0];
const transformedPoint = matrix.applyTransform([], point, m);
console.log('Transformed point:', transformedPoint);

// Matrix multiplication
const m1 = matrix.identity();
const m2 = matrix.identity();
matrix.scale(m1, m1, [2, 2]);
matrix.rotate(m2, m2, Math.PI / 2);

const combined = matrix.mul([], m1, m2);

Vector Mathematics

import { vector } from "zrender";

// Vector operations
const v1 = vector.create(3, 4);
const v2 = vector.create(1, 2);

const sum = vector.add([], v1, v2);        // [4, 6]
const length = vector.len(v1);             // 5
const normalized = vector.normalize([], v1); // [0.6, 0.8]
const distance = vector.distance(v1, v2);  // ~2.83

// Interpolation
const lerped = vector.lerp([], v1, v2, 0.5); // Midpoint between v1 and v2

// Dot product for angle calculations
const dotProduct = vector.dot(v1, v2); // 11
const angle = Math.acos(dotProduct / (vector.len(v1) * vector.len(v2)));

Color Manipulation

import { color } from "zrender";

// Color parsing and conversion
const rgbaArray = color.parse('#ff6b6b'); // [255, 107, 107, 1]
const hexColor = color.toHex('rgb(255, 107, 107)'); // '#ff6b6b'
const hslColor = color.toHSL('#ff6b6b'); // 'hsl(0, 100%, 71%)'

// Color interpolation
const startColor = '#ff0000';
const endColor = '#00ff00';
const midColor = color.lerp(0.5, startColor, endColor); // Blend colors

// Color modification
const brighterColor = color.modifyHSL('#3498db', 0, 0.2, 0.1); // Increase saturation and lightness
const transparentColor = color.modifyAlpha('#3498db', 0.5); // 50% opacity

// Color analysis
const luminance = color.lum('#3498db'); // Get relative luminance
const randomColor = color.random(); // Generate random color

// Palette generation
const palette = [];
for (let i = 0; i < 5; i++) {
  palette.push(color.lerp(i / 4, '#ff6b6b', '#4ecdc4'));
}

Path Processing

import { path, parseSVG } from "zrender";

// Create path from SVG string
const svgPath = "M 10 10 L 100 10 L 100 100 L 10 100 Z";
const pathProxy = path.createFromString(svgPath);

// Get path properties
const bounds = path.getPathBoundingRect(pathProxy);
const length = path.getPathLength(pathProxy);

// Get point at specific position along path
const midPoint = path.getPointAtPath(pathProxy, 0.5); // 50% along path

// Transform path
const transformMatrix = matrix.identity();
matrix.scale(transformMatrix, transformMatrix, [2, 2]);
path.transformPath(pathProxy, transformMatrix);

// Parse SVG content
const svgElement = document.querySelector('svg')!;
const elements = parseSVG(svgElement);
// Returns ZRender elements created from SVG

Custom Utilities Integration

import { util, BoundingRect } from "zrender";

// Custom utility function using ZRender utilities
function createBoundedElements(bounds: RectLike, count: number) {
  const elements = [];
  
  for (let i = 0; i < count; i++) {
    // Use util functions for safe operations
    const x = bounds.x + Math.random() * bounds.width;
    const y = bounds.y + Math.random() * bounds.height;
    const size = 10 + Math.random() * 20;
    
    const circle = new Circle({
      shape: { cx: x, cy: y, r: size },
      style: { 
        fill: color.random(),
        opacity: 0.7
      }
    });
    
    elements.push(circle);
  }
  
  return elements;
}

// Use the custom utility
const canvasBounds = new BoundingRect(0, 0, 800, 600);
const randomElements = createBoundedElements(canvasBounds.plain(), 50);

randomElements.forEach(el => zr.add(el));

Performance Optimized Operations

import { util } from "zrender";

// Efficient array operations
const largeArray = new Array(10000).fill(0).map((_, i) => i);

// Use ZRender's optimized utilities instead of native methods when possible
const processedData = util.map(largeArray, (value, index) => {
  return { id: index, value: value * 2, processed: true };
});

// Efficient object creation
const hashMap = util.createHashMap<number>();
for (let i = 0; i < 1000; i++) {
  hashMap.set(`key${i}`, i);
}

// Memory-efficient cloning
const originalData = { 
  positions: [[0, 0], [100, 100], [200, 200]],
  colors: ['#ff0000', '#00ff00', '#0000ff'],
  metadata: { created: Date.now() }
};

const clonedData = util.clone(originalData); // Deep clone

SVG Processing

SVG Parser

Parse SVG markup into ZRender elements for rendering and manipulation:

/**
 * Parse SVG markup into ZRender graphics elements
 * @param svg - SVG string, Document, or SVGElement to parse
 * @param options - Parsing configuration options
 * @returns Parsed SVG result with root group and metadata
 */
function parseSVG(svg: string | Document | SVGElement, options?: SVGParserOption): SVGParserResult;

interface SVGParserOption {
  width?: number;        // Default width if not specified in SVG
  height?: number;       // Default height if not specified in SVG  
  ignoreViewBox?: boolean; // Whether to ignore SVG viewBox
}

interface SVGParserResult {
  root: Group;           // Root group containing all parsed elements
  width: number;         // Computed viewport width
  height: number;        // Computed viewport height
  viewBoxRect: RectLike; // ViewBox rectangle if specified
  viewBoxTransform: {    // Transform from viewBox to viewport
    scale: number[];
    position: number[];
  };
}

Usage Examples:

import { parseSVG } from "zrender";

// Parse SVG string
const svgString = `
  <svg width="200" height="200">
    <circle cx="100" cy="100" r="50" fill="red"/>
    <rect x="50" y="50" width="100" height="100" fill="blue" opacity="0.5"/>
  </svg>
`;

const result = parseSVG(svgString, {
  width: 400,
  height: 400
});

// Add parsed elements to ZRender instance
zr.add(result.root);

// Access parsed elements
console.log(`SVG dimensions: ${result.width}x${result.height}`);
console.log(`Root contains ${result.root.children().length} elements`);

Debug Utilities

Debug Dirty Rectangle Visualization

Development utility for visualizing dirty rectangles in canvas rendering:

/**
 * Show debug visualization of dirty rectangles on canvas
 * @param zr - ZRender instance to debug
 * @param options - Debug visualization options
 */
function showDebugDirtyRect(zr: ZRender, options?: DebugDirtyRectOptions): void;

interface DebugDirtyRectOptions {
  style?: {
    backgroundColor?: string;  // Default: 'rgba(0, 0, 255, 0.2)'
    border?: string;          // Default: '1px solid #00f'
    [key: string]: any;       // Additional CSS properties
  };
  autoHideDelay?: number;     // Auto-hide delay in milliseconds
}

Usage Examples:

import { init, showDebugDirtyRect } from "zrender";

// Initialize ZRender with debug mode
const zr = init(document.getElementById('canvas'));

// Enable dirty rectangle visualization  
showDebugDirtyRect(zr, {
  style: {
    backgroundColor: 'rgba(255, 0, 0, 0.3)',
    border: '2px solid #f00'
  },
  autoHideDelay: 1000
});

// Now dirty rectangles will be highlighted when elements are updated
const circle = new Circle({
  shape: { cx: 100, cy: 100, r: 50 },
  style: { fill: 'blue' }
});

zr.add(circle);

// This update will show a debug rectangle
circle.attr('shape', { cx: 150, cy: 150 });

Install with Tessl CLI

npx tessl i tessl/npm-zrender

docs

animation.md

core-zrender.md

events.md

graphics-primitives.md

index.md

shapes.md

styling.md

text-images.md

utilities.md

tile.json