Annotorious入门教程:图片注释工具

本文简介

最近有工友问我前端怎么给图片做标注。使用 Fabric.js 或者 Konva.js 等库确实可以实现,但我又好奇有没有专门做图片标注的工具呢?

在网上搜了一下发现 Annotorious 可以实现这个功能。Annotorious 提供了图片注释和标注功能,而且用法很简单。

file


本文分为 【快速入门】和【API讲解】两部分。

【快速入门】部分包含 Annotorious 的安装、使用、导入导出的讲解。这几点应该是项目中比较核心的流程,给希望快速入门的工友提供一丢丢帮助。

【API讲解】这部分主要讲一下我认为比较常用的功能。注意:是“我认为”。



快速入门

快速入门部分会讲解Annotorious 的安装、使用、导入和导出数据功能。


安装 Annotorious

CDN

<!-- 引入样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@recogito/annotorious@2.7.10/dist/annotorious.min.css"><!-- 引入js -->
<script src="https://cdn.jsdelivr.net/npm/@recogito/annotorious@2.7.10/dist/annotorious.min.js"></script>

你可以把这两份文件下载到自己的项目里再引入。


NPM

用以下命令安装 Annotorious

npm install @recogito/annotorious

然后在项目中引入

import { Annotorious } from '@recogito/annotorious'
import '@recogito/annotorious/dist/annotorious.min.css'

使用 annotorious

Annotorious 安装到项目后就可以使用了。

Annotorious 的用法很简单,只需做以下2步:

  1. 在html部分插入图片
  2. 初始化 Annotorious,并绑定图片元素(元素的ID或者元素本身)

file


CDNNPM 在初始化时的用法稍微有点不同。

CDN

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image' // 元素ID
})
</script>

使用 CDN 的方式引入 Annotorious,在初始化时要 Annotorious.init 这样写。


NPM

<img src="./img.jpg" id="my-image" /><script>
const anno = new Annotorious({image: document.getElementById('my-image') // 元素本身
})
</script>

使用 NPM 的方式引入 Annotorious 在初始化时需要 new Annotorious 这样写。


注意:在 Annotorious 初始化代码最好放在你所使用的框架的页面加载完成后的生命周期函数里!


导出数据 getAnnotations()

如果你需要将图片上的标注保存到服务器,就需要把数据导出。

所用到的方法是 getAnnotations()

file

<button οnclick="save()">保存</button>
<img src="./44.jpg" id="img" /><script>let anno = nullonload = function() {anno = Annotorious.init({image: 'img'})}function save() {let res = anno.getAnnotations()console.log(res)}
</script>

导入数据 loadAnnotations(url)

Annotorious 可以通过 loadAnnotations() 方法加载数据。

loadAnnotations(url) 支持传入一个 URL 参数,这个 URL 所指的是数据文件地址。

比如我在本地创建一个 data.json 文件,文件内容是使用前面讲到的 getAnnotations() 方法导出的数据,我的数据内容如下:

[{"@context": "http://www.w3.org/ns/anno.jsonld","type": "Annotation","body": [{"type": "TextualBody","value": "1","purpose": "commenting"}],"target": {"source": "http://127.0.0.1:5500/44.jpg","selector": {"type": "FragmentSelector","conformsTo": "http://www.w3.org/TR/media-frags/","value": "xywh=pixel:100,100,500,300"}},"id": "#cabe2e71-b19f-4499-80c6-235882fd50ba"}
]

在本地测试时,我使用了本地服务器把 data.json 管理起来,在浏览器可以通过 http://127.0.0.1:5500/data.json 访问到该文件。

然后再使用 loadAnnotations(url) 方法把数据渲染出来即可。

file

<button οnclick="load()">加载</button>
<img src="./44.jpg" id="img" /><script>
let anno = nullonload = function() {anno = Annotorious.init({image: 'img'})
}function load() {anno.loadAnnotations("http://127.0.0.1:5500/data.json")
}
</script>

点击加载按钮后,图片上就会出现一个选框,点击选框可以看到数据已经成功加载出来。


添加数据 addAnnotation()

但在实际项目中,后台不一定会给前端返回一个文件地址,后台可能会直接返回一个json数据。

这时候如果使用 loadAnnotations() 方法加载 json 数据是行不通的,要通过遍历读取数据中心的 data 里的数据,然后调用 addAnnotation() 方法将元素添加到页面。


我使用 json-server 简单的在本地搭建一个服务器给前端访问对应的资源,前端用 axios 请求资源。

<button οnclick="load()">加载</button>
<img src="./44.jpg" id="img" /><script>
let anno = nullonload = function() {anno = Annotorious.init({image: 'img'})
}function load() {axios.get('http://localhost:3000/anno').then(res => {res.data.data.forEach(item => {anno.addAnnotation(item)})})
}
</script>

很久之前写过一篇 《『前端必备』本地数据接口 —— json-server 从入门到膨胀》 文章介绍 json-server 的基础用法,有兴趣的工友可以去瞧瞧。



API讲解

这部分主要讲一些我关注到的功能,如果想全面了解 Annotorious 可以查看文档。


汉化 locale

Annotorious 是根据浏览器的设置来确定使用哪种语言。

file


如果需要修改 Annotorious 使用的语言,可以在初始化时配置一下 locale 字段。

比如配置简体中文可以用 zh-CN,配置繁体中文可以用 zh-TW

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',locale: 'zh-CN' // 修改语言
})
</script>

自定义提示文本 messages

如果想自定义按钮或者输入框的提示文本可以配置 messages

<img src="./img.jpg" id="my-image" /><script>// 创建一个包含自定义消息的对象
var customMessages = {"Add a comment...": "评论评论","Add a reply...": "回复两句","Add tag...": "这是标签啊","Cancel": "取消","Close": "关闭","Edit": "编辑~","Delete": "删除❌","Ok": "确定"
}let anno = Annotorious.init({image: 'my-image',messages: customMessages // 自定义消息内容
})
</script>

如果同时配置了 localemessages ,会优先使用 message 的值。


空注释 allowEmpty

默认情况下,如果框选后没输入标签或者评论就按确定是不会保存选框的。

file

如果想保存空选框,可以将 allowEmpty 设置为 true

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',allowEmpty: true // 允许空注释
})
</script>

框选辅助线 crosshair

有些鼠标指针可能并不是那么标准,会影响你框选的准确性。

如果需要非常准确去框选,可以开启辅助线功能,只需将 crosshair 设置为 true 即可。

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',crosshair: true // 开启辅助线
})
</script>

只读 readOnly

如果不打算提供框选、添加和删除信息的操作给用户,可以将 readOnly 设置为 true

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',readOnly: true // 只读模式
})
</script>

禁止编辑 disableEditor

如果只需要画框框,不需要写注释,可以将 disableEditorallowEmpty 同时设置为 true

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',allowEmpty: true, // 允许空注释disableEditor: true // 禁用编辑
})
</script>

为什么要同时将 allowEmpty 设为 true

因为如果你不允许注释为空的话,当你点击空白处时选框就会消失。


禁止选中选框 disableSelect

disableSelect 设置为 true 后,画布上的选框就无法再次选中了。

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',disableSelect: true // 禁止选中选框
})
</script>

虽然还没想到有什么引用场景,但还是打算记录一下。


手柄半径 handleRadius

箭头所指的就是手柄。

file

手柄的默认半径是6。如果需要修改手柄半径可以设置 handleRadius 属性。

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',handleRadius: 20 // 设置手柄半径
})
</script>

自定义选框样式

Annotorious 的选框和编辑器都是可以使用 css 设置样式的。

选框部分使用了 SVG ,编辑器部分直接用了 HTML 元素。

SVG 不了解的工友可以阅读 《SVG专栏》。


回到 Annotorious ,官方也有给出一个自定义样式的案例 《Customizing Visual Appearance》。

file

<style>/* 选框 *//* 隐藏外部形状-对于这种风格,我们只需要一个 */svg.a9s-annotationlayer .a9s-selection .a9s-outer, svg.a9s-annotationlayer .a9s-annotation .a9s-outer {display:none;}svg.a9s-annotationlayer .a9s-handle .a9s-handle-outer {display:none;}/* 虚线边框 */svg.a9s-annotationlayer .a9s-selection .a9s-inner,svg.a9s-annotationlayer .a9s-annotation .a9s-inner  {stroke-width:4;stroke:white;stroke-dasharray:5;}/* 选中时的填充色 */svg.a9s-annotationlayer .a9s-annotation.editable:hover .a9s-inner {fill:transparent;}/* 手柄颜色 */svg.a9s-annotationlayer .a9s-handle .a9s-handle-inner {fill:white;stroke:white;}/* 选中选框时,遮罩层颜色 */svg.a9s-annotationlayer .a9s-selection-mask {fill:rgba(0, 0, 0, 0.6);}/* 编辑器 *//* 容器 */.r6o-editor .r6o-editor-inner {box-sizing: border-box;padding: 10px;border-radius: 6px;background: #F4F2DE;}/* 箭头 */.r6o-editor .r6o-arrow:after {background-color: #F4F2DE;}/* 编辑器 */.r6o-widget.comment.editable,.r6o-widget.r6o-tag {background-color: #EEE3CB;}.r6o-widget.comment {background-color: #D7C0AE;}.r6o-editor .r6o-editor-inner .r6o-widget {border-bottom-color: #7C9D96;}.r6o-editor .r6o-editor-inner .r6o-widget.r6o-tag {border-bottom: none;}/* 按钮 */.r6o-editor .r6o-btn {border-radius: 100px;background-color: #7C9D96;border-color: #7C9D96;color: #fff;}/* 线框按钮 */.r6o-editor .r6o-btn.outline {color: #7C9D96;background-color: transparent;}
</style><img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',locale: 'zh-CN' // 修改语言
})
</script>

上面这份代码选框的样式是从 Annotorious 官网教程搬过来的。

编辑器的样式我随便配了一下,工友们也可以打开浏览器控制台看 Elements 面板的 HTML 代码,根据结构去修改样式即可。


筛选功能

输入时需要快速添加预选项时,可以这样配置:

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image',widgets: ['COMMENT',{ widget: 'TAG', vocabulary: [ '雷猴', '鲨鱼辣椒', '蝎子莱莱'] }]
})
</script>

多边形选框

使用 setDrawingTool(toolName) 方法可以设置不同的绘制工具。

如果需要讲选框设置成多边形,可以传入 'polygon'

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image'
})anno.setDrawingTool("polygon")
</script>

想要知道当前有哪些绘图工具,可以使用 anno.listDrawingTools() 方法查看

file

<img src="./img.jpg" id="my-image" /><script>
let anno = Annotorious.init({image: 'my-image'
})const toolNames = anno.listDrawingTools()
console.log(toolNames)
</script>

其他

除了上面介绍到的 API 外,Annotorious 还有很多玩法的,比如删除指定注释、清空所有注释等。

详情请看 《annotorious API文档》



插件

Annotorious 也有一些好玩的插件,有兴趣的可以看看 《Annotorious 插件推荐》。



推荐阅读

👍《提升日期处理效率:day.js 实战经验分享》

👍《OpenLayers.js 入门教程:打造互动地图的入门指南》

👍《物理世界的互动之旅:Matter.js入门指南》

👍《p5.js 光速入门》

👍《眨个眼就学会了Pixi.js》

👍《Fabric.js 从入门到膨胀》


点赞 + 关注 + 收藏 = 学会了 代码仓库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/179416.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化时代,数据仓库是什么?有什么用?

在激烈的市场竞争和全新的数字经济共同作用下&#xff0c;数字化转型成为了大多数企业的共识&#xff0c;也是获取数字经济的最佳方式。在整个数据价值生产链路中&#xff0c;数据仓库的主要作用就是中心化分发&#xff0c;将原始数据与数据价值挖掘活动隔离。 所有的原始数据…

图像二值化阈值调整——cv2.threshold方法

二值化阈值调整&#xff1a;调整是指在进行图像二值化处理时&#xff0c;调整阈值的过程。阈值决定了将图像中的像素分为黑色和白色的界限&#xff0c;大于阈值的像素被设置为白色&#xff0c;小于等于阈值的像素被设置为黑色。 首先画出灰度直方图&#xff1a;横坐标是灰度值…

React中的状态管理

目录 前言 1. React中的状态管理 1.1 本地状态管理 1.2 全局状态管理 Redux React Context 2. React状态管理的优势 总结 前言 当谈到前端开发中的状态管理时&#xff0c;React是一个备受推崇的选择。React的状态管理机制被广泛应用于构建大型、复杂的应用程序&#xf…

【漏洞复现】74cms任意文件读取

漏洞描述 74CMS 是一款国内用的比较多招聘网站管理系统&#xff08;Job Board CMS&#xff09;&#xff0c;专注于招聘和人力资源领域的网站建设&#xff0c;存在任意文件读取漏洞 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c…

面向网络安全-Python语言

目录 1、变量 2、字符串 3、列表 4、字典 5、网络 6、条件选择语句 7、异常处理 1、变量 变量是指储存在某个内存地址上的数据 主要有&#xff1a;整型数、实数、布尔值、字符串、列表、元组、字典 这些数据在声明后&#xff0c;解释器就会自动确定每个变量的类型&…

opencv在linux上调用usb摄像头进行拍照

功能 1.按照指定的文件名创建文件夹&#xff0c;创建之前判断该文件夹是否存在 2.调用摄像头按可调整窗口大小的方式显示 3.按esc退出摄像头画面 4.按p保存当前摄像头的画面&#xff0c;并按当前时间为照片的名字进行保存打开终端查看是否有摄像头 ls /dev/video*一般video1就…

MyBatis实现多表映射、分页显示、逆向工程

目录 一、MyBatis实现多表映射 1.1 实体类设计 1.2 一对一关系实现案例 1.3 对多配置实现案例 1.4 设置自动映射与n张表关联映射 二、MyBatis实现分页功能 2.1 mybatis插件工作原理 2.2 引入插件与插件的使用 三、逆向工程插件 3.1 什么是逆向工程 3.2 MyBat…

Stable Diffusion WebUI扩展sd-webui-controlnet安装教程

话不多说,上链接: https://github.com/Mikubill/sd-webui-controlnethttps://github.com/Mikubill/sd-webui-controlnet同样,直接安装到extensions文件中。 什么conda还是python安装也不多说了,前面很多讲了如何安装,这里就不当赘婿了。 安装好后,我们最好手动安装模型…

毕马威加入IBM量子网络,已搭建完成通信行业量子电路!

毕马威全球量子中心主管Bent Dalager&#xff08;图片来源&#xff1a;网络&#xff09; 随着全球企业技术的持续转型&#xff0c;量子计算在开发创新解决方案上越来越重要。为此&#xff0c;毕马威(KPMG)公司加入了IBM量子网络&#xff0c;旨在利用量子计算解决当今最复杂的业…

SpringBoot可以同时处理多少请求?

前言 前两天面试的时候&#xff0c;面试官问我&#xff1a;一个ip发请求过来&#xff0c;是一个ip对应一个线程吗&#xff1f;我突然愣住了&#xff0c;对于SpringBoot如何处理请求好像从来没仔细思考过&#xff0c;所以面试结束后就仔细研究了一番&#xff0c;现在就来探讨一…

go语言 | grpc原理介绍(一)

参考 https://www.nowcoder.com/discuss/389810396381683712?sourceSSRsearch 这里是b站对应的csdn博客&#xff0c;比较详细的介绍grpc相关原理说明&#xff0c;首先是大概的一个流程图说明。 什么是 RPC &#xff1f; 远程过程调用&#xff08;RPC&#xff09;是计算机科…

一文全览各种 ES 查询在 Java 中的实现

2 词条查询 所谓词条查询&#xff0c;也就是ES不会对查询条件进行分词处理&#xff0c;只有当词条和查询字符串完全匹配时&#xff0c;才会被查询到。 &#xfeff; 2.1 等值查询-term 等值查询&#xff0c;即筛选出一个字段等于特定值的所有记录。 &#xfeff; SQL&…

LLaMA-Adapter源码解析

LLaMA-Adapter源码解析 伪代码 def transformer_block_with_llama_adapter(x, gating_factor, soft_prompt):residual xy zero_init_attention(soft_prompt, x) # llama-adapter: prepend prefixx self_attention(x)x x gating_factor * y # llama-adapter: apply zero_init…

PY32F071单片机,主频最高72 M,带一路DAC,USB

PY32F071 系列微控制器采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围的 MCU。嵌入高达128 Kbytes flash 和 16 Kbytes SRAM 存储器&#xff0c;最高工作频率 72 MHz。包含多种不同封装类型多款产品。芯片集成多路 I2C、SPI、USART 等通讯外设&#xff0c;1 …

配置git并把本地项目连接github

一.配置git 1.下载git&#xff08;Git&#xff09;&#xff0c;但推荐使用国内镜像下载&#xff08;CNPM Binaries Mirror&#xff09; 选好64和版本号下载&#xff0c;全部点下一步 下载完成后打开终端&#xff0c;输入 git --version 出现版本号则说明安装成功 然后继续…

C# OpenCvSharp DNN 部署L2CS-Net人脸朝向估计

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Dnn; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms;namespace OpenCvSharp_DNN_Demo …

MySQL中表的增删改查

目录 一、CRUD 二、新增&#xff08;Create&#xff09; &#xff08;1&#xff09;语法 &#xff08;2&#xff09;单行数据全列插入 &#xff08;3&#xff09;多行数据指定列插入 三、查询&#xff08;Retrieve&#xff09; &#xff08;1&#xff09;语法 …

swift语言下SurfGen库做的爬虫是什么样的 ?

Swift语言并没有内置的爬虫库&#xff0c;但是你可以使用第三方库来实现爬虫功能。其中比较常用的是Alamofire和SwiftyJSON。Alamofire是一个基于Swift语言的HTTP网络库&#xff0c;可以用来发送HTTP请求和接收HTTP响应。而SwiftyJSON则是一个用于处理JSON数据的Swift库&#x…

vue使用JsBarcode生成条形码

在工作中&#xff0c;有一个需求是接口返回的订单号生成条形码&#xff0c;如图&#xff1a; 1.安装依赖 yarn add jsbarcode2.引入 在script标签中引入 import JsBarcode from jsbarcode 3.使用 this.$refs.a.src的值为条形码的地址。 <template><div><img…

自定义类型结构体(下)

目录 结构体传参结构体实现位段什么是位段位段的内存分配位段的跨平台问题总结&#xff1a; 位段的应用位段使用的注意事项** 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978;&#x1f978;&a…