Cropper.js 實(shí)現(xiàn)裁剪圖片并上傳(PC端)
由于之前做項(xiàng)目的時(shí)候有需求是需要實(shí)現(xiàn)裁剪圖片來(lái)做頭像并上傳到服務(wù)器,所以上網(wǎng)查詢(xún)了很多資料,也試用了許多案例,發(fā)現(xiàn)cropper插件裁剪是比較完善的,所以結(jié)合之前的使用情況,編寫(xiě)了此案例。本案例是參考cropper站點(diǎn)實(shí)例,進(jìn)行修改簡(jiǎn)化。
option相關(guān)參數(shù)說(shuō)明:
viewMode 顯示模式
Type: Number
Default: 0
Options:
0: the crop box is just within the container 裁剪框只能在 1內(nèi)移動(dòng)
1: the crop box should be within the canvas 裁剪框 只能在 2圖片內(nèi)移動(dòng)
2: the canvas should not be within the container 2圖片 不全部鋪滿1 (即縮小時(shí)可以有一邊出現(xiàn)空隙)
3: the container should be within the canvas 2圖片 全部鋪滿1 (即 再怎么縮小也不會(huì)出現(xiàn)空隙)
dragMode 拖動(dòng)模式
Default: ‘crop'
Options:
‘crop': create a new crop box 當(dāng)鼠標(biāo) 點(diǎn)擊一處時(shí)根據(jù)這個(gè)點(diǎn)重新生成一個(gè) 裁剪框
‘move': move the canvas 可以拖動(dòng)圖片
‘none': do nothing 圖片就不能拖動(dòng)了
toggleDragModeOnDblclick: 默認(rèn)true .是否允許 拖動(dòng)模式 “crop” 跟“move” 的切換狀態(tài)。。即當(dāng)點(diǎn)下為crop 模式,如果未松開(kāi)拖動(dòng)這時(shí)就是“move”模式。放開(kāi)后又為“crop”模式。
preview: 截圖的顯示位置。類(lèi)型:String
responsive:是否在窗口尺寸改變的時(shí)候重置cropper。類(lèi)型:Boolean,默認(rèn)值true。
checkImageOrigin:類(lèi)型:Boolean,默認(rèn)值true。默認(rèn)情況下,插件會(huì)檢測(cè)圖片的源,如果是跨域圖片,圖片元素會(huì)被添加crossOriginclass,并會(huì)為圖片的url添加一個(gè)時(shí)間戳來(lái)使getCroppedCanvas變?yōu)榭捎谩L砑訒r(shí)間戳?xí)箞D片重新加載,以使跨域圖片能夠使用getCroppedCanvas。在圖片上添加crossOriginclass會(huì)阻止在圖片url上添加時(shí)間戳,及圖片的重新加載。
background:類(lèi)型:Boolean,默認(rèn)值true。是否在容器上顯示網(wǎng)格背景。 要想改背景,是直接改,cropper.css樣式中的 cropper-bg。
canvas(圖片)相關(guān)
movable:類(lèi)型:Boolean,默認(rèn)值true。是否允許移動(dòng)圖片
rotatable:類(lèi)型:Boolean,默認(rèn)值true。是否允許旋轉(zhuǎn)圖片。
scalable: 默認(rèn) true 。 是否允許擴(kuò)展圖片。(暫時(shí)不知道干嘛用)
zoomable: 默認(rèn)true, 石頭允許縮放圖片。
zoomOnWheel: 默認(rèn) true 是否允許鼠標(biāo)滾軸 縮放圖片
zoomOnTouch: 默認(rèn)true 是否允許觸摸縮放圖片(觸摸屏上兩手指操作。)
wheelZoomRatio: 默認(rèn)0.1 師表滾軸縮放圖片比例。即滾一下。圖片縮放多少。如 0.1 就是圖片的10%
crop(裁剪框)相關(guān)
aspectRatio裁剪框比例 默認(rèn)NaN
例如:: 1 / 1,//裁剪框比例 1:1
modal:類(lèi)型:Boolean,默認(rèn)值true。是否在剪裁框上顯示黑色的模態(tài)窗口。
cropBoxMovable:默認(rèn)true ,是否允許拖動(dòng)裁剪框
cropBoxResizable:默認(rèn) true,//是否允許拖動(dòng) 改變裁剪框大小
autoCrop:類(lèi)型:Boolean,默認(rèn)值true。是否允許在初始化時(shí)自動(dòng)出現(xiàn)裁剪框。
autoCropArea:類(lèi)型:Number,默認(rèn)值0.8(圖片的80%)。0-1之間的數(shù)值,定義自動(dòng)剪裁框的大小。
highlight:類(lèi)型:Boolean,默認(rèn)值true。是否在剪裁框上顯示白色的模態(tài)窗口。
guides:類(lèi)型:Boolean,默認(rèn)值true。是否在剪裁框上顯示虛線。
center: 默認(rèn)true 是否顯示裁剪框 中間的+ restore : 類(lèi)型:Boolean,默認(rèn)值true 是否
調(diào)整窗口大小后恢復(fù)裁剪區(qū)域。
大小相關(guān)
minContainerWidth:類(lèi)型:Number,默認(rèn)值200。容器的最小寬度。
minContainerHeight:類(lèi)型:Number,默認(rèn)值100。容器的最小高度。
minCanvasWidth:類(lèi)型:Number,默認(rèn)值0。canvas 的最小寬度(image wrapper)。
minCanvasHeight:類(lèi)型:Number,默認(rèn)值0。canvas 的最小高度(image wrapper)。
監(jiān)聽(tīng)觸發(fā)的方法
build:類(lèi)型:Function,默認(rèn)值null。build.cropper
事件的簡(jiǎn)寫(xiě)方式。 ====== ??丶跏蓟皥?zhí)行
built:類(lèi)型:Function,默認(rèn)值null。built.cropper
事件的簡(jiǎn)寫(xiě)方式。 ====== 空間初始化完成后執(zhí)行
dragstart:類(lèi)型:Function,默認(rèn)值null。dragstart.cropper
事件的簡(jiǎn)寫(xiě)方式。 ====== 拖動(dòng)開(kāi)始執(zhí)行
dragmove:類(lèi)型:Function,默認(rèn)值null。dragmove.cropper
事件的簡(jiǎn)寫(xiě)方式。====== 拖動(dòng)移動(dòng)中執(zhí)行
dragend:類(lèi)型:Function,默認(rèn)值null。dragend.cropper
事件的簡(jiǎn)寫(xiě)方式。====== 拖動(dòng)結(jié)束執(zhí)行
zoomin:類(lèi)型:Function,默認(rèn)值null。zoomin.cropper
事件的簡(jiǎn)寫(xiě)方式。 ====== 縮小執(zhí)行
zoomout:類(lèi)型:Function,默認(rèn)值null。zoomout.cropper
事件的簡(jiǎn)寫(xiě)方式。 ====== 放大執(zhí)行
index.html代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" rel="external nofollow" >
<link rel="stylesheet" href="css/cropper.css" rel="external nofollow" >
<link rel="stylesheet" href="css/main.css" rel="external nofollow" >
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!--[if lt IE 8]>
<p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a rel="external nofollow" >upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<!-- Content -->
<div class="container" style="margin-top:50px;">
<div class="row">
<div class="col-md-9">
<!-- <h3>Demo:</h3> -->
<div class="img-container">

</div>
</div>
<div class="col-md-3">
<!-- <h3>Preview:</h3> -->
<div class="docs-preview clearfix">
<div class="img-preview preview-lg"></div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-9 docs-buttons">
<!-- <h3>Toolbar:</h3> -->
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="zoom" data-option="0.1" title="Zoom In">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("zoom", 0.1)">
放大
</span>
</button>
<button type="button" class="btn btn-primary" data-method="zoom" data-option="-0.1" title="Zoom Out">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("zoom", -0.1)">
縮小
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="move" data-option="-10" data-second-option="0" title="Move Left">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("move", -10, 0)">
左移
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="10" data-second-option="0" title="Move Right">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("move", 10, 0)">
右移
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="0" data-second-option="-10" title="Move Up">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("move", 0, -10)">
上移
</span>
</button>
<button type="button" class="btn btn-primary" data-method="move" data-option="0" data-second-option="10" title="Move Down">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("move", 0, 10)">
下移
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="rotate" data-option="-90" title="Rotate Left">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("rotate", -90)">
左轉(zhuǎn)90º
</span>
</button>
<button type="button" class="btn btn-primary" data-method="rotate" data-option="90" title="Rotate Right">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("rotate", 90)">
右轉(zhuǎn)90º
</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-primary" data-method="reset" title="Reset">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="$().cropper("reset")">
刷新
</span>
</button>
<label class="btn btn-primary btn-upload" for="inputImage" title="Upload image file">
<input type="file" class="sr-only" id="inputImage" name="file" accept=".jpg,.jpeg,.png,.gif,.bmp,.tiff">
<span class="docs-tooltip" data-toggle="tooltip" data-animation="false" title="Import image with Blob URLs">
上傳圖片
</span>
</label>
</div>
<div class="btn-group btn-group-crop">
<button class="btn btn-primary" data-method="getCroppedCanvas" data-option="{ "width": 180, "height": 90 }" type="button">
上傳頭像
</button>
</div>
<!-- Show the cropped image in modal -->
<div class="modal fade docs-cropped" id="getCroppedCanvasModal" aria-hidden="true" aria-labelledby="getCroppedCanvasTitle" role="dialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="getCroppedCanvasTitle">Cropped</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<a class="btn btn-primary" id="download" href="javascript:void(0);" rel="external nofollow" download="cropped.jpg">Download</a>
</div>
</div>
</div>
</div><!-- /.modal -->
</div><!-- /.docs-buttons -->
</div>
<!-- Scripts -->
<script src="js/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="js/cropper.js"></script>
<script src="js/main.js"></script>
</body>
</html>
cropper.js部分參數(shù)代碼:
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('jquery')) :
typeof define === 'function' && define.amd ? define(['jquery'], factory) :
(factory(global.$));
}(this, (function ($) { 'use strict';
$ = 'default' in $ ? $['default'] : $;
var DEFAULTS = {
// Define the view mode of the cropper
viewMode: 0, // 0, 1, 2, 3 顯示
// Define the dragging mode of the cropper
dragMode: 'crop', // 'crop', 'move' or 'none'
// Define the aspect ratio of the crop box
aspectRatio: NaN,
// An object with the previous cropping result data
data: null,
// A selector for adding extra containers to preview
preview: '',
// Re-render the cropper when resize the window
responsive: true,
// Restore the cropped area after resize the window
restore: true,
// Check if the current image is a cross-origin image
checkCrossOrigin: true,
// Check the current image's Exif Orientation information
checkOrientation: true,
// Show the black modal
modal: true,
// Show the dashed lines for guiding
guides: true,
// Show the center indicator for guiding
center: true,
// Show the white modal to highlight the crop box
highlight: true,
// Show the grid background
background: true,
// Enable to crop the image automatically when initialize
autoCrop: true,
// Define the percentage of automatic cropping area when initializes
autoCropArea: 0.8,
// Enable to move the image
movable: true,
// Enable to rotate the image
rotatable: true,
// Enable to scale the image
scalable: true,
// Enable to zoom the image
zoomable: true,
// Enable to zoom the image by dragging touch
zoomOnTouch: true,
// Enable to zoom the image by wheeling mouse
zoomOnWheel: true,
// Define zoom ratio when zoom the image by wheeling mouse
wheelZoomRatio: 0.1,
// Enable to move the crop box
cropBoxMovable: true,
// Enable to resize the crop box
cropBoxResizable: true,
// Toggle drag mode between "crop" and "move" when click twice on the cropper
toggleDragModeOnDblclick: true,
// Size limitation
minCanvasWidth: 0,
minCanvasHeight: 0,
minCropBoxWidth: 0,
minCropBoxHeight: 0,
minContainerWidth: 200,
minContainerHeight: 100,
// Shortcuts of events
ready: null,
cropstart: null,
cropmove: null,
cropend: null,
crop: null,
zoom: null
};
main.js 代碼如下:
$(function () {
'use strict';//表示強(qiáng)規(guī)則
var console = window.console || { log: function () {} };
var URL = window.URL || window.webkitURL;
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 options = {
aspectRatio: 1 / 1, //裁剪框比例1:1
preview: '.img-preview',
crop: function (e) {
$dataX.val(Math.round(e.x));
$dataY.val(Math.round(e.y));
$dataHeight.val(Math.round(e.height));
$dataWidth.val(Math.round(e.width));
$dataRotate.val(e.rotate);
$dataScaleX.val(e.scaleX);
$dataScaleY.val(e.scaleY);
}
};
var originalImageURL = $image.attr('src');
var uploadedImageURL;
// Tooltip
$('[data-toggle="tooltip"]').tooltip();
// Cropper
$image.on({
ready: function (e) {
console.log(e.type);
},
cropstart: function (e) {
console.log(e.type, e.action);
},
cropmove: function (e) {
console.log(e.type, e.action);
},
cropend: function (e) {
console.log(e.type, e.action);
},
crop: function (e) {
console.log(e.type, e.x, e.y, e.width, e.height, e.rotate, e.scaleX, e.scaleY);
},
zoom: function (e) {
console.log(e.type, e.ratio);
}
}).cropper(options);
// Buttons
if (!$.isFunction(document.createElement('canvas').getContext)) {
$('button[data-method="getCroppedCanvas"]').prop('disabled', true);
}
if (typeof document.createElement('cropper').style.transition === 'undefined') {
$('button[data-method="rotate"]').prop('disabled', true);
$('button[data-method="scale"]').prop('disabled', true);
}
// Download
if (typeof $download[0].download === 'undefined') {
$download.addClass('disabled');
}
// Options
$('.docs-toggles').on('change', 'input', function () {
var $this = $(this);
var name = $this.attr('name');
var type = $this.prop('type');
var cropBoxData;
var canvasData;
if (!$image.data('cropper')) {
return;
}
if (type === 'checkbox') {
options[name] = $this.prop('checked');
cropBoxData = $image.cropper('getCropBoxData');
canvasData = $image.cropper('getCanvasData');
options.ready = function () {
$image.cropper('setCropBoxData', cropBoxData);
$image.cropper('setCanvasData', canvasData);
};
} else if (type === 'radio') {
options[name] = $this.val();
}
$image.cropper('destroy').cropper(options);
});
// Methods
// 點(diǎn)擊開(kāi)始計(jì)算圖片位置,獲取位置
$('.docs-buttons').on('click', '[data-method]', function () {
var $this = $(this);
var data = $this.data();
var $target;
var result;
if ($this.prop('disabled') || $this.hasClass('disabled')) {
return;
}
if ($image.data('cropper') && data.method) {
data = $.extend({}, data); // Clone a new one
if (typeof data.target !== 'undefined') {
$target = $(data.target);
if (typeof data.option === 'undefined') {
try {
data.option = JSON.parse($target.val());
} catch (e) {
console.log(e.message);
}
}
}
if (data.method === 'rotate') {
$image.cropper('clear');
}
result = $image.cropper(data.method, data.option, data.secondOption);
if (data.method === 'rotate') {
$image.cropper('crop');
}
switch (data.method) {
case 'scaleX':
case 'scaleY':
$(this).data('option', -data.option);
break;
case 'getCroppedCanvas':
//上傳頭像
if (result) {
var imgBase=result.toDataURL('image/jpeg');
var data={imgBase:imgBase};
$.post('/docs/upload.php',data,function(ret){
if(ret=='true'){
alert('上傳成功');
}else{
alert('上傳失敗');
}
},'text');
}
break;
case 'destroy':
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
uploadedImageURL = '';
$image.attr('src', originalImageURL);
}
break;
}
if ($.isPlainObject(result) && $target) {
try {
$target.val(JSON.stringify(result));
} catch (e) {
console.log(e.message);
}
}
}
});
// 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;
}
});
// Import image
var $inputImage = $('#inputImage');
if (URL) {
$inputImage.change(function () {
var files = this.files;
var file;
if (!$image.data('cropper')) {
return;
}
if (files && files.length) {
file = files[0];
if (/^image\/\w+$/.test(file.type)) {
if (uploadedImageURL) {
URL.revokeObjectURL(uploadedImageURL);
}
uploadedImageURL = URL.createObjectURL(file);
$image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
$inputImage.val('');
} else {
window.alert('Please choose an image file.');
}
}
});
} else {
$inputImage.prop('disabled', true).parent().addClass('disabled');
}
});
使用canvas生成的截圖轉(zhuǎn)換生成base64代碼。
后臺(tái)處理base64代碼片段(PHP服務(wù)端)。
upload.php代碼如下:
<?php
error_reporting(0);//禁用錯(cuò)誤報(bào)告
if (IS_POST) {
header('Content-type:text/html;charset=utf-8');
$base64_image_content = $_POST['imgBase'];
//將base64編碼轉(zhuǎn)換為圖片保存
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
$type = $result[2];
$new_file = "./uploads/";
if (!file_exists($new_file)) {
//檢查是否有該文件夾,如果沒(méi)有就創(chuàng)建,并給予最高權(quán)限
mkdir($new_file, 0700);
}
$img=time() . ".{$type}";
$new_file = $new_file . $img;
//將圖片保存到指定的位置
if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))) {
echo 'true';
}else{
echo 'false';
}
}else{
echo 'false';
}
}
?>
實(shí)現(xiàn)效果:

選擇要截取的圖片位置,按“上傳頭像”按鈕,截取的圖片就上傳并保存到服務(wù)器本站點(diǎn)目錄的uploads文件夾中。
總結(jié)
以上所述是小編給大家介紹的Cropper.js 實(shí)現(xiàn)裁剪圖片并上傳(PC端) ,希望對(duì)大家有所幫助,
相關(guān)文章
JavaScript async&await方法中的異常處理方案
在 async/await 方法中,可以使用 try-catch 塊來(lái)處理異常,通過(guò)使用 try-catch,可以捕獲異步操作中拋出的異常,并在 catch 塊中進(jìn)行適當(dāng)?shù)奶幚?本文給大家詳細(xì)介紹了async&await方法中異常如何處理,需要的朋友可以參考下2023-08-08
小程序?qū)崿F(xiàn)分頁(yè)查詢(xún)列表的模板
這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)分頁(yè)查詢(xún)列表的模板,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
30個(gè)高逼格代碼的JavaScript高級(jí)單行代碼
這篇文章中列出了一個(gè)系列的 30 個(gè) JavaScript 單行代碼,它們?cè)谑褂?nbsp;vanilla js(≥ ES6)進(jìn)行開(kāi)發(fā)時(shí)非常有用,它們也是使用該語(yǔ)言在最新版本中為我們提供的所有功能來(lái)解決問(wèn)題的優(yōu)雅方式,將它們分為以下5大類(lèi):日期、字符串、數(shù)字、數(shù)組、工具2023-08-08
用js+iframe形成頁(yè)面的一種遮罩效果的具體實(shí)現(xiàn)
用js形成頁(yè)面的一種遮罩效果,選擇想要進(jìn)行遮罩的窗口,在這里想要遮罩的是一個(gè)iframe窗口,具體的實(shí)現(xiàn)如下,感興趣的朋友可以參參考下2013-12-12
iframe子頁(yè)面與父頁(yè)面在同域或不同域下的js通信
根據(jù)iframe中src屬性是同域鏈接還是跨域鏈接,通信方式也不同,下面有個(gè)不錯(cuò)的示例,需要的朋友可以參考下2014-05-05

