recogito-js:用于文本注释/图像注释的前端插件

创建批注:

继续批注:

右侧批注列表:

1、功能与应用

  • 文本注释:recogito-js可以将注释功能添加到网页上,或者作为构建完全自定义注释应用程序的工具箱。
  • 图像注释:除了文本注释外,它还支持为网页中的图像添加绘图、注释和标签功能。
  • PDF注释:通过@recogito/recogito-react-pdf插件,它还能够支持在React中注释PDF文档。

2、官网及示例

官网:https://github.com/recogito/recogito-js/wiki/API-Reference

示例:https://recogito.github.io/recogito-js/

3、需求:

前面的文章提到过很多的tinyMCE、Vditor、cherryMarkdown、wangEditor等等markdown和富文本编辑器,在这些编辑器生成的文本内容的预览基础上要加上批注功能,用户选中文本后就要弹出批注弹窗,确认批注后右侧会相应展示出批注内容,同时在右侧进行批注的编辑、删除

4、安装与使用:

javascript 复制代码
npm i @recogito/recogito-js@1.8.2

以下示例为文本注释功能:

javascript 复制代码
import { Recogito } from "@recogito/recogito-js";
import "@recogito/recogito-js/dist/recogito.min.css";

// 初始化批注
const initRecogito = () => {
  getAnnoList();
  r = new Recogito({
    content: document.querySelector(".artDetail"), // 批注区域
    readOnly: false,  // 是否只读
    locale: "auto", // 可选择语言 auto会根据浏览器设置选择语言
  });
  r.setServerTime(Date.now()); // 设置批注日期
  r.setAuthInfo({   // 这里设置每个批注携带的默认信息
    id: useUserStore().userId,
    displayName: useUserStore().nickName,
  });
  // 创建批注事件
  r.on("createAnnotation", async function (annotation, overrideId) {
    // 定义一个getInitAnnotate方法拿到创建的这个批注信息
    let newAnno = getInitAnnotate("create", annotation);
    // 因为批注插件不管有没有输入内容都会创建,这里要求了没有批注内容时不允许新建批注
    if (!newAnno.annotationContent?.trim()?.length) {
      getAnnoList(); // 刷新批注列表避免页面出现空批注内容
      return proxy.$modal.msgWarning("请先输入批注内容");
    }
    // 将批注信息存入后端
    submitAnnotation(newAnno)
      .then(({ data }) => {
        recogitoList.value.push(data);  // 在页面右侧回展示批注信息
        proxy.$modal.msgSuccess("新增成功!");
      })
      .catch((err) => {
        getAnnoList();// 刷新批注列表避免页面出现空批注内容
      });
  });

 

  // 在已有批注基础上补充批注
  r.on("updateAnnotation", function (annotation, previous) {
    let newAnno = getInitAnnotate("update", annotation);
    if (!newAnno.annotationContent?.trim()?.length) {
      getAnnoList();
      return proxy.$modal.msgWarning("请先输入批注内容");
    }
    submitAnnotation(newAnno)
      .then(({ data }) => {
        // 补充批注时
        let index = recogitoList.value.findIndex((item) => item.id === data.id);
        recogitoList.value[index] = data;
        proxy.$modal.msgSuccess("新增成功!");
      })
      .catch((err) => {
        getAnnoList();
      });
  });
};

// 更改批注参数
const getInitAnnotate = (title, newAnno, pkId) => {
  let data = {};
  // 创建批注时
  if (title === "create") {
    data.annotationContent = newAnno.body[0]?.value;
    data.textContent = newAnno.target.selector.find(
      (item) => item.type === "TextQuoteSelector"
    )?.exact;
  // 修改批注时
  } else if (title === "update") {
    data.annotationContent = newAnno.body[newAnno.body?.length - 1]?.value;
  } else {
    // 通过外部input框编辑批注
    let annoBody = newAnno.body.find((item) => item.pkId === pkId);
    data.annotationContent = annoBody?.iptValue;
    data.pkId = pkId;
  }
  let annoPosition = newAnno.target.selector.find(
    (item) => item.type === "TextPositionSelector"
  );
  // 按照后端入参要求组装批注内容的结构
  data.annotationId = newAnno.id;
  data.createdBy = useUserStore().name;
  data.endCoordinate = annoPosition.end;
  data.startCoordinate = annoPosition.start;
  data.knwlgId = artDetails.value.pkId;
  data.knwlgNo = artDetails.value.knwlgNo;
  return data;
};

// 获取批注列表并回显
const getAnnoList = () => {
  getAnnotationList({ knwlgId: artDetails.value.pkId })
    .then((res) => {
      recogitoList.value = res.data;  // 批注列表
      setTimeout(() => {
        r.clearAnnotations(); //清除所有批注
        r.setAnnotations(recogitoList.value); // 设置已有批注内容
      }, 500);
    })
    .catch(() => {});
};

// 根据批注id在点击右侧批注列表激活文本域内批注弹窗
const selectAnnotation = (id) => {
  let domList = document.querySelectorAll(".r6o-annotation");
  let activeTop =
    Array.from(domList).find(
      (item) => item.dataset.id === id && item.innerText?.length
    )?.offsetTop - 5;
  document.querySelector(".article-container").scrollTop = activeTop;
  r.selectAnnotation(id);
};
相关推荐
new出一个对象5 小时前
uniapp接入BMapGL百度地图
javascript·百度·uni-app
你挚爱的强哥6 小时前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
前端Hardy6 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189116 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
小镇程序员9 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
疯狂的沙粒9 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript
瑞雨溪9 小时前
AJAX的基本使用
前端·javascript·ajax
力透键背9 小时前
display: none和visibility: hidden的区别
开发语言·前端·javascript
程楠楠&M10 小时前
node.js第三方Express 框架
前端·javascript·node.js·express
weiabc10 小时前
学习electron
javascript·学习·electron