上传图片时压缩图片 - 前端(canvas)做法

HTML前端代码:

<?php $this->layout('head'); ?>
<?php $this->layout('sidebar'); ?>
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
        <style type="text/css">
            #preview {
                display: inline-block;
                width: 24.56rem;
                height: 24.56rem;
                position: relative;
                background-image: url(img/iconfont-tianjia.png);
                background-repeat: no-repeat;
                background-size:cover ;
            }            
            #file {
                /*width: 100%;*/
                height: 100%;
                /*opacity: 0;*/
                position: absolute;
                left: 0;
                top: 0;
                cursor: pointer;
                z-index: 5;
            }
        </style>
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
  <!-- Content Header (Page header) -->
  <section class="content-header">

  </section>

  <div class="col-md-12">
    <div class="box">
      <div class="box-header with-border">
        <h3 class="box-title">商品图库</h3>
        
      </div>
    
    <!-- 第一种 -->
    <input type="file" accept="image/*" name="picture"  id="file" value="点击" />
    <div id="preview"></div>
    
    <!-- 第二种 -->
    <input type="file" id="tesImg" onchange="tes(this)" />
    <img      id="tesId">
    <img      id="tesId1">
    <img      id="tesId2">
   
      <!-- /.box-header -->
      <div class="box-body" style="font-size: 1.3rem">

                   
      </div><!-- /.box-body -->

      <div class="box-footer clearfix ">
            
      </div>
    </div><!-- /.box -->
  </div>
  <div class=" clearfix "></div>
</div>



<?php $this->layout('footer'); ?>

<!-- 第一种 -->
<script type="text/javascript">
    var eleFile = document.querySelector('#file');
    var preview = document.querySelector('#preview');
    // 压缩图片需要的一些元素和对象
    var reader = new FileReader(),
    //创建一个img对象
        img = new Image();

    // 选择的文件对象
    var file = null;

    // 缩放图片需要的canvas
    var canvas = document.createElement('canvas');
    var context = canvas.getContext('2d');

    // base64地址图片加载完毕后
    img.onload = function() {
        // 图片原始尺寸
        var originWidth = this.width;
        var originHeight = this.height;
        // 最大尺寸限制,可通过设置宽高来实现图片压缩程度
        var maxWidth = 800,
            maxHeight = 800
        // 目标尺寸
        var targetWidth = originWidth,
            targetHeight = originHeight;
        // 图片尺寸超过400x400的限制
        if(originWidth > maxWidth || originHeight > maxHeight) {
            if(originWidth / originHeight > maxWidth / maxHeight) {
                // 更宽,按照宽度限定尺寸
                targetWidth = maxWidth;
                targetHeight = Math.round(maxWidth * (originHeight / originWidth));
            } else {
                targetHeight = maxHeight;
                targetWidth = Math.round(maxHeight * (originWidth / originHeight));
            }
        }
        // canvas对图片进行缩放
        canvas.width = targetWidth;
        canvas.height = targetHeight;
        // 清除画布
        context.clearRect(0, 0, targetWidth, targetHeight);
        // 图片压缩
        context.drawImage(img, 0, 0, targetWidth, targetHeight);
        /*第一个参数是创建的img对象;第二个参数是左上角坐标,后面两个是画布区域宽高*/
        //压缩后的图片base64 url
        /*canvas.toDataURL(mimeType, qualityArgument),mimeType 默认值是'image/jpeg';
         * qualityArgument表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92*/
        var newUrl = canvas.toDataURL('image/jpeg', 0.8);//base64 格式
        $.post(
            '/business/test_canvas'
            ,{img:newUrl}
            ,function(data){
                console.log(data);
            }
        );
        // console.log(canvas.toDataURL('image/jpeg', 0.92));return;
     preview.style.backgroundImage='url(' + newUrl + ')';
    };

    // 文件base64化,以便获知图片原始尺寸
    reader.onload = function(e) {
        img.src = e.target.result;
    };
    eleFile.addEventListener('change', function(event) {
        file = event.target.files[0];
        // 选择的文件是图片
        if(file.type.indexOf("image") == 0) {
            reader.readAsDataURL(file);
        }
    });
</script>

<!-- 第二种 -->
<script>
    /*
    var imgOb=new Image();
    var imgDom=$("#tesId");
    imgOb是图片对象,而imgDom是dom对象;
    imgDom[0]是图片对象,与imgOb一样。
    要想获取图片对象的宽与高
    必须等图片对象加载后才能获取
    imgOb.onload=function(e){
        alert(imgOb.width);
     alert(imgOb.width);
    }
   */
    function tes(ob){
        var file=ob.files[0];
        var reader=new FileReader();
        reader.readAsDataURL(file);
        reader.onload=function(e){
            var imgObj=new Image();
            imgObj.src=this.result;
            imgObj.onload=function(a){
                var canvas = document.createElement('canvas');
                canvas.width = 100;
                canvas.height = 100;
                var ctx = canvas.getContext("2d");
                ctx.drawImage(imgObj, 0, 0, 100, 100);
                $("#tesId").attr('src',canvas.toDataURL("image/jpeg", 0.9));
                canvas.width = 800;
                canvas.height = 800;
                ctx.drawImage(imgObj, 0, 0, 800, 800);
                var img = canvas.toDataURL("image/jpg", 0.1);
                $("#tesId1").attr('src',canvas.toDataURL("image/jpg", 0.1));
                $.post(
                    '/business/test_canvas'
                    ,{img: img}
                    ,function(data){

                    }
                );
                canvas.width = 300;
                canvas.height = 100;
                ctx.drawImage(imgObj, 0, 0, 300, 100);
                $("#tesId2").attr('src',canvas.toDataURL("image/jpeg", 0.6));
            }
        }
    }
</script>

PHP后端接收前端 ajax方法传来base64格式图片保存:

    // 测试canvas
    public function test_canvas()
    {
        if($_POST){
            // echo new BasicReturn(true, 0, '', $_POST);

            $img = $_POST['img'];
            $abs_path = \sdk\config\Config::getUpPath()['upload'];
            $goods_path = "goods/" . date("Y/m/d/");  //图片上传路径
            if (!file_exists($abs_path . $goods_path))
                mkdir($abs_path . $goods_path, 0777, 1);
            $file_name = microtime(true) * 10000;
            $imgPath = $goods_path . $file_name;

            // 保存图片
            $type = $this->save_img_real($abs_path . $imgPath,$img);

        }
        $this->view('test_canvas');
    }

    private function save_img_real($path, $base64_image_content)
    {
        //匹配出图片的格式

        if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
            $type = $result[2];
            if ($type == 'jpeg') {
                $type = 'jpg';
            }
            if ($type == 'jpg' || $type == 'gif' || $type == 'png') {
                if (file_put_contents($path . '.' . $type, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
                    return $type;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        } elseif (preg_match('/^(data:;base64,)/', $base64_image_content, $result)) {
            $img_data = base64_decode(str_replace($result[1], '', $base64_image_content));
            $types = $this->check_image_type($img_data);
            if ($types) {
                if (file_put_contents($path . '.' . $types, $img_data)) {
                    return $types;
                } else {
                    return false;
                }
            } else {
                return false;
            }
        }
    }

    private function check_image_type($image)
    {
        $bits = array(
            'jpg' => "\xFF\xD8\xFF",
            'gif' => "GIF",
            'png' => "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a",
        );
        foreach ($bits as $type => $bit) {
            if (substr($image, 0, strlen($bit)) === $bit) {
                return $type;
            }
        }
        return false;
    }

需要注意的是:图片宽高 250 x 250 太小会失真,我这里就设置成 800 x 800

posted @ 2018-08-31 18:36  一粒小米-博客  阅读(427)  评论(0编辑  收藏  举报