移动端cropper.js上传图片、裁剪

代码全部贴出来,包括外链,比较长。
cropper.js官网:http://fengyuanchen.github.io/cropper/

先引入CSS

  <link rel="stylesheet" href="css/bootstrap.min.css">
  <link rel="stylesheet" href="css/cropper.css">
  <link rel="stylesheet" href="css/myCrop.css">

结构部分

<section>
    <input class="photoBtn" type="button" onclick="document.querySelector('.inputImage').click()" value="选择照片" >

    <input class="inputImage" type="file" accept="image/*" style="display: none;" data-area="&quot;width&quot;: 320, &quot;height&quot;: 180" />
    <br />
    <img class="showImg"/>
  </section>

  <div class="container containerDiv" style="padding:0;position:fixed;display: none;top: 0;left: 0;z-index: 200;">
    <div class="imgEdit" style="display: none">
      <div>
        <div class="img-container">
          <img src="" alt="Picture" class="image">
        </div>
      </div>
    </div>

    <div class="actions">
      <div class=" docs-buttons">
        
        <div class="btn-group btn-group-crop">
          <button type="button" class="btn btn-primary imgCutConfirm"  data-method="getCroppedCanvas"
            data-option="{ &quot;width&quot;: 200, &quot;height&quot;: 180}" ><!-- 生成图片的大小,以宽度计算,然后乘以剪切框比例 -->
            <span class="docs-tooltip" data-toggle="tooltip" title="">确认</span>
          </button>
        </div>

        <div class="btn-group">
          <button type="button" class="btn btn-primary" data-method="destroy" title="Destroy">
            <span class="docs-tooltip" data-toggle="tooltip">取消</span>
          </button>
        </div>

      </div>

    </div>
  </div>

JS

<script src="js/jquery-3.4.1.min.js"></script>
  <script src="js/bootstrap.bundle.min.js"></script>
  <script src="js/cropper.js"></script>
  <script src="js/myCrop.js"></script>
  <script type="text/javascript">
    var fileImg = "";

    $(function () {

      $(".imgCutConfirm").bind("click", function () {
        $(".containerDiv").hide();
        $(".imgEdit").hide();
        $(".getCroppedCanvasModal").modal("hide");
      })
    })

    //提交表达
    function submitForm() {
      $(".registerForm").attr("enctype", "multipart/form-data");

      var formData = new FormData($(".registerForm")[0]);
      formData.append("imgBase64", encodeURIComponent(fileImg));//
      formData.append("fileFileName", "photo.jpg");


      $.ajax({
        url: "",
        type: 'POST',
        data: formData,
        timeout: 10000, //超时时间设置,单位毫秒
        async: true,
        cache: false,
        contentType: false,
        processData: false,
        success: function (result) {
        },
        error: function (returndata) {
          Alert.closedLoading();
        }
      });
    }
  </script>

myCrop.css

/* Basic */

body {
  margin: 0;
  overflow-x: hidden;
}

.browserupgrade {
  margin: 0;
  padding: .5em 1em;
  background-color: #fcfcfc;
  text-align: center;
}


/* Header */

.docs-header {
  margin-bottom: 0;
}

.navbar-toggle:hover,
.navbar-toggle:focus {
  border-color: #0074d9;
}

.navbar-toggle .icon-bar {
  background-color: #0074d9;
}


/* Jumbotron */

.docs-jumbotron {
  background-color: #0074d9;
  color: #fff;
}

.docs-jumbotron .version {
  font-size: 14px;
  color: #fff;
  filter: alpha(opacity=50);
  opacity: 0.5;
}


/* Content */

.img-container,
.img-preview {
  background-color: #f7f7f7;
  width: 100%;
  text-align: center;
}

.img-container {
  min-height: 200px;
  max-height: 516px;
}

.img-container > img {
  max-width: 100%;
}

.docs-preview {
  margin-right: -15px;
}

.img-preview {
  float: left;
  margin-right: 10px;
  margin-bottom: 10px;
  overflow: hidden;
}

.img-preview > img {
  max-width: 100%;
}

.preview-lg {
  width: 263px;
  height: 148px;
}

.preview-md {
  width: 139px;
  height: 78px;
}

.preview-sm {
  width: 69px;
  height: 39px;
}

.preview-xs {
  width: 35px;
  height: 20px;
  margin-right: 0;
}

.docs-data > .input-group {
  margin-bottom: 10px;
}

.docs-data > .input-group > label {
  min-width: 80px;
}

.docs-data > .input-group > span {
  min-width: 50px;
}
.docs-buttons{
  text-align: center;
}
.docs-buttons > .btn,
.docs-buttons > .btn-group,
.docs-buttons > .form-control {
  margin-right: 5px;
}

.docs-toggles > .btn,
.docs-toggles > .btn-group,
.docs-toggles > .dropdown {
  margin-bottom: 10px;
}

.docs-tooltip {
  display: block;
}

.docs-tooltip > .icon {
  margin: 0 -3px;
  vertical-align: top;
}

.tooltip-inner {
  white-space: normal;
}

.btn-upload .tooltip-inner {
  white-space: nowrap;
}

.docs-options .dropdown-menu {
  width: 100%;
}

.docs-options .dropdown-menu > li {
  padding: 3px 20px;
}

.docs-options .dropdown-menu > li:hover {
  background-color: #f7f7f7;
}

.docs-options .dropdown-menu > li > label {
  display: block;
}

myCrop.js

window.onload = function() {
  ('use strict');

  var Cropper = window.Cropper;
  var URL = window.URL || window.webkitURL;
  var container = document.querySelector('.img-container');
  var image = container.getElementsByTagName('img').item(0);
  var actions = document.querySelector('.actions');
  var screenWidth = $(window).width();
  var screenHeight = $(window).height();
  var inputImage = document.querySelector('.inputImage');
  var dataArea;//dataArea里面width、height是裁剪框的尺寸
  dataArea = {
    area: inputImage.getAttribute('data-area') || undefined,
  };
  var cropArea = dataArea.area;
  cropArea = cropArea.replace(/"/g, '').replace(/\s*/g, '');//去除""和空格
  var areaObj = {};//将width、height转换成对象
  var arr = cropArea.split(',');
  for (var i = 0; i < arr.length; i++) {
    var kv = arr[i].split(':');
    if (areaObj[kv[0]]) {
      areaObj[kv[0]] += ',' + kv[1];
    } else {
      areaObj[kv[0]] = kv[1];
    }
  }

  var options = {
    minContainerHeight: screenHeight,
    minContainerWidth: screenWidth,
    aspectRatio: areaObj.width / areaObj.height,//根据页面中dataArea里面width、height设置裁剪框比例
    viewMode: 3, //显示
    guides: false, //裁剪框虚线 默认true有
    dragMode: 'move',
    autoCropArea: 0.8, //自动裁剪面积大小(百分比)和图片进行对比

    ready: function(e) {
      $('.containerDiv').show();
      $('.imgEdit').show();
    },

    background: true, // 容器是否显示网格背景
    movable: true, //是否能移动图片
    cropBoxMovable: true, //是否允许拖动裁剪框
    cropBoxResizable: false, //是否允许拖动 改变裁剪框大小
    toggleDragModeOnDblclick: false, //定义当点击两次时可以在“crop”和“move”之间切换拖拽模式
  };
  console.log(options.aspectRatio);
  console.log(options.autoCropArea);

  var cropper = new Cropper(image, options);
  var originalImageURL = image.src;
  var uploadedImageType = 'image/jpeg';
  var uploadedImageName = 'cropped.jpg';
  var uploadedImageURL;

  // // Buttons
  if (!document.createElement('canvas').getContext) {
    $('button[data-method="getCroppedCanvas"]').prop('disabled', true);
  }

  if (typeof document.createElement('cropper').style.transition === 'undefined') {
    $('button[data-method="scale"]').prop('disabled', true);
  }

  // Methods

  actions.querySelector('.docs-buttons').onclick = function(event) {
    var e = event || window.event;
    var target = e.target || e.srcElement;
    var cropped;
    var result;
    var input;
    var data;

    if (!cropper) {
      return;
    }

    while (target !== this) {
      if (target.getAttribute('data-method')) {
        break;
      }

      target = target.parentNode;
    }

    if (target === this || target.disabled || target.className.indexOf('disabled') > -1) {
      return;
    }

    data = {
      method: target.getAttribute('data-method'),
      option: target.getAttribute('data-option') || undefined,
      secondOption: target.getAttribute('data-second-option') || undefined,
    };

    // cropped = cropper.cropped;
    if (data.method) {
      switch (data.method) {
        // case 'rotate':
        //   if (cropped && options.viewMode > 0) {
        //     cropper.clear();
        //   }

        //   break;

        case 'getCroppedCanvas':
          try {
            data.option = JSON.parse(data.option);
          } catch (e) {
            console.log(e.message);
          }

          if (uploadedImageType === 'image/jpeg') {
            if (!data.option) {
              data.option = {};
            }

            data.option.fillColor = '#fff';
          }

          break;
      }

      result = cropper[data.method](data.option, data.secondOption);

      switch (data.method) {
        case 'rotate':
          if (cropped && options.viewMode > 0) {
            cropper.crop();
          }

          break;

        case 'scaleX':
        case 'scaleY':
          target.setAttribute('data-option', -data.option);
          break;

        case 'getCroppedCanvas':
          if (result) {
            fileImg = result.toDataURL('image/jpg');
            $('.showImg')
              .attr('src', fileImg)
              .show();
          }

          break;
        case 'destroy':
          $('.inputImage').val('');
          $('.containerDiv').hide();
          $('.imgEdit').hide();
          break;
      }

      if (typeof result === 'object' && result !== cropper && input) {
        try {
          input.value = JSON.stringify(result);
        } catch (e) {
          console.log(e.message);
        }
      }
    }
  };

  document.body.onkeydown = function(event) {
    var e = event || window.event;

    if (e.target !== this || !cropper || this.scrollTop > 300) {
      return;
    }
  };

  // Import image
  var inputImage = document.querySelector('.inputImage');

  if (URL) {
    inputImage.onchange = function() {
      var files = this.files;
      var file;

      if (cropper && files && files.length) {
        file = files[0];

        if (/^image\/\w+/.test(file.type)) {
          uploadedImageType = file.type;
          uploadedImageName = file.name;

          if (uploadedImageURL) {
            URL.revokeObjectURL(uploadedImageURL);
          }

          image.src = uploadedImageURL = URL.createObjectURL(file);
          cropper.destroy();
          cropper = new Cropper(image, options);
          inputImage.value = null;
        } else {
          window.alert('Please choose an image file.');
        }
      }
    };
  } else {
    inputImage.disabled = true;
    inputImage.parentNode.className += ' disabled';
  }
};

参考https://blog.csdn.net/qq727013465/article/details/51823231

我们项目用裁剪的地方比较多,所以做了一些更改,可以在HTML通过data-area中定义裁剪框比例
至于坑,感觉裁剪生成的图片比较模糊,没有官方文档清晰,应该是canvas绘图在高清屏显示问题,对canvas暂时还没有研究,等后面学习了再来填坑

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 229,517评论 6 539
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,087评论 3 423
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 177,521评论 0 382
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,493评论 1 316
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,207评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,603评论 1 325
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,624评论 3 444
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,813评论 0 289
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,364评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,110评论 3 356
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,305评论 1 371
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,874评论 5 362
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,532评论 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,953评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,209评论 1 291
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,033评论 3 396
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,268评论 2 375

推荐阅读更多精彩内容