MST

星途 面试题库

面试题:TypeScript实现基于Canvas的复杂交互绘图系统类型抽象

设计一个基于Canvas的复杂交互绘图系统,用户可以通过鼠标进行图形的绘制、选择、移动、缩放等操作。使用TypeScript对整个系统进行类型抽象,包括定义事件类型(如鼠标点击、拖动等)、图形对象类型、操作状态类型等。并构建一个状态机来管理不同操作状态下系统的行为,同时要保证类型安全。请详细阐述设计架构,并提供核心代码示例。
23.3万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计架构

  1. 类型定义
    • 事件类型:定义鼠标点击、拖动、释放等事件类型。
    • 图形对象类型:描述不同图形(如矩形、圆形等)的属性和方法。
    • 操作状态类型:例如绘制状态、选择状态、移动状态、缩放状态等。
  2. 状态机
    • 管理系统在不同操作状态下的行为。比如在绘制状态下处理鼠标事件进行图形绘制,在选择状态下处理鼠标事件进行图形选择等。
  3. 核心模块
    • Canvas 交互模块:负责监听 Canvas 上的鼠标事件,并根据当前状态机的状态进行相应处理。
    • 图形管理模块:管理图形对象的创建、存储、检索和修改。

核心代码示例

  1. 类型定义
// 事件类型
type MouseEventType = 'click' | 'drag' |'release';

// 图形对象类型,以矩形为例
interface Rectangle {
    type: 'rectangle';
    x: number;
    y: number;
    width: number;
    height: number;
    draw(ctx: CanvasRenderingContext2D): void;
}

// 操作状态类型
type OperationState = 'drawing' |'selecting' |'moving' |'scaling';
  1. 状态机
class StateMachine {
    private currentState: OperationState;
    constructor(initialState: OperationState) {
        this.currentState = initialState;
    }

    public transition(state: OperationState) {
        this.currentState = state;
    }

    public getState(): OperationState {
        return this.currentState;
    }
}
  1. Canvas 交互模块(简化示例)
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const stateMachine = new StateMachine('drawing');

canvas.addEventListener('mousedown', (e) => {
    if (stateMachine.getState() === 'drawing') {
        // 开始绘制图形逻辑
    }
});

canvas.addEventListener('mousemove', (e) => {
    if (stateMachine.getState() === 'dragging') {
        // 处理图形拖动逻辑
    }
});

canvas.addEventListener('mouseup', (e) => {
    if (stateMachine.getState() === 'drawing') {
        // 完成绘制图形逻辑
    }
});
  1. 图形管理模块(简化示例)
class ShapeManager {
    private shapes: (Rectangle)[] = [];

    public addShape(shape: Rectangle) {
        this.shapes.push(shape);
    }

    public getShapes(): (Rectangle)[] {
        return this.shapes;
    }

    public drawAll(ctx: CanvasRenderingContext2D) {
        this.shapes.forEach(shape => shape.draw(ctx));
    }
}
  1. 图形绘制(以矩形为例)
function createRectangle(x: number, y: number, width: number, height: number): Rectangle {
    return {
        type:'rectangle',
        x,
        y,
        width,
        height,
        draw(ctx) {
            ctx.fillRect(this.x, this.y, this.width, this.height);
        }
    };
}