康巴易测肤/伤疤uniapp小程序类
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

173 lines
5.5KB

  1. <template>
  2. <view class="container">
  3. <button @click="chooseImage">选择图片</button>
  4. <view class="canvas-container" v-if="imagePath">
  5. <canvas canvas-id="imageCanvas"
  6. :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"></canvas>
  7. <view :class="[
  8. 'crop-area',
  9. cropShape === 'circle' ? 'circle' : 'rectangle'
  10. ]" :style="{
  11. left: cropX + 'px',
  12. top: cropY + 'px',
  13. width: cropWidth + 'px',
  14. height: cropHeight + 'px'
  15. }" @touchstart="startDrag" @touchmove="drag" @touchend="endDrag"></view>
  16. </view>
  17. <view class="button-group">
  18. <button @click="changeCropShape">切换裁剪形状</button>
  19. <button @click="resetCanvas">重置画布</button>
  20. <button @click="cropImage">裁剪图片</button>
  21. </view>
  22. </view>
  23. </template>
  24. <script>
  25. export default {
  26. data() {
  27. return {
  28. imagePath: '',
  29. canvasWidth: 300,
  30. canvasHeight: 300,
  31. cropX: 50,
  32. cropY: 50,
  33. cropWidth: 200,
  34. cropHeight: 200,
  35. cropShape: 'rectangle',
  36. isDragging: false,
  37. startX: 0,
  38. startY: 0
  39. };
  40. },
  41. methods: {
  42. chooseImage() {
  43. uni.chooseImage({
  44. count: 1,
  45. success: (res) => {
  46. this.imagePath = res.tempFilePaths[0];
  47. this.drawImageOnCanvas();
  48. }
  49. });
  50. },
  51. drawImageOnCanvas() {
  52. const ctx = uni.createCanvasContext('imageCanvas', this);
  53. ctx.drawImage(this.imagePath, 0, 0, this.canvasWidth, this.canvasHeight);
  54. ctx.draw();
  55. },
  56. startDrag(e) {
  57. this.isDragging = true;
  58. this.startX = e.touches[0].clientX;
  59. this.startY = e.touches[0].clientY;
  60. },
  61. drag(e) {
  62. if (this.isDragging) {
  63. const deltaX = e.touches[0].clientX - this.startX;
  64. const deltaY = e.touches[0].clientY - this.startY;
  65. let newX = this.cropX + deltaX;
  66. let newY = this.cropY + deltaY;
  67. // 限制裁剪区域不超出图片范围
  68. newX = Math.max(0, Math.min(newX, this.canvasWidth - this.cropWidth));
  69. newY = Math.max(0, Math.min(newY, this.canvasHeight - this.cropHeight));
  70. this.cropX = newX;
  71. this.cropY = newY;
  72. this.startX = e.touches[0].clientX;
  73. this.startY = e.touches[0].clientY;
  74. }
  75. },
  76. endDrag() {
  77. this.isDragging = false;
  78. },
  79. changeCropShape() {
  80. this.cropShape = this.cropShape === 'rectangle' ? 'circle' : 'rectangle';
  81. },
  82. resetCanvas() {
  83. this.cropX = 50;
  84. this.cropY = 50;
  85. this.cropWidth = 200;
  86. this.cropHeight = 200;
  87. this.cropShape = 'rectangle';
  88. this.drawImageOnCanvas();
  89. },
  90. cropImage() {
  91. if (this.cropShape === 'rectangle') {
  92. uni.canvasToTempFilePath({
  93. canvasId: 'imageCanvas',
  94. x: this.cropX,
  95. y: this.cropY,
  96. width: this.cropWidth,
  97. height: this.cropHeight,
  98. success: (res) => {
  99. console.log('裁剪后的图片路径:', res.tempFilePath);
  100. uni.previewImage({
  101. urls: [res.tempFilePath]
  102. });
  103. },
  104. fail: (err) => {
  105. console.error('裁剪失败:', err);
  106. }
  107. }, this);
  108. } else {
  109. const ctx = uni.createCanvasContext('imageCanvas', this);
  110. const centerX = this.cropX + this.cropWidth / 2;
  111. const centerY = this.cropY + this.cropHeight / 2;
  112. const radius = Math.min(this.cropWidth, this.cropHeight) / 2;
  113. ctx.save();
  114. ctx.beginPath();
  115. ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
  116. ctx.clip();
  117. ctx.drawImage(this.imagePath, 0, 0, this.canvasWidth, this.canvasHeight);
  118. ctx.restore();
  119. ctx.draw(false, () => {
  120. uni.canvasToTempFilePath({
  121. canvasId: 'imageCanvas',
  122. x: centerX - radius,
  123. y: centerY - radius,
  124. width: 2 * radius,
  125. height: 2 * radius,
  126. success: (res) => {
  127. console.log('裁剪后的图片路径:', res.tempFilePath);
  128. uni.previewImage({
  129. urls: [res.tempFilePath]
  130. });
  131. },
  132. fail: (err) => {
  133. console.error('裁剪失败:', err);
  134. }
  135. }, this);
  136. });
  137. }
  138. }
  139. }
  140. };
  141. </script>
  142. <style scoped>
  143. .container {
  144. padding: 20px;
  145. }
  146. .canvas-container {
  147. position: relative;
  148. margin-top: 20px;
  149. }
  150. .crop-area {
  151. position: absolute;
  152. border: 2px dashed blue;
  153. box-sizing: border-box;
  154. }
  155. .circle {
  156. border-radius: 50%;
  157. }
  158. .button-group {
  159. margin-top: 20px;
  160. display: flex;
  161. justify-content: space-around;
  162. }
  163. </style>