我的编程空间,编程开发者的网络收藏夹
学习永远不晚

在React中用canvas对图片标注的实现

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

在React中用canvas对图片标注的实现

在审核业务中难免会有需要对图片进行标注的需求,本次用一个最小demo来演示如何对图片进行矩形标注。

首先我们要理解canvas是一块画布,而这块画布需要在我们要标注的图片上层,图片和canvas外层的div用相对位置,内层的图片和canvas用绝对位置,即可保证canvas重叠于图片之上。如图:

我们来看下canvas的初始化,在img、canvas中都有ref属性,不同的是img的ref属性直接就是一个useRef引用,而canvas中的ref是一个回调函数。它在组件被加载或卸载时会立即执行,加载时ref回调接收当前组件实例作为参数,卸载时ref回调接收null作为参数。在initCanvas函数中,用canvas的ref引用承接了canvas节点,并且通过drawImage函数,初始化了一块400*400的画布,第一个参数为需要绘制到的上下文元素:

<img class="lazy" data-src={lancome} ref={imgInstance} className="App-logo" alt="logo" />
<canvas className="canvas" ref={initCanvas} width="400px" height="400px" />
const canvasRef = useRef(null);
const imgInstance = useRef(null);

const initCanvas =  useCallback((node) => {
      canvasRef.current = node;
      const context = node.getContext('2d');
      context.drawImage(imgInstance.current, 0, 0, 400, 400);
  }, []);

接下来,我们通过invalidLocations来保存之前的标注位置信息,addInvalidLocation函数是为了添加标注位置信息。最需要注意的是我们在useEffect中所监听的三个函数,startDraw、drawingDeal和drawingEnd。

鼠标落下时,startDraw为起始点的x,y坐标赋值,并且拖拽状态位isDrawing置为true。鼠标移动时,drawingDeal函数会边通过clearRect函数更新画布,边根据鼠标的最新位置通过highlightInvalid来更新标注,经过确定矩形位置大小,内容填充,描边三个步骤来绘制出矩形。鼠标抬起时,drawingEnd函数会通过addInvalidLocation函数添加标注位置,然后初始化参数。

const [invalidLocations, setInvalidLocations] = useState([]);

const addInvalidLocation = useCallback((newMark) => {
    setInvalidLocations([...invalidLocations, newMark]);
}, [invalidLocations])

const highlightInvalid = (context, x1, y1, x2, y2) => {
    context.beginPath();
    context.rect(x1, y1, x2 - x1, y2 - y1);
    context.fillStyle = 'rgba(255, 0, 0, 0.2)';
    context.fill();
    context.strokeStyle = '#FF0070';
    context.lineWidth = 1;
    context.stroke();
    console.log('drawing', x2, y2);
};

const clearRect = (drawContext) => {
    drawContext.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height);
};

useEffect(() => {
    const canvasElem = canvasRef.current;
    let x = 0; let y = 0;
    let isDrawing = false;
    const drawContext = canvasRef.current.getContext('2d');
    let canvasRect;
    const lastCursorPosition = {
      x: 0,
      y: 0,
    };
    const startDraw = (e) => {
      console.log(e.type, 'start');
      canvasRect = canvasRef.current.getBoundingClientRect();
      x = e.clientX - canvasRect.left;
      y = e.clientY - canvasRect.top;
      if (x < 0) x = 0;
      if (y < 0) y = 0;
      isDrawing = true;
    };
    const drawingDeal = (e) => {
      console.log(e.type, 'move');
      if (isDrawing) {
        const x1 = e.clientX - canvasRect.left;
        const y1 = e.clientY - canvasRect.top;
        clearRect(drawContext);
        highlightInvalid(drawContext, x, y, x1, y1);
        lastCursorPosition.x = x1;
        lastCursorPosition.y = y1;
      }
    };
    const drawingEnd = () => {
      if (isDrawing) {
        if (lastCursorPosition.x && lastCursorPosition.y) {
          const width = lastCursorPosition.x - x + 1;
          const height = lastCursorPosition.y - y + 1;
          addInvalidLocation({ x, y, width, height });
          lastCursorPosition.x = 0;
          lastCursorPosition.y = 0;
        }
        clearRect(drawContext);
        isDrawing = false;
        x = 0;
        y = 0;
      }
    };
    canvasElem.addEventListener('mousedown', startDraw);
    canvasElem.addEventListener('mousemove', drawingDeal);
    canvasElem.addEventListener('mouseup', drawingEnd);
    return () => {
      canvasElem.removeEventListener('mousedown', startDraw);
      canvasElem.removeEventListener('mousemove', drawingDeal);
      canvasElem.removeEventListener('mouseup', drawingEnd);
    };
}, [invalidLocations, addInvalidLocation]);

在添加完标注位置之后,模板中我们通过迭代返回绝对定位的div来实现已经标注过的矩形。

<div className="img-wrap">
    <img class="lazy" data-src={lancome} ref={imgInstance} className="App-logo" alt="logo" />
    <canvas className="canvas" ref={initCanvas} width="400px" height="400px" />
    {invalidLocations && invalidLocations.map((location, index) => { 
        const { width, height, x, y } = location;
            return <div
                     key={`${width}_${height}_${x}_${y}`}
                     tabIndex={-1}
                     className={'remark'}
                     style={{ width: `${width}px`, height: `${height}px`, left: `${x}px`, top: `${y}px` }}
            ></div>
    })}
</div>

最后效果:

到此这篇关于在React中用canvas对图片标注的实现 的文章就介绍到这了,更多相关React canvas对图片标注内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

在React中用canvas对图片标注的实现

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在html5中使用canvas实现柱状图

这篇文章给大家介绍怎么在html5中使用canvas实现柱状图,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。使用方式首先我们看一下使用方式,参考了部分ECharts的使用方式,先传入要显示图表的html标签,接着调用i
2023-06-09

JavaScript利用canvas实现炫酷的碎片切图效果

这篇文章主要和大家分享一个炫酷的碎片式切图效果,本文主要利用canvas来实现,代码量不多,但有些地方还是需要花点时间去理解的,感兴趣的可以学习一下
2022-11-13

DW实现鼠标放在图片上就换另一个图片的功能

本篇内容介绍了“DW实现鼠标放在图片上就换另一个图片的功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Dw是我们设计网页的软件,这个软件功
2023-06-08

怎么在html2中使用canvas生成一个清晰的图片

怎么在html2中使用canvas生成一个清晰的图片?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。基本用法window.html2canvas(dom, {
2023-06-09

C#怎么实现获取Excel中图片所在坐标位置

本文小编为大家详细介绍“C#怎么实现获取Excel中图片所在坐标位置”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#怎么实现获取Excel中图片所在坐标位置”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。【程序
2023-06-30

html2中canvas如何生成清晰的图片实现打印功能

小编给大家分享一下html2中canvas如何生成清晰的图片实现打印功能,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!基本用法window.html2canvas(dom, { scale: scale,
2023-06-09

在html中实现图片排版的方法

这篇文章将为大家详细讲解有关在html中实现图片排版的方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在html中实现图片排版的方法:首先新建文件,并建立盒子;然后设置图片盒子,使用p标签来区别段落;接
2023-06-06

vue怎么使用js对图片进行点击标注圆点并记录它的坐标

这篇文章主要介绍“vue怎么使用js对图片进行点击标注圆点并记录它的坐标”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“vue怎么使用js对图片进行点击标注圆点并记录它的坐标”文章能帮助大家解决问题。
2023-06-30

autojs长宽不定的图片在正方形图片居中实现详解

这篇文章主要为大家介绍了autojs长宽不定的图片在正方形图片居中实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-31

编程热搜

目录