vue 實現剪裁圖片並上傳伺服器

phoebeCodeSpace發表於2018-02-28

效果圖

預覽連結 點選預覽

cropper

需求

  • [x] 預覽:根據選擇影象大小自適應填充左側裁剪區域
  • [x] 裁剪:移動裁剪框右側預覽區域可實時預覽
  • [x] 上傳&清空:點選確認上傳裁剪圖片,點選取消按鈕清空影象
  • [ ] 裁剪框可調節大小

實現步驟

methods:funName() - 對應原始碼中methods中的funName方法

data:dataName - 對應原始碼中data中的dataName資料

1. 圖片選擇與讀取

  • 選擇圖片:(methods:selectPic) 使用input[type="file"]彈出選擇圖片框,js 主動觸發點選事件;
  • 讀取圖片: (methods:readImage) 建立圖片物件,使用createObjectURL顯示圖片。 objectURL = URL.createObjectURL(blob);

2. 在canvas中展示圖片

需要掌握的 canvas 相關知識:

  1. 清空畫布 ctx.clearRect(x,y,width,height);
  2. 填充矩形 ctx.fillRect(x,y,width,height);
  3. 繪製圓弧 ctx.arc(x,y,r,startAngle,endAngle,counterclockwise); 繪製矩形 ctx.rect(x,y,width,height);
  4. 繪製影象 drawImage
    drawImage
        # 語法
        ctx.drawImage(image, dx, dy);
        ctx.drawImage(image, dx, dy, dWidth, dHeight);
        ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
        # 引數
        image                # 繪製的元素(可以為HTMLImageElement,HTMLVideoElement,或者 HTMLCanvasElement。)
        dx,dy                # 目標畫布(destination canvas)左上角的座標
        dWidth,dHeight       # 目標畫布(destination canvas)上繪製影象寬高
        sx,sy                # 源畫布(source canvase)左上角的座標
        sWidth,sHeight       # 源畫布(source canvase)選擇的影象寬高
    複製程式碼
  5. 剪裁圖片 ctx.clip();

具體步驟:

  • 計算canvas寬高:(methods:calcCropperSize) 根據圖片大小,計算canvas寬高(data:cropperCanvasSize),以致圖片能夠在裁剪區域自適應展示,並確定裁剪的左上角位置(data:cropperLocation)。
  • 繪製左側裁剪區域影象:(methods:renderCropperImg)

裁剪區域vue data示意圖:

vue data

  • 繪製右側預覽圖片:(methods:renderPreviewImg)

3. 移動裁剪框

知識點: onmousedown、onmousemove、onmouseup

具體實現:

methods:drag()

記錄滑鼠座標,滑鼠移動根據偏移量計算圓心位置。

      canvas.onmousedown = e => {
        let [lastX, lastY] = [e.offsetX, e.offsetY];
        self.movement = true;
        canvas.onmousemove = e => {
          self.circleCenter = {
            X:
              self.cropperCanvasSize.width > 2 * self.slectRadius
                ? self.circleCenter.X + (e.offsetX - lastX)
                : self.cropperCanvasSize.width / 2,
            Y:
              self.cropperCanvasSize.height > 2 * self.slectRadius
                ? self.circleCenter.Y + (e.offsetY - lastY)
                : self.cropperCanvasSize.height / 2
          };
          self.renderCropperImg();
          [lastX, lastY] = [e.offsetX, e.offsetY];
        };
        canvas.onmouseup = e => {
          self.movement = false;
          canvas.onmousemove = null;
          canvas.onmouseup = null;
        };
      };
複製程式碼

4. 上傳圖片至伺服器

知識點:

具體實現:

methods:upload()

      this.$refs.preview.toBlob((blob)=> {
        const url = URL.createObjectURL(blob);
        const formData = new FormData();
        formData.append(this.uploadProps.name, blob, `${Date.now()}.png`);
        if(this.data){
            Object.keys(this.uploadProps.data).forEach(key => {
                formData.append(key, this.uploadProps.data[key]);
            });
        }
        const request = new XMLHttpRequest();
        request.open("POST", this.uploadProps.action, true);
        request.send(formData);

        request.onreadystatechange = () => {
          if (request.readyState === 4 && request.status === 200) {
                // ...
          }
        };
      });
複製程式碼

原始碼地址 原文連結

相關文章