zoukankan      html  css  js  c++  java
  • h5 canvas 图片上传操作

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

    html:

    1 <pre name="code" class=" 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 10 Regular Expression Matching(字符串匹配)
    LeetCode 9 Palindrome Number(回文数字判断)
    操作系统期末复习资料分享
    计算机网络那些事~(二)
    seL4之hello-3征途
    计算机网络那些事~(一)
    seL4之hello-2旅途(完成更新)
    博客声明
    seL4环境配置
    Canvas链式操作
  • 原文地址:https://www.cnblogs.com/Grewer/p/7075243.html
Copyright © 2011-2022 走看看