仿一下微信的截图标注功能

就像用画图软件在图片上画框框:

打开一张图片

选择红色/黄色/蓝色框框

在图片上拖拽画框

画错了可以撤销(后退)

撤销了又想恢复(前进)

功能概述

这个工具允许用户在图片上进行矩形标注,支持三种不同类型的标注,并提供前进/后退功能来撤销或重做操作。

核心实现思路

1. 数据结构设计

typescript 复制代码
export interface MarkerType {
  x: number,        // 标记左上角x坐标
  y: number,        // 标记左上角y坐标
  height: number,   // 标记高度
  width: number,    // 标记宽度
  type: "1" | "2" | "3"  // 标记类型
}

export interface ImgMarkerType {
  img: string,      // 图片地址
  markList: MarkerType[]  // 标记列表
}

2. 关键状态管理

typescript 复制代码
// 图片标注数据
const imgMarkerData = reactive<ImgMarkerType>({
  img: url,
  markList: []
});

// 当前标注类型
const nowType = ref<"1" | "2" | "3">("1");

// 当前操作索引(用于前进后退)
const nowIndex = ref(0);

// 是否可以绘制(鼠标按下时)
const canDraw = ref(false);

3. 核心功能实现

3.1 渲染画布

typescript 复制代码
function renderCanvas() {
  if (!ctx.value) return;
  
  // 清空画布
  ctx.value.clearRect(0, 0, 800, 800);
  
  // 绘制图片
  if (img.value) {
    ctx.value.drawImage(img.value, 0, 0, 800, 800);
  }
  
  // 绘制标记
  imgMarkerData.markList.forEach((marker, index) => {
    if (index > nowIndex.value) return; // 前进后退控制
    
    // 根据类型设置颜色
    const colorMap = {
      "1": "red",
      "2": "yellow", 
      "3": "blue"
    };
    
    ctx.value!.strokeStyle = colorMap[marker.type];
    ctx.value!.strokeRect(marker.x, marker.y, marker.width, marker.height);
  });
}

3.2 鼠标事件处理

typescript 复制代码
function mousedown(e: MouseEvent) {
  canDraw.value = true;
  
  // 创建新标记
  const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
  const newMarker: MarkerType = {
    x: e.clientX - rect.left,
    y: e.clientY - rect.top,
    width: 0,
    height: 0,
    type: nowType.value
  };
  
  imgMarkerData.markList.push(newMarker);
  nowIndex.value = imgMarkerData.markList.length - 1;
}

function mousemove(e: MouseEvent) {
  if (!canDraw.value) return;
  
  const rect = (e.target as HTMLCanvasElement).getBoundingClientRect();
  const currentX = e.clientX - rect.left;
  const currentY = e.clientY - rect.top;
  
  // 更新当前标记的尺寸
  const currentMarker = imgMarkerData.markList[nowIndex.value];
  currentMarker.width = currentX - currentMarker.x;
  currentMarker.height = currentY - currentMarker.y;
  
  renderCanvas(); // 重新渲染
}

function mouseup() {
  canDraw.value = false;
  renderCanvas(); // 最终渲染
}

3.3 前进后退功能

typescript 复制代码
function goBack() {
  if (nowIndex.value > 0) {
    nowIndex.value--;
    renderCanvas();
  }
}

function goForward() {
  if (nowIndex.value < imgMarkerData.markList.length - 1) {
    nowIndex.value++;
    renderCanvas();
  }
}
相关推荐
炫饭第一名39 分钟前
速通Canvas指北🦮——基础入门篇
前端·javascript·程序员
王晓枫1 小时前
flutter接入三方库运行报错:Error running pod install
前端·flutter
符方昊1 小时前
React 19 对比 React 16 新特性解析
前端·react.js
ssshooter1 小时前
又被 Safari 差异坑了:textContent 拿到的值居然没换行?
前端
曲折1 小时前
Cesium-气象要素PNG色斑图叠加
前端·cesium
Forever7_1 小时前
Electron 淘汰!新的桌面端框架 更强大、更轻量化
前端·vue.js
Angelial2 小时前
Vue3 嵌套路由 KeepAlive:动态缓存与反向配置方案
前端·vue.js
jiayu2 小时前
Angular学习笔记24:Angular 响应式表单 FormArray 与 FormGroup 相互嵌套
前端
jiayu2 小时前
Angular6学习笔记13:HTTP(3)
前端
小码哥_常2 小时前
Kotlin抽象类与接口:相爱相杀的编程“CP”
前端