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

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

打开一张图片

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

在图片上拖拽画框

画错了可以撤销(后退)

撤销了又想恢复(前进)

功能概述

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

核心实现思路

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();
  }
}
相关推荐
_AaronWong2 小时前
前端工程化:基于Node.js的自动化版本管理与发布说明生成工具
前端·javascript·node.js
Healer9183 小时前
纯css实现高度0-auto动画过度interpolate-size 和 height: calc-size(auto,size)
前端
智慧源点3 小时前
解决 Vite + React 项目部署 GitHub Pages 的完整指南:从 404 到成功部署
前端·react.js·github
葡萄城技术团队3 小时前
浏览器端音视频处理新选择:Mediabunny 让 Web 媒体开发飞起来
前端·音视频·媒体
FogLetter3 小时前
深入浅出 JavaScript 闭包:从背包理论到实战应用
前端·javascript
前端大卫3 小时前
表单与上传组件校验
前端·javascript·vue.js
伊织code3 小时前
Cap‘n Web - JavaScript原生RPC系统
前端·javascript·rpc
周尛先森4 小时前
匠心管控 package.json:让前端依赖告别臃肿与混乱
前端
90后的晨仔4 小时前
Vue3 事件处理详解:从入门到精通
前端·vue.js