最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在React中用canvas對圖片標注的實現(xiàn)

 更新時間:2022年05月17日 14:29:39   作者:大洋洋2020  
本文主要介紹了在React中用canvas對圖片標注的實現(xiàn) ,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

在審核業(yè)務(wù)中難免會有需要對圖片進行標注的需求,本次用一個最小demo來演示如何對圖片進行矩形標注。

首先我們要理解canvas是一塊畫布,而這塊畫布需要在我們要標注的圖片上層,圖片和canvas外層的div用相對位置,內(nèi)層的圖片和canvas用絕對位置,即可保證canvas重疊于圖片之上。如圖:

我們來看下canvas的初始化,在img、canvas中都有ref屬性,不同的是img的ref屬性直接就是一個useRef引用,而canvas中的ref是一個回調(diào)函數(shù)。它在組件被加載或卸載時會立即執(zhí)行,加載時ref回調(diào)接收當前組件實例作為參數(shù),卸載時ref回調(diào)接收null作為參數(shù)。在initCanvas函數(shù)中,用canvas的ref引用承接了canvas節(jié)點,并且通過drawImage函數(shù),初始化了一塊400*400的畫布,第一個參數(shù)為需要繪制到的上下文元素:

<img 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函數(shù)是為了添加標注位置信息。最需要注意的是我們在useEffect中所監(jiān)聽的三個函數(shù),startDraw、drawingDeal和drawingEnd。

鼠標落下時,startDraw為起始點的x,y坐標賦值,并且拖拽狀態(tài)位isDrawing置為true。鼠標移動時,drawingDeal函數(shù)會邊通過clearRect函數(shù)更新畫布,邊根據(jù)鼠標的最新位置通過highlightInvalid來更新標注,經(jīng)過確定矩形位置大小,內(nèi)容填充,描邊三個步驟來繪制出矩形。鼠標抬起時,drawingEnd函數(shù)會通過addInvalidLocation函數(shù)添加標注位置,然后初始化參數(shù)。

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來實現(xiàn)已經(jīng)標注過的矩形。

<div className="img-wrap">
    <img 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>

最后效果:

到此這篇關(guān)于在React中用canvas對圖片標注的實現(xiàn) 的文章就介紹到這了,更多相關(guān)React canvas對圖片標注內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于React動態(tài)加載路由處理的相關(guān)問題

    關(guān)于React動態(tài)加載路由處理的相關(guān)問題

    這篇文章主要介紹了關(guān)于React動態(tài)加載路由處理的相關(guān)問題,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • React+Redux實現(xiàn)簡單的待辦事項列表ToDoList

    React+Redux實現(xiàn)簡單的待辦事項列表ToDoList

    這篇文章主要為大家詳細介紹了React+Redux實現(xiàn)簡單的待辦事項列表ToDoList,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • React-Native中一些常用組件的用法詳解(二)

    React-Native中一些常用組件的用法詳解(二)

    這篇文章主要跟大家介紹了關(guān)于React-Native中一些常用組件的用法的相關(guān)資料,其中詳細介紹了關(guān)于ScrollView組件、ListView組件、Navigator組件、TableBarIOS組件以及網(wǎng)絡(luò)請求等相關(guān)內(nèi)容,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-06-06
  • React useEffect、useLayoutEffect底層機制及區(qū)別介紹

    React useEffect、useLayoutEffect底層機制及區(qū)別介紹

    useEffect 是 React 中的一個 Hook,允許你在函數(shù)組件中執(zhí)行副作用操作,本文給大家介紹React useEffect、useLayoutEffect底層機制及區(qū)別介紹,感興趣的朋友一起看看吧
    2025-04-04
  • react echarts刷新不顯示問題的解決方法

    react echarts刷新不顯示問題的解決方法

    最近在寫項目的時候遇到了一個問題,當編輯完代碼后echarts圖正常展示 , 可再次刷新頁面 , echarts會消失,所以本文給大家介紹了react echarts刷新不顯示問題原因和解決方法,需要的朋友可以參考下
    2024-02-02
  • React18中的useDeferredValue示例詳解

    React18中的useDeferredValue示例詳解

    這篇文章主要介紹了React18中的useDeferredValue的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-03-03
  • React?保留和重置State

    React?保留和重置State

    這篇文章主要為大家介紹了React?保留和重置State實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • React中useEffect原理的代碼簡單實現(xiàn)詳解

    React中useEffect原理的代碼簡單實現(xiàn)詳解

    React的useEffect鉤子是React函數(shù)組件中處理副作用,本文將通過一個簡單的例子解釋如何用代碼實現(xiàn)useEffect的基本原理,感興趣的小伙伴可以了解下
    2023-12-12
  • React中useState的理解和使用案例

    React中useState的理解和使用案例

    Hook是React16.8的新增特性,它可以讓你在不編寫class的情況下使用state以及其他的React特性,本文中講解的useState就是React中的其中一個Hook,這篇文章主要給大家介紹了關(guān)于React中useState理解和使用的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • 淺談React組件props默認值的設(shè)置

    淺談React組件props默認值的設(shè)置

    本文主要介紹了淺談React組件props默認值的設(shè)置,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04

最新評論

洛阳市| 嘉祥县| 辽阳县| 启东市| 会宁县| 中卫市| 金沙县| 东港市| 景德镇市| 图木舒克市| 盐池县| 梁山县| 边坝县| 石景山区| 浦北县| 进贤县| 如皋市| 苏尼特左旗| 抚州市| 凉城县| 宜兰市| 西充县| 邵阳县| 农安县| 洱源县| 大埔县| 大同市| 工布江达县| 通城县| 称多县| 津市市| 舟山市| 合山市| 乌拉特后旗| 赤壁市| 永靖县| 临安市| 蒙自县| 沽源县| 余姚市| 高密市|