效果圖
預覽連結 點選預覽
需求
- [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 相關知識:
- 清空畫布
ctx.clearRect(x,y,width,height)
; - 填充矩形
ctx.fillRect(x,y,width,height)
; - 繪製圓弧
ctx.arc(x,y,r,startAngle,endAngle,counterclockwise)
; 繪製矩形ctx.rect(x,y,width,height);
- 繪製影像 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)選擇的影像寬高 複製程式碼
- 剪裁圖片
ctx.clip()
;
具體步驟:
- 計算canvas寬高:(methods:calcCropperSize) 根據圖片大小,計算canvas寬高(data:cropperCanvasSize),以致圖片能夠在裁剪區域自適應展示,並確定裁剪的左上角位置(data:cropperLocation)。
- 繪製左側裁剪區域影像:(methods:renderCropperImg)
裁剪區域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) {
// ...
}
};
});
複製程式碼