Konva Designer Sample

repository·master·Indexed 41 days ago

https://github.com/xachary/konva-designer-sample

A sample implementation of a professional designer interface using the Konva canvas library. It demonstrates complex canvas interactions including an infinite canvas, grid snapping, node connectivity with A* pathfinding, and advanced object manipulation for shapes like Bezier curves, circles, and rectangles.

Tokens
10.3K
Snippets
35
Records
48
Agent score
52%

What's inside Konva Designer Sample

  1. How the Render class manages layers

    master

    The Render class organizes the canvas into three primary layers to manage drawing priority and interaction:

    1. layer (Main Layer): Contains the actual design assets (shapes, text, groups).
    2. layerFloor (Background Layer): Used for background elements like grid patterns or background colors.
    3. layerCover (Overlay Layer): Contains transient UI elements that should always appear on top, such as connection lines, alignment guides, rulers, context menus, and the selection transformer/rect.
  2. Understand Link Drawing Modes

    master

    The LinkDraw logic supports three distinct modes for connecting elements in the designer, determined by the linkType property of a pair:

    1. Manual (Bezier/Curved): Uses manualPointsMap to store custom inflection points (拐点). Users can drag these points to shape the connection. The line is rendered using BezierSceneFunc.
    2. Straight: Connects two anchor points directly with a straight line using Konva.Arrow.
    3. Automatic (A Pathfinding)**: Calculates an optimal path between two groups using an A algorithm. It treats group boundaries as forbidden areas and finds a path through an available "access area" (通过区域) using a grid-based matrix.

    When drawing, the system uses Konva.Arrow for the visible line and Konva.Circle for interactive elements like connection points and manual inflection points.

  3. Define link connections with LinkDrawPair and LinkDrawPoint

    master

    The designer uses LinkDrawPoint to represent connection points on an asset and LinkDrawPair to represent the connection between two points. This system supports various line types like straight, manual (polyline), curve, and bezier.

    export enum LinkType {
      'auto' = 'auto',
      'straight' = 'straight',
      'manual' = 'manual',
      'curve' = 'curve',
      'bezier' = 'bezier'
    }
    
    export interface LinkDrawPair {
      id: string
      from: { groupId: string; pointId: string; rawGroupId?: string }
      to: { groupId: string; pointId: string; rawGroupId?: string }
      disabled?: boolean
      linkType?: LinkType
      style?: Konva.LineConfig & LinkSettings
    }
    
    export interface LinkDrawPoint {
      id: string
      groupId: string
      rawGroupId?: string
      visible: boolean
      pairs: LinkDrawPair[]
      x: number
      y: number
      direction?: 'top' | 'bottom' | 'left' | 'right'
      alias?: string
    }
  4. Manage Manual Link Inflection Points

    master

    For links with a manual type, inflection points are stored in a manualPointsMap attribute on the group.

    • Adding/Moving Points: When a user drags a link-manual-point (a Konva.Circle), the system updates the manualPoints array. If the movement exceeds a specific threshold (this.option.size), the new coordinates are saved back to the group's manualPointsMap attribute.
    • Visual Feedback: While dragging, a manualing-line (a dashed Konva.Arrow) is rendered to show the projected path of the link.
  5. How LinkDraw manages waypoints (manual points)

    master

    When using Types.LinkType.manual, LinkDraw allows users to add and move waypoints along a connection line.

    1. Insertion: Dragging a new point between two existing points (or an anchor and a point) beyond the option.size threshold inserts a new waypoint into the manualPointsMap of the source group.
    2. Modification: Dragging an existing waypoint updates its coordinates in the manualPointsMap.
    3. Storage: Waypoints are stored as an array of { x, y } objects within the manualPointsMap attribute of the group they belong to, keyed by the pair.id.

    This mechanism ensures that connection shapes are persistent and can be re-rendered correctly.

  6. Understand Circle anchor and link anchor configurations

    master

    The Circle implementation defines specific anchor types for interaction:

    Adjustment Anchors (8 types): Used for resizing the shape. These are mapped to adjustType:

    • top, bottom, left, right
    • top-left, top-right, bottom-left, bottom-right

    Link Anchors (5 types): Used for connecting lines to the shape. These are mapped to alias:

    • top, bottom, left, right, center
  7. How Curve anchor and manual point adjustment works

    master

    The Curve implementation uses a dual-layer approach for interaction:

    1. Anchors (adjustType): These define how the curve can be manipulated. Types include:

      • 'start': Adjusts the beginning of the line.
      • 'end': Adjusts the end of the line.
      • 'manual': Represents intermediate control points (bends) in the curve.
    2. Shadows (anchorShadow): These are Konva.Circle objects used to visually represent the position of the anchors on the stage. The updateAnchorShadows and updateLinkAnchorShadows methods ensure these visual markers stay synchronized with the actual coordinates of the Konva.Line points.

    3. Manual Points: For curves with bends, the class maintains a manualPoints attribute on the Konva.Line shape. These points are sorted by an index to maintain the correct path order. When a manual anchor is moved, the adjust method updates the corresponding entry in the manualPoints array and recalculates the line's points.

  8. Manage connection points during transformation

    master

    When nodes are transformed (rotated or dragged), SelectionHandlers ensures that associated connection points (links) are updated to maintain visual integrity.

    1. Rotation: During transform, the handler calculates the rotation delta and uses rotatePoint to update the manualPointsMap of the connected groups.
    2. Dragging: During dragmove, the handler updates the position of connection points. It supports both standard dragging and 'magnetic' dragging (via attractTool) by calculating offsets relative to the transformer's position.
    3. State Management: The handler uses manualPointsMapBefore to store the state of points before a transformation begins, allowing for accurate recalculations.
  9. Initialize the Render class

    master

    The Render class is the central controller for the Konva-based designer. To use it, instantiate it by passing a target HTMLDivElement and a RenderConfig object. The constructor sets up the Konva Stage, multiple layers (main, floor, cover), various tools (selection, asset, link, etc.), and event handlers.

    import { Render } from './Render';
    
    const container = document.getElementById('container') as HTMLDivElement;
    const config = {
      width: 800,
      height: 600,
      showRuler: true,
      showBg: true,
      readonly: false
    };
    
    const renderer = new Render(container, config);
  10. Create Connections between Anchor Points

    master

    To create a new link between two existing elements, users interact with link-point circles located at the anchors of a group.

    1. Initiate: mousedown on a link-point circle starts a temporary linking-line (a blue Konva.Line) that follows the pointer.
    2. Complete: mouseup on a different link-point circle finalizes the connection.
    3. Data Structure: A new pair is added to the fromPoint.pairs array with the following structure:
      {
        id: nanoid(),
        from: { groupId: string, pointId: string },
        to: { groupId: string, pointId: string },
        linkType: LinkType // e.g., 'straight', 'manual', or 'auto'
      }
    4. Post-action: The system triggers updateHistory(), clears alignment lines via attractTool.alignLinesClear(), and performs a redraw() of the relevant drawing layers.
  11. Configure the Render engine with RenderConfig

    master

    The RenderConfig interface defines the visual and behavioral settings for the designer's rendering engine. Use it to control the canvas dimensions and the visibility of UI elements like rulers, grids, and context menus.

    export interface RenderConfig {
      width: number
      height: number
      // UI Visibility
      showBg?: boolean
      showRuler?: boolean
      showRefLine?: boolean
      showPreview?: boolean
      showContextmenu?: boolean
      // Interaction Behavior
      attractResize?: boolean
      attractBg?: boolean
      attractNode?: boolean
      // Mode
      readonly?: boolean
    }