基于canvas的图片方向矫正、压缩、上传、合成

在这次项目中,我们需要这样一个应用场景。在手机里选择一张图片,并和明星图片合成。

  • 难点1:ios下部分图片实际方向和预览方向不一直,需要先矫正方向
  • 难点2:图片过大,实际用来合成的图片需要压缩
  • 难点3:图片需要通过手指的滑动,进行位移,缩放
  • 难点4:调整好图片位置后需要与指定图片和文字进行合成

选择图片后

document.getElementById("file").addEventListener("change", function () {
    var file = this.files[0];
    $(this).data('file', selfImg);
    this.value = "";
    //判断是否是图片类型
    if (!/image\/\w+/.test(file.type)) {
        alert("只能选择图片");
        return false;
    }
    $("#mask-msg").html("上传中");
    $(".loading").show();
    //图片旋转
    //图片压缩
    //图片上传
    
})
    
复制代码

解决难点1: 页面head间引入

<script src="https://cdn.bootcss.com/exif-js/2.2.1/exif.min.js"></script>
复制代码
function rotate(file, callback) {
    console.time('rotate');
    console.log('loading-start');


    window.EXIF.getData(file, function () {
        window.EXIF.getAllTags(this);
        var orientation = window.EXIF.getTag(this, 'Orientation');
        console.log('loading-end');
        // alert('loading-end');
        console.log(orientation);
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function (e) {
            var image = new Image();
            image.src = e.target.result;
            image.onload = function () {
                var height = this.height, width = this.width;
                var max = Math.max(height, width);
                if (max > 800 && max < 1500) {
                    max /= 2;
                    height /= 2;
                    width /= 2;
                }
                if (max > 1500 && max < 2500) {
                    max /= 3;
                    height /= 3;
                    width /= 3;
                }
                if (max > 2500) {
                    max /= 4;
                    height /= 4;
                    width /= 4;
                }

                var angel = 0;
                if (1 == orientation) {
                    angel = 0;
                }
                else if (6 == orientation) {
                    //6旋转90
                    angel = 90;
                }
                else if (3 == orientation) {
                    //3旋转180
                    angel = 180;
                }
                else if (8 == orientation) {
                    //8旋转90
                    angel = 270;
                }

                var canvas1 = document.createElement('canvas');
                canvas1.setAttribute("height", max);
                canvas1.setAttribute("width", max);
                canvas1.style.width = '100%';
                var ctx1 = canvas1.getContext('2d');

                ctx1.translate(max / 2, max / 2);
                ctx1.rotate(angel * Math.PI / 180);
                ctx1.translate(-max / 2, -max / 2);
                ctx1.drawImage(this, 0, 0, width, height);


                var x = 0, y = 0, w = width, h = height;
                if (orientation == 6 || orientation == 8) {
                    x = max - height;
                    y = max - width;
                    w = height;
                    h = width;
                }
                var imageData = ctx1.getImageData(x, y, w, h);
                var canvas2 = document.createElement('canvas');
                canvas2.setAttribute("height", h);
                canvas2.setAttribute("width", w);
                canvas2.style.width = '100%';
                var ctx2 = canvas2.getContext('2d');
                ctx2.putImageData(imageData, 0, 0);

                var reImg = new Image();
                reImg.src = canvas2.toDataURL("image/png");
                reImg.onload = function () {
                    callback && callback(reImg);
                    console.timeEnd('rotate');
                }
            }
        };
    });
}

复制代码

解决难点2

function compress(src, callback) {
    var img = new Image();
    img.src = src;
    img.onload = function () {
        //等比缩放图片达到缩小文件的目的
        var width = 1000;
        if (img.height > width) {
            var height = img.height * (width / img.width);
            img.width = width;
            img.height = height;
        }
        var canvas = document.createElement('canvas');
        canvas.setAttribute('height', img.height);
        canvas.setAttribute('width', img.width);
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, img.width, img.height);

        var dataURL = canvas.toDataURL();
        // var blod = this.dataURLtoBlob(dataURL);
        callback && callback(dataURL);
    };
}

复制代码

上传七牛 页面的head间引入

 <script src="https://cdn.staticfile.org/qiniu-js-sdk/1.0.14-beta/qiniu.js"></script>
复制代码
function dataURLtoBlob(dataurl) {
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: mime });
}

function uploadFile(pic, cb) {
 


    var url = "https://upload-z2.qbox.me";
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open('POST', url, true);
    xmlHttp.setRequestHeader('X-Qiniu-Performance', 'true');
    xmlHttp.onreadystatechange = function () {
        if (xmlHttp.readyState == 4) {

            cb(qiniu.domain + JSON.parse(xmlHttp.responseText).key);
            console.log(qiniu.domain + JSON.parse(xmlHttp.responseText).key);
           
        }
    };
    var f = new FormData();
    var blob = dataURLtoBlob(pic);
    console.log(blob);
    f.append('file', blob);
    f.append('token', qiniu.uptoken);
    xmlHttp.send(f);

  

}

复制代码

解决难点3 在页面head中需要引入


    <script src="https://cdn.bootcss.com/hammer.js/2.0.8/hammer.min.js"></script>

复制代码
var selfImg = {
    height: 0,
    width: 0,
    index: 0,
    times: 2,
    top: 0,
    left: 0,
    defaultHeight: parseInt($img.css('height')),
    boxHeight: parseInt($box.css('height')),
    boxWidth: parseInt($box.css('width'))
}, selfLogo = {
    height: 0,
    width: 0,
    index: 0,
    times: 2,
    top: 0,
    left: 0,
    defaultHeight: parseInt($img.css('height')),
    boxHeight: parseInt($box.css('height')),
    boxWidth: parseInt($box.css('width'))
}, saveData = {};
var first = true;
var hammer = new Hammer(document.getElementById("self"));
hammer.get('pinch').set({ enable: true });
hammer.get('rotate').set({ enable: true });
hammer.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammer.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });

hammer.on('panstart', function (ev) {
    createImg(selfImg, $img);
    selfImg.imgX = ev.deltaX;
    selfImg.imgY = ev.deltaY;
});
hammer.on('panmove', function (ev) {
    if (first) {
        selfImg.left -= selfImg.imgX - ev.deltaX;
        selfImg.top -= selfImg.imgY - ev.deltaY;
        moveImg($img, selfImg);
        selfImg.imgX = ev.deltaX;
        selfImg.imgY = ev.deltaY;
    }
});
hammer.on('panend', function (ev) {
    initImg(selfImg, $img);
});

hammer.on('pinchstart', function (ev) {
    createImg(selfImg, $img);
});
hammer.on('pinchin', function (ev) {
    if (selfImg.index % 2 == 0) {
        pinchImg(ev, selfImg, $img);
    }
    selfImg.index++;
});
hammer.on('pinchout', function (ev) {
    if (selfImg.index % 2 == 0) {
        pinchImg(ev, selfImg, $img);
    }
    selfImg.index++;
});
hammer.on('pinchend', function (ev) {
    initImg(selfImg, $img);
});


var hammerLogo = new Hammer(document.getElementById("self-logo"));
hammerLogo.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammerLogo.get('swipe').set({ direction: Hammer.DIRECTION_VERTICAL });
hammerLogo.on('panstart', function (ev) {
    console.log(selfLogo);
    createImg(selfLogo, $selfLogo);
    first = false;
    selfLogo.imgX = ev.deltaX;
    selfLogo.imgY = ev.deltaY;
});
hammerLogo.on('panmove', function (ev) {
    console.log('panmove');
    selfLogo.left -= selfLogo.imgX - ev.deltaX;
    selfLogo.top -= selfLogo.imgY - ev.deltaY;
    moveImg($selfLogo, selfLogo);
    selfLogo.imgX = ev.deltaX;
    selfLogo.imgY = ev.deltaY;
});
hammerLogo.on('panend', function (ev) {
    console.log(selfLogo);
    first = true;
    var change = false;
    if (selfLogo.top < 0) {
        selfLogo.top = 0;
        change = true;
    }
    if (selfLogo.left < 0) {
        selfLogo.left = 0;
        change = true;
    }
    if (selfLogo.left + selfLogo.width > selfLogo.boxWidth) {
        selfLogo.left = selfLogo.boxWidth - selfLogo.width;
        change = true;
    }
    if (selfLogo.top + selfLogo.height > selfLogo.boxHeight * 0.74) {
        selfLogo.top = selfLogo.boxHeight * 0.74 - selfLogo.height;
        change = true;
    }
    if (change) {
        moveImg($selfLogo, selfLogo);
    }
});

//初始化图片对象
function initImg(_img, _node) {
    _img.index = 0;
    var change = false;
    if (_img.top > 0) {
        _img.top = 0;
        change = true;
        console.log(1);
    }
    if (_img.left > 0) {
        _img.left = 0;
        change = true;
        console.log(2);
    }
    if (-_img.left >= _img.width - _img.boxWidth) {
        _img.left = -(_img.width - _img.boxWidth);
        change = true;
        console.log(3);
    }
    if (_img.top < 0 && (-_img.top) + $footer.height() >= _img.height - _img.boxHeight) {
        _img.top = -(_img.height - _img.boxHeight + $footer.height());
        change = true;
        console.log(4);
    }
    if (change) {
        moveImg(_node, _img);
    }
}

//创建图片
function createImg(_img, _node) {
    _img.height = parseInt(_node.css('height'));
    _img.width = parseInt(_node.css('width'));
}

//缩放图片
function pinchImg(ev, _img, _node) {
    console.log(_img);
    var obj = {};
    obj.height = parseInt(_node.css('height'));
    obj.width = parseInt(_node.css('width'));

    if ((obj.width / obj.height) < (_img.boxWidth / _img.boxHeight)) {
        var w = (_img.width * ev.scale);
        if (w < _img.boxWidth) {
            w = _img.boxWidth;
        }
        if (w > 2 * _img.boxWidth) {
            w = 2 * _img.boxWidth;
        }
        _node.css("width", w + 'px');
    } else {
        var h = (_img.height * ev.scale);
        if (h < _img.boxHeight) {
            h = _img.boxHeight;
        }
        if (h > 2 * _img.boxHeight) {
            h = 2 * _img.boxHeight;
        }
        _node.css("height", h + 'px');
    }
    _img.top += (obj.height - parseInt(_node.css('height'))) * ((ev.center.y - _img.top) / obj.height);
    _img.left += (obj.width - parseInt(_node.css('width'))) * ((ev.center.x - _img.left) / obj.width);
    moveImg(_node, _img);
    createImg(_img, _node);
}

//移动图片
function moveImg(_node, _img) {
    _node.css("transform", "translate3d(" + _img.left + "px," + _img.top + "px,0)");
}

复制代码

难点4

 var image = new Image();
        image.src = node.src;
        image.onload = function () {
            ctx.drawImage(image, _img.left, _img.top , $node.width(), $node.height() );
       }
复制代码

转载于:https://juejin.im/post/5acad7c4518825485153697e

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值