cut.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. (function(global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.weCropper = factory());
  5. }(this, (function() {
  6. 'use strict';
  7. var device = void 0;
  8. var TOUCH_STATE = ['touchstarted', 'touchmoved', 'touchended'];
  9. function firstLetterUpper(str) {
  10. return str.charAt(0).toUpperCase() + str.slice(1);
  11. }
  12. function setTouchState(instance) {
  13. for (var _len = arguments.length, arg = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
  14. arg[_key - 1] = arguments[_key];
  15. }
  16. TOUCH_STATE.forEach(function(key, i) {
  17. if (arg[i] !== undefined) {
  18. instance[key] = arg[i];
  19. }
  20. });
  21. }
  22. function validator(instance, o) {
  23. Object.defineProperties(instance, o);
  24. }
  25. function getDevice() {
  26. if (!device) {
  27. device = wx.getSystemInfoSync();
  28. }
  29. return device;
  30. }
  31. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
  32. return typeof obj;
  33. } : function(obj) {
  34. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" :
  35. typeof obj;
  36. };
  37. var classCallCheck = function(instance, Constructor) {
  38. if (!(instance instanceof Constructor)) {
  39. throw new TypeError("Cannot call a class as a function");
  40. }
  41. };
  42. var createClass = function() {
  43. function defineProperties(target, props) {
  44. for (var i = 0; i < props.length; i++) {
  45. var descriptor = props[i];
  46. descriptor.enumerable = descriptor.enumerable || false;
  47. descriptor.configurable = true;
  48. if ("value" in descriptor) descriptor.writable = true;
  49. Object.defineProperty(target, descriptor.key, descriptor);
  50. }
  51. }
  52. return function(Constructor, protoProps, staticProps) {
  53. if (protoProps) defineProperties(Constructor.prototype, protoProps);
  54. if (staticProps) defineProperties(Constructor, staticProps);
  55. return Constructor;
  56. };
  57. }();
  58. var slicedToArray = function() {
  59. function sliceIterator(arr, i) {
  60. var _arr = [];
  61. var _n = true;
  62. var _d = false;
  63. var _e = undefined;
  64. try {
  65. for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
  66. _arr.push(_s.value);
  67. if (i && _arr.length === i) break;
  68. }
  69. } catch (err) {
  70. _d = true;
  71. _e = err;
  72. } finally {
  73. try {
  74. if (!_n && _i["return"]) _i["return"]();
  75. } finally {
  76. if (_d) throw _e;
  77. }
  78. }
  79. return _arr;
  80. }
  81. return function(arr, i) {
  82. if (Array.isArray(arr)) {
  83. return arr;
  84. } else if (Symbol.iterator in Object(arr)) {
  85. return sliceIterator(arr, i);
  86. } else {
  87. throw new TypeError("Invalid attempt to destructure non-iterable instance");
  88. }
  89. };
  90. }();
  91. var tmp = {};
  92. var DEFAULT = {
  93. id: {
  94. default: 'cropper',
  95. get: function get$$1() {
  96. return tmp.id;
  97. },
  98. set: function set$$1(value) {
  99. if (typeof value !== 'string') {}
  100. tmp.id = value;
  101. }
  102. },
  103. width: {
  104. default: 750,
  105. get: function get$$1() {
  106. return tmp.width;
  107. },
  108. set: function set$$1(value) {
  109. tmp.width = value;
  110. }
  111. },
  112. height: {
  113. default: 750,
  114. get: function get$$1() {
  115. return tmp.height;
  116. },
  117. set: function set$$1(value) {
  118. tmp.height = value;
  119. }
  120. },
  121. scale: {
  122. default: 2.5,
  123. get: function get$$1() {
  124. return tmp.scale;
  125. },
  126. set: function set$$1(value) {
  127. tmp.scale = value;
  128. }
  129. },
  130. zoom: {
  131. default: 5,
  132. get: function get$$1() {
  133. return tmp.zoom;
  134. },
  135. set: function set$$1(value) {
  136. tmp.zoom = value;
  137. }
  138. },
  139. src: {
  140. default: 'cropper',
  141. get: function get$$1() {
  142. return tmp.src;
  143. },
  144. set: function set$$1(value) {
  145. tmp.src = value;
  146. }
  147. },
  148. cut: {
  149. default: {},
  150. get: function get$$1() {
  151. return tmp.cut;
  152. },
  153. set: function set$$1(value) {
  154. tmp.cut = value;
  155. }
  156. },
  157. onReady: {
  158. default: null,
  159. get: function get$$1() {
  160. return tmp.ready;
  161. },
  162. set: function set$$1(value) {
  163. tmp.ready = value;
  164. }
  165. },
  166. onBeforeImageLoad: {
  167. default: null,
  168. get: function get$$1() {
  169. return tmp.beforeImageLoad;
  170. },
  171. set: function set$$1(value) {
  172. tmp.beforeImageLoad = value;
  173. }
  174. },
  175. onImageLoad: {
  176. default: null,
  177. get: function get$$1() {
  178. return tmp.imageLoad;
  179. },
  180. set: function set$$1(value) {
  181. tmp.imageLoad = value;
  182. }
  183. },
  184. onBeforeDraw: {
  185. default: null,
  186. get: function get$$1() {
  187. return tmp.beforeDraw;
  188. },
  189. set: function set$$1(value) {
  190. tmp.beforeDraw = value;
  191. }
  192. }
  193. };
  194. function prepare() {
  195. var self = this;
  196. var _getDevice = getDevice(),
  197. windowWidth = _getDevice.windowWidth;
  198. self.attachPage = function() {
  199. var pages = getCurrentPages();
  200. var pageContext = pages[pages.length - 1];
  201. pageContext.wecropper = self;
  202. };
  203. self.createCtx = function() {
  204. var id = self.id;
  205. if (id) {
  206. self.ctx = wx.createCanvasContext(id);
  207. }
  208. };
  209. self.deviceRadio = windowWidth / 750;
  210. self.deviceRadio = self.deviceRadio.toFixed(2)
  211. }
  212. function observer() {
  213. var self = this;
  214. var EVENT_TYPE = ['ready', 'beforeImageLoad', 'beforeDraw', 'imageLoad'];
  215. self.on = function(event, fn) {
  216. if (EVENT_TYPE.indexOf(event) > -1) {
  217. if (typeof fn === 'function') {
  218. event === 'ready' ? fn(self) : self['on' + firstLetterUpper(event)] = fn;
  219. }
  220. }
  221. return self;
  222. };
  223. }
  224. function methods() {
  225. var self = this;
  226. var deviceRadio = self.deviceRadio;
  227. var boundWidth = self.width;
  228. var boundHeight = self.height;
  229. var _self$cut = self.cut,
  230. _self$cut$x = _self$cut.x,
  231. x = _self$cut$x === undefined ? 0 : _self$cut$x,
  232. _self$cut$y = _self$cut.y,
  233. y = _self$cut$y === undefined ? 0 : _self$cut$y,
  234. _self$cut$width = _self$cut.width,
  235. width = _self$cut$width === undefined ? boundWidth : _self$cut$width,
  236. _self$cut$height = _self$cut.height,
  237. height = _self$cut$height === undefined ? boundHeight : _self$cut$height;
  238. self.updateCanvas = function() {
  239. if (self.croperTarget) {
  240. self.ctx.drawImage(self.croperTarget, self.imgLeft, self.imgTop, self.scaleWidth, self.scaleHeight);
  241. }
  242. typeof self.onBeforeDraw === 'function' && self.onBeforeDraw(self.ctx, self);
  243. self.setBoundStyle();
  244. self.ctx.draw();
  245. return self;
  246. };
  247. self.pushOrign = function(src) {
  248. self.src = src;
  249. typeof self.onBeforeImageLoad === 'function' && self.onBeforeImageLoad(self.ctx, self);
  250. uni.getImageInfo({
  251. src: src,
  252. success: function success(res) {
  253. var innerAspectRadio = res.width / res.height;
  254. self.croperTarget = res.path || src;
  255. if (innerAspectRadio < width / height) {
  256. self.rectX = x;
  257. self.baseWidth = width;
  258. self.baseHeight = width / innerAspectRadio;
  259. self.rectY = y - Math.abs((height - self.baseHeight) / 2);
  260. } else {
  261. self.rectY = y;
  262. self.baseWidth = height * innerAspectRadio;
  263. self.baseHeight = height;
  264. self.rectX = x - Math.abs((width - self.baseWidth) / 2);
  265. }
  266. self.imgLeft = self.rectX;
  267. self.imgTop = self.rectY;
  268. self.scaleWidth = self.baseWidth;
  269. self.scaleHeight = self.baseHeight;
  270. self.updateCanvas();
  271. typeof self.onImageLoad === 'function' && self.onImageLoad(self.ctx, self);
  272. }
  273. });
  274. self.update();
  275. return self;
  276. };
  277. self.getCropperImage = function() {
  278. for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  279. args[_key] = arguments[_key];
  280. }
  281. var id = self.id;
  282. var ARG_TYPE = toString.call(args[0]);
  283. switch (ARG_TYPE) {
  284. case '[object Object]':
  285. var _args$0$quality = args[0].quality,
  286. quality = _args$0$quality === undefined ? 10 : _args$0$quality;
  287. uni.canvasToTempFilePath({
  288. canvasId: id,
  289. x: x,
  290. y: y,
  291. fileType: "jpg",
  292. width: width,
  293. height: height,
  294. destWidth: width * quality / (deviceRadio * 10),
  295. destHeight: height * quality / (deviceRadio * 10),
  296. success: function success(res) {
  297. typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath);
  298. }
  299. });
  300. break;
  301. case '[object Function]':
  302. uni.canvasToTempFilePath({
  303. canvasId: id,
  304. x: x,
  305. y: y,
  306. fileType: "jpg",
  307. width: width,
  308. height: height,
  309. destWidth: width,
  310. destHeight: height,
  311. success: function success(res) {
  312. typeof args[args.length - 1] === 'function' && args[args.length - 1](res.tempFilePath);
  313. }
  314. });
  315. break;
  316. }
  317. return self;
  318. };
  319. }
  320. function update() {
  321. var self = this;
  322. if (!self.src) return;
  323. self.__oneTouchStart = function(touch) {
  324. self.touchX0 = touch.x;
  325. self.touchY0 = touch.y;
  326. };
  327. self.__oneTouchMove = function(touch) {
  328. var xMove = void 0,
  329. yMove = void 0;
  330. if (self.touchended) {
  331. return self.updateCanvas();
  332. }
  333. xMove = touch.x - self.touchX0;
  334. yMove = touch.y - self.touchY0;
  335. var imgLeft = self.rectX + xMove;
  336. var imgTop = self.rectY + yMove;
  337. self.outsideBound(imgLeft, imgTop);
  338. self.updateCanvas();
  339. };
  340. self.__twoTouchStart = function(touch0, touch1) {
  341. var xMove = void 0,
  342. yMove = void 0,
  343. oldDistance = void 0;
  344. self.touchX1 = self.rectX + self.scaleWidth / 2;
  345. self.touchY1 = self.rectY + self.scaleHeight / 2;
  346. xMove = touch1.x - touch0.x;
  347. yMove = touch1.y - touch0.y;
  348. oldDistance = Math.sqrt(xMove * xMove + yMove * yMove);
  349. self.oldDistance = oldDistance;
  350. };
  351. self.__twoTouchMove = function(touch0, touch1) {
  352. var xMove = void 0,
  353. yMove = void 0,
  354. newDistance = void 0;
  355. var scale = self.scale,
  356. zoom = self.zoom;
  357. xMove = touch1.x - touch0.x;
  358. yMove = touch1.y - touch0.y;
  359. newDistance = Math.sqrt(xMove * xMove + yMove * yMove
  360. // 使用0.005的缩放倍数具有良好的缩放体验
  361. );
  362. self.newScale = self.oldScale + 0.001 * zoom * (newDistance - self.oldDistance);
  363. // 设定缩放范围
  364. self.newScale <= 1 && (self.newScale = 1);
  365. self.newScale >= scale && (self.newScale = scale);
  366. self.scaleWidth = self.newScale * self.baseWidth;
  367. self.scaleHeight = self.newScale * self.baseHeight;
  368. var imgLeft = self.touchX1 - self.scaleWidth / 2;
  369. var imgTop = self.touchY1 - self.scaleHeight / 2;
  370. self.outsideBound(imgLeft, imgTop);
  371. self.updateCanvas();
  372. };
  373. self.__xtouchEnd = function() {
  374. self.oldScale = self.newScale;
  375. self.rectX = self.imgLeft;
  376. self.rectY = self.imgTop;
  377. };
  378. }
  379. var handle = {
  380. touchStart: function touchStart(e) {
  381. var self = this;
  382. var _e$touches = slicedToArray(e.touches, 2),
  383. touch0 = _e$touches[0],
  384. touch1 = _e$touches[1];
  385. if (!touch0.x) {
  386. touch0.x = touch0.clientX;
  387. touch0.y = touch0.clientY;
  388. if (touch1) {
  389. touch1.x = touch1.clientX;
  390. touch1.y = touch1.clientY;
  391. }
  392. }
  393. setTouchState(self, true, null, null);
  394. self.__oneTouchStart(touch0);
  395. if (e.touches.length >= 2) {
  396. self.__twoTouchStart(touch0, touch1);
  397. }
  398. },
  399. touchMove: function touchMove(e) {
  400. var self = this;
  401. var _e$touches2 = slicedToArray(e.touches, 2),
  402. touch0 = _e$touches2[0],
  403. touch1 = _e$touches2[1];
  404. if (!touch0.x) {
  405. touch0.x = touch0.clientX;
  406. touch0.y = touch0.clientY;
  407. if (touch1) {
  408. touch1.x = touch1.clientX;
  409. touch1.y = touch1.clientY;
  410. }
  411. }
  412. setTouchState(self, null, true);
  413. if (e.touches.length === 1) {
  414. self.__oneTouchMove(touch0);
  415. }
  416. if (e.touches.length >= 2) {
  417. self.__twoTouchMove(touch0, touch1);
  418. }
  419. },
  420. touchEnd: function touchEnd(e) {
  421. var self = this;
  422. setTouchState(self, false, false, true);
  423. self.__xtouchEnd();
  424. }
  425. };
  426. function cut() {
  427. var self = this;
  428. var deviceRadio = self.deviceRadio;
  429. var boundWidth = self.width;
  430. var boundHeight = self.height;
  431. var _self$cut = self.cut,
  432. _self$cut$x = _self$cut.x,
  433. x = _self$cut$x === undefined ? 0 : _self$cut$x,
  434. _self$cut$y = _self$cut.y,
  435. y = _self$cut$y === undefined ? 0 : _self$cut$y,
  436. _self$cut$width = _self$cut.width,
  437. width = _self$cut$width === undefined ? boundWidth : _self$cut$width,
  438. _self$cut$height = _self$cut.height,
  439. height = _self$cut$height === undefined ? boundHeight : _self$cut$height;
  440. self.outsideBound = function(imgLeft, imgTop) {
  441. self.imgLeft = imgLeft >= x ? x : self.scaleWidth + imgLeft - x <= width ? x + width - self.scaleWidth : imgLeft;
  442. self.imgTop = imgTop >= y ? y : self.scaleHeight + imgTop - y <= height ? y + height - self.scaleHeight : imgTop;
  443. };
  444. self.setBoundStyle = function() {
  445. var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
  446. _ref$color = _ref.color,
  447. color = _ref$color === undefined ? '#04b00f' : _ref$color,
  448. _ref$mask = _ref.mask,
  449. mask = _ref$mask === undefined ? 'rgba(0, 0, 0, 0.5)' : _ref$mask,
  450. _ref$lineWidth = _ref.lineWidth,
  451. lineWidth = _ref$lineWidth === undefined ? 1 : _ref$lineWidth;
  452. self.ctx.beginPath();
  453. self.ctx.setFillStyle(mask);
  454. self.ctx.fillRect(0, 0, x, boundHeight);
  455. self.ctx.fillRect(x, 0, width, y);
  456. self.ctx.fillRect(x, y + height, width, boundHeight - y - height);
  457. self.ctx.fillRect(x + width, 0, boundWidth - x - width, boundHeight);
  458. self.ctx.fill();
  459. self.ctx.beginPath();
  460. self.ctx.setStrokeStyle(color);
  461. self.ctx.setLineWidth(lineWidth);
  462. self.ctx.moveTo(x - lineWidth, y + 10 - lineWidth);
  463. self.ctx.lineTo(x - lineWidth, y - lineWidth);
  464. self.ctx.lineTo(x + 10 - lineWidth, y - lineWidth);
  465. self.ctx.stroke();
  466. self.ctx.beginPath();
  467. self.ctx.setStrokeStyle(color);
  468. self.ctx.setLineWidth(lineWidth);
  469. self.ctx.moveTo(x - lineWidth, y + height - 10 + lineWidth);
  470. self.ctx.lineTo(x - lineWidth, y + height + lineWidth);
  471. self.ctx.lineTo(x + 10 - lineWidth, y + height + lineWidth);
  472. self.ctx.stroke();
  473. self.ctx.beginPath();
  474. self.ctx.setStrokeStyle(color);
  475. self.ctx.setLineWidth(lineWidth);
  476. self.ctx.moveTo(x + width - 10 + lineWidth, y - lineWidth);
  477. self.ctx.lineTo(x + width + lineWidth, y - lineWidth);
  478. self.ctx.lineTo(x + width + lineWidth, y + 10 - lineWidth);
  479. self.ctx.stroke();
  480. self.ctx.beginPath();
  481. self.ctx.setStrokeStyle(color);
  482. self.ctx.setLineWidth(lineWidth);
  483. self.ctx.moveTo(x + width + lineWidth, y + height - 10 + lineWidth);
  484. self.ctx.lineTo(x + width + lineWidth, y + height + lineWidth);
  485. self.ctx.lineTo(x + width - 10 + lineWidth, y + height + lineWidth);
  486. self.ctx.stroke();
  487. };
  488. }
  489. var __version__ = '1.1.4';
  490. var weCropper = function() {
  491. function weCropper(params) {
  492. classCallCheck(this, weCropper);
  493. var self = this;
  494. var _default = {};
  495. validator(self, DEFAULT);
  496. Object.keys(DEFAULT).forEach(function(key) {
  497. _default[key] = DEFAULT[key].default;
  498. });
  499. Object.assign(self, _default, params);
  500. self.prepare();
  501. self.attachPage();
  502. self.createCtx();
  503. self.observer();
  504. self.cutt();
  505. self.methods();
  506. self.init();
  507. self.update();
  508. return self;
  509. }
  510. createClass(weCropper, [{
  511. key: 'init',
  512. value: function init() {
  513. var self = this;
  514. var src = self.src;
  515. self.version = __version__;
  516. typeof self.onReady === 'function' && self.onReady(self.ctx, self);
  517. if (src) {
  518. self.pushOrign(src);
  519. }
  520. setTouchState(self, false, false, false);
  521. self.oldScale = 1;
  522. self.newScale = 1;
  523. return self;
  524. }
  525. }]);
  526. return weCropper;
  527. }();
  528. Object.assign(weCropper.prototype, handle);
  529. weCropper.prototype.prepare = prepare;
  530. weCropper.prototype.observer = observer;
  531. weCropper.prototype.methods = methods;
  532. weCropper.prototype.cutt = cut;
  533. weCropper.prototype.update = update;
  534. return weCropper;
  535. })));