jQuery.cropper是一款使用簡單且功能強大的圖片剪裁jQuery插件。該圖片剪裁插件支持圖片放大縮小,支持圖片旋轉,支持觸摸屏設備,支持canvas,並且支持跨瀏覽器使用。
官網:https://github.com/fengyuanchen/cropper
使用方法
使用該圖片剪裁插件首先要引入必要的js和css文件。
<script src="/path/to/jquery.js"></script><!-- jQuery is required -->
<link href="/path/to/cropper.css" rel="stylesheet">
<script src="/path/to/cropper.js"></script>
HTML結構
可以將圖片或canvas直接包裹到一個塊級元素中。
<!-- Wrap the image or canvas with a block element -->
<div class="container">
<img src="picture.jpg">
</div>
調用插件
可以使用$.fn.cropper方法來初始化該圖片剪裁插件。
var options = { aspectRatio: 4 / 3,//設置裁切框的寬高比。默認情況下,裁剪框是自由比例。 preview: '.img-preview', crop: function (e) { $dataX.html(Math.round(e.x)); $dataY.html(Math.round(e.y)); $dataHeight.html(Math.round(e.height)); $dataWidth.html(Math.round(e.width)); $dataRotate.html(e.rotate); $dataScaleX.html(e.scaleX); $dataScaleY.html(e.scaleY); var _$dataWH = reductionTo(Math.round(e.width), Math.round(e.height)); $dataWH.html(_$dataWH[0] + '/' + _$dataWH[1]); } }; // 初始化函數 $image.cropper(options); $image.cropper({ built: function () { } });
參數
-
你可以通過$().cropper(options)方法來設置參數。如果你想改變全局默認參數,可以使用$.fn.cropper.setDefaults(options)方法。
-
aspectRatio:類型:Number,默認值NaN。設置剪裁容器的比例。
-
crop:類型:Function,默認值null。當改變剪裁容器或圖片時的事件函數。
-
preview:類型:String(jQuery選擇器),默認值''。添加額外的元素(容器)的預覽。注意:
-
最大寬度是剪裁容器的初始化寬度
-
最大高度是剪裁容器的初始化高度
-
如果你設置了aspectRatio參數,確保預覽容器具有相同的比例
-
strict:類型:Boolean,默認值true。在strict模式中,canvas不能小於容器,剪裁容器不能再canvas之外。
-
responsive:類型:Boolean,默認值true。是否在窗口尺寸改變的時候重置cropper。
-
checkImageOrigin:類型:Boolean,默認值true。默認情況下,插件會檢測圖片的源,如果是跨域圖片,圖片元素會被添加crossOrigin class,並會為圖片的url添加一個時間戳來使getCroppedCanvas變為可用。添加時間戳會使圖片重新加載,以使跨域圖片能夠使用getCroppedCanvas。在圖片上添加crossOrigin class會阻止在圖片url上添加時間戳,及圖片的重新加載。
-
background:類型:Boolean,默認值true。是否在容器上顯示網格背景。
-
modal:類型:Boolean,默認值true。是否在剪裁框上顯示黑色的模態窗口。
-
guides:類型:Boolean,默認值true。是否在剪裁框上顯示虛線。
-
highlight:類型:Boolean,默認值true。是否在剪裁框上顯示白色的模態窗口。
-
autoCrop:類型:Boolean,默認值true。是否在初始化時允許自動剪裁圖片。
-
autoCropArea:類型:Number,默認值0.8(圖片的80%)。0-1之間的數值,定義自動剪裁區域的大小。
-
dragCrop:類型:Boolean,默認值true。是否允許移除當前的剪裁框,並通過拖動來新建一個剪裁框區域。
-
movable:類型:Boolean,默認值true。是否允許移動剪裁框。
-
resizable:類型:Boolean,默認值true。是否允許改變剪裁框的大小。
-
zoomable:類型:Boolean,默認值true。是否允許放大縮小圖片。
-
mouseWheelZoom:類型:Boolean,默認值true。是否允許通過鼠標滾輪來縮放圖片。
-
touchDragZoom:類型:Boolean,默認值true。是否允許通過觸摸移動來縮放圖片。
-
rotatable:類型:Boolean,默認值true。是否允許旋轉圖片。
-
minContainerWidth:類型:Number,默認值200。容器的最小寬度。
-
minContainerHeight:類型:Number,默認值100。容器的最小高度。
-
minCanvasWidth:類型:Number,默認值0。canvas 的最小寬度(image wrapper)。
-
minCanvasHeight:類型:Number,默認值0。canvas 的最小高度(image wrapper)。
-
build:類型:Function,默認值null。build.cropper事件的簡寫方式。
-
built:類型:Function,默認值null。built.cropper事件的簡寫方式。
-
dragstart:類型:Function,默認值null。dragstart.cropper事件的簡寫方式。
-
dragmove:類型:Function,默認值null。dragmove.cropper事件的簡寫方式。
-
dragend:類型:Function,默認值null。dragend.cropper事件的簡寫方式。
-
zoomin:類型:Function,默認值null。zoomin.cropper事件的簡寫方式。
-
zoomout:類型:Function,默認值null。zoomout.cropper事件的簡寫方式。
eg:
//index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="css/cropper.css"> <link rel="stylesheet" href="css/main.css"> </head> <body> <div class="wrapper"> <!--用塊元素(容器)包裝圖像或畫布元素--> <div class="img-container"> <img id="image" src="images/picture.jpg" alt=""> </div> <div class="img-preview-container"> <h1>預覽區域</h1> <div class="img-preview"> <img src="" alt=""> </div> </div> <div class="text-container"> <div class="param-container"> <div class="param"> <div class="name">X:</div> <div class="value" id="dataX"></div> <div class="unit">px</div> </div> <div class="param"> <div class="name">Y:</div> <div class="value" id="dataY"></div> <div class="unit">px</div> </div> <div class="param"> <div class="name">Width:</div> <div class="value" id="dataWidth"></div> <div class="unit">px</div> </div> <div class="param"> <div class="name">Height:</div> <div class="value" id="dataHeight"></div> <div class="unit">px</div> </div> <div class="param"> <div class="name">Rotate:</div> <div class="value" id="dataRotate"></div> <div class="unit">deg</div> </div> <div class="param"> <div class="name">ScaleX:</div> <div class="right-value" id="dataScaleX"></div> </div> <div class="param"> <div class="name">ScaleY:</div> <div class="right-value" id="dataScaleY"></div> </div> <div class="param"> <div class="name">W/H:</div> <div class="right-value" id="dataWH"></div> </div> </div> </div> <div class="btn-container" id="ratio_container"> <div class="btn" data-ratio="16/9">16/9</div> <div class="btn" data-ratio="4/3">4/3</div> <div class="btn" data-ratio="1">1/1</div> <div class="btn" data-ratio="2/3">2/3</div> <div class="btn" data-ratio="">Free</div> </div> <div class="btn-container" id="move_container"> <div class="btn" data-movex="0" data-movey="-10">上移</div> <div class="btn" data-movex="0" data-movey="10">下移</div> <div class="btn" data-movex="-10" data-movey="0">左移</div> <div class="btn" data-movex="10" data-movey="0">右移</div> </div> <div class="btn-container" id="zoom_container"> <div class="btn" data-zoom="0.1">放大</div> <div class="btn" data-zoom="-0.1" data-movey="10">縮小</div> </div> <div class="btn-container" id="rotate_container"> <div class="btn" data-rotate="45">順時針旋轉</div> <div class="btn" data-rotate="-45" data-movey="10">逆時針旋轉</div> </div> <div class="btn-container" id="scale_container"> <div class="btn" data-scale="x">左右翻轉</div> <div class="btn" data-scale="y" data-movey="10">上下翻轉</div> </div> <div class="btn-container"> <div class="btn" id="enable">可用</div> <div class="btn" id="disable">凍結</div> <div class="btn" id="reset1">重置1</div> <div class="btn" id="reset2">重置2</div> <div class="btn" id="clear">清空</div> <div class="btn" id="destroy">銷毀</div> <div class="btn"> <input class="input-upload" id="upload" type="file"> 上傳圖片 </div> </div> <div class="btn-container"> <div class="btn" id="replace">修改圖片地址</div> </div> <div class="btn-container"> <div class="btn" id="getCroppedCanvas">裁剪:get Cropped Canvas</div> </div> <div class="btn-container"> <div class="btn" id="submit">提交</div> </div> <img src="" id="test" width="500px" height="500px" alt=""> <div class="fixed-canvas hiddle"> <div class="fixed-bg"></div> <div class="canvas-container"> <h1>裁剪區域</h1> <div class="canvas" id="canvas"> </div> <div class="btn-container" id="modal_canvas_btn"> <a class="btn" href="javascript:;" >取消</a> <a class="btn" id="download" href="javascript:;" download="images/picture.jpg">下載</a> </div> </div> </div> </div> <script src="js/jquery-3.2.1.js"></script> <script src="js/cropper.js"></script> <script src="js/main.js"></script> </body> </html>
//main.css *{margin: 0;padding: 0;outline: none} *:active{-webkit-tap-highlight-color: rgba(0,0,0,0)} a{text-decoration: none} .disabled{pointer-events: none;opacity:.65} h1{font-size: 18px;margin-bottom: 20px} .hiddle{display: none!important;} .wrapper{margin: 20px auto;min-width: 1200px} .img-container{margin-left: 20px;display: inline-block;width: 600px;height: 342px;overflow: hidden;} .img-preview-container{margin-left: 10px;display: inline-block;vertical-align: top} .img-preview-container .img-preview{width: 300px;height: 171px;overflow: hidden;border: 1px #ccc solid} .img-preview-container img{border: 1px #aaa solid} .fixed-canvas{position: fixed;left: 50%;top:20px; width: 600px;margin-left: -300px;border:1px #aaa solid;border-radius: 6px;} .fixed-canvas .fixed-bg{position: fixed;left: 0%;top:0%;right:0;bottom:0;background: rgba(0,0,0,.6);z-index:1} .fixed-canvas .canvas-container{background: #fff;padding: 30px 20px;width: 100%;height: 100%;position: relative;z-index: 2;border-radius: 6px;box-sizing: border-box} .fixed-canvas .canvas-container .canvas{width: 456px;border: 1px #ccc solid} .fixed-canvas .canvas-container .canvas canvas{width: 100%} /*限制圖像寬度以避免容器溢出*/ .img-container img{max-width: 100%} /*這個規則很重要,請不要忽略這個*/ .text-container{display: inline-block;padding-left: 20px} .text-container .param-container{vertical-align: top} .param-container .param{display: inline-block;margin: 10px;width: 202px;height:33px;border: 1px #aaa solid;border-radius: 6px;box-sizing: border-box;font-size: 0} .param-container .param .name,.param-container .param .value,.param-container .param .unit,.param-container .param .right-value{display: inline-block;height:100%;box-sizing: border-box;text-align: center;color:#495057;vertical-align: top;font-size: 16px;line-height: 31px} .param-container .param .name,.param-container .param .unit{background: #ccc} .param-container .param .name{width: 80px} .param-container .param .value{width: 80px} .param-container .param .unit{width: 40px} .param-container .param .right-value{width: 120px;} .btn-container{margin: 20px;display: inline-block;height: 33px;background: #007bff;border-radius: 6px} .btn-container .btn{position: relative;padding: 0 20px;display: inline-block;height: 100%;vertical-align: top;color: #fff;line-height: 33px;cursor: pointer;overflow: hidden} .input-upload{position: absolute;top: 0;left: 0;bottom: 0;right: 0;display: inline-block;border: 1px red solid;opacity: 0;}
//main.js $(function () { 'use strict'; var $image = $('#image'); var $download = $('#download'); var $dataX = $('#dataX'); var $dataY = $('#dataY'); var $dataHeight = $('#dataHeight'); var $dataWidth = $('#dataWidth'); var $dataRotate = $('#dataRotate'); var $dataScaleX = $('#dataScaleX'); var $dataScaleY = $('#dataScaleY'); var $dataWH = $('#dataWH'); var options = { aspectRatio: 4 / 3,//設置裁切框的寬高比。默認情況下,裁剪框是自由比例。 preview: '.img-preview', crop: function (e) { $dataX.html(Math.round(e.x)); $dataY.html(Math.round(e.y)); $dataHeight.html(Math.round(e.height)); $dataWidth.html(Math.round(e.width)); $dataRotate.html(e.rotate); $dataScaleX.html(e.scaleX); $dataScaleY.html(e.scaleY); var _$dataWH = reductionTo(Math.round(e.width), Math.round(e.height)); $dataWH.html(_$dataWH[0] + '/' + _$dataWH[1]); } }; // 初始化函數 $image.cropper(options); $image.cropper({ built: function () { } }); // 修改裁剪比例函數 $('#ratio_container .btn').click(function (event) { event.stopPropagation(); var dataRatio = $(this).attr('data-ratio'); $image.cropper('destroy').cropper({'aspectRatio': dataRatio}); }); // 移動函數 $('#move_container .btn').click(function (event) { event.stopPropagation(); var dataMovex = parseInt($(this).attr('data-movex')); var dataMovey = parseInt($(this).attr('data-movey')); $image.cropper('move', dataMovex, dataMovey) }); // 移動函數 $('#move_container .btn').click(function (event) { event.stopPropagation(); var dataMovex = parseInt($(this).attr('data-movex')); var dataMovey = parseInt($(this).attr('data-movey')); $image.cropper('move', dataMovex, dataMovey) }); // Keyboard $(document.body).on('keydown', function (e) { if (!$image.data('cropper') || this.scrollTop > 300) { return; } switch (e.which) { case 37: e.preventDefault(); $image.cropper('move', -1, 0); break; case 38: e.preventDefault(); $image.cropper('move', 0, -1); break; case 39: e.preventDefault(); $image.cropper('move', 1, 0); break; case 40: e.preventDefault(); $image.cropper('move', 0, 1); break; } }); // 放大縮小 $('#zoom_container .btn').click(function (event) { event.stopPropagation(); var dataZoom = $(this).attr('data-zoom'); $image.cropper('zoom', dataZoom); }); // 旋轉 $('#rotate_container .btn').click(function (event) { event.stopPropagation(); var dataRotate = $(this).attr('data-rotate'); $image.cropper('rotate', dataRotate); }); // 翻轉 var scalexVal = 1; var scaleyVal = 1; $('#scale_container .btn').click(function (event) { event.stopPropagation(); var dataScale = $(this).attr('data-scale'); if (dataScale == 'x') { scalexVal = -scalexVal; $image.cropper('scaleX', scalexVal); } else if (dataScale == 'y') { scaleyVal = -scaleyVal; $image.cropper('scaleY', scaleyVal); } }); // enable():使cropper可用。 $('#enable').click(function (event) { event.stopPropagation(); $image.cropper('enable'); }); // disable():凍結cropper。 $('#disable').click(function (event) { event.stopPropagation(); $image.cropper('disable'); }); // reset():重置剪裁區域的圖片到初始狀態。 $('#reset1').click(function (event) { event.stopPropagation(); $image.cropper('crop'); $image.cropper('destroy').cropper({'preview': '.img-preview'}); }); $('#reset2').click(function (event) { event.stopPropagation(); $image.cropper('reset'); $image.cropper('destroy').cropper({'preview': '.img-preview'}); }); // clear():清空剪裁區域。 $('#clear').click(function (event) { event.stopPropagation(); $image.cropper('clear'); }); // destroy():銷毀剪裁函數。 $('#destroy').click(function (event) { event.stopPropagation(); $image.cropper('destroy'); }); //上傳圖片 $('#upload').change(function (event) { var files = this.files; if (files && files.length) { var file = files[0]; if (/\.(gif|jpg|jpeg|png|GIF|JPG|PNG)$/.test(file.name)) { var uploadedImageURL = window.URL.createObjectURL(file); $image.cropper('destroy').attr('src', uploadedImageURL).cropper(options); $download.attr('download', uploadedImageURL); $('#upload').val(''); } else { alert('請選擇正確的圖片格式!'); } } }); //修改圖片地址 var imgUrl = 'images/picture.jpg'; $('#replace').click(function (event) { event.stopPropagation(); imgUrl = (imgUrl == 'images/picture_new.jpg' ? 'images/picture.jpg' : 'images/picture_new.jpg'); $image.cropper('replace', imgUrl); $download.attr('download', imgUrl); }); // 輸出裁剪好的圖片 $('#getCroppedCanvas').click(function (event) { event.stopPropagation(); var imgurl = $image.cropper("getCroppedCanvas"); $("#canvas").html(imgurl); $download.attr('href', imgurl.toDataURL()); $('.fixed-canvas').removeClass('hiddle'); }); //點擊取消或者下載之后 $('#modal_canvas_btn .btn').click(function (event) { $('.fixed-canvas').addClass('hiddle'); }); // 獲取數據 $('#getData').click(function (event) { event.stopPropagation(); var getData = $image.cropper("getData") console.log(getData); }); //提交裁剪好的圖片到后台 $('#submit').click(function (event) { var imgData = $image.cropper("getCroppedCanvas").toDataURL(); // console.log(imgData); $.ajax({ url: '', dataType: 'json', type: "POST", data: {"image": imgData}, success: function () { console.log('Upload success'); }, error: function () { console.log('Upload error'); } }); }); }); function destory() { $image.cropper('destroy').cropper(options); } //m,n為正整數的分子和分母 function reductionTo(m, n) { var arr = []; if (!isInteger(m) || !isInteger(n)) { // console.log('m和n必須為整數'); arr[0] = 0; arr[1] = 0; return arr; } else if (m <= 0 || n <= 0) { // console.log('m和n必須大於0'); arr[0] = 0; arr[1] = 0; return arr; } var a = m; var b = n; (a >= b) ? (a = m, b = n) : (a = n, b = m); if (m != 1 && n != 1) { for (var i = b; i >= 2; i--) { if (m % i == 0 && n % i == 0) { m = m / i; n = n / i; } } } arr[0] = m; arr[1] = n; return arr; } //判斷一個數是否為整數 function isInteger(obj) { return obj % 1 === 0 }

