当前位置:   article > 正文

uniapp图片裁剪插件开发整理

uniapp图片裁剪

工作之余,把工作中需要用的一个小工具封装成uniapp插件分享给大家!!! 

图片裁剪 

使用场景:

  • 头像裁剪、对照片尺寸有特定要求的;

实现思路:

  1. 布局: 做上下两层展示,下层展示一张亮度低一点全图,充当遮住部分(效果可以自定义比如说高斯模糊等);上层展示裁剪部分图片,这里显示原图高亮部分;
  2. 拖拽控制裁剪区域:通过手指拖动来控制裁剪框移动,并动态改变框里的背景图显示位置来做到跟底图同步的效果,放大/缩小框也是同样道理;
  3. 利用canvas绘图功能把需要裁剪的图片绘制到画布上;
  4. 最后保存图片完成裁剪,so easy
插件截图1
插件截图2

实现过程: 

1、首先,把要裁剪的图片渲染到组件里作为底图,并根据视图大小来确定底图的大小和裁剪框可移动的区域范围; 

  1. <view class="image-box"
  2. :style="{
  3. backgroundImage: 'url('+ src +')',
  4. width: imageBoxWidth + 'px',
  5. height: imageBoxHeight + 'px',
  6. }">
  7. <view class="mask"></view>
  8. </view>
  9. </view>
  1. windowInfo = uni.getWindowInfo();
  2. uni.getImageInfo({
  3. src: this.src,
  4. success: (res) => {
  5. imageOriginalWidth = res.width;
  6. imageOriginalHeight = res.height;
  7. let widthZoomRatio = imageOriginalWidth / windowInfo.windowWidth;
  8. let heightZoomRatio = imageOriginalHeight / windowInfo.windowHeight;
  9. imageZoomRatio = widthZoomRatio > heightZoomRatio ? widthZoomRatio : heightZoomRatio;
  10. this.imageBoxWidth = imageOriginalWidth / imageZoomRatio;
  11. this.imageBoxHeight = imageOriginalHeight / imageZoomRatio;
  12. this.setRatio('1:1');
  13. }
  14. })

2、在底图上方绘制裁剪框(蓝色框),并绑定事件可控制大小和位置,这里为了裁剪框的区域图是高亮的,也需要给裁剪框加一个底图背景;

  1. <view
  2. class="cropping-box"
  3. @touchstart.stop="touchstart"
  4. @touchmove.stop="touchmove"
  5. :style="{
  6. top: cropBoxY + 'px',
  7. left: cropBoxX + 'px',
  8. width: cropBoxWidth + 'px',
  9. height: cropBoxHeight + 'px',
  10. backgroundImage: 'url('+ src +')',
  11. backgroundSize: imageBoxWidth + 'px' + ' ' + imageBoxHeight + 'px',
  12. backgroundPositionX: (-cropBoxX - 2) + 'px',
  13. backgroundPositionY: (-cropBoxY - 2) + 'px',
  14. borderRadius: cropShape == 'rect' ? '' : '50%'
  15. }"
  16. >

常规的通过拖动来调整位置和大小实现:

  1. touchstart(event){
  2. startX = event.touches[0].clientX;
  3. startY = event.touches[0].clientY;
  4. if(event.target.dataset.body == "handle"){
  5. this.mode = 'zoom';
  6. boxWidth = this.cropBoxWidth;
  7. boxHeight = this.cropBoxHeight;
  8. }else {
  9. this.mode = 'move';
  10. boxX = this.cropBoxX;
  11. boxY = this.cropBoxY;
  12. }
  13. },
  14. touchmove(event){
  15. let distanceX = event.touches[0].clientX - startX;
  16. let distanceY = event.touches[0].clientY - startY;
  17. let x = boxX + distanceX;
  18. let y = boxY + distanceY;
  19. let width = boxWidth + distanceX;
  20. let height = boxHeight + distanceY;
  21. let maxX = this.imageBoxWidth-this.cropBoxWidth;
  22. let maxY = this.imageBoxHeight-this.cropBoxHeight;
  23. let maxWidth = this.imageBoxWidth-this.cropBoxX;
  24. let maxHeight = this.imageBoxHeight-this.cropBoxY;
  25. switch (this.mode) {
  26. case 'move':
  27. this.cropBoxX = x < 0 ? 0 : (x > maxX ? maxX : x);
  28. this.cropBoxY = y < 0 ? 0 : (y > maxY ? maxY : y);
  29. break;
  30. case 'zoom':
  31. if(this.cropShape == 'rect'){
  32. this.cropBoxWidth = width > maxWidth ? maxWidth : width;
  33. this.cropBoxHeight = height > maxHeight ? maxHeight : height;
  34. }else{
  35. this.cropBoxHeight = height > maxHeight ? maxHeight : height;
  36. this.cropBoxWidth = height > maxHeight ? maxHeight : height;
  37. }
  38. break;
  39. }
  40. },

3、再通过用户在界面上操作裁剪框的位置和大小,来确定要裁剪图片的哪个部分;

4、再利用canvas绘制图像并生成base64格式图片;

  1. async cropping(){
  2. let x = this.cropBoxX * imageZoomRatio;
  3. let y = this.cropBoxY * imageZoomRatio;
  4. let w = this.cropBoxWidth * imageZoomRatio;
  5. let h = this.cropBoxHeight * imageZoomRatio;
  6. // 方式2:
  7. const canvas = uni.createOffscreenCanvas({type: '2d',width: w, height: h});
  8. const context = canvas.getContext('2d');
  9. const image = canvas.createImage();
  10. await new Promise((resolve,reject) => {
  11. image.onload = resolve
  12. image.onerror = reject
  13. image.src = this.src;
  14. // image.src = "https://pic4.ntimg.cn/file/20191225/30544261_221404258307_1.jpg";
  15. })
  16. context.clearRect(0, 0, w, h);
  17. if(this.cropShape == 'circular'){
  18. context.beginPath();
  19. context.arc(w/2,h/2,w/2,0,Math.PI * 2);
  20. context.fill();
  21. context.clip();
  22. }
  23. context.drawImage(image,x,y,w,h,0, 0, w, h);
  24. const DataURL = canvas.toDataURL();
  25. return DataURL;
  26. }

5、最后看一下该插件支持的属性,如果大家有需要可以到uniapp插件库下载使用

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/287099?site
推荐阅读