Using html2canvas to upload pictures to generate posters

Posted by libertyct on Fri, 08 Nov 2019 19:14:40 +0100

Link: Link description
Using Vue + html2canvas + EXIF JS
github address
Online demo

major function

  • Upload pictures
  • Operate on pictures: move, enlarge and shrink
  • Synthetic Poster

Specific functions:

Upload pictures

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() { // Get image data
                Exif.getAllTags(this); // Get all the data of the image, and the value is returned as an object
                orientation = Exif.getTag(this, "Orientation"); // Obtain the shooting direction of the image
                var rotateCanvas = document.createElement("canvas"),
                rotateCtx = rotateCanvas.getContext("2d");
                 // Processing for image direction
                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 degrees clockwise
                        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 degrees
                        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);
                });
            })
        }) 
    })
}

Mobile pictures

Bind @ touchstart @ touchmove @ touchend to pictures and frames

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

Composite picture

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('Please upload the picture')
    }
}

Problems encountered

1) prevent scaling on Browser

Use event.preventDefault() when tounchmove

2) sharpness of composite pictures

When html2canvas writes parameters, scale = window.devicePixelRatio

3) judge the distance when zooming the picture

There are two situations that need to be distinguished:
-Two finger zoom
 -One finger move  
After two finger scaling, one hand will let the other hand continue to operate. In this way, at touchend, there is an element in e.touches. So we need to make a judgment here.

4) writing problems when using vue's: style = "inline style"

:style="{transform:'scale('+ myImg.scale+ ') translate('+myImg.position.x+'px,'+myImg.position.y+'px)'}"

5) there is a problem with the direction of the pictures taken directly by using the mobile phone

Topics: Javascript Vue Mobile github