首頁 > 軟體

Vue實現簡單基礎的圖片裁剪功能

2022-09-18 22:00:33

近日,在寫公司專案的時候接到一個需求:對已載入的大圖中可擷取部分圖片用來入庫或者布控,說白了就是截圖嘛,於是我使用了vue-cropper來完成。完成後因為前邊也沒自己實現過,所以就想看看是如何實現的。因此本文寫的是最簡易基礎的實現方法用作學習,肯定有考慮不周的地方,還請大家諒解。工作中還是使用成熟的輪子為好。

一、準備工作

本文中我所使用的環境為vue2 。現在可以在隨便一個vue專案中新建一個vue檔案開始了。

二、基本結構

在本文中會使用到兩個canvas,一個用來繪製我們要載入的圖片,一個用來繪製矩形框選區域,就像下面這樣,並且在兩個canvas身上分別加上ref屬性。

html

<template>
  <div>
    <div class="wrap">
      <canvas id="canvas" ref="imgCanvas"></canvas>
      <canvas
        id="drawCanvas"
        ref="drawCanvas"
      ></canvas>
    </div>
  </div>
</template>

下方樣式設定兩個canvas重疊

<style>
#drawCanvas {
  position: absolute;
  top: 0;
  left: 0;
}
.wrap {
  position: relative;
}
</style>

三、新增功能

首先我們需要將兩個canvas的寬高都設定為相同的,由於上面沒有設定canvas的寬高,因此我們在data選項中新增好需要的寬高資料 width: 500,height: 300,稍後將它設定為canvas的大小,請記住,不要用css設定canvas的大小,這其實是將canvas拉伸了。然後在data中新增 ctx 和 imgCtx兩個屬性用於儲存上下文。 接著在mounted生命週期中對canvas進行操作,並且獲取到要載入的圖片

    let imgCanvas = this.$refs.imgCanvas;//繪製圖片的canvas
    let drawCanvas = this.$refs.drawCanvas;//繪製框選款的canvas
    //設定兩個canvas的寬高
    imgCanvas.width = this.width;
    imgCanvas.height = this.height;
    drawCanvas.width = this.width;
    drawCanvas.height = this.height;
    //獲取兩個canvas的上下文並且儲存在data中
    this.ctx = drawCanvas.getContext("2d");
    this.imgCtx = imgCanvas.getContext("2d");
    //載入圖片
    let img = new Image();
    img.src = "https://www.auok.ltd/background.jpg";
    img.crossOrigin = "anonymous";
    img.onload = () => {
      console.log("載入完成", img);
      //圖片載入完成後開始繪製圖片
      this.imgCtx.drawImage(img, 0, 0, this.width, this.height);
    };

以上步驟搞定後現在的頁面中應該如下面一樣了

接下來讓我們給drawCanvas新增事件監聽。需要監聽的事件有以下幾個

  • 滑鼠按下
  • 滑鼠擡起
  • 滑鼠移動
  • 滑鼠移出

我們來改寫一下模板結構,像下面這樣

<template>
  <div>
    <div class="wrap">
      <canvas id="canvas" ref="imgCanvas"></canvas>
      <canvas
        id="drawCanvas"
        ref="drawCanvas"
        @mousedown="onMouseDown"
        @mousemove="onMouseMove"
        @mouseup="onMouseUp"
        @mouseleave="onMouseLeave"
      ></canvas>
    </div>
    <img :src="curSrc" alt="" style="margin: 10px 10px 0 0" />
    <canvas id="outCanvas"></canvas>
  </div>
</template>

然後在methods中新增對應的onMouseDown、onMouseUp、onMouseMove、onMouseLeave四個方法。然後我們來編寫這四個方法就好

onMouseDown

這個方法是滑鼠按下事件的監聽處理常式。主要負責以下幾點

  • 清除drawCanvas
  • 獲取滑鼠按下時的位置
  • 設定一下繪製線條的樣式

程式碼如下: 編寫這個方法前我們要現在data中增加ddownPoint和down兩個屬性用來儲存點的位置標識滑鼠是否按下

 onMouseDown(e) {
      console.log("滑鼠按下", e.offsetX, e.offsetY);
      this.downPoint = [e.offsetX, e.offsetY];
      this.down = true;
      this.ctx.strokeStyle = "#fff";
      this.ctx.lineWidth = 2;
    }

onMouseMove

滑鼠按下了,下面就要移動了。此方法是滑鼠移動的監聽處理常式。負責以下幾點

  • 獲取滑鼠移動的位置
  • 繪製矩形選框
  • 繪製遮罩層
   onMouseMove(e) {
   //滑鼠未按下不執行操作
      if (!this.down) {
        return;
      }
    console.log("滑鼠移動", e.offsetX, e.offsetY);
    //當前滑鼠移動的位置
    let movePoint = [e.offsetX, e.offsetY];
      this.ctx.fillStyle = "rgba(0,0,0,.5)";//設定遮罩層填充顏色
      //清空drawCanvas
      this.ctx.clearRect(0, 0, this.width, this.height);
      //使用設定的填充顏色來設定drawCanvas的顏色
      this.ctx.fillRect(0, 0, this.width, this.height);
      //清除指定區域的顏色,因為需要繪製的選框中間是沒有顏色的,不然的話選框區域都是遮罩層的顏色。如下圖
      this.ctx.clearRect(
        downPoint[0],
        downPoint[1],
        movePoint[0] - this.downPoint[0],
        movePoint[1] - this.downPoint[1]
      );
      //繪製描邊矩形 四個引數是x座標 , y座標 , 矩形的長,矩形的寬
      this.ctx.strokeRect(
        downPoint[0],
        downPoint[1],
        movePoint[0] - this.downPoint[0],
        movePoint[1] - this.downPoint[1]
      );
    },

onMouseUp

這個方法是滑鼠鬆開按鍵的事件處理常式,主要負責

  • 獲取滑鼠鬆開的座標
  • 獲取框選部分的圖片 上面的步驟中截圖區域已經選擇完成。接下來就是要獲取截圖部分的圖片了。

程式碼如下

    onMouseUp(e) {
        console.log("滑鼠擡起", e.offsetX, e.offsetY);
        //獲取座標
        let upPoint = [e.offsetX, e.offsetY];
        //重置滑鼠按下狀態
        this.down = false;
        //獲取指定區域的圖片資料
        let cutImgData = this.imgCtx.getImageData(
          this.downPoint[0],
          this.downPoint[1],
          upPoint[0] - this.downPoint[0],
          upPoint[1] - this.downPoint[1]
        );
        //獲取返回的圖片資料中的寬高
        let { width, height } = cutImgData;
        console.log(cutImgData);
        //建立一個用於放置圖片的canvas用來輸出圖片
        let outCanvas = document.createElement("canvas");
        let outCtx = outCanvas.getContext("2d");
        outCanvas.height = height;
        outCanvas.width = width;
        //將圖片放置到canvas上
        outCtx.putImageData(cutImgData, 0, 0);
        //以blob的形式輸出圖片
        outCanvas.toBlob((blob) => {
          this.curSrc = URL.createObjectURL(blob);
    }

通過呼叫getImageData獲取了圖片指定區域的資料,然後將獲取到的圖片資料使用putImageData放到建立好的canvas中,再通過canvas的toBlob或者toDataURL方法就可以輸入圖片的二進位制資料或者base64字串了,這裡我用的是blob,再通過URL.createObjectURL獲取到圖片的本地地址,這種形式:blob:http://localhost:8080/e835d581-cdfe-48ff-b562-743bfcd4970d,可以用來顯示或者上傳。 在模板中新增一個img標籤,並且在data中新增cruSrc屬性,最後就如下圖

  <img :src="curSrc" alt="" style="margin: 10px 10px 0 0" />

onMouseLeave

這個方法是在滑鼠移出canvas區域後重置canvas的狀態的。將滑鼠狀態down重置為false,然後再清除canvas。

四、總結

如果要實際的實現一個和vue-cropper功能差不多的是比較複雜,要考慮很多東西,比如影象的縮放比例、選框的移動及大小調整之類的。這些部分還沒有寫。

以上就是Vue實現簡單基礎的圖片裁剪功能的詳細內容,更多關於Vue圖片裁剪的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com