当前位置:   article > 正文

uniapp图像裁剪_uniapp compressimage 裁切

uniapp compressimage 裁切

第一步:拿到图片信息

第二步:计算基准框大小,设置预览图片基准值

第三步:预览图片宽高处理

第四步:获取屏幕宽高,绘制蒙层

第五步:图片预览

第六步:预览图拖拽处理

第七步:图像裁剪

  1. <template>
  2. <view class="settingHeadImage" @touchstart="onTouchstart" @touchmove.stop.prevent="onTouchmove" @touchend="touchE">
  3. <!-- 蒙层 -->
  4. <canvas class="pre-canvas" canvas-id="firstCanvas" :style="{ width: 100 + 'vw', height: 100 + 'vh' }"></canvas>
  5. <!-- img预览 -->
  6. <view class="preImage" :style="{ width: preImgW + 'px' }">
  7. <canvas canvas-id="mycanvas" class="pre-i"
  8. :style="{ width: preImgW + 'px', height: preImgH + 'px', transform: `translate(${x}px,${y}px)` }"></canvas>
  9. </view>
  10. <!-- 工具 -->
  11. <view class="setting-btns"><text @click="onCrop">确定</text></view>
  12. </view>
  13. </template>
  14. <script>
  15. export default {
  16. data() {
  17. return {
  18. maxW: 250, // 最大宽度
  19. maxH: 250,
  20. screenWidth: '', // 屏幕宽
  21. screenHeight: '',
  22. xToTop: 0, // x方向距离顶部距离
  23. scale: 1, // 缩放
  24. preSrc: '',
  25. preImgW: '',
  26. preImgH: '',
  27. x: 0,
  28. y: 0,
  29. oldx: 0,
  30. oldy: 0,
  31. isMove: false,
  32. start: {
  33. left: 0,
  34. top: 0
  35. }
  36. };
  37. },
  38. computed: {},
  39. onLoad(option) {
  40. // 选择照片信息
  41. let data = JSON.parse(decodeURIComponent(option.item));
  42. const query = uni.createSelectorQuery();
  43. query.select('.settingHeadImage').boundingClientRect();
  44. query.exec(res => {
  45. // 设置屏幕大小
  46. this.screenWidth = res[0].width;
  47. this.screenHeight = res[0].height;
  48. // 设置图像基准值,图像基准值按屏幕宽度设置,两边留白各40
  49. this.maxH = res[0].width - 80;
  50. this.maxW = res[0].width - 80;
  51. // 设置X轴值,算式:屏幕高度的一半减去基准框高度的一半
  52. this.xToTop = this.screenHeight / 2 - this.maxH / 2;
  53. this.setImageSize(data);
  54. });
  55. },
  56. methods: {
  57. // 宽高处理
  58. setImageSize(data) {
  59. const {
  60. tempFilePath
  61. } = data;
  62. const {
  63. maxH,
  64. maxW
  65. } = this;
  66. uni.getImageInfo({
  67. src: tempFilePath,
  68. success: res => {
  69. const {
  70. errMsg,
  71. path,
  72. width,
  73. height
  74. } = res;
  75. let w = '';
  76. let h = '';
  77. if (errMsg === 'getImageInfo:ok') {
  78. w = width;
  79. h = height;
  80. // 宽大与高大于最大宽度
  81. if (width > height && width > maxW) {
  82. w = Math.floor((width / height) * maxW);
  83. h = maxH;
  84. }
  85. // 高大于宽大于最大高度
  86. if (height > width && height > maxH) {
  87. h = Math.floor((height / width) * maxH);
  88. w = maxW;
  89. }
  90. // 宽高相等或者宽高小于最大值
  91. if (width === height || (width < maxW && height < maxH)) {
  92. h = maxH;
  93. w = maxW;
  94. }
  95. this.preSrc = path;
  96. this.preImgH = h;
  97. this.preImgW = w;
  98. // 设置蒙层
  99. this.setBgBox();
  100. // 图像预览
  101. this.previewCanvas({
  102. w,
  103. h,
  104. path
  105. });
  106. }
  107. }
  108. });
  109. },
  110. // 设置蒙层
  111. setBgBox() {
  112. const {
  113. maxW,
  114. maxH,
  115. screenHeight,
  116. screenWidth,
  117. xToTop
  118. } = this;
  119. const ctx = uni.createCanvasContext('firstCanvas');
  120. // 先清除矩形
  121. ctx.clearRect(0, 0, screenWidth, screenHeight);
  122. // 设置canvas透明度
  123. ctx.setGlobalAlpha(0.7);
  124. // 设置蒙层颜色
  125. ctx.setFillStyle('#000000');
  126. // 绘制蒙层
  127. ctx.fillRect(0, 0, screenWidth, screenHeight);
  128. // 基准框留白
  129. ctx.clearRect(40, xToTop, maxW, maxH);
  130. // 绘制基准框
  131. ctx.beginPath();
  132. ctx.setStrokeStyle('#FFFFFF');
  133. ctx.strokeRect(40, xToTop, maxW, maxH);
  134. ctx.closePath();
  135. ctx.draw();
  136. },
  137. // 预览
  138. previewCanvas({
  139. w,
  140. h,
  141. path
  142. }) {
  143. const ctx = uni.createCanvasContext('mycanvas');
  144. ctx.drawImage(path, 0, 0, w, h);
  145. ctx.draw();
  146. },
  147. onTouchstart(ev) {
  148. if (ev.changedTouches.length === 1) {
  149. this.isMove = true;
  150. this.start.left = ev.changedTouches[0].clientX;
  151. this.start.top = ev.changedTouches[0].clientY;
  152. }
  153. },
  154. onTouchmove(ev) {
  155. const {
  156. maxW,
  157. maxH,
  158. preImgH,
  159. preImgW,
  160. xToTop
  161. } = this;
  162. if (this.isMove && ev.changedTouches.length === 1) {
  163. let clientX = ev.changedTouches[0].clientX,
  164. clientY = ev.changedTouches[0].clientY;
  165. this.x = preImgW <= maxW ? 0 : this.oldx + clientX - this.start.left;
  166. this.y = preImgH <= maxH ? 0 : this.oldy + clientY - this.start.top;
  167. }
  168. },
  169. touchE(val) {
  170. const {
  171. preImgH,
  172. preImgW,
  173. maxH,
  174. maxW
  175. } = this;
  176. const query = uni.createSelectorQuery();
  177. const fx = this.x;
  178. query.select('.pre-i').boundingClientRect();
  179. query.exec(res => {
  180. // x、y回弹计算
  181. let y = (res[0].height - res[0].width) / 2;
  182. /**
  183. * 判断照片可移动的距离是否大于留白的值,如果大于向右划时图片的宽减去基准框的宽减去留白向左时留白,小于时按图片的可移动值
  184. * */
  185. let x = (preImgW - maxW) / 2 > 40 ? (fx < 0 ? preImgW - maxW - 40 : 40) : (preImgW - maxW) / 2;
  186. if (preImgH > maxH) {
  187. this.y = this.y > y ? y : this.y < -y ? -y : this.y;
  188. }
  189. if (preImgW > maxW) {
  190. this.x = this.x > x ? x : this.x < -x ? -x : this.x;
  191. }
  192. this.oldx = this.x;
  193. this.oldy = this.y;
  194. this.isMove = false;
  195. });
  196. },
  197. // 裁剪
  198. onCrop() {
  199. let y = 0;
  200. let x = 0;
  201. const query = uni.createSelectorQuery();
  202. query.select('.pre-i').boundingClientRect();
  203. query.exec(res => {
  204. // 获取预览img距离左上的距离
  205. y = Math.abs(res[0].top);
  206. x = Math.abs(res[0].left);
  207. const {
  208. maxW,
  209. maxH,
  210. preImgH,
  211. preImgW,
  212. xToTop
  213. } = this;
  214. uni.canvasToTempFilePath({
  215. x: Math.abs(res[0].left < 0 ? x + 40 : x - 40),
  216. y: Math.abs(res[0].top < 0 ? xToTop + y : xToTop - y),
  217. width: maxW,
  218. height: maxH,
  219. destWidth: maxW,
  220. destHeight: maxH,
  221. canvasId: 'mycanvas',
  222. success: fileRes => {
  223. console.log(fileRes);
  224. uni.previewImage({
  225. count: 1,
  226. urls: [fileRes.tempFilePath]
  227. });
  228. },
  229. fail: function(err) {
  230. console.log(err);
  231. uni.showToast({
  232. title: '上传失败:图片生成过程中遇到错误',
  233. icon: 'none'
  234. });
  235. }
  236. });
  237. });
  238. }
  239. }
  240. };
  241. </script>
  242. <style lang="scss" scoped>
  243. .settingHeadImage {
  244. background-color: #000000;
  245. overflow: hidden;
  246. .pre-canvas {
  247. position: fixed;
  248. top: 0;
  249. left: 0;
  250. z-index: 20;
  251. }
  252. .preImage {
  253. min-width: 100vw;
  254. height: 100vh;
  255. display: flex;
  256. justify-content: center;
  257. align-items: center;
  258. overflow: hidden;
  259. z-index: 1;
  260. .pre-i {
  261. // transition: all 0.1s;
  262. }
  263. }
  264. .setting-btns {
  265. position: fixed;
  266. bottom: 0;
  267. left: 0;
  268. z-index: 20;
  269. font-size: 14px;
  270. color: #ffffff;
  271. }
  272. }
  273. </style>

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