洛阳学员端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

283 lines
6.9 KiB

10 months ago
3 months ago
10 months ago
3 months ago
10 months ago
3 months ago
10 months ago
3 months ago
10 months ago
  1. <template>
  2. <view class="content">
  3. <view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
  4. <canvas
  5. class="cropper"
  6. :disable-scroll="true"
  7. @touchstart="touchStart"
  8. @touchmove="touchMove"
  9. @touchend="touchEnd"
  10. :style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
  11. canvas-id="cropper"
  12. id="cropper"
  13. ></canvas>
  14. <canvas
  15. class="cropper"
  16. :disable-scroll="true"
  17. :style="{
  18. position: 'fixed',
  19. top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
  20. left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
  21. width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
  22. height: `${cropperOpt.height * cropperOpt.pixelRatio}`
  23. }"
  24. canvas-id="targetId"
  25. id="targetId"
  26. ></canvas>
  27. </view>
  28. <view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
  29. <view class="upload" @click="uploadTap">取消</view>
  30. <view class="getCropperImage" @click="getCropperImage(false)">完成</view>
  31. </view>
  32. </view>
  33. </template>
  34. <script>
  35. import WeCropper from './weCropper.js';
  36. export default {
  37. props: {
  38. // 裁剪矩形框的样式,其中可包含的属性为lineWidth-边框宽度(单位rpx),color: 边框颜色,
  39. // mask-遮罩颜色,一般设置为一个rgba的透明度,如"rgba(0, 0, 0, 0.35)"
  40. boundStyle: {
  41. type: Object,
  42. default() {
  43. return {
  44. lineWidth: 4,
  45. borderColor: 'rgb(245, 245, 245)',
  46. mask: 'rgba(0, 0, 0, 0.35)'
  47. };
  48. }
  49. },
  50. avatarSrc: {
  51. type: String,
  52. default: ''
  53. }
  54. // // 裁剪框宽度,单位rpx
  55. // rectWidth: {
  56. // type: [String, Number],
  57. // default: 400
  58. // },
  59. // // 裁剪框高度,单位rpx
  60. // rectHeight: {
  61. // type: [String, Number],
  62. // default: 400
  63. // },
  64. // // 输出图片宽度,单位rpx
  65. // destWidth: {
  66. // type: [String, Number],
  67. // default: 400
  68. // },
  69. // // 输出图片高度,单位rpx
  70. // destHeight: {
  71. // type: [String, Number],
  72. // default: 400
  73. // },
  74. // // 输出的图片类型,如果发现裁剪的图片很大,可能是因为设置为了"png",改成"jpg"即可
  75. // fileType: {
  76. // type: String,
  77. // default: 'jpg',
  78. // },
  79. // // 生成的图片质量
  80. // // H5上无效,目前不考虑使用此参数
  81. // quality: {
  82. // type: [Number, String],
  83. // default: 1
  84. // }
  85. },
  86. data() {
  87. return {
  88. // 底部导航的高度
  89. bottomNavHeight: 50,
  90. originWidth: 200,
  91. width: 0,
  92. height: 0,
  93. cropperOpt: {
  94. id: 'cropper',
  95. targetId: 'targetCropper',
  96. pixelRatio: 1,
  97. width: 0,
  98. height: 0,
  99. scale: 2.5,
  100. zoom: 8,
  101. cut: {
  102. x: (this.width - this.originWidth) / 2,
  103. y: (this.height - this.originWidth) / 2,
  104. width: this.originWidth,
  105. height: this.originWidth
  106. },
  107. boundStyle: {
  108. lineWidth: uni.upx2px(this.boundStyle.lineWidth),
  109. mask: this.boundStyle.mask,
  110. color: this.boundStyle.borderColor
  111. }
  112. },
  113. // 裁剪框和输出图片的尺寸,高度默认等于宽度
  114. // 输出图片宽度,单位px
  115. destWidth: 240,
  116. // 裁剪框宽度,单位px
  117. rectWidth: 240,
  118. // 输出的图片类型,如果'png'类型发现裁剪的图片太大,改成"jpg"即可
  119. fileType: 'png',
  120. src: '', // 选择的图片路径,用于在点击确定时,判断是否选择了图片
  121. };
  122. },
  123. onLoad(options) {
  124. let rectInfo = uni.getSystemInfoSync();
  125. this.width = rectInfo.windowWidth;
  126. this.height = rectInfo.windowHeight - this.bottomNavHeight;
  127. this.cropperOpt.width = this.width;
  128. this.cropperOpt.height = this.height;
  129. this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
  130. if (this.destWidth) this.destWidth = this.destWidth;
  131. if (this.rectWidth) {
  132. let rectWidth = Number(this.rectWidth);
  133. this.cropperOpt.cut = {
  134. x: (this.width - rectWidth) / 2,
  135. y: (this.height - rectWidth) / 2,
  136. width: rectWidth,
  137. height: 320
  138. };
  139. }
  140. this.rectWidth = this.rectWidth;
  141. if (this.fileType) this.fileType = this.fileType;
  142. // 初始化
  143. this.cropper = new WeCropper(this.cropperOpt)
  144. .on('ready', ctx => {
  145. // wecropper is ready for work!
  146. })
  147. .on('beforeImageLoad', ctx => {
  148. // before picture loaded, i can do something
  149. })
  150. .on('imageLoad', ctx => {
  151. // picture loaded
  152. })
  153. .on('beforeDraw', (ctx, instance) => {
  154. // before canvas draw,i can do something
  155. });
  156. // 设置导航栏样式,以免用户在page.json中没有设置为黑色背景
  157. uni.setNavigationBarColor({
  158. frontColor: '#ffffff',
  159. backgroundColor: '#000000'
  160. });
  161. this.src = decodeURIComponent(options.url)
  162. // 获取裁剪图片资源后,给data添加src属性及其值
  163. this.cropper.pushOrign(this.src);
  164. },
  165. methods: {
  166. touchStart(e) {
  167. this.cropper.touchStart(e);
  168. },
  169. touchMove(e) {
  170. this.cropper.touchMove(e);
  171. },
  172. touchEnd(e) {
  173. this.cropper.touchEnd(e);
  174. },
  175. getCropperImage(isPre = false) {
  176. if(!this.src) return this.$u.toast('请先选择图片再裁剪');
  177. let cropper_opt = {
  178. destHeight: 320, // uni.canvasToTempFilePath要求这些参数为数值
  179. destWidth: Number(this.destWidth),
  180. fileType: this.fileType
  181. };
  182. this.cropper.getCropperImage(cropper_opt, (path, err) => {
  183. if (err) {
  184. uni.showModal({
  185. title: '温馨提示',
  186. content: err.message
  187. });
  188. } else {
  189. if (isPre) {
  190. uni.previewImage({
  191. current: '', // 当前显示图片的 http 链接
  192. urls: [path] // 需要预览的图片 http 链接列表
  193. });
  194. } else {
  195. uni.$emit('uAvatarCropper', path);
  196. uni.navigateBack()
  197. }
  198. }
  199. });
  200. },
  201. uploadTap() {
  202. uni.navigateBack()
  203. return
  204. const self = this;
  205. uni.chooseImage({
  206. count: 1, // 默认9
  207. sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
  208. sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
  209. success: (res) => {
  210. self.src = res.tempFilePaths[0];
  211. // 获取裁剪图片资源后,给data添加src属性及其值
  212. self.cropper.pushOrign(this.src);
  213. }
  214. });
  215. }
  216. }
  217. };
  218. </script>
  219. <style scoped lang="scss">
  220. @import '@/uni_modules/uview-ui/libs/css/components.scss';
  221. .content {
  222. background: rgba(255, 255, 255, 1);
  223. }
  224. .cropper {
  225. position: absolute;
  226. top: 0;
  227. left: 0;
  228. width: 100%;
  229. height: 100%;
  230. z-index: 11;
  231. }
  232. .cropper-buttons {
  233. background-color: #000000;
  234. color: #eee;
  235. }
  236. .cropper-wrapper {
  237. position: relative;
  238. // @include vue-flex;
  239. flex-direction: row;
  240. justify-content: space-between;
  241. align-items: center;
  242. width: 100%;
  243. background-color: #000;
  244. }
  245. .cropper-buttons {
  246. width: 100vw;
  247. // @include vue-flex;
  248. flex-direction: row;
  249. justify-content: space-between;
  250. align-items: center;
  251. position: fixed;
  252. bottom: 0;
  253. left: 0;
  254. font-size: 28rpx;
  255. }
  256. .cropper-buttons .upload,
  257. .cropper-buttons .getCropperImage {
  258. width: 50%;
  259. text-align: center;
  260. }
  261. .cropper-buttons .upload {
  262. text-align: left;
  263. padding-left: 50rpx;
  264. }
  265. .cropper-buttons .getCropperImage {
  266. text-align: right;
  267. padding-right: 50rpx;
  268. }
  269. </style>