【JS】Cropper.js ~ 画像の切り取り ~

■ はじめに

 JavaScriptで、画像の切り取りについて調べていたら、
Cropper.js ってのを見つけて、思いのほかハマったので、メモ。



■ サンプル

【例1】Hello World

https://github.com/fengyuanchen/cropperjs/blob/master/examples/customize-preview.html
https://codepen.io/blackjacques/pen/YZmvjw
<!DOCTYPE html>
<html lang="jp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="">https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.3/cropper.css">
<style>
.container {
  max-width: 960px;
  margin: 20px auto;
}

img {
  max-width: 100%;
}

.row,
.preview {
  overflow: hidden;
}

.col {
  float: left;
}

.col-1 {
  width: 50%;
}

.col-2 {
  width: 25%;
}
</style>
<title>Demo</title>
</head>
<body>
<div class="container">
  <h1>Hello World for Cropper</h1>
  <div class="row">
    <div class="col col-1">
      <img id="image" src="https://raw.githubusercontent.com/fengyuanchen/cropperjs/master/docs/images/picture.jpg" alt="Picture">
    </div>
    <div class="col col-2">
      <div class="preview"></div>
    </div>
  </div>
</div>
<script src="">https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.3/cropper.js">
<script type="text/javascript">
function each(arr, callback) {
  var length = arr.length;
  var i;
  for (i = 0; i < length; i++) {
    callback.call(arr, arr[i], i, arr);
  }
  return arr;
}

window.addEventListener('DOMContentLoaded', function () {
  init();
});

function init() {
  var image = document.querySelector('#image');
  var previews = document.querySelectorAll('.preview');
  var cropper = new Cropper(image, {
      ready: function () {
        var clone = this.cloneNode();
        clone.className = '';
        clone.style.cssText = (
          'display: block;' +
          'width: 100%;' +
          'min-width: 0;' +
          'min-height: 0;' +
          'max-width: none;' +
          'max-height: none;'
        );
        each(previews, function (elem) {
          elem.appendChild(clone.cloneNode());
        });
      },
      crop: function (event) {
        var data = event.detail;
        var cropper = this.cropper;
        var imageData = cropper.getImageData();
        var previewAspectRatio = data.width / data.height;
        each(previews, function (elem) {
          var previewImage = elem.getElementsByTagName('img').item(0);
          var previewWidth = elem.offsetWidth;
          var previewHeight = previewWidth / previewAspectRatio;
          var imageScaledRatio = data.width / previewWidth;
          elem.style.height = previewHeight + 'px';
          if (previewImage) {
            previewImage.style.width = imageData.naturalWidth / imageScaledRatio + 'px';
            previewImage.style.height = imageData.naturalHeight / imageScaledRatio + 'px';
            previewImage.style.marginLeft = -data.x / imageScaledRatio + 'px';
            previewImage.style.marginTop = -data.y / imageScaledRatio + 'px';
          }
        });
      },
    });
}
</script>
</body>
</html>

【例2】回転などメソッド

<!DOCTYPE html>
<html lang="jp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="">https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.3/cropper.css">
<style>
.container {
  max-width: 960px;
  margin: 20px auto;
}

img {
  max-width: 100%;
}

.row,
.preview {
  overflow: hidden;
}

.col {
  float: left;
}

.col-1 {
  width: 50%;
}

.col-2 {
  width: 25%;
}
</style>
<title>Demo</title>
</head>
<body>
<div class="container">
  <h1>Hello World for Cropper</h1>
  <div class="row">
    <div class="col col-1">
      <img id="image" src="https://raw.githubusercontent.com/fengyuanchen/cropperjs/master/docs/images/picture.jpg" alt="Picture">
    </div>
    <div class="col col-2">
      <div class="preview"></div>
    </div>
  </div>

  <button onclick="rotate()">rotate</button>
  <button onclick="resetCropper()">reset</button>
  <button onclick="clearCropper()">clear</button>
  <button onclick="enable()">enable</button>
  <button onclick="destroy()">destroy</button>
</div>
<script src="">https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.4.3/cropper.js">
<script type="text/javascript">
function each(arr, callback) {
  var length = arr.length;
  var i;
  for (i = 0; i < length; i++) {
    callback.call(arr, arr[i], i, arr);
  }
  return arr;
}

var cropper = null;
window.addEventListener('DOMContentLoaded', function () {
  init();
});

function init() {
  var image = document.querySelector('#image');
  var previews = document.querySelectorAll('.preview');
  cropper = new Cropper(image, {
      ready: function () {
        var clone = this.cloneNode();
        clone.className = '';
        clone.style.cssText = (
          'display: block;' +
          'width: 100%;' +
          'min-width: 0;' +
          'min-height: 0;' +
          'max-width: none;' +
          'max-height: none;'
        );
        each(previews, function (elem) {
          elem.appendChild(clone.cloneNode());
        });
      },
      crop: function (event) {
        var data = event.detail;
        var cropper = this.cropper;
        var imageData = cropper.getImageData();
        var previewAspectRatio = data.width / data.height;
        each(previews, function (elem) {
          var previewImage = elem.getElementsByTagName('img').item(0);
          var previewWidth = elem.offsetWidth;
          var previewHeight = previewWidth / previewAspectRatio;
          var imageScaledRatio = data.width / previewWidth;
          elem.style.height = previewHeight + 'px';
          if (previewImage) {
            previewImage.style.width = imageData.naturalWidth / imageScaledRatio + 'px';
            previewImage.style.height = imageData.naturalHeight / imageScaledRatio + 'px';
            previewImage.style.marginLeft = -data.x / imageScaledRatio + 'px';
            previewImage.style.marginTop = -data.y / imageScaledRatio + 'px';
          }
        });
      },
    });
}

function rotate() {
  if (cropper) {
    cropper.rotate(45);
  }
}

function resetCropper() {
  if (cropper) {
    cropper.reset();
  }
}

function clearCropper() {
  if (cropper) {
    cropper.clear();
  }
}

function enable() {
  if (!cropper) {
    init();
  }
  cropper.enable();
}

function destroy() {
  if (cropper) {
    cropper.destroy();
  }
  cropper = null;
}


</script>
</body>
</html>