### Install Leafer-UI Source: https://deepwiki.com/leaferjs/leafer-ui/1-overview Install the core leafer-ui package using npm. This is the first step to getting started with the framework. ```bash npm install leafer-ui ``` -------------------------------- ### Install @leafer-ui/miniapp for Mini Programs Source: https://deepwiki.com/leaferjs/leafer-ui/7.2-platform-implementations Install the @leafer-ui/miniapp package for WeChat or Alipay mini programs. ```bash npm install @leafer-ui/miniapp ``` -------------------------------- ### Install Node.js Platform Source: https://deepwiki.com/leaferjs/leafer-ui/7.2-platform-implementations Install the Node.js platform package and a native canvas library for server-side rendering and headless exports. ```bash npm install @leafer-ui/node npm install canvas # or skia-canvas ``` -------------------------------- ### Install @leafer-ui/node for Node.js Source: https://deepwiki.com/leaferjs/leafer-ui/7.2-platform-implementations Install the @leafer-ui/node package for server-side rendering or headless exports. ```bash npm install @leafer-ui/node ``` -------------------------------- ### Install Full Leafer Ecosystem Package Source: https://deepwiki.com/leaferjs/leafer-ui/9.1-getting-started Install the full package if you need the complete ecosystem, including official plugins like Animation and State. This includes Leafer-UI and all @leafer-in/* packages. ```bash npm install leafer ``` -------------------------------- ### Install @leafer-ui/worker for Web Workers Source: https://deepwiki.com/leaferjs/leafer-ui/7.2-platform-implementations Install the @leafer-ui/worker package for use in Web Worker contexts with OffscreenCanvas. ```bash npm install @leafer-ui/worker ``` -------------------------------- ### Image Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Shows the Image component for loading and displaying bitmap images. It extends Rect and can be configured with image sources. ```javascript const image = new Image({ url: 'path/to/your/image.png', width: 100, height: 100 }); ``` -------------------------------- ### Rect Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Shows the Rect component for creating rectangles. It accepts properties like 'width', 'height', and 'fill'. ```javascript const rect = new Rect({ width: 100, height: 100, fill: '#37cd74' }); ``` -------------------------------- ### Pen Component Drawing Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Demonstrates the Pen component, which provides a canvas-like drawing API. It uses methods like 'moveTo' and 'lineTo' to define paths. ```javascript const pen = new Pen(); pen.moveTo(10, 10); pen.lineTo(50, 50); pen.stroke('red'); ``` -------------------------------- ### Text Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Illustrates the Text component for rendering styled text. It supports properties for text content, font styles, and layout. ```javascript const text = new Text({ text: 'Hello Leafer!', fill: 'black', fontSize: 24 }); ``` -------------------------------- ### Pointer Event Flow Example Source: https://deepwiki.com/leaferjs/leafer-ui/5.1-interaction-architecture The InteractionBase processes pointer events through three primary entry points: pointerDown, pointerMove, and pointerUp. ```typescript interaction.pointerDown(event) interaction.pointerMove(event) interaction.pointerUp(event) ``` -------------------------------- ### Ellipse Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Demonstrates the Ellipse component for creating circles or arc segments. Properties include 'startAngle' and 'endAngle' for arc creation. ```javascript const ellipse = new Ellipse({ width: 100, height: 100, startAngle: 0, endAngle: 180, fill: 'blue' }); ``` -------------------------------- ### Group Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Demonstrates the basic Group component, a standard container for managing child elements. It includes properties like 'children' and methods for adding and removing children. ```javascript const group = new Group(); group.add(new Rect({ fill: 'red' })); group.add(new Circle({ fill: 'blue' })); ``` -------------------------------- ### Box Component Example Source: https://deepwiki.com/leaferjs/leafer-ui/2-core-components Illustrates the Box component, a sized container that extends Group with overflow control. It features properties like 'width', 'height', and 'overflow'. ```javascript const box = new Box({ width: 100, height: 100, overflow: 'visible', children: [new Rect({ fill: 'green' })] }); ``` -------------------------------- ### Interaction Mode Flags Example Source: https://deepwiki.com/leaferjs/leafer-ui/5.1-interaction-architecture These computed properties determine the current interaction mode based on various conditions. ```typescript if (interactionMode === InteractionMode.drag) { // Handle drag mode } if (interactionMode === InteractionMode.move) { // Handle move mode } if (interactionMode === InteractionMode.scale) { // Handle scale mode } if (interactionMode === InteractionMode.rotate) { // Handle rotate mode } ``` -------------------------------- ### Paint Computation Flow Example Source: https://deepwiki.com/leaferjs/leafer-ui/4-rendering-system Illustrates the lazy computation of paint data when the '__needComputePaint' flag is set. This ensures that paint properties are only processed when necessary, optimizing performance. ```typescript async __updatePaint(): Promise { if (!this.__needComputePaint) return; const { __leaf, __paint } = this; const leafPaint = await this.getLeafPaint(); if (leafPaint) { if (__paint) { __paint.delete(); } this.__paint = leafPaint; __leaf.add(leafPaint); } this.__needComputePaint = false; } ``` -------------------------------- ### Move and Drag Logic Example Source: https://deepwiki.com/leaferjs/leafer-ui/5.1-interaction-architecture When the pointer moves, the system distinguishes between standard hover/move and dragging/panning based on distance and configuration. Dragging is initiated only after moving beyond config.pointer.dragDistance. If moveMode is active (e.g., holding Space), the system triggers MoveEvent instead of DragEvent. Real-time dragging of elements is handled by the Dragger class. ```typescript if (moveMode === MoveMode.space) { // Handle space key drag } else if (distance > config.pointer.dragDistance) { // Handle normal drag } else { // Handle hover or move } ``` -------------------------------- ### Complex Rendering Path Example Source: https://deepwiki.com/leaferjs/leafer-ui/4-rendering-system Handles advanced rendering features including multiple paints, effects, and special compositing. This path is used when the element has rounded corners, multiple fills/strokes, or uses effects like shadows or filters. ```typescript async __draw(): Promise { const { __leaf, __transform, __opacity, __blendMode, __effects, __clip, __transform3d, __visible, __isWorld } = this; if (!__visible) return; const { __transformChanged, __opacityChanged, __blendModeChanged, __effectsChanged, __clipChanged, __transform3dChanged, __isWorldChanged } = __updateChange(); const { __renderTransform, __renderOpacity, __renderBlendMode, __renderEffects, __renderClip, __renderTransform3d, __renderIsWorld } = __updateRenderState(); if (__transformChanged || __opacityChanged || __blendModeChanged || __effectsChanged || __clipChanged || __transform3dChanged || __isWorldChanged) { __leaf.save(); if (__renderClip) __leaf.clip(__renderClip); if (__renderTransform3d) __leaf.transform3d(__renderTransform3d); if (__renderTransform) __leaf.transform(__renderTransform); if (__renderOpacity !== undefined && __renderOpacity !== 1) __leaf.opacity(__renderOpacity); if (__renderBlendMode) __leaf.blendMode(__renderBlendMode); if (__renderEffects && __renderEffects.length > 0) { for (const effect of __renderEffects) { await effect.render(__leaf); } } if (__isWorld) __leaf.worldTransform(); } await this.__drawRenderPath(); await this.__drawAfterFill(); if (__transformChanged || __opacityChanged || __blendModeChanged || __effectsChanged || __clipChanged || __transform3dChanged || __isWorldChanged) { __leaf.restore(); } } ``` -------------------------------- ### UIData Paint Computation Trigger Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline This method is called at the start of the complex rendering path if the `__needComputePaint` flag is set. It checks for fill and stroke properties and delegates computation to the external `Paint.compute` function. ```typescript public __computePaint(): void { const { fill, stroke } = this.__input if (fill) Paint.compute('fill', this.__leaf) if (stroke) Paint.compute('stroke', this.__leaf) this.__needComputePaint = undefined } ``` -------------------------------- ### MiniApp Platform Canvas Initialization Source: https://deepwiki.com/leaferjs/leafer-ui/7-platform-support Shows the MiniApp platform checking for the `wx` global before initializing canvas. This highlights platform-specific conditional logic. ```javascript useCanvas('miniapp', wx) ``` -------------------------------- ### Web Platform Canvas Initialization Source: https://deepwiki.com/leaferjs/leafer-ui/7-platform-support Demonstrates how the Web platform initializes canvas using `useCanvas`. This is part of the platform-specific adapter system. ```javascript useCanvas('canvas') ``` -------------------------------- ### Basic Initialization Flow Source: https://deepwiki.com/leaferjs/leafer-ui/9.1-getting-started Demonstrates the typical flow for initializing Leafer-UI: creating a view container, initializing the engine, and adding elements to the scene graph. Use App for complex scenarios and Leafer for simpler drawings. ```javascript // Example of initialization flow (conceptual) // const app = new App({ view: '#my-canvas' }) // const leafer = new Leafer({ view: '#my-canvas' }) // const rect = new Rect(50, 50, { fill: 'blue' }) // leafer.add(rect) ``` -------------------------------- ### InteractionBase Lifecycle Methods Source: https://deepwiki.com/leaferjs/leafer-ui/5-interaction-system Key methods for managing the interaction lifecycle, including initialization, starting/stopping, input entry points, path resolution, and event dispatch. ```typescript constructor() start() stop() pointerDown() pointerMove() pointerUp() findPath() checkPath() emit() ``` -------------------------------- ### Interaction Configuration Properties Source: https://deepwiki.com/leaferjs/leafer-ui/5-interaction-system Configurable properties for pointer sensitivity, timing, and move mode behavior. Adjust these to fine-tune interaction responsiveness. ```typescript pointer: { hitRadius, tapTime, longPressTime, dragDistance } move: { drag, dragEmpty, holdSpaceKey, holdMiddleKey } wheel: { zoomSpeed, moveSpeed, rotateSpeed } ``` -------------------------------- ### Pointer Interaction State Machine Source: https://deepwiki.com/leaferjs/leafer-ui/5-interaction-system Illustrates the state transitions for pointer interactions, crucial for understanding gesture detection and event flow. ```typescript // State machine logic for pointer interaction // ... (details omitted for brevity) ``` -------------------------------- ### Plugin Rewriting Mechanism Source: https://deepwiki.com/leaferjs/leafer-ui/8-extension-systems Demonstrates how external plugins can hook into the core UI class using a 'rewrite' pattern, enabling features like animation and state management. ```typescript The UI system is designed to be extended by external plugins such as: * Animation : animate() and transition methods. * State : hoverStyle, pressStyle, and states. * Editor : Visual editing tools and configurations. The emit system in @leafer-ui/interaction also demonstrates extensibility by checking for State.updateEventStyle to apply hoverStyle or pressStyle during event propagation ``` -------------------------------- ### Decorator Behaviors for Property Changes Source: https://deepwiki.com/leaferjs/leafer-ui/8-extension-systems Illustrates how different decorators trigger specific framework behaviors like rendering updates or layout changes in response to property modifications. ```typescript effectType: triggers renderChange() and surfaceChange() resizeType: triggers boxChange() and calls __updateSize() on the canvas zoomLayerType: dynamically resolves the zoomLayer property based on whether the instance is an App, Leafer, or a standard UI element ``` -------------------------------- ### UIRender Module Core Methods Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline Core rendering methods in the UIRender module. These are mixed into the UI class prototype and called during different stages of the rendering process. ```javascript function __updateChange() { // Analyzes element properties to determine rendering complexity and set optimization flags } function __drawFast() { // Performs optimized rendering for simple solid fills/strokes without effects } function __draw() { // Main rendering method that routes to appropriate rendering path based on complexity } function __drawShape() { // Renders element shape for effect processing (ignores actual paint colors) } function __drawAfterFill() { // Handles content rendering after fill (e.g., clipping for Box components) } function __drawRenderPath() { // Generates the path geometry on the canvas (implemented by subclasses) } ``` -------------------------------- ### Rendering Path Decision Logic Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline The logic for selecting one of three rendering paths based on element complexity. This optimizes for common cases while supporting advanced effects. ```javascript if (__complex) { if (__isFastShadow) { __drawShadow(); } else { __draw(); } } else { __drawFast(); } ``` -------------------------------- ### Fast Path Implementation Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline The `drawFast()` helper function for the fast rendering path. It performs direct fill and stroke operations without intermediate canvases or effect processing. ```javascript function drawFast() { // Direct fill and stroke operations } ``` -------------------------------- ### Paint Type Transformation Source: https://deepwiki.com/leaferjs/leafer-ui/3-data-and-type-system Illustrates the transformation of input paint types (IPaint) to computed types (ILeafPaint) used by the rendering engine. This process ensures type safety and prepares data for the Canvas API. ```typescript /** * Input stage: defines what the user provides. * Example: Solid color, gradient, or image. */ interface IPaint { // ... properties for solid, gradient, image } /** * Data stage: stores properties and intermediate flags. * Managed by UIData. */ interface IUIData { // ... properties and flags } /** * Computed stage: final renderable data for Canvas API. * Example: CanvasPattern or CanvasGradient. */ interface ILeafPaint { // ... computed properties for Canvas API } // Transformation logic (simplified example): function transformPaint(input: IPaint): ILeafPaint { // ... logic to convert IPaint to ILeafPaint // This involves computation based on input data and internal state. return computedPaint; } ``` -------------------------------- ### External Module Architecture in Leafer UI Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline This diagram illustrates how Leafer UI integrates with external modules for specialized rendering operations. These modules are implemented by partner packages at runtime, providing a flexible architecture. ```typescript export interface IExternal { Paint: IPaint PaintImage: IPaintImage Effect: IEffect Filter: IFilter ColorConvert: IColorConvert } export const external: IExternal = {} as IExternal export function use(obj: IExternal) { Object.assign(external, obj) } ``` -------------------------------- ### Paint.compute() Process - Recycling Images Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Before processing paints, existing images are recycled using PaintImage.recycleImage() to manage resource lifecycles. ```typescript PaintImage.recycleImage(this._fill as ILeafPaint[]); PaintImage.recycleImage(this._stroke as ILeafPaint[]); ``` -------------------------------- ### Paint Setter Logic for Simple Colors Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Handles string or null/undefined inputs for fill and stroke properties. It stores the value directly, checks for transparency, and removes complex paints if present. ```typescript if (typeof value === 'string' || value == null) { this._fill = value; ColorConvert.hasTransparent(value) && (this.__isTransparentFill = true); this.__removePaint(); } ``` -------------------------------- ### Paint Type Handlers - Solid Color Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Solid color paints are processed using ColorConvert.string() to convert them into the required format. ```typescript case 'solid': return ColorConvert.string(paint); ``` -------------------------------- ### External Module Integration Source: https://deepwiki.com/leaferjs/leafer-ui/8-extension-systems Shows how external modules are aggregated via the @leafer-ui/external package to provide specialized processing for features like export, paint, and path arrows. ```typescript The @leafer-ui/external package serves as the bridge for: * Export : Image and file generation. * Paint : Complex fill and stroke processing. * PathArrow : Path-based arrow decorations. ``` -------------------------------- ### Transform Tool Interaction Handlers Source: https://deepwiki.com/leaferjs/leafer-ui/6.2-editbox-and-transform-tools Methods within ITransformTool that process user input events like drag, zoom, or rotate to calculate transformation deltas. These handlers determine how user interactions translate into geometric changes. ```typescript interface ITransformTool { onMove(e: IDragEvent): void onScale(e: IDragEvent): void onRotate(e: IDragEvent): void onSkew(e: IDragEvent): void // ... other methods } ``` -------------------------------- ### Paint Setter Logic for Complex Paints Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Handles object or array inputs for fill and stroke properties by storing them in '__input' and setting internal flags. A placeholder is used for '_fill'/'_stroke' until computation. ```typescript if (typeof value === 'object' && value !== null) { this.__setPaint(value); this.__isFills = true; this._fill = emptyPaint; } ``` -------------------------------- ### UIData Class Overview Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management The UIData class extends LeafData and implements IUIData, serving as the data storage layer for UI elements. It sits between user-facing APIs and the internal rendering system. ```typescript class UIData extends LeafData implements IUIData { // ... } ``` -------------------------------- ### Path Setter Logic for Multiple Input Formats Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management The setPath() method processes SVG path strings, object arrays, or existing canvas data to normalize path input. ```typescript if (typeof value === 'string') { this.__pathInputed = PathConvert.parse(value); } else if (Array.isArray(value)) { this.__pathInputed = PathConvert.objectToCanvasData(value); } else { this.__pathInputed = value; } ``` -------------------------------- ### ImageData Class - Automatic Fill Setting Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management The ImageData class automatically sets the 'fill' property based on the 'url' property, simplifying image handling. ```typescript if (this.url) { this.fill = this.url; } ``` -------------------------------- ### LineData Class - Path Box Determination Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management The LineData class determines '__usePathBox' based on whether points or an input path are provided, optimizing path rendering. ```typescript this.__usePathBox = !!(options.points || options.path); ``` -------------------------------- ### Paint.compute() Process - Storing Computed Paints Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management After computation, the transformed paint objects are stored in the '_fill' or '_stroke' arrays. ```typescript this._fill = computedFills; this._stroke = computedStrokes; ``` -------------------------------- ### BoxData Class - Overflow and Clip Logic Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management The BoxData class manages 'overflow' and '__clipAfterFill' logic, essential for controlling content display within containers. ```typescript this.overflow = options.overflow; this.__clipAfterFill = options.__clipAfterFill; ``` -------------------------------- ### UIData Property Storage Pattern Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management UIData uses a protected field pattern for property storage, with private fields like `_fill` and public setter methods like `setFill` that include validation logic. ```typescript protected _fill?: IValue protected setFill(value: IValue) { // ... validation logic } ``` -------------------------------- ### Dimensional Property Setter for Negative Values Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Width and height setters convert negative values into negative scale factors to maintain correct rendering. ```typescript if (value < 0) { this.scaleX = -1; value = -value; } this._width = value; ``` -------------------------------- ### EditPoint Types Source: https://deepwiki.com/leaferjs/leafer-ui/6.2-editbox-and-transform-tools Defines the different types of control points (handles) available on an EditBox. Each type corresponds to a specific transformation behavior like moving, resizing, rotating, or skewing. ```typescript enum EditPointType { move = 'move', resize = 'resize', rotate = 'rotate', skew = 'skew', 'resize-rotate' = 'resize-rotate' } ``` -------------------------------- ### UIData Critical Optimization Flags Source: https://deepwiki.com/leaferjs/leafer-ui/3.1-uidata-and-property-management Internal flags like `__complex`, `__isFastShadow`, `__hasMultiPaint`, and `__fillAfterStroke` are used by the rendering system to optimize rendering paths and decisions. ```typescript // Controls branching in UIRender.__draw() __complex: boolean // Shadow rendering optimization __isFastShadow: boolean // Indicates layered rendering is needed __hasMultiPaint: boolean // Changes rendering order for specific stroke/fill combinations __fillAfterStroke: boolean ``` -------------------------------- ### EditBox Interface Properties Source: https://deepwiki.com/leaferjs/leafer-ui/6.2-editbox-and-transform-tools Key properties of the IEditBoxBase interface, which defines the interactive controls around a selected UI element. These properties manage the target element, drag state, and transformation logic. ```typescript interface IEditBoxBase extends IGroup { target: IUI dragPoint: IEditPoint dragStartData: IEditorDragStartData transformTool: ITransformTool } ``` -------------------------------- ### Define Export Plugin Interface Source: https://deepwiki.com/leaferjs/leafer-ui/8.2-plugin-and-module-system Defines the contract for the lazy-loaded export plugin, specifying methods for exporting leaf elements. ```typescript export interface IExportModule { running?: boolean export(leaf: ILeaf, filename: string, options?: IExportOptions): Promise syncExport(leaf: ILeaf, filename: string, options?: IExportOptions): IExportResult } ``` -------------------------------- ### Transform Tool Geometric Execution Source: https://deepwiki.com/leaferjs/leafer-ui/6.2-editbox-and-transform-tools Methods within ITransformTool that apply geometric transformations to an element. These methods take origin and transformation values (e.g., translation, scale, rotation) to modify the element's geometry. ```typescript interface ITransformTool { // ... interaction handlers move(x: number, y: number): void scaleOf(origin: IAlign | IPointData, scaleX: number, scaleY: number): void rotateOf(origin: IAlign | IPointData, rotation: number): void skewOf(origin: IAlign | IPointData, skewX: number, skewY: number): void } ``` -------------------------------- ### Fill Property Setter in UIData Source: https://deepwiki.com/leaferjs/leafer-ui/4.1-rendering-pipeline When a fill property is set to an object or array, this method stores the input value and sets flags that will trigger paint computation. It ensures that paint properties are processed before rendering. ```typescript __setPaint(value: any): void { this.__input.fill = value this.__needComputePaint = true this.__leaf.set('fill', value) } ```