js馬賽克

參考1 參考2 參考3 參考4 參考5

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)
            }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章