• h5 canvas 图片上传操作


    最近写的小 demo,使用的是h5的 canvas来对图片进行放大,移动,剪裁等等
    这是最原始的代码,比较接近我的思路,后续会再对格式和结构进行优化

    html:

    1 <pre name="code" class="brush: html;" rows="15" cols="300">
    2 <input type="file" name="" accept="image/gif, image/jpeg" id="upload">
    3 <canvas id="showimg" style="border:1px solid #aaa;"></canvas>
    4 <p>移动:</p>     
    5 <input type="range" min="0" max="2" id="move" step="0.01" value="1" class="range-control" oninput="translateall()"/><br/>
    6 <button id="crop">剪裁输出</button>
    7 <img id="img" src="" style="border:1px solid #aaa;">

    js:初始代码

    var img = new Image();
    var can = document.getElementById('showimg');
    var ctx = can.getContext("2d");
    can.width = 500;
    can.height = 400;
    var fictitious_imgwidth,fictitious_imgheight,flag;
    var distance_x = 0;
    var distance_y = 0;
    var orign_x,orign_y//鼠标点击时的坐标
    var present_x,present_y//记录图片做上角的坐标
    var substitute_x,substitute_y//暂时记录图片左上角坐标
    ctx.fillStyle = "#aaa";   
    ctx.fillRect(0,0,500,400); 
    ctx.beginPath();
    ctx.moveTo(100,100);   
    ctx.lineTo(400,100);
    ctx.lineTo(400,300);
    ctx.lineTo(100,300); 
    ctx.lineTo(100,100); 
    ctx.lineWidth = 3;
    ctx.strokeStyle = '#333'
    ctx.stroke();
    ctx.clip();
    ctx.closePath();
    ctx.clearRect(0, 0, can.width, can.height);   
    $('#upload').change(function(){
        console.log('this is runing')
        ctx.clearRect(0, 0, can.width, can.height); 
        
        img.onload = function(){
            fictitious_imgwidth = img.width;
            fictitious_imgheight = img.height;
            present_x = can.width*0.5-img.width*0.5;
            present_y = can.height*0.5-img.height*0.5;
            ctx.drawImage(img,present_x,present_y,img.width,img.height);
        }
        img.src = getFileUrl('upload');
        
    })
    function translateall(){
        var val = document.getElementById("move").value;
        reprint(val)
    }
    function reprint(scale){
        ctx.clearRect(0, 0, can.width, can.height);
        fictitious_imgwidth = img.width*scale;
        fictitious_imgheight = img.height*scale;
        check_present();
        ctx.drawImage(img,present_x,present_y,fictitious_imgwidth,fictitious_imgheight)
    }
    function getFileUrl(sourceId) { 
        var url; 
        if (navigator.userAgent.indexOf("MSIE")>=1) { // IE 
            url = document.getElementById(sourceId).value; 
        } else if(navigator.userAgent.indexOf("Firefox")>0) { // Firefox 
            url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0)); 
        } else if(navigator.userAgent.indexOf("Chrome")>0) { // Chrome 
            url = window.URL.createObjectURL(document.getElementById(sourceId).files.item(0)); 
        }
        return url; 
    } 
    $('#showimg').mousedown(function(e){
        console.log('mousedown is running')
        orign_x = e.offsetX;
        orign_y = e.offsetY;
        judgment_isinimg(e);
    
    }).mousemove(function(e){
        if(flag){
            distance_x = e.offsetX - orign_x;
            distance_y = e.offsetY - orign_y;
            ctx.clearRect(0, 0, can.width, can.height); 
            substitute_x = present_x + distance_x;
            substitute_y = present_y + distance_y;
            ctx.drawImage(img,substitute_x,substitute_y,fictitious_imgwidth,fictitious_imgheight);
            
        }
    }).mouseleave(function(){
        flag = false
        present_x = substitute_x;
        present_y =substitute_y;
    }).mouseup(function(){
        flag = false
        present_x = substitute_x;
        present_y =substitute_y;
    })
    
    function judgment_isinimg(e){
        var ll = present_x
        var lt = present_y
        var rl = present_x+fictitious_imgwidth
        var rt = present_y+fictitious_imgheight
        
    
        var x=event.clientX-can.getBoundingClientRect().left;
        var y=event.clientY-can.getBoundingClientRect().top;
    
        if(ll < x && x < rl && lt < y && y < rt){
            flag = true;
        }else{
            flag = false;
        }
    }
    
    function check_present(){
        if(typeof present_x == 'undefined' || typeof present_y == 'undefined'){
            present_x = can.width*0.5-fictitious_imgwidth*0.5;
            present_y = can.height*0.5-fictitious_imgheight*0.5;
        }
    }
    
    $('#crop').click(function(){
        crop_canvas = document.createElement('canvas');
        crop_canvas.width = 300;  
        crop_canvas.height = 200;
        crop_ctx =crop_canvas.getContext('2d')
        crop_ctx.fillStyle = "#fff";
        crop_ctx.fillRect(0,0,300,200);
        check_present();
        crop_ctx.drawImage(img,Number(present_x)-100,Number(present_y)-100,fictitious_imgwidth,fictitious_imgheight);
        var fullQuality = crop_canvas.toDataURL('image/jpeg', 1.0);
        $('#img').attr('src',fullQuality);
    })
    View Code

     修改后:

    -(function($){
            var crop = {
                init:function(){
                    this.img = new Image();
                    this.can = document.getElementById('showimg');
                    var ctx = this.ctx = this.can.getContext("2d");
                    this.width = this.can.width = 500;
                    this.height = this.can.height = 400;
                    ctx.fillStyle = "#aaa";  
                    ctx.fillRect(0,0,500,400); 
                    ctx.beginPath();
                    ctx.moveTo(100,100);   
                    ctx.lineTo(400,100);
                    ctx.lineTo(400,300);
                    ctx.lineTo(100,300); 
                    ctx.lineTo(100,100); 
                    ctx.lineWidth = 3;
                    ctx.strokeStyle = '#333'
                    ctx.stroke();
                    ctx.clip();
                    ctx.closePath();
                    this.clear();  
                    this.addListen();
                },
                change:function(){
                    this.clear();
                    this.img.onload = function(){
                        var $this = crop;
                        $this.img_width = $this.img.width;
                        $this.img_height = $this.img.height;
                        $this.fictitious_imgwidth = $this.img_width;
                        $this.fictitious_imgheight = $this.img_height;
                        $this.present_x = $this.width*0.5-$this.img_width*0.5;
                        $this.present_y = $this.height*0.5-$this.img_height*0.5;
                        $this.ctx.drawImage($this.img,$this.present_x,$this.present_y,$this.img_width,$this.img_height);
                    }
                    this.img.src = this.getFileUrl('upload');
                },
                translate:function(){
                    var val = document.getElementById("move").value;
                    this.clear();
                    this.fictitious_imgwidth = this.img_width*val;
                    this.fictitious_imgheight = this.img_height*val;
                    this.ctx.drawImage(this.img,this.present_x,this.present_y,this.fictitious_imgwidth,this.fictitious_imgheight);
                },
                mouseDown:function(e){
                    this.orign_x = e.offsetX;
                    this.orign_y = e.offsetY;
                    this.judgmentIsInImg(e);
                },
                mouseMove:function(e){
                    var e = e || event;
                    if(this.flag){
                        this.distance_x = e.offsetX - this.orign_x;
                        this.distance_y = e.offsetY - this.orign_y;
                        this.clear();
                        this.substitute_x = this.present_x + this.distance_x;
                        this.substitute_y = this.present_y + this.distance_y;
                        this.ctx.drawImage(this.img,this.substitute_x,this.substitute_y,this.fictitious_imgwidth,this.fictitious_imgheight);
                    }
                },
                mouseLeave:function(){
                    if(this.flag){
                        this.present_x = this.substitute_x;
                        this.present_y = this.substitute_y;
                        this.flag = false;
                    }
                    
                },
                out:function(){
                    var crop_canvas = document.createElement('canvas');
                    crop_canvas.width = 300;  
                    crop_canvas.height = 200;
                    crop_ctx = crop_canvas.getContext('2d');
                    crop_ctx.fillStyle = "#fff";
                    crop_ctx.fillRect(0,0,300,200);
                    crop_ctx.drawImage(this.img,Number(this.present_x)-100,Number(this.present_y)-100,this.fictitious_imgwidth,this.fictitious_imgheight);
                    var fullQuality = crop_canvas.toDataURL('image/jpeg', 1.0);
                    $('#img').attr('src',fullQuality);
                },
                judgmentIsInImg:function(e){
                    var e = e || event;
                    var ll = this.present_x;
                    var lt = this.present_y;
                    var rl = this.present_x+this.fictitious_imgwidth;
                    var rt = this.present_y+this.fictitious_imgheight;
                    
                    var x=e.clientX-this.can.getBoundingClientRect().left;
                    var y=e.clientY-this.can.getBoundingClientRect().top;
    
                    if(ll < x && x < rl && lt < y && y < rt){
                        this.flag = true;
                    }else{
                        this.flag = false;
                    }
                    
                },
                clear:function(){
                    this.ctx.clearRect(0, 0, this.width, this.height);
                },
                getFileUrl:function(id){
                    var url;
                    try{
                        if (navigator.userAgent.indexOf("MSIE")>=1) { // IE 
                            url = document.getElementById(id).value; 
                        } else if(navigator.userAgent.indexOf("Firefox")>0) { // Firefox 
                            url = window.URL.createObjectURL(document.getElementById(id).files.item(0)); 
                        } else if(navigator.userAgent.indexOf("Chrome")>0) { // Chrome 
                            url = window.URL.createObjectURL(document.getElementById(id).files.item(0)); 
                        }
                    }catch(e){
                        throw new Error('you can ignore it')
                    }
                    return url;
                },
                addListen:function(){
                    $('#upload').on('change',this.change.bind(this));
                    $('#move').on('input',this.translate.bind(this));
                    $('#showimg').on('mousedown',this.mouseDown.bind(this))
                    .on('mousemove',this.mouseMove.bind(this))
                    .on('mouseleave mouseup',this.mouseLeave.bind(this));
                    $('#crop').on('click',this.out.bind(this));
                }
            }
            return crop.init();
        })(jQuery)
    View Code

    如果还有何不足,请多多指正

    12.16日修改 因为最近讨论到了头像上传,剪裁的问题,我又对此进行了回顾,发现该 demo 也有不足之处,所以我花了点时间重新修改一下再添加了注释:

    最新代码:

    -(function($) {
        var crop = {
            init: function() {
                this.img = new Image();
                this.can = document.getElementById('showimg');
                var ctx = this.ctx = this.can.getContext("2d");
                this.width = this.can.width = 500;
                this.height = this.can.height = 400;
                ctx.fillStyle = "#aaa";
                ctx.fillRect(0, 0, 500, 400);
                ctx.beginPath();
                ctx.moveTo(100, 100);
                ctx.lineTo(400, 100);
                ctx.lineTo(400, 300);
                ctx.lineTo(100, 300);
                ctx.lineTo(100, 100);
                ctx.lineWidth = 3;
                ctx.strokeStyle = '#333'
                ctx.stroke();
                ctx.clip();
                ctx.closePath();
                this.clear();
                this.addListen();
            },
            render(src) {
                this.img = new Image();
                this.img.onload = function() {
                    var $this = crop;
                    $this.img_width = $this.img.width; //原图像横坐标
                    $this.img_height = $this.img.height; //原图像纵坐标
                    $this.fictitious_imgwidth = $this.img_width; //被缩放的图像横坐标
                    $this.fictitious_imgheight = $this.img_height; //被缩放的图像纵坐标
                    //因为后面图像的变化后长度都不是原长度了,后面使用图像长度是就使用fictitious属性
                    $this.init_x = $this.width * 0.5; //图片中心点横坐标
                    $this.init_y = $this.height * 0.5; //图片中心点纵坐标
                    //绘图时同过中心点减去fictitious/2长度来确定图像左上角的坐标
                    $this.ctx.drawImage($this.img, $this.init_x - $this.img_width / 2, $this.init_y - $this.img_height / 2, $this.img_width, $this.img_height);
                };
                this.img.src = src;
            },
            change: function() {
                this.clear();
                $('#move').val(1) //根据实际需要进行初始化
                var reader = new FileReader();
                var img = $('#upload').get(0).files[0];
    
                reader.onload = function(e) {
                    crop.render(e.target.result);
                };
    
                reader.readAsDataURL(img);
            },
            translate: function() {
                var val = document.getElementById("move").value;
                this.clear();
                this.fictitious_imgwidth = this.img_width * val;
                this.fictitious_imgheight = this.img_height * val;
                this.ctx.drawImage(this.img, this.init_x - this.fictitious_imgwidth / 2, this.init_y - this.fictitious_imgheight / 2, this.fictitious_imgwidth, this.fictitious_imgheight);
            },
            mouseDown: function(e) {
                this.orign_x = e.offsetX;
                this.orign_y = e.offsetY;
                this.judgmentIsInImg(e); //判断点击是否在图像内
            },
            mouseMove: function(e) {
                var e = e || event;
                if (this.flag) {
                    this.distance_x = e.offsetX - this.orign_x; //鼠标移动的长度
                    this.distance_y = e.offsetY - this.orign_y;
                    this.clear();
                    this.substitute_x = this.init_x + this.distance_x;
                    this.substitute_y = this.init_y + this.distance_y;
                    this.ctx.drawImage(this.img, this.substitute_x - this.fictitious_imgwidth / 2, this.substitute_y - this.fictitious_imgheight / 2, this.fictitious_imgwidth, this.fictitious_imgheight);
                }
            },
            mouseLeave: function() {
                if (this.flag) {
                    this.init_x = this.substitute_x;
                    this.init_y = this.substitute_y;
                    this.flag = false;
                }
    
            },
            out: function() {
                //输出图像
                var crop_canvas = document.createElement('canvas');
                crop_canvas.width = 300;
                crop_canvas.height = 200;
                crop_ctx = crop_canvas.getContext('2d');
                crop_ctx.fillStyle = "#fff";
                crop_ctx.fillRect(0, 0, 300, 200);
                crop_ctx.drawImage(this.img, this.init_x - this.fictitious_imgwidth / 2 - 100, this.init_y - this.fictitious_imgheight / 2 - 100, this.fictitious_imgwidth, this.fictitious_imgheight);
                //这边的减去100 是原 canvas 阴影边框的长度
                var fullQuality = crop_canvas.toDataURL('image/jpeg', 1.0);
                $('#img').attr('src', fullQuality);
            },
            judgmentIsInImg: function(e) {
                var e = e || event;
    
                var ll = this.init_x - this.fictitious_imgwidth / 2;
                var lt = this.init_y - this.fictitious_imgheight / 2;
                var rl = this.init_x + this.fictitious_imgwidth / 2;
                var rt = this.init_y + this.fictitious_imgheight / 2;
                //图像四个角的坐标
    
                var x = e.clientX - this.can.getBoundingClientRect().left;
                var y = e.clientY - this.can.getBoundingClientRect().top;
    
                if (ll < x && x < rl && lt < y && y < rt) {
                    this.flag = true;
                } else {
                    this.flag = false;
                }
    
            },
            clear: function() {
                this.ctx.clearRect(0, 0, this.width, this.height);
            },
            addListen: function() {
                $('#upload').on('change', this.change.bind(this));
                $('#move').on('input', this.translate.bind(this));
                $('#showimg').on('mousedown', this.mouseDown.bind(this))
                    .on('mousemove', this.mouseMove.bind(this))
                    .on('mouseleave mouseup', this.mouseLeave.bind(this));
                $('#crop').on('click', this.out.bind(this));
            }
        }
        return crop.init();
    })(jQuery)

    修改之后,进行缩放时不是原来的按左上角坐标缩放,而是按图像中心缩放,因为这样的缩放方式,所以不能靠记录图像左上角坐标进行绘制,而是记录图像中心点位置,还解决了手机端的图片获取兼容问题,原来的获取图片 url 方法只能在 PC端有效;

    gitHub:https://github.com/Grewer/JsDemo/tree/master/crop

    demo:https://grewer.github.io/JsDemo/crop/crop.html

    如果这篇文章帮助到了你,请给我一个 star

  • 相关阅读:
    【leetcode】1020. Partition Array Into Three Parts With Equal Sum
    【leetcode】572. Subtree of Another Tree
    【leetcode】123. Best Time to Buy and Sell Stock III
    【leetcode】309. Best Time to Buy and Sell Stock with Cooldown
    【leetcode】714. Best Time to Buy and Sell Stock with Transaction Fee
    【leetcode】467. Unique Substrings in Wraparound String
    【leetcode】823. Binary Trees With Factors
    【leetcode】143. Reorder List
    【leetcode】1014. Capacity To Ship Packages Within D Days
    【leetcode】1013. Pairs of Songs With Total Durations Divisible by 60
  • 原文地址:https://www.cnblogs.com/Grewer/p/7075243.html
Copyright © 2020-2023  润新知