移動端上傳圖片進行平移放大縮小操作後生成海報

我是大哥的女朋友發表於2018-08-16

使用vue+html2canvas+exif-js
github地址
線上demo

主要功能

  • 上傳圖片
  • 對圖片進行操作:移動、放大、縮小
  • 合成海報

具體功能:

上傳圖片

html:

<input type="file" value="" accept="image/*" @click="getPhoto" id="image-input">
複製程式碼

js

getPhoto () {
    var imageInput = document.querySelector('#image-input')
    var that = this
    imageInput.addEventListener('change', function (e) {
        reads = new FileReader()
        reads.readAsDataURL(this.files[0])
        reads.addEventListener('load', function (e) {
            that.imgUrl = this.result
            that.myImg.position.x = 0
            that.myImg.position.y = 0
            that.myImg.scale = 1
            var orientation
            that.previewImg.addEventListener('load', function () {
                Exif.getData(that.previewImg, function() { // 獲取影象的資料
                Exif.getAllTags(this); // 獲取影象的全部資料,值以物件的方式返回
                orientation = Exif.getTag(this, "Orientation"); // 獲取影象的拍攝方向
                var rotateCanvas = document.createElement("canvas"),
                rotateCtx = rotateCanvas.getContext("2d");
                 // 針對影象方向進行處理
                switch (orientation) {
                    case 1 :
                        rotateCanvas.width = that.previewImg.width;
                        rotateCanvas.height = that.previewImg.height;
                        rotateCtx.drawImage(that.previewImg, 0, 0, that.previewImg.width, that.previewImg.height);
                        break;
                    case 6 : // 順時針 90 度
                        rotateCanvas.width = that.previewImg.height;
                        rotateCanvas.height = that.previewImg.width;
                        rotateCtx.translate(0, 0);
                        rotateCtx.rotate(90 * Math.PI / 180);
                        rotateCtx.drawImage(that.previewImg, 0, -that.previewImg.height, that.previewImg.width, that.previewImg.height);
                        break;
                    case 8 :
                        rotateCanvas.width = that.previewImg.height;
                        rotateCanvas.height = that.previewImg.width;
                        rotateCtx.translate(0, 0);
                        rotateCtx.rotate(-90 * Math.PI / 180);
                        rotateCtx.drawImage(that.previewImg, -that.previewImg.width, 0, that.previewImg.width, that.previewImg.height);
                        break;
                    case 3 : // 180 度
                        rotateCanvas.width = that.previewImg.width;
                        rotateCanvas.height = that.previewImg.height;
                        rotateCtx.translate(0, 0);
                        rotateCtx.rotate(Math.PI);
                        rotateCtx.drawImage(that.previewImg, -that.previewImg.width, -that.previewImg.height, that.previewImg.width, that.previewImg.height);
                        break;
                    default :
                        rotateCanvas.width = that.previewImg.width;
                        rotateCanvas.height = that.previewImg.height;
                        rotateCtx.drawImage(that.previewImg, 0, 0, that.previewImg.width, that.previewImg.height);
                    }
                    var rotateBase64 = rotateCanvas.toDataURL("image/jpeg", 0.5);
                });
            })
        }) 
    })
}
複製程式碼

移動圖片

對圖片和相框繫結@touchstart @touchmove @touchend

getInitPosition (e) {
    event.preventDefault()
    if (this.imgUrl) {
        var length = e.touches.length
         if (length > 1) {
            let pointOne = e.touches[0]
            let pointTwo = e.touches[1]
            this.initTouchX = pointOne.clientX - pointTwo.clientX
            this.initTouchY = pointOne.clientY - pointTwo.clientY
        } else {
            var touches = e.touches[0]
            this.initTouchX = touches.clientX
            this.initTouchY = touches.clientY
        }   
    }
},
 getMovePosition (e) {
    event.preventDefault()
    if (this.imgUrl) {
        var length = e.touches.length
        if (length > 1) {
            let pointOne = e.touches[0]
            let pointTwo = e.touches[1]
            this.changeTouchX = pointOne.clientX - pointTwo.clientX
            this.changeTouchY = pointOne.clientY - pointTwo.clientY
            var scale = (this.changeTouchX - this.initTouchX) > (this.changeTouchY - this.initTouchY) ? (this.changeTouchX / this.initTouchX) : (this.changeTouchY / this.initTouchY) 
            scale *= this.myImg.lastScale
            this.myImg.scale = scale > 3 ? 3 : scale < 0.5 ? 0.5 : scale
        } else {
            var touches = e.touches[0]
            this.changeTouchX = touches.clientX - this.initTouchX
            this.changeTouchY = touches.clientY - this.initTouchY
            this.myImg.position.x = this.lastTouchX + (this.changeTouchX / this.myImg.scale)
            this.myImg.position.y = this.lastTouchY + (this.changeTouchY / this.myImg.scale)
        }   
    }
},
getLeavePosition (e) {
    this.myImg.lastScale = this.myImg.scale
    if (e.touches.length > 0) {
        var touches = e.touches[0]
        this.initTouchX = touches.clientX
        this.initTouchY = touches.clientY
    }
    this.lastTouchX = this.myImg.position.x
    this.lastTouchY = this.myImg.position.y
},
複製程式碼

合成圖片

createPhoto () {
    if (this.imgUrl) {
        let photoBox = document.querySelector('.photo-box')
        newImgWidth = photoBox.style.offsetWidth
        let newImgHeight = photoBox.style.offsetHeight
        let scale = window.devicePixelRatio
        let that = this
        html2canvas(photoBox, {
            width: newImgWidth,
            height: newImgHeight,
            scale: scale,
            useCORS: true
        }).then(function (canvas) { 
            var dataUrl = canvas.toDataURL('image/jpg')
            localStorage.imgData = dataUrl
            that.$router.push({
                name: 'share',
                params: {
                    storage: 'imgData'
                }
            })
        })
    } else {
        alert('請上傳圖片')
    }
}
複製程式碼

遇到的問題

  1. 在瀏覽器上阻止縮放的問題
    在tounchmove時使用event.preventDefault()
  2. 合成圖片的清晰度 在html2canvas寫引數時,scale = window.devicePixelRatio
  3. 對圖片進行縮放時,對距離的判斷
    這裡需要區分兩種情況:
    • 兩指縮放
    • 一指移動
      在兩指縮放後會有一個手放手另一個手繼續操作的情況。這樣在touchend時,e.touches還存在一個元素。所以需要在這裡做一個判斷。
  4. 使用vue的:style="內聯樣式"時遇上的寫法問題
    :style="{transform:'scale('+ myImg.scale+ ') translate('+myImg.position.x+'px,'+myImg.position.y+'px)'}"
    複製程式碼

相關文章