vue實現
data () {
return {
// 馬賽克操作對象
mosaicObj: {
canvas: '', // 畫布
context: '', // canvas.context
quan: 1, // 畫筆大小
num: 9, // 一次操作包含馬賽克的個數
lastImgArr: [] // 歷史操作數組
}
}
},
// 馬賽克
mosaic () {
this.mosaicObj.canvas = $('#canvas')[0]
this.mosaicObj.context = this.mosaicObj.canvas.getContext('2d')
let imgObj = new Image()
imgObj.crossOrigin = 'Anonymous' // 用於解決圖片跨域問題
imgObj.src = img.src
// 待圖片加載完後,將其顯示在canvas上
imgObj.onload = () => {
// 設置模態框的寬度
$('#imgDialog').find('.el-dialog').css({width: `${imgObj.width + 100}px`})
this.mosaicObj.canvas.width = imgObj.width
this.mosaicObj.canvas.height = imgObj.height
this.mosaicObj.context.drawImage(imgObj, 0, 0)
// 監聽鼠標
this.start()
}
},
// 獲取坐標
getCoordinate (evt) {
// 點擊的坐標
let dx = evt.clientX - $('.el-dialog')[0].offsetLeft
let dy = evt.clientY - $('.el-dialog')[0].offsetTop + $('#imgDialog').scrollTop()
return { dx, dy }
},
// 監聽鼠標事件
start () {
let { canvas, context, quan, num, lastImgArr } = this.mosaicObj
canvas.onmousedown = (ev) => {
// 每次下筆前先保存
lastImgArr.push(context.getImageData(0, 0, canvas.width, canvas.height))
let evt = ev || window.event
// 點擊的坐標
let { dx, dy } = this.getCoordinate(evt)
// 繪製馬賽克
this.drawLine(dx, dy, canvas, context, quan, num)
document.onmousemove = (ev) => {
let sEvt = ev || window.event
let mx = this.getCoordinate(sEvt).dx
let my = this.getCoordinate(sEvt).dy
// (quan*馬賽克個數*2)的平方
if (Math.pow(dx - mx, 2) + Math.pow(dy - my, 2) >= Math.pow(quan * num, 2)) {
this.drawLine(dx, dy, canvas, context, quan, num)
dx = mx
dy = my
}
}
// 銷毀事件
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
}
}
},
// 繪製馬賽克
drawLine (dx, dy, canvas, context, quan, num) {
// 原始圖像
let originalImgData = context.getImageData(0, 0, canvas.width, canvas.height)
let originalPxData = originalImgData.data
// 用於循環修改
let modifyImgData = context.getImageData(0, 0, canvas.width, canvas.height)
let modifyPxData = modifyImgData.data
for (let i = dx - quan * num; i < dx + quan * num; i = i + 2 * quan + 1) {
for (let j = dy - quan * num; j < dy + quan * num; j = j + 2 * quan + 1) {
// 中心點(dx,dy)
let sumR = 0
let sumG = 0
let sumB = 0
// 找他周圍的元素
for (let x = -quan; x <= quan; x++) {
for (let y = -quan; y <= quan; y++) {
let xx = i + x
let yy = j + y
let pp = yy * canvas.width + xx // 周圍的元素
sumR += originalPxData[pp * 4 + 0]
sumG += originalPxData[pp * 4 + 1]
sumB += originalPxData[pp * 4 + 2]
}
}
// 獲取rgb平均值
let totlal = (2 * quan + 1) * (2 * quan + 1)
let avgR = sumR / totlal
let avgG = sumG / totlal
let avgB = sumB / totlal
// 將點擊周圍填充
for (let sx = -quan; sx <= quan; sx++) {
for (let sy = -quan; sy <= quan; sy++) {
let sxx = i + sx
let syy = j + sy
let spp = syy * canvas.width + sxx // 周圍的元素
modifyPxData[spp * 4 + 0] = avgR
modifyPxData[spp * 4 + 1] = avgG
modifyPxData[spp * 4 + 2] = avgB
}
}
}
}
context.putImageData(modifyImgData, 0, 0, 0, 0, canvas.width, canvas.height)
}