2023.11.16使用原生js和canvas实现图片矩形框标注功能

2023.11.16使用原生js和canvas实现图片矩形框标注功能

做训练的时候需要一些数据集,但是网上数据集有时不能满足自身的使用需求,自己编制一个标注软件实现数据采集功能。
记录的数据集可以传入后端,在后端再次进行处理。
在这里插入图片描述

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <link rel="stylesheet" href="">
    <!-- css style -->
    <title>Canvas tutorial</title>
</head>
<body>
    <button id="saveBtn">保存</button><br>
</body>
<!-- js style -->
<script type="text/javascript">
    // 功能完全,手动保存
    var canvas = document.createElement("canvas");  // 创建一个"canvas"节点
    var ctx = canvas.getContext("2d"); 
    // 创建图片对象
    var img = new Image();    
    img.onload = function(){
        // 设置画布大小与图片大小一致
        canvas.width = img.width;
        canvas.height =img.height;
        // 绘制图片
        ctx.drawImage(img, 0, 0);
    }
    img.src = '../images/cat01.png'; // 设置图片源地址
    document.body.appendChild(canvas);

    // 绘制矩形的函数
    function drawRectangle(x1, y1, x2, y2) {
        ctx.clearRect(0, 0, canvas.width, canvas.height)    // 清除子路径的内容,如果不清楚,下次画又会把子路径的东西再画一遍
        ctx.drawImage(img, 0, 0);
        ctx.beginPath();    // beginPath() 方法在一个画布中开始子路径的一个新的集合
        ctx.rect(x1, y1, x2 - x1, y2 - y1);   // Rect矩形类,可以实现对矩形的多种用法
        rectangle = { x1: x1, y1: y1, x2: x2, y2: y2 };
        ctx.strokeStyle = "red";        // 设置矩形框的颜色,如果需要不同的矩形框设置不同的颜色,可以每次画图的时候都设置
        ctx.lineWidth = 5;        // 设置矩形框的粗细,如果需要不同的矩形框设置不同的粗细,可以每次画图的时候都设置
        ctx.stroke();   // 开始绘制的意思
    }

    // 点击鼠标时,开始记录鼠标位置,并打开绘制模式
    var isDrawing = false;
    var startX, startY;
    canvas.addEventListener("mousedown", function (event) {
        isDrawing = true;
        startX = event.clientX - canvas.offsetLeft;
        startY = event.clientY - canvas.offsetTop;
    })

    // 当拖动鼠标时,更新绘图区域的大小并重绘图像以显示矩形
    canvas.addEventListener("mousemove", function (event) {
        if (isDrawing) {
            var x = event.clientX - canvas.offsetLeft;
            var y = event.clientY - canvas.offsetTop;
            drawRectangle(startX, startY, x, y);          
        }
    })

    // 当释放鼠标时,结束绘制并关闭绘制模式
    canvas.addEventListener("mouseup", function (event) {
        isDrawing = false;
    })

    // 另外还可以添加其他标注工具,例如线条,文本框等

    // 保存标注数据
    var saveBtn = document.getElementById("saveBtn");
    var annotations = [];

    saveBtn.addEventListener("click",function () {
        var annotation = {
            x1:startX,
            y1:startY,
            x2:event.clientX - canvas.offsetLeft,
            y2:event.clientY - canvas.offsetTop,
        };
        annotations.push(annotation);
        // 将标注数据转换成字符串
        var dataStr = JSON.stringify(annotations)
        // 存储标注数据到localStorage中,其中"imageAnnotations"为指定存储的键名,可以自行设置
        localStorage.setItem("imageAnnotations", dataStr);
        console.log(dataStr);
    })
</script>
</html>
<think>嗯,用户想要了解基于pdf.js实现的一个PDF编辑批注的JS插件库,支持多种工具保存功能。首先,我需要确认用户的需求场景。可能是他们在开发一个需要PDF标注功能的Web应用,或者想集成这样的功能到现有系统中。用户提到的功能包括高亮、下划线、插入图片、形状、文本、画笔,以及保存批注到PDF中,这些都比较全面。 接下来,我应该考虑pdf.js的基础知识。pdf.js是Mozilla开源的库,主要用于在浏览器中渲染PDF,但本身不支持编辑批注。所以用户需要一个基于pdf.js的插件库来扩展这些功能。这时候,可能需要解释如何利用pdf.js的API来实现批注的添加交互。 然后,实现这些功能的关键点在哪里呢?比如,高亮下划线可能涉及在PDF页面上覆盖DOM元素,并捕获用户的选择区域。而形状、箭头等可能需要Canvas或SVG来绘制,并处理用户的鼠标事件。保存批注到PDF中,可能需要修改PDF的元数据或者使用pdf-lib这样的库来操作PDF文件结构。 另外,用户提到的支持写入批注并保存,这里可能涉及到将批注数据嵌入到PDF文件中,或者单独存储批注数据并与PDF关联。需要区分这两种方式,因为直接修改PDF文件可能更复杂,但更独立,而外部存储则需要管理关联数据。 可能存在的挑战包括批注的坐标定位,确保在不同分辨率下位置准确,以及处理PDF页面的缩放旋转。此外,保存批注时,如果是直接修改PDF文件,可能需要处理PDF的二进制结构,这可能比较困难,需要借助其他库如pdf-lib或jsPDF。 用户可能还想知道现有的开源库,比如Annotations.js或PDFAnnotate,这些是否满足需求,或者是否需要自行开发。如果有现成的库,可以推荐并说明其优缺点;如果没有,需要指导他们如何自行实现。 最后,需要确保回答结构清晰,分步骤说明实现思路,可能的技术选型,以及注意事项。同时,提醒用户关于性能的问题,比如大量批注可能导致渲染变慢,以及跨浏览器兼容性等潜在问题。</think>以下是一个分步解析的解决方案介绍: 一、技术基础 1. 核心依赖:PDF.js - Mozilla开源的Web端PDF渲染库 - 提供底层PDF解析Canvas/SVG渲染能力 - 原生不支持批注功能,需二次开发 2. 功能扩展原理 - 基于PDF.js Viewer构建UI层 - 通过Canvas叠加层实现批注绘制 - 利用PDF.js AnnotationLayer扩展批注系统 二、核心功能实现 1. 批注工具开发 ``` // 工具基类示例 class AnnotationTool { constructor(pdfViewer) { this.pdfViewer = pdfViewer; this.currentPage = null; } beginAnnotation(event) { const pageNum = this._getPageFromEvent(event); this.currentPage = pageNum; } _getPageFromEvent(event) { // 坐标转换逻辑... } } ``` 2. 坐标系统处理 - PDF坐标 ↔ 页面坐标 ↔ 视口坐标 转换 - 矩阵变换公式: $$ x' = \frac{x - viewport.transform[4]}{viewport.width} \times pageWidth $$ $$ y' = \frac{y - viewport.transform[5]}{viewport.height} \times pageHeight $$ 3. 批注持久化 - 方案1:存储到PDF文件 ```javascript import { PDFDocument } from 'pdf-lib'; async function saveAnnotations(pdfBytes, annotations) { const pdfDoc = await PDFDocument.load(pdfBytes); annotations.forEach(ann => { const page = pdfDoc.getPage(ann.page); page.drawRectangle({ x: ann.x, y: ann.y, width: ann.width, height: ann.height, borderColor: rgb(1,0,0), }); }); return await pdfDoc.save(); } ``` - 方案2:独立存储(推荐) ```json { "annotations": [{ "type": "highlight", "page": 1, "rect": [100,200,50,30], "color": "#FFFF00", "content": "重要内容" }] } ``` 三、推荐扩展库 1. 开源方案 - Annotorious PDF:基础批注架 - PDFAnnotate:完整工具套件 - PSPDFKit for Web(商业方案) 2. 自研建议 - 工具分层架构: ``` PDF Viewer Layer ↑ Annotation Service Layer ↑ UI Interaction Layer ↑ Data Persistence Layer ``` 四、关键挑战 1. 坐标系一致性 2. 跨分辨率适配 3. 撤销/重做实现 4. 批注数据压缩 5. 大文件性能优化 五、实施步骤建议 1. 基础环境搭建 ```bash npm install pdfjs-dist pdf-lib ``` 2. 功能开发顺序 (1) 基础渲染 → (2) 选择工具 → (3) 绘制工具 → (4) 数据存储 → (5) 导入导出 3. 推荐扩展方向 - 协同批注:通过WebSocket实现实时同步 - OCR集成:文字识别批注 - 版本对比:批注变更追踪 六、注意事项 1. 移动端适配需单独处理触控事件 2. 字体嵌入需遵循PDF规范 3. 加密文档需特殊处理 4. 建议使用Web Workers处理复杂计算 当前主流方案通常采用混合模式: - 轻量批注直接写入PDF - 复杂批注采用外部存储+PDF引用标记 - 使用IndexedDB进行本地缓存优化 实际开发中建议优先实现核心批注功能,再逐步扩展高级特性,同时注意遵循PDF规范以确保跨平台兼容性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leigh_chen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值