yhdsl-cropper.vue 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974
  1. <template>
  2. <view class="yhdsl" v-show="isShow">
  3. <view>
  4. <view class="cropper-content">
  5. <view v-if="isShowImg" class="uni-corpper"
  6. :style="'width:' + cropperInitW + 'px;height:' + cropperInitH + 'px;background:#000'">
  7. <view class="uni-corpper-content" :style="
  8. 'width:' +
  9. cropperW +
  10. 'px;height:' +
  11. cropperH +
  12. 'px;left:' +
  13. cropperL +
  14. 'px;top:' +
  15. cropperT +
  16. 'px'
  17. ">
  18. <image :src="imageSrc" :style="'width:' + cropperW + 'px;height:' + cropperH + 'px'"></image>
  19. <view class="uni-corpper-crop-box" @touchstart.stop="contentStartMove"
  20. @touchmove.stop="contentMoveing" @touchend.stop="contentTouchEnd" :style="
  21. 'left:' + cutL + 'px;top:' + cutT + 'px;right:' + cutR + 'px;bottom:' + cutB + 'px'
  22. ">
  23. <view class="uni-cropper-view-box">
  24. <view class="uni-cropper-dashed-h"></view>
  25. <view class="uni-cropper-dashed-v"></view>
  26. <!-- 截图区域顶部 -->
  27. <view class="uni-cropper-line-t" data-drag="top" @touchstart.stop="dragStart"
  28. @touchmove.stop="dragMove"></view>
  29. <!-- 截图区域右侧 -->
  30. <view class="uni-cropper-line-r" data-drag="right" @touchstart.stop="dragStart"
  31. @touchmove.stop="dragMove"></view>
  32. <!-- 截图区域底部 -->
  33. <view class="uni-cropper-line-b" data-drag="bottom" @touchstart.stop="dragStart"
  34. @touchmove.stop="dragMove"></view>
  35. <!-- 截图区域左侧 -->
  36. <view class="uni-cropper-line-l" data-drag="left" @touchstart.stop="dragStart"
  37. @touchmove.stop="dragMove"></view>
  38. <!-- 右下角截图滑块 -->
  39. <view class="uni-cropper-point point-t" data-drag="top" @touchstart.stop="dragStart"
  40. @touchmove.stop="dragMove"></view>
  41. <view class="uni-cropper-point point-tr" data-drag="topTight"></view>
  42. <view class="uni-cropper-point point-r" data-drag="right" @touchstart.stop="dragStart"
  43. @touchmove.stop="dragMove"></view>
  44. <view class="uni-cropper-point point-rb" data-drag="rightBottom"
  45. @touchstart.stop="dragStart" @touchmove.stop="dragMove"></view>
  46. <view class="uni-cropper-point point-b" data-drag="bottom" @touchstart.stop="dragStart"
  47. @touchmove.stop="dragMove" @touchend.stop="dragEnd"></view>
  48. <view class="uni-cropper-point point-bl" data-drag="bottomLeft"></view>
  49. <view class="uni-cropper-point point-l" data-drag="left" @touchstart.stop="dragStart"
  50. @touchmove.stop="dragMove"></view>
  51. <view class="uni-cropper-point point-lt" data-drag="leftTop"></view>
  52. </view>
  53. </view>
  54. </view>
  55. </view>
  56. </view>
  57. <view class="cropper-config">
  58. <view class="button-box">
  59. <button type="warn" @click="chooseImage">{{$t('order.quxiao')}}</button>
  60. <!-- <button type="warn" @click="previewImg">预览</button> -->
  61. <button type="warn" @click="finish">{{$t('comp.queren')}}</button>
  62. </view>
  63. </view>
  64. <canvas canvas-id="myCanvas" :style="
  65. 'position:absolute;border: 2px solid red; width:' +
  66. imageW +
  67. 'px;height:' +
  68. imageH +
  69. 'px;top:-9999px;left:-9999px;'
  70. "></canvas>
  71. </view>
  72. </view>
  73. </template>
  74. <script>
  75. let sysInfo = uni.getSystemInfoSync();
  76. let SCREEN_WIDTH = sysInfo.screenWidth;
  77. let SCREEN_HEIGHT = sysInfo.windowHeight + 40;
  78. let PAGE_X, // 手按下的x位置
  79. PAGE_Y, // 手按下y的位置
  80. PR = sysInfo.pixelRatio, // dpi
  81. T_PAGE_X, // 手移动的时候x的位置
  82. T_PAGE_Y, // 手移动的时候Y的位置
  83. CUT_L, // 初始化拖拽元素的left值
  84. CUT_T, // 初始化拖拽元素的top值
  85. CUT_R, // 初始化拖拽元素的
  86. CUT_B, // 初始化拖拽元素的
  87. CUT_W, // 初始化拖拽元素的宽度
  88. CUT_H, // 初始化拖拽元素的高度
  89. IMG_RATIO, // 图片比例
  90. IMG_REAL_W, // 图片实际的宽度
  91. IMG_REAL_H, // 图片实际的高度
  92. DRAFG_MOVE_RATIO = 1, //移动时候的比例,
  93. INIT_DRAG_POSITION = 100, // 初始化屏幕宽度和裁剪区域的宽度之差,用于设置初始化裁剪的宽度
  94. DRAW_IMAGE_W = sysInfo.screenWidth; // 设置生成的图片宽度
  95. export default {
  96. /**
  97. * 页面的初始数据
  98. */
  99. data() {
  100. return {
  101. imageSrc: "",
  102. isShow: false,
  103. isShowImg: false,
  104. // 初始化的宽高
  105. cropperInitW: SCREEN_WIDTH,
  106. cropperInitH: SCREEN_HEIGHT,
  107. // 动态的宽高
  108. cropperW: SCREEN_WIDTH,
  109. cropperH: SCREEN_HEIGHT - 100,
  110. // 动态的left top值
  111. cropperL: 0,
  112. cropperT: 0,
  113. transL: 0,
  114. transT: 0,
  115. // 图片缩放值
  116. scaleP: 0,
  117. imageW: 0,
  118. imageH: 0,
  119. // 裁剪框 宽高
  120. cutL: 0,
  121. cutT: 0,
  122. cutB: SCREEN_WIDTH,
  123. cutR: "100%",
  124. qualityWidth: DRAW_IMAGE_W,
  125. innerAspectRadio: DRAFG_MOVE_RATIO,
  126. };
  127. },
  128. props: {
  129. /* 截图质量,压缩比 */
  130. quality: {
  131. type: Number | String,
  132. default: 1,
  133. },
  134. src: String,
  135. fileType: {
  136. type: String,
  137. default: "png",
  138. validator: function(t) {
  139. // 这个值必须匹配下列字符串中的一个
  140. return t === "png" || t === "jpg";
  141. },
  142. },
  143. /* 截取类型,自由截取free;固定比例截取(正方形)fixed */
  144. mode: {
  145. type: String,
  146. default: "free",
  147. validator: function(t) {
  148. // 这个值必须匹配下列字符串中的一个
  149. return t === "free" || t === "fixed" || t === "scale";
  150. },
  151. },
  152. scale: {
  153. type: Number,
  154. default: 1,
  155. },
  156. },
  157. created() {
  158. if (this.src) {
  159. this.imageSrc = this.src;
  160. this.loadImage();
  161. this.isShow = true;
  162. this.isShowImg = true;
  163. }
  164. },
  165. methods: {
  166. setData: function(obj) {
  167. let that = this;
  168. Object.keys(obj).forEach(function(key) {
  169. that.$set(that.$data, key, obj[key]);
  170. });
  171. },
  172. /* 选择图片 */
  173. chooseImage: function() {
  174. var _this = this;
  175. uni.chooseImage({
  176. count: 1,
  177. sizeType:['compressed'],
  178. sourceType:['album'],
  179. success: function(res) {
  180. if(res.tempFiles[0].size / 1024 < 1024) {
  181. _this.setData({
  182. imageSrc: res.tempFilePaths[0],
  183. });
  184. _this.loadImage();
  185. _this.isShow = true;
  186. } else {
  187. uni.showToast({
  188. title: '图片大小不能超过1024KB,当前大小' + (res.tempFiles[0].size / 1024).toFixed(2) + 'KB',
  189. icon: 'none'
  190. })
  191. }
  192. },
  193. });
  194. },
  195. /* 将图片加载到画布 */
  196. loadImage: function() {
  197. var _this = this;
  198. uni.showLoading({
  199. title: "loading...",
  200. });
  201. /* 获取图片信息 */
  202. uni.getImageInfo({
  203. src: _this.imageSrc,
  204. success: function success(res) {
  205. let imgH = res.height;
  206. let imgW = res.width;
  207. // let IMG_SCR_H_R = SCREEN_HEIGHT / imgH;
  208. // let IMG_SCR_W_R = SCREEN_WIDTH / imgW;
  209. /* 图片的宽高比 */
  210. IMG_RATIO = imgW / imgH;
  211. /**
  212. * 如果图片更高一些,为确保图片能够完整在视窗内显示需如下处理
  213. * 1. 缩放图片的高为 视窗高度减去底部菜单按钮高度(120)
  214. * 2. 根据图片缩放后的高度,根据图片宽高比计算图片的宽度
  215. * 3. 如果步骤2计算的图片宽度大于屏幕宽度,则需要再次调整图片宽度为视窗宽度-margin(10)
  216. * 4. 根据步骤3的宽度,结合图片宽高比重新计算图片的高度
  217. */
  218. if (IMG_RATIO < 1 && (SCREEN_HEIGHT - 120) * IMG_RATIO < SCREEN_WIDTH - 10) {
  219. IMG_REAL_W = (SCREEN_HEIGHT - 120) * IMG_RATIO;
  220. IMG_REAL_H = SCREEN_HEIGHT - 120;
  221. } else {
  222. IMG_REAL_W = SCREEN_WIDTH - 10;
  223. IMG_REAL_H = IMG_REAL_W / IMG_RATIO;
  224. }
  225. /* 初始化裁剪区域的位置和形状 */
  226. let [cutT, cutB, cutL, cutR] = _this.initCutArea(IMG_RATIO, IMG_REAL_H,
  227. IMG_REAL_W);
  228. _this.setData({
  229. /* 裁剪区域的宽高同图片尺寸 */
  230. cropperW: IMG_REAL_W,
  231. cropperH: IMG_REAL_H,
  232. /* 上下左右各留一定的margin已便更好的拖动裁剪区域 */
  233. cropperL: Math.ceil((SCREEN_WIDTH - IMG_REAL_W) / 2),
  234. /* 留出底部操作按钮位置 70 */
  235. cropperT: Math.ceil((SCREEN_HEIGHT - IMG_REAL_H - 90) / 2),
  236. cutL: cutL,
  237. cutT: cutT,
  238. cutR: cutR,
  239. cutB: cutB,
  240. // 图片缩放值
  241. imageW: IMG_REAL_W,
  242. imageH: IMG_REAL_H,
  243. scaleP: IMG_REAL_W / SCREEN_WIDTH,
  244. qualityWidth: DRAW_IMAGE_W,
  245. innerAspectRadio: IMG_RATIO,
  246. });
  247. _this.setData({
  248. isShowImg: true,
  249. });
  250. uni.hideLoading();
  251. },
  252. });
  253. },
  254. initCutArea(IMG_RATIO, IMG_REAL_H, IMG_REAL_W) {
  255. let _this = this;
  256. /* 自由裁剪裁剪区域默认覆盖整个图片 */
  257. let cutT = 0;
  258. let cutB = 0;
  259. let cutL = 0;
  260. let cutR = 0;
  261. /* 正方形裁剪,初始化裁剪区域为正方形并居中 */
  262. if (_this.mode == "fixed") {
  263. if (IMG_RATIO < 1) {
  264. /* 图片比较高 */
  265. cutT = (IMG_REAL_H - IMG_REAL_W) / 2;
  266. cutB = (IMG_REAL_H - IMG_REAL_W) / 2;
  267. } else {
  268. /* 图片比较宽 */
  269. cutL = (IMG_REAL_W - IMG_REAL_H) / 2;
  270. cutR = (IMG_REAL_W - IMG_REAL_H) / 2;
  271. }
  272. }
  273. /* 固定比例裁剪,初始化裁剪区域比例和设定值相同 */
  274. if (_this.mode == "scale") {
  275. let scale = +_this.scale;
  276. if (IMG_RATIO < 1) {
  277. /* 图片比较高 */
  278. if (IMG_REAL_W / scale > IMG_REAL_H) {
  279. cutT = cutB = 0;
  280. cutL = cutR = (IMG_REAL_W - IMG_REAL_H * scale) / 2;
  281. } else {
  282. cutR = cutL = 0;
  283. cutT = cutB = (IMG_REAL_H - IMG_REAL_W / scale) / 2;
  284. }
  285. } else {
  286. /* 图片比较宽 */
  287. if (IMG_REAL_H * scale > IMG_REAL_W) {
  288. cutL = cutR = 0;
  289. cutB = cutT = (IMG_REAL_H - IMG_REAL_W / scale) / 2;
  290. } else {
  291. cutT = cutB = 0;
  292. cutL = cutR = (IMG_REAL_W - IMG_REAL_H * scale) / 2;
  293. }
  294. }
  295. }
  296. return [cutT, cutB, cutL, cutR];
  297. },
  298. // 拖动时候触发的touchStart事件
  299. contentStartMove(e) {
  300. PAGE_X = e.touches[0].pageX;
  301. PAGE_Y = e.touches[0].pageY;
  302. },
  303. // 拖动时候触发的touchMove事件
  304. contentMoveing(e) {
  305. var _this = this;
  306. var dragLengthX = (PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  307. var dragLengthY = (PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  308. // 左移
  309. if (dragLengthX > 0) {
  310. if (this.cutL - dragLengthX < 0) dragLengthX = this.cutL;
  311. } else {
  312. if (this.cutR + dragLengthX < 0) dragLengthX = -this.cutR;
  313. }
  314. if (dragLengthY > 0) {
  315. if (this.cutT - dragLengthY < 0) dragLengthY = this.cutT;
  316. } else {
  317. if (this.cutB + dragLengthY < 0) dragLengthY = -this.cutB;
  318. }
  319. this.setData({
  320. cutL: this.cutL - dragLengthX,
  321. cutT: this.cutT - dragLengthY,
  322. cutR: this.cutR + dragLengthX,
  323. cutB: this.cutB + dragLengthY,
  324. });
  325. PAGE_X = e.touches[0].pageX;
  326. PAGE_Y = e.touches[0].pageY;
  327. },
  328. contentTouchEnd() {},
  329. // 获取图片尺寸信息
  330. previewImg() {
  331. try {
  332. var _this = this;
  333. uni.showLoading({
  334. title: "loading...",
  335. });
  336. // 将图片写入画布
  337. const ctx = uni.createCanvasContext("myCanvas", _this);
  338. ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
  339. ctx.draw(true, () => {
  340. // 获取画布要裁剪的位置和宽度 均为百分比 * 画布中图片的宽度 保证了在微信小程序中裁剪的图片模糊 位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
  341. var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W;
  342. var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H;
  343. var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W;
  344. var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H;
  345. uni.canvasToTempFilePath({
  346. x: canvasL,
  347. y: canvasT,
  348. width: canvasW,
  349. height: canvasH,
  350. // destWidth: canvasW,
  351. // destHeight: canvasH,
  352. quality: +this.quality,
  353. fileType: this.fileType,
  354. canvasId: "myCanvas",
  355. success: function(res) {
  356. uni.hideLoading();
  357. // 成功获得地址的地方
  358. uni.previewImage({
  359. current: "", // 当前显示图片的http链接
  360. urls: [res.tempFilePath], // 需要预览的图片http链接列表
  361. });
  362. },
  363. fail: function(err) {
  364. uni.hideLoading();
  365. uni.showToast({
  366. title: "图片截取失败!",
  367. icon: "none",
  368. });
  369. },
  370. },
  371. _this
  372. );
  373. });
  374. } catch (e) {}
  375. },
  376. /* 完成裁剪,输出裁剪后的图片路径 */
  377. finish: function() {
  378. var _this = this;
  379. uni.showLoading({
  380. title: "loading...",
  381. });
  382. // 将图片写入画布
  383. const ctx = uni.createCanvasContext("myCanvas", _this);
  384. ctx.drawImage(_this.imageSrc, 0, 0, IMG_REAL_W, IMG_REAL_H);
  385. ctx.draw(true, () => {
  386. // 获取画布要裁剪的位置和宽度 均为百分比 * 画布中图片的宽度 保证了在微信小程序中裁剪的图片模糊 位置不对的问题 canvasT = (_this.cutT / _this.cropperH) * (_this.imageH / pixelRatio)
  387. var canvasW = ((_this.cropperW - _this.cutL - _this.cutR) / _this.cropperW) * IMG_REAL_W;
  388. var canvasH = ((_this.cropperH - _this.cutT - _this.cutB) / _this.cropperH) * IMG_REAL_H;
  389. var canvasL = (_this.cutL / _this.cropperW) * IMG_REAL_W;
  390. var canvasT = (_this.cutT / _this.cropperH) * IMG_REAL_H;
  391. uni.canvasToTempFilePath({
  392. x: canvasL,
  393. y: canvasT,
  394. width: canvasW,
  395. height: canvasH,
  396. // destWidth: canvasW,
  397. // destHeight: canvasH,
  398. quality: +this.quality,
  399. fileType: this.fileType,
  400. canvasId: "myCanvas",
  401. success: function(res) {
  402. uni.hideLoading();
  403. // 成功获得地址的地方
  404. _this.$emit("uploadImg", res.tempFilePath);
  405. _this.isShow = false;
  406. },
  407. fail: function(err) {
  408. uni.hideLoading();
  409. uni.showToast({
  410. title: "图片截取失败!",
  411. icon: "none",
  412. });
  413. },
  414. },
  415. _this
  416. );
  417. });
  418. },
  419. // 设置大小的时候触发的touchStart事件
  420. dragStart(e) {
  421. T_PAGE_X = e.touches[0].pageX;
  422. T_PAGE_Y = e.touches[0].pageY;
  423. CUT_L = this.cutL;
  424. CUT_R = this.cutR;
  425. CUT_B = this.cutB;
  426. CUT_T = this.cutT;
  427. },
  428. // 设置大小的时候触发的touchMove事件
  429. dragMove(e) {
  430. // this.mode == "fixed" ? this.fixedScaleDrag(e) : this.freeDrag(e);
  431. this[this.mode + "Drag"](e);
  432. },
  433. /* 固定比例(正方形)截取 ,只有右下角裁剪滑动拖动有效*/
  434. fixedDrag(e) {
  435. var _this = this;
  436. var dragType = e.target.dataset.drag;
  437. switch (dragType) {
  438. case "rightBottom":
  439. var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  440. // var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  441. // if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B;
  442. if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R;
  443. /* 右侧和底部同比变化 */
  444. let cutB = CUT_B + dragLengthX;
  445. let cutR = CUT_R + dragLengthX;
  446. /* 越界判断 */
  447. if (_this.cutB == 0 && cutB < 0) return;
  448. if (_this.cutR == 0 && cutR < 0) return;
  449. (_this.cutB > 0 || CUT_B == 0) &&
  450. this.setData({
  451. cutB: cutB < 0 ? 0 : cutB,
  452. cutR: cutR,
  453. });
  454. break;
  455. default:
  456. break;
  457. }
  458. },
  459. /* 等比例截图,只能通过右下角的滑块改变截图区域 */
  460. scaleDrag(e) {
  461. var _this = this;
  462. var dragType = e.target.dataset.drag;
  463. switch (dragType) {
  464. case "rightBottom":
  465. var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  466. // var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  467. // if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B;
  468. if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R;
  469. /* 右侧和底部同比变化 */
  470. let cutB = CUT_B + dragLengthX / _this.scale;
  471. let cutR = CUT_R + dragLengthX;
  472. /* 越界判断 */
  473. if (_this.cutB == 0 && cutB < 0) return;
  474. if (_this.cutR == 0 && cutR < 0) return;
  475. (_this.cutB > 0 || CUT_B == 0) &&
  476. this.setData({
  477. cutB: cutB < 0 ? 0 : cutB,
  478. cutR: cutR,
  479. });
  480. break;
  481. default:
  482. break;
  483. }
  484. },
  485. /* 自由截取,整个裁剪边框均能拖动 */
  486. freeDrag(e) {
  487. var _this = this;
  488. var dragType = e.target.dataset.drag;
  489. switch (dragType) {
  490. case "right":
  491. var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  492. if (CUT_R + dragLength < 0) dragLength = -CUT_R;
  493. this.setData({
  494. cutR: CUT_R + dragLength,
  495. });
  496. break;
  497. case "left":
  498. var dragLength = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  499. if (CUT_L - dragLength < 0) dragLength = CUT_L;
  500. if (CUT_L - dragLength > this.cropperW - this.cutR)
  501. dragLength = CUT_L - (this.cropperW - this.cutR);
  502. this.setData({
  503. cutL: CUT_L - dragLength,
  504. });
  505. break;
  506. case "top":
  507. var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  508. if (CUT_T - dragLength < 0) dragLength = CUT_T;
  509. if (CUT_T - dragLength > this.cropperH - this.cutB)
  510. dragLength = CUT_T - (this.cropperH - this.cutB);
  511. this.setData({
  512. cutT: CUT_T - dragLength,
  513. });
  514. break;
  515. case "bottom":
  516. var dragLength = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  517. if (CUT_B + dragLength < 0) dragLength = -CUT_B;
  518. this.setData({
  519. cutB: CUT_B + dragLength,
  520. });
  521. break;
  522. case "rightBottom":
  523. var dragLengthX = (T_PAGE_X - e.touches[0].pageX) * DRAFG_MOVE_RATIO;
  524. var dragLengthY = (T_PAGE_Y - e.touches[0].pageY) * DRAFG_MOVE_RATIO;
  525. if (CUT_B + dragLengthY < 0) dragLengthY = -CUT_B;
  526. if (CUT_R + dragLengthX < 0) dragLengthX = -CUT_R;
  527. let cutB = CUT_B + dragLengthY;
  528. let cutR = CUT_R + dragLengthX;
  529. this.setData({
  530. cutB: cutB,
  531. cutR: cutR,
  532. });
  533. break;
  534. default:
  535. break;
  536. }
  537. },
  538. },
  539. };
  540. </script>
  541. <style>
  542. /* pages/uni-cropper/index.wxss */
  543. .yhdsl {
  544. background-color: #fff;
  545. position: fixed;
  546. top: 0;
  547. left: 0;
  548. right: 0;
  549. bottom: 50px;
  550. display: block;
  551. align-items: center;
  552. flex-direction: column;
  553. z-index: 998;
  554. height: 100vh;
  555. }
  556. .cropper-config {
  557. position: fixed;
  558. z-index: 999;
  559. bottom: 10px;
  560. left: 0;
  561. right: 0;
  562. width: 90%;
  563. margin: 0 auto;
  564. /* padding: 20upx 40upx; */
  565. }
  566. .button-box {
  567. position: absolute;
  568. bottom: 0;
  569. display: flex;
  570. flex-direction: row;
  571. justify-content: space-between;
  572. width: 100%;
  573. }
  574. .button-box button {
  575. width: 25%;
  576. line-height: 35px;
  577. height: 35px;
  578. background-color: #509cff;
  579. }
  580. .cropper-content {
  581. width: 100%;
  582. min-height: 750upx;
  583. }
  584. .uni-corpper {
  585. position: relative;
  586. overflow: hidden;
  587. box-sizing: border-box;
  588. margin: 0 auto;
  589. -webkit-user-select: none;
  590. -moz-user-select: none;
  591. -ms-user-select: none;
  592. user-select: none;
  593. -webkit-tap-highlight-color: transparent;
  594. -webkit-touch-callout: none;
  595. }
  596. .uni-corpper-content {
  597. position: relative;
  598. }
  599. .uni-corpper-content image {
  600. display: block;
  601. width: 100%;
  602. min-width: 0 !important;
  603. max-width: none !important;
  604. /* height: 100%; */
  605. min-height: 0 !important;
  606. /* max-height: none !important; */
  607. max-height: calc(100vh - 100upx);
  608. margin: 0 auto;
  609. image-orientation: 0deg !important;
  610. }
  611. /* 移动图片效果 */
  612. .uni-cropper-drag-box {
  613. position: absolute;
  614. z-index: 1;
  615. top: 0;
  616. right: 0;
  617. bottom: 0;
  618. left: 0;
  619. cursor: move;
  620. background: rgba(0, 0, 0, 0.479);
  621. }
  622. /* 内部的信息 */
  623. .uni-corpper-crop-box {
  624. position: absolute;
  625. z-index: 2;
  626. max-height: calc(100vh - 100upx);
  627. background: rgba(56, 50, 50, 0.479);
  628. }
  629. .uni-corpper-crop-box .uni-cropper-view-box {
  630. position: relative;
  631. display: block;
  632. overflow: visible;
  633. width: 100%;
  634. height: 100%;
  635. max-height: calc(100vh - 100upx);
  636. outline: 5upx solid rgb(43, 89, 255);
  637. outline-color: rgba(255, 255 255, 1);
  638. }
  639. /* 横向虚线 */
  640. .uni-cropper-dashed-h {
  641. position: absolute;
  642. top: 33.33333333%;
  643. left: 0;
  644. width: 100%;
  645. height: 33.33333333%;
  646. border-top: 1upx dashed rgba(255, 255, 255, 0.5);
  647. border-bottom: 1upx dashed rgba(255, 255, 255, 0.5);
  648. }
  649. /* 纵向虚线 */
  650. .uni-cropper-dashed-v {
  651. position: absolute;
  652. top: 0;
  653. left: 33.33333333%;
  654. width: 33.33333333%;
  655. height: 100%;
  656. border-right: 1upx dashed rgba(255, 255, 255, 0.5);
  657. border-left: 1upx dashed rgba(255, 255, 255, 0.5);
  658. }
  659. /* 四个方向的线 为了之后的拖动事件*/
  660. .uni-cropper-line-t {
  661. position: absolute;
  662. top: 0;
  663. left: 0;
  664. display: block;
  665. width: 100%;
  666. height: 3upx;
  667. cursor: n-resize;
  668. opacity: 0.1;
  669. background-color: white;
  670. }
  671. .uni-cropper-line-t::before {
  672. position: absolute;
  673. z-index: 11;
  674. top: 50%;
  675. right: 0upx;
  676. bottom: 0;
  677. width: 100%;
  678. height: 41upx;
  679. content: "";
  680. -webkit-transform: translate3d(0, -50%, 0);
  681. transform: translate3d(0, -50%, 0);
  682. background: transparent;
  683. }
  684. .uni-cropper-line-r {
  685. position: absolute;
  686. top: 0;
  687. right: 0upx;
  688. display: block;
  689. width: 3upx;
  690. height: 100%;
  691. cursor: e-resize;
  692. opacity: 0.1;
  693. background-color: white;
  694. }
  695. .uni-cropper-line-r::before {
  696. position: absolute;
  697. z-index: 11;
  698. top: 0;
  699. bottom: 0;
  700. left: 50%;
  701. width: 41upx;
  702. height: 100%;
  703. content: "";
  704. -webkit-transform: translate3d(-50%, 0, 0);
  705. transform: translate3d(-50%, 0, 0);
  706. background: transparent;
  707. }
  708. .uni-cropper-line-b {
  709. position: absolute;
  710. bottom: 0;
  711. left: 0;
  712. display: block;
  713. width: 100%;
  714. height: 3upx;
  715. cursor: s-resize;
  716. opacity: 0.1;
  717. background-color: white;
  718. }
  719. .uni-cropper-line-b::before {
  720. position: absolute;
  721. z-index: 11;
  722. top: 50%;
  723. right: 0upx;
  724. bottom: 0;
  725. width: 100%;
  726. height: 41upx;
  727. content: "";
  728. -webkit-transform: translate3d(0, -50%, 0);
  729. transform: translate3d(0, -50%, 0);
  730. background: transparent;
  731. }
  732. .uni-cropper-line-l {
  733. position: absolute;
  734. top: 0;
  735. left: 0;
  736. display: block;
  737. width: 3upx;
  738. height: 100%;
  739. cursor: w-resize;
  740. opacity: 0.1;
  741. background-color: white;
  742. }
  743. .uni-cropper-line-l::before {
  744. position: absolute;
  745. z-index: 11;
  746. top: 0;
  747. bottom: 0;
  748. left: 50%;
  749. width: 41upx;
  750. height: 100%;
  751. content: "";
  752. -webkit-transform: translate3d(-50%, 0, 0);
  753. transform: translate3d(-50%, 0, 0);
  754. background: transparent;
  755. }
  756. .uni-cropper-point {
  757. position: absolute;
  758. z-index: 3;
  759. width: 5upx;
  760. height: 5upx;
  761. opacity: 0.75;
  762. background-color: rgb(145, 132, 132);
  763. }
  764. .point-t {
  765. top: -3upx;
  766. left: 50%;
  767. margin-left: -3upx;
  768. cursor: n-resize;
  769. }
  770. .point-tr {
  771. top: -3upx;
  772. left: 100%;
  773. margin-left: -3upx;
  774. cursor: n-resize;
  775. }
  776. .point-r {
  777. top: 50%;
  778. left: 100%;
  779. margin-top: -3upx;
  780. margin-left: -3upx;
  781. cursor: n-resize;
  782. }
  783. .point-rb {
  784. position: absolute;
  785. z-index: 1112;
  786. top: 100%;
  787. left: 100%;
  788. width: 30upx;
  789. height: 30upx;
  790. border-radius: 50%;
  791. cursor: n-resize;
  792. -webkit-transform: translate3d(-50%, -50%, 0);
  793. transform: translate3d(-50%, -50%, 0);
  794. opacity: 1;
  795. background-color: rgb(231, 222, 222);
  796. background-color: #509cff;
  797. }
  798. .point-b {
  799. top: 100%;
  800. left: 50%;
  801. margin-top: -3upx;
  802. margin-left: -3upx;
  803. cursor: n-resize;
  804. }
  805. .point-bl {
  806. top: 100%;
  807. left: 0;
  808. margin-top: -3upx;
  809. margin-left: -3upx;
  810. cursor: n-resize;
  811. }
  812. .point-l {
  813. top: 50%;
  814. left: 0;
  815. margin-top: -3upx;
  816. margin-left: -3upx;
  817. cursor: n-resize;
  818. }
  819. .point-lt {
  820. top: 0;
  821. left: 0;
  822. margin-top: -3upx;
  823. margin-left: -3upx;
  824. cursor: n-resize;
  825. }
  826. /* 裁剪框预览内容 */
  827. .uni-cropper-viewer {
  828. position: relative;
  829. overflow: hidden;
  830. width: 100%;
  831. height: 100%;
  832. }
  833. .uni-cropper-viewer image {
  834. position: absolute;
  835. z-index: 2;
  836. }
  837. </style>