1. 前言
在现代 Web 应用中,图片裁剪是一个常见需求,无论是头像上传、封面设置还是商品图片处理,都需要直观、高效的裁剪工具。Cropper.js 作为一款优秀的 JavaScript 图片裁剪库,以其轻量、灵活和功能丰富的特点,成为开发者的首选工具。
Cropper.js 是一个基于 HTML5 Canvas 的图片裁剪库,具有以下特点:
- 轻量级,核心文件仅约 80KB
- 支持多种裁剪形状(矩形、圆形等)
- 支持缩放、旋转、平移等操作
- 支持触摸设备,适配移动界面
- 提供丰富的 API,便于自定义
- 无外部依赖,可独立使用
- 支持多种图片格式输入输出
2. 快速开始
Cropper.js 提供多种安装方式:
1. CDN 引入
html
<!-- 引入 CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.css">
<!-- 引入 JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.6.1/cropper.min.js"></script>
2. npm 安装
bash
npm install cropperjs --save
引入方式:
javascript
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';
2.1. 基本用法
使用 Cropper.js 实现图片裁剪只需几个简单步骤:
- 创建基本 HTML 结构:
html
<!-- 原始图片容器 -->
<div>
<img id="image" src="sample.jpg" alt="待裁剪图片">
</div>
<!-- 裁剪结果预览 -->
<div>
<h3>预览:</h3>
<div id="preview" style="width: 200px; height: 200px; overflow: hidden;"></div>
</div>
<!-- 操作按钮 -->
<button id="cropBtn">裁剪图片</button>
- 初始化 Cropper 实例:
javascript
// 获取图片元素
const image = document.getElementById('image');
// 初始化裁剪器
const cropper = new Cropper(image, {
aspectRatio: 1, // 裁剪框宽高比 1:1
viewMode: 1, // 视图模式
preview: '#preview', // 预览容器
guides: true, // 显示裁剪框虚线
autoCropArea: 0.8, // 自动裁剪区域占图片的比例
movable: true, // 是否可以移动图片
rotatable: true, // 是否可以旋转图片
scalable: true, // 是否可以缩放图片
zoomable: true, // 是否可以放大缩小图片
});
- 实现裁剪功能:
javascript
// 裁剪按钮点击事件
document.getElementById('cropBtn').addEventListener('click', () => {
// 获取裁剪后的图片数据URL
const croppedCanvas = cropper.getCroppedCanvas({
width: 400, // 裁剪后图片宽度
height: 400, // 裁剪后图片高度
fillColor: '#fff' // 填充色
});
// 将裁剪结果显示在页面上
const result = document.createElement('img');
result.src = croppedCanvas.toDataURL('image/jpeg');
document.body.appendChild(result);
// 也可以获取 Blob 对象用于上传
croppedCanvas.toBlob((blob) => {
// 在这里可以将 blob 上传到服务器
console.log('裁剪后的图片 Blob 对象', blob);
}, 'image/jpeg');
});
3. 核心配置选项
Cropper.js 提供了丰富的配置选项,让你可以精确控制裁剪行为:
3.1. 基本配置
javascript
const cropper = new Cropper(image, {
// 裁剪框的宽高比,1表示正方形,16/9表示宽屏
aspectRatio: 1,
// 视图模式,控制裁剪框是否可以超出图片范围
// 0: 无限制 1: 限制裁剪框在图片内 2: 限制裁剪框在图片内且图片填充模式
// 3: 限制裁剪框在图片内且图片必须完全可见
viewMode: 1,
// 拖动模式,'crop' 拖动裁剪框,'move' 拖动图片,'none' 不可拖动
dragMode: 'crop',
// 自动裁剪区域大小(0-1)
autoCropArea: 0.8,
// 是否显示裁剪框
autoCrop: true,
// 是否可以调整裁剪框大小
resizable: true,
// 是否可以移动裁剪框
movable: true,
});
3.2. 样式配置
javascript
const cropper = new Cropper(image, {
// 裁剪框的样式
cropBoxBorderColor: '#ff6600',
cropBoxBorderWidth: 2,
// 虚线的样式
guides: true, // 是否显示
guideColor: '#39f',
guideLineWidth: 1,
// 遮罩层样式
background: true, // 是否显示
maskColor: 'rgba(0, 0, 0, 0.5)',
// 点的样式(调整裁剪框大小时显示)
cropBoxMovable: true,
cropBoxResizable: true,
cornerColor: '#39f',
cornerStrokeColor: '#fff',
cornerSize: 15,
cornerRadius: 5,
});
3.3. 预览与多比例裁剪
javascript
const cropper = new Cropper(image, {
// 多个预览容器
preview: [
'#preview-small',
'#preview-medium',
'#preview-large'
],
// 支持多种裁剪比例切换
aspectRatio: NaN, // 设为NaN允许自由比例
responsive: true, // 响应式调整
restore: true, // 调整窗口大小时恢复裁剪区域
});
4. 常用 API 方法
Cropper.js 提供了丰富的 API 方法,用于控制裁剪器的各种操作:
4.1. 裁剪相关
javascript
// 获取裁剪后的Canvas对象
const canvas = cropper.getCroppedCanvas({
width: 400,
height: 400,
minWidth: 200,
minHeight: 200,
maxWidth: 800,
maxHeight: 800,
fillColor: '#fff',
imageSmoothingQuality: 'high'
});
// 转换为DataURL
const dataUrl = canvas.toDataURL('image/jpeg', 0.9);
// 转换为Blob对象
canvas.toBlob((blob) => {
// 处理blob对象,如上传到服务器
}, 'image/jpeg', 0.9);
4.2. 图片操作
javascript
// 旋转图片
cropper.rotate(90); // 顺时针旋转90度
cropper.rotate(-90); // 逆时针旋转90度
// 缩放图片
cropper.zoom(0.1); // 放大10%
cropper.zoom(-0.1); // 缩小10%
// 翻转图片
cropper.scaleX(-1); // 水平翻转
cropper.scaleY(-1); // 垂直翻转
// 重置图片
cropper.reset();
// 替换图片
cropper.replace('new-image.jpg');
4.3. 裁剪框操作
javascript
// 设置裁剪框位置和大小
cropper.setData({
x: 100,
y: 100,
width: 200,
height: 200,
rotate: 0,
scaleX: 1,
scaleY: 1
});
// 获取裁剪框数据
const data = cropper.getData();
// 移动裁剪框
cropper.move(10, 10); // 向右下移动10px
// 调整裁剪框大小
cropper.resize(100, 100); // 设置宽高为100px
5. 事件处理
Cropper.js 提供了多种事件,让你可以在裁剪过程中执行自定义逻辑:
javascript
const cropper = new Cropper(image, {
// 当裁剪区域发生变化时触发
crop: function(e) {
console.log('裁剪区域变化:', e.detail);
// e.detail包含裁剪区域的位置、大小等信息
},
// 当开始拖动裁剪框或图片时触发
start: function(e) {
console.log('开始拖动:', e.type, e.detail.action);
},
// 当结束拖动时触发
end: function(e) {
console.log('结束拖动:', e.type, e.detail.action);
},
// 当图片加载完成时触发
ready: function(e) {
console.log('图片加载完成');
},
// 当图片被缩放时触发
zoom: function(e) {
console.log('缩放比例:', e.detail.ratio);
}
});
也可以通过 on()
方法动态绑定事件:
javascript
cropper.on('cropend', function(e) {
console.log('裁剪结束');
});
// 解绑事件
cropper.off('cropend');
6. 实际应用场景
下面是一些实际应用场景模拟:
6.1. 头像上传与裁剪
html
<div>
<input type="file" id="fileInput" accept="image/*">
<div id="imageContainer" style="display: none;">
<img id="avatar" src="" alt="头像">
<div class="controls">
<button id="rotateLeft">向左旋转</button>
<button id="rotateRight">向右旋转</button>
<button id="zoomIn">放大</button>
<button id="zoomOut">缩小</button>
<button id="confirmCrop">确认裁剪</button>
</div>
<div id="avatarPreview" style="width: 150px; height: 150px; overflow: hidden;"></div>
</div>
<div id="result"></div>
</div>
javascript
let cropper;
const fileInput = document.getElementById('fileInput');
const imageContainer = document.getElementById('imageContainer');
const avatar = document.getElementById('avatar');
const result = document.getElementById('result');
// 监听文件选择
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
if (!file) return;
// 读取文件并显示
const reader = new FileReader();
reader.onload = (e) => {
avatar.src = e.target.result;
imageContainer.style.display = 'block';
// 销毁之前的裁剪器实例
if (cropper) {
cropper.destroy();
}
// 初始化裁剪器,1:1比例适合头像
cropper = new Cropper(avatar, {
aspectRatio: 1,
viewMode: 1,
preview: '#avatarPreview',
autoCropArea: 0.8,
});
};
reader.readAsDataURL(file);
});
// 旋转控制
document.getElementById('rotateLeft').addEventListener('click', () => {
cropper.rotate(-45);
});
document.getElementById('rotateRight').addEventListener('click', () => {
cropper.rotate(45);
});
// 缩放控制
document.getElementById('zoomIn').addEventListener('click', () => {
cropper.zoom(0.1);
});
document.getElementById('zoomOut').addEventListener('click', () => {
cropper.zoom(-0.1);
});
// 确认裁剪
document.getElementById('confirmCrop').addEventListener('click', () => {
// 获取裁剪后的图片
const canvas = cropper.getCroppedCanvas({
width: 300,
height: 300,
});
// 显示结果
result.innerHTML = '';
const img = document.createElement('img');
img.src = canvas.toDataURL('image/jpeg');
img.style.maxWidth = '100%';
result.appendChild(img);
// 这里可以将 canvas 转换为 Blob 并上传到服务器
canvas.toBlob((blob) => {
const formData = new FormData();
formData.append('avatar', blob, 'avatar.jpg');
// 上传逻辑
/*
fetch('/upload-avatar', {
method: 'POST',
body: formData
}).then(response => {
// 处理上传结果
});
*/
});
});
6.2. 多比例裁剪工具
实现一个支持多种比例切换的图片裁剪工具:
html
<div>
<select id="ratioSelect">
<option value="1">1:1 (正方形)</option>
<option value="1.777">16:9 (宽屏)</option>
<option value="0.75">3:4 (竖屏)</option>
<option value="NaN">自由比例</option>
</select>
<img id="photo" src="sample.jpg" alt="图片">
<button id="applyCrop">应用裁剪</button>
</div>
javascript
const image = document.getElementById('photo');
const ratioSelect = document.getElementById('ratioSelect');
// 初始化裁剪器
const cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 2,
});
// 监听比例选择变化
ratioSelect.addEventListener('change', () => {
const ratio = parseFloat(ratioSelect.value);
cropper.setAspectRatio(ratio);
});
// 应用裁剪
document.getElementById('applyCrop').addEventListener('click', () => {
const canvas = cropper.getCroppedCanvas();
// 替换原图为裁剪后的图片
image.src = canvas.toDataURL();
// 重新初始化裁剪器
cropper.destroy();
cropper = new Cropper(image, {
aspectRatio: parseFloat(ratioSelect.value),
viewMode: 2,
});
});
7. 与前端框架集成
下面介绍如何和常用前端框架集成:
7.1. 与 React 集成
jsx
import React, { useRef, useState, useEffect } from 'react';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';
function ImageCropper({ imageUrl, onCropComplete }) {
const imageRef = useRef(null);
const [cropper, setCropper] = useState(null);
// 初始化裁剪器
useEffect(() => {
if (imageRef.current && imageUrl) {
const newCropper = new Cropper(imageRef.current, {
aspectRatio: 1,
viewMode: 1,
autoCropArea: 0.8,
});
setCropper(newCropper);
// 清理函数
return () => {
newCropper.destroy();
};
}
}, [imageUrl]);
// 执行裁剪
const handleCrop = () => {
if (cropper) {
const canvas = cropper.getCroppedCanvas({
width: 400,
height: 400,
});
canvas.toBlob(blob => {
onCropComplete(blob);
}, 'image/jpeg');
}
};
return (
<div>
<img ref={imageRef} src={imageUrl} alt="待裁剪" style={{ maxWidth: '100%' }} />
<button onClick={handleCrop}>完成裁剪</button>
</div>
);
}
export default ImageCropper;
7.2. 与 Vue 集成
vue
<template>
<div>
<img
ref="image"
:src="imageUrl"
alt="待裁剪图片"
style="max-width: 100%;"
>
<button @click="cropImage">裁剪图片</button>
</div>
</template>
<script>
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';
export default {
props: {
imageUrl: String
},
data() {
return {
cropper: null
};
},
mounted() {
if (this.imageUrl) {
this.initCropper();
}
},
watch: {
imageUrl(newVal) {
// 图片URL变化时重新初始化
if (this.cropper) {
this.cropper.destroy();
}
this.initCropper();
}
},
methods: {
initCropper() {
this.cropper = new Cropper(this.$refs.image, {
aspectRatio: 16 / 9,
viewMode: 1,
});
},
cropImage() {
if (this.cropper) {
const canvas = this.cropper.getCroppedCanvas();
canvas.toBlob(blob => {
this.$emit('crop-complete', blob);
});
}
}
},
beforeUnmount() {
if (this.cropper) {
this.cropper.destroy();
}
}
};
</script>
8. 常见问题及解决方案
下面是一些常见问题及解决方案:
8.1. 图片跨域问题
当裁剪跨域图片时,可能会遇到画布污染问题,导致无法获取裁剪结果。解决方案:
html
<!-- 添加 crossOrigin 属性 -->
<img src="https://example.com/image.jpg" crossOrigin="anonymous">
javascript
// 初始化时设置 checkCrossOrigin
const cropper = new Cropper(image, {
checkCrossOrigin: true,
// 其他配置...
});
8.2. 图片加载顺序问题
确保图片完全加载后再初始化裁剪器:
javascript
const image = document.getElementById('image');
// 确保图片加载完成
if (image.complete) {
initCropper();
} else {
image.addEventListener('load', initCropper);
}
function initCropper() {
const cropper = new Cropper(image, {
// 配置...
});
}
8.3. 响应式布局适配
在窗口大小变化时调整裁剪器:
javascript
const cropper = new Cropper(image, {
responsive: true,
restore: true,
});
// 手动触发调整(如果需要)
window.addEventListener('resize', () => {
cropper.resize();
});
8.4. 移动设备适配
优化移动设备上的裁剪体验:
javascript
const cropper = new Cropper(image, {
// 移动设备上禁用鼠标滚轮缩放(避免冲突)
zoomOnWheel: !(/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)),
// 触摸缩放灵敏度
wheelZoomRatio: 0.1,
// 支持触摸操作
touchDragZoom: true,
// 拖动模式自动切换
dragMode: 'auto',
});
通过本文介绍的基本用法、核心配置和实际应用场景,你应该已经掌握了如何利用 Cropper.js 实现专业级的图片裁剪功能。
要了解更多关于 Cropper.js 的信息,可以访问其 官方文档 获取最新的 API 参考和示例。
本次分享就到这儿啦,我是鹏多多,如果看了觉得有帮助的,欢迎 点赞 关注 评论,在此谢过道友;
往期文章