概述
在项目中,我们常常遇到图片裁剪的问题。不论是某个博文封面或者头像,都会用到裁剪。今天我们就来说说大致的思路。
图片准备
如果是写在项目中的裁剪,我们最好将它封成组件,这样在需要的地方方便调用。巧妇难为无米之炊,所以我们的第一步便是准备图片。
<input type="file" id="myfile" class="coverpic" accept="image/*" onchange="handleOnchange(this)"/>
<label for="myfile" class='btn'>Choose a file</label>
ps: input标签上传文件的样式不是很好看,故 lable 标签,在这里的作用便是将input与其关联,将input标签display:none;之后,自定义上传button样式。
在input的onChange事件回调中获取图片。
将图片转换为url
function fileToUrl() {
const imgFilter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i
if (url && typeof url === 'string') {
setSrc(url)
} else if (file && URL.createObjectURL && imgFilter.test(file[0].type)) {
setSrc(URL.createObjectURL(file[0]))
} else if (file && imgFilter.test(file[0].type)) {
const reader = new FileReader()
file && reader.readAsDataURL(file[0])
reader.onload = function(e: ProgressEvent) {
setSrc(get(e, 'target.result', ''))
}
}
}
图片转为url之后,变可以填入裁剪区域的img标签内。在这里有一个问题,就是假若裁剪区域为400*400,我们上传的照片大小不一,长宽比也不一致,那么填入img标签的宽高怎么设?
方案:比较长宽,哪个大,就把哪个缩小至400,另一个则根据大的缩小比例进行缩小。
裁剪框的移动及判断
在这里就拿左右移动作为例子,进行说明。
左右移动,即x轴上的移动,我们计算movx,即移动后e.clientX减去初始e.clientX再加上移动前裁剪框的左边距,也就是说,我们算的movx总是最新的左边距。同理,movy即是最新的上边距。
- 如果movy小于0 ,并且movx小于0,那说明现在在左上角,边界情况,不能再移动,故此我们设置裁剪框移动参数如下
setCropper({ top: 0,left: 0,})
- 边界情况2,movy小于0,并且movx>裁剪区域宽减去裁剪框的宽,这时说明,移动到最右
setCropper({ top: 0,left: 裁剪区域宽-裁剪框的宽-裁剪框的两个黑边})
- movy小于0,在除去上面两种情况的前提下,movx算是在正常区域移动,故设置如下
setCropper({ top: 0,left: moveX})
之后再对movy不能再向下移动的情况下,对x进行讨论。以及movx两种边界情况,进行讨论。
裁剪框拉伸处理
同样,画个图,对各种边界情况进行处理,改变裁剪框的大小信息。
结合裁剪信息和 cavans 进行图片导出
- canvas 宽高设置。
- drawImage传参
- imgge: 要处理的图片、视频
- sx: 开始剪切的x坐标位置
- sy: 开始剪切的y坐标位置
- swidth: 被剪切的图像的宽度
- sheight: 被剪切的图像的高度
- x:在画布上放置图像的x坐标位置
- y:在画布上放置的图像的y坐标位置
- width: 要使用的图像的宽度
- height: 要使用的图像的高度
function handleData() {
const image = new Image()
image.setAttribute('crossorigin', 'anonymous')
image.src = src
image.onload = function() {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.width = 122
shape === 'rectangle' ? (canvas.height = 91.5) : (canvas.height = 122)
ctx &&
ctx.drawImage(
image,
(left * originalW) / tailorWidth,
(top * originalH) / height,
(size * originalW) / tailorWidth,
(size * originalH) / height,
0,
0,
122,
122
)
setImgUrl(canvas.toDataURL('image/jpeg', 0.92))
}
}