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

styling.mddocs/

Styling and Gradients

ZRender provides a comprehensive styling system for controlling the visual appearance of graphics elements. This includes solid colors, gradients, patterns, shadows, and advanced rendering effects.

Basic Styling Properties

All visual elements support these fundamental styling properties:

interface PathStyleProps {
  // Fill properties
  fill?: string | LinearGradient | RadialGradient | Pattern;
  fillOpacity?: number;
  
  // Stroke properties
  stroke?: string;
  strokeOpacity?: number;
  lineWidth?: number;
  lineDash?: number[];
  lineDashOffset?: number;
  lineCap?: 'butt' | 'round' | 'square';
  lineJoin?: 'bevel' | 'round' | 'miter';
  miterLimit?: number;
  
  // Overall opacity
  opacity?: number;
  
  // Shadow effects
  shadowBlur?: number;
  shadowColor?: string;
  shadowOffsetX?: number;
  shadowOffsetY?: number;
  
  // Advanced rendering
  blend?: string;
  globalCompositeOperation?: string;
}

Gradient Classes

LinearGradient

Creates linear gradients with customizable direction and color stops:

class LinearGradient {
  constructor(x1: number, y1: number, x2: number, y2: number, colorStops: ColorStop[], globalCoord?: boolean);
  
  x1: number;    // Start point X (0-1 in local coordinates)
  y1: number;    // Start point Y (0-1 in local coordinates)  
  x2: number;    // End point X (0-1 in local coordinates)
  y2: number;    // End point Y (0-1 in local coordinates)
  colorStops: ColorStop[];
  global: boolean; // Use global coordinates instead of local
}

interface LinearGradientObject {
  type: 'linear';
  x1: number;
  y1: number;
  x2: number;
  y2: number;
  colorStops: ColorStop[];
  global?: boolean;
}

interface ColorStop {
  offset: number;    // Position along gradient (0-1)
  color: string;     // Color at this stop
}

RadialGradient

Creates radial gradients emanating from a center point:

class RadialGradient {
  constructor(x: number, y: number, r: number, colorStops: ColorStop[], globalCoord?: boolean);
  
  x: number;     // Center X (0-1 in local coordinates)
  y: number;     // Center Y (0-1 in local coordinates)
  r: number;     // Radius (0-1 in local coordinates)
  colorStops: ColorStop[];
  global: boolean; // Use global coordinates instead of local
}

interface RadialGradientObject {
  type: 'radial';
  x: number;
  y: number;
  r: number;
  colorStops: ColorStop[];
  global?: boolean;
}

Pattern Class

Creates pattern fills using images or other elements:

class Pattern {
  constructor(image: PatternImageSource, repeat: PatternRepeat);
  
  image: PatternImageSource;
  repeat: PatternRepeat;
}

type PatternImageSource = 
  | HTMLImageElement 
  | HTMLCanvasElement 
  | HTMLVideoElement
  | string; // URL or data URI

type PatternRepeat = 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat';

interface PatternObjectBase {
  type: 'pattern';
  repeat: PatternRepeat;
}

interface ImagePatternObject extends PatternObjectBase {
  image: HTMLImageElement | HTMLCanvasElement | string;
  x?: number;
  y?: number;
  rotation?: number;
  scaleX?: number;
  scaleY?: number;
}

interface SVGPatternObject extends PatternObjectBase {
  svgElement: SVGElement;
  svgWidth: number;
  svgHeight: number;
  x?: number;
  y?: number;
  rotation?: number;
  scaleX?: number;
  scaleY?: number;
}

type PatternObject = ImagePatternObject | SVGPatternObject;

Text Styling

Text elements have additional styling properties:

interface TextStyleProps {
  // Text content and basic properties
  text?: string;
  fontSize?: number;
  fontFamily?: string;
  fontStyle?: 'normal' | 'italic' | 'oblique';
  fontWeight?: string | number;
  
  // Text positioning and alignment
  textAlign?: 'left' | 'center' | 'right';
  textVerticalAlign?: 'top' | 'middle' | 'bottom';
  textBaseline?: 'top' | 'middle' | 'bottom' | 'alphabetic' | 'ideographic' | 'hanging';
  
  // Text appearance
  fill?: string | LinearGradient | RadialGradient | Pattern;
  stroke?: string;
  lineWidth?: number;
  opacity?: number;
  
  // Text shadows
  textShadowBlur?: number;
  textShadowColor?: string;
  textShadowOffsetX?: number;
  textShadowOffsetY?: number;
  
  // Text layout
  width?: number;
  height?: number;
  textPadding?: number | number[];
  textLineHeight?: number;
  
  // Rich text formatting
  rich?: Record<string, TextStyleProps>;
  
  // Text truncation
  truncate?: {
    outerWidth?: number;
    outerHeight?: number;
    ellipsis?: string;
    placeholder?: string;
  };
  
  // Rendering effects
  blend?: string;
}

Usage Examples

Solid Colors and Basic Styling

import { Circle, Rect } from "zrender";

// Simple solid color fill
const circle = new Circle({
  shape: { cx: 100, cy: 100, r: 50 },
  style: {
    fill: '#ff6b6b',      // Solid red fill
    stroke: '#d63031',     // Dark red border
    lineWidth: 3,
    opacity: 0.8
  }
});

// Advanced stroke styling
const rect = new Rect({
  shape: { x: 200, y: 50, width: 120, height: 80 },
  style: {
    fill: 'none',
    stroke: '#74b9ff',
    lineWidth: 4,
    lineDash: [10, 5],     // Dashed line
    lineCap: 'round',      // Rounded line ends
    lineJoin: 'round'      // Rounded corners
  }
});

zr.add(circle);
zr.add(rect);

Linear Gradients

import { Rect, LinearGradient } from "zrender";

// Horizontal gradient
const horizontalGradient = new LinearGradient(0, 0, 1, 0, [
  { offset: 0, color: '#ff7675' },
  { offset: 0.5, color: '#fd79a8' },
  { offset: 1, color: '#fdcb6e' }
]);

// Vertical gradient
const verticalGradient = new LinearGradient(0, 0, 0, 1, [
  { offset: 0, color: '#74b9ff' },
  { offset: 1, color: '#0984e3' }
]);

// Diagonal gradient
const diagonalGradient = new LinearGradient(0, 0, 1, 1, [
  { offset: 0, color: '#00b894' },
  { offset: 1, color: '#00cec9' }
]);

const rect1 = new Rect({
  shape: { x: 50, y: 50, width: 150, height: 80 },
  style: { fill: horizontalGradient }
});

const rect2 = new Rect({
  shape: { x: 250, y: 50, width: 80, height: 150 },
  style: { fill: verticalGradient }
});

const rect3 = new Rect({
  shape: { x: 50, y: 180, width: 120, height: 120 },
  style: { fill: diagonalGradient }
});

zr.add(rect1);
zr.add(rect2);
zr.add(rect3);

Radial Gradients

import { Circle, RadialGradient } from "zrender";

// Center-focused radial gradient
const radialGradient = new RadialGradient(0.5, 0.5, 0.5, [
  { offset: 0, color: '#ffffff' },
  { offset: 0.7, color: '#74b9ff' },
  { offset: 1, color: '#0984e3' }
]);

// Off-center radial gradient for lighting effect
const lightingGradient = new RadialGradient(0.3, 0.3, 0.8, [
  { offset: 0, color: '#fff5b4' },
  { offset: 0.4, color: '#ffda79' },
  { offset: 1, color: '#e17055' }
]);

const circle1 = new Circle({
  shape: { cx: 150, cy: 150, r: 80 },
  style: { fill: radialGradient }
});

const circle2 = new Circle({
  shape: { cx: 350, cy: 150, r: 80 },
  style: { 
    fill: lightingGradient,
    stroke: '#d63031',
    lineWidth: 2
  }
});

zr.add(circle1);
zr.add(circle2);

Pattern Fills

import { Rect, Pattern } from "zrender";

// Create pattern from image
const createImagePattern = (imageUrl: string) => {
  const img = new Image();
  img.src = imageUrl;
  return new Pattern(img, 'repeat');
};

// Create pattern from canvas
const createCanvasPattern = () => {
  const canvas = document.createElement('canvas');
  canvas.width = 20;
  canvas.height = 20;
  const ctx = canvas.getContext('2d')!;
  
  // Draw a simple pattern
  ctx.fillStyle = '#e17055';
  ctx.fillRect(0, 0, 10, 10);
  ctx.fillStyle = '#fdcb6e';
  ctx.fillRect(10, 10, 10, 10);
  
  return new Pattern(canvas, 'repeat');
};

const patternRect = new Rect({
  shape: { x: 100, y: 100, width: 200, height: 150 },
  style: {
    fill: createCanvasPattern(),
    stroke: '#2d3436',
    lineWidth: 2
  }
});

zr.add(patternRect);

Shadow Effects

import { Circle, Text } from "zrender";

// Drop shadow effect
const shadowCircle = new Circle({
  shape: { cx: 150, cy: 150, r: 60 },
  style: {
    fill: '#74b9ff',
    shadowBlur: 20,
    shadowColor: 'rgba(116, 185, 255, 0.6)',
    shadowOffsetX: 10,
    shadowOffsetY: 10
  }
});

// Glow effect
const glowCircle = new Circle({
  shape: { cx: 350, cy: 150, r: 50 },
  style: {
    fill: '#00b894',
    shadowBlur: 30,
    shadowColor: '#00b894'
    // No offset for glow effect
  }
});

// Text with shadow
const shadowText = new Text({
  style: {
    text: 'Shadow Text',
    fontSize: 24,
    fill: '#2d3436',
    textShadowBlur: 5,
    textShadowColor: 'rgba(0, 0, 0, 0.5)',
    textShadowOffsetX: 2,
    textShadowOffsetY: 2
  },
  position: [200, 300]
});

zr.add(shadowCircle);
zr.add(glowCircle);
zr.add(shadowText);

Advanced Text Styling

import { Text } from "zrender";

// Rich text with multiple styles
const richText = new Text({
  style: {
    text: '{title|ZRender} {subtitle|Graphics Library}\n{body|Create beautiful 2D graphics}',
    rich: {
      title: {
        fontSize: 28,
        fontWeight: 'bold',
        fill: '#2d3436'
      },
      subtitle: {
        fontSize: 16,
        fill: '#636e72',
        fontStyle: 'italic'
      },
      body: {
        fontSize: 14,
        fill: '#74b9ff',
        textPadding: [10, 0, 0, 0]
      }
    },
    width: 300,
    textAlign: 'center'
  },
  position: [150, 100]
});

// Gradient text fill
const gradientText = new Text({
  style: {
    text: 'Gradient Text',
    fontSize: 32,
    fontWeight: 'bold',
    fill: new LinearGradient(0, 0, 1, 0, [
      { offset: 0, color: '#ff7675' },
      { offset: 0.5, color: '#fd79a8' },
      { offset: 1, color: '#e84393' }
    ]),
    stroke: '#2d3436',
    lineWidth: 1
  },
  position: [150, 250]
});

zr.add(richText);
zr.add(gradientText);

Animated Styling

import { Circle, LinearGradient } from "zrender";

// Create animated gradient
const animatedCircle = new Circle({
  shape: { cx: 200, cy: 200, r: 60 },
  style: {
    fill: new LinearGradient(0, 0, 1, 0, [
      { offset: 0, color: '#74b9ff' },
      { offset: 1, color: '#0984e3' }
    ]),
    shadowBlur: 0
  }
});

// Animate color transitions
animatedCircle.animate('style')
  .when(1000, {
    shadowBlur: 20,
    shadowColor: '#74b9ff'
  })
  .when(2000, {
    shadowBlur: 0
  })
  .start('easeInOut');

// Animate gradient color stops
const animateGradient = () => {
  const newGradient = new LinearGradient(0, 0, 1, 0, [
    { offset: 0, color: '#e17055' },
    { offset: 1, color: '#fdcb6e' }
  ]);
  
  animatedCircle.animate('style')
    .when(1500, { fill: newGradient })
    .start();
};

// Trigger gradient animation on click
animatedCircle.on('click', animateGradient);

zr.add(animatedCircle);

Style State Management

import { Rect } from "zrender";

// Interactive styling with state management
const interactiveRect = new Rect({
  shape: { x: 100, y: 100, width: 120, height: 80, r: 8 },
  style: {
    fill: '#74b9ff',
    stroke: '#0984e3',
    lineWidth: 2,
    opacity: 1
  }
});

// Store original style
const originalStyle = { ...interactiveRect.style };

// Hover states
interactiveRect.on('mouseover', () => {
  interactiveRect.animate('style')
    .when(200, {
      fill: '#a29bfe',
      shadowBlur: 10,
      shadowColor: '#74b9ff',
      opacity: 0.9
    })
    .start('easeOut');
});

interactiveRect.on('mouseout', () => {
  interactiveRect.animate('style')
    .when(200, originalStyle)
    .start('easeOut');
});

// Active/pressed state
interactiveRect.on('mousedown', () => {
  interactiveRect.animate('style')
    .when(100, {
      fill: '#6c5ce7',
      shadowBlur: 5
    })
    .start();
});

interactiveRect.on('mouseup', () => {
  interactiveRect.animate('style')
    .when(100, {
      fill: '#a29bfe',
      shadowBlur: 10
    })
    .start();
});

zr.add(interactiveRect);

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