ImagePreview.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. exports.__esModule = true;
  4. exports["default"] = void 0;
  5. var _babelHelperVueJsxMergeProps = _interopRequireDefault(require("@vue/babel-helper-vue-jsx-merge-props"));
  6. var _utils = require("../utils");
  7. var _event = require("../utils/event");
  8. var _popup = require("../mixins/popup");
  9. var _touch = require("../mixins/touch");
  10. var _swipe = _interopRequireDefault(require("../swipe"));
  11. var _swipeItem = _interopRequireDefault(require("../swipe-item"));
  12. var _use = (0, _utils.use)('image-preview'),
  13. sfc = _use[0],
  14. bem = _use[1];
  15. function getDistance(touches) {
  16. return Math.sqrt(Math.abs((touches[0].clientX - touches[1].clientX) * (touches[0].clientY - touches[1].clientY)));
  17. }
  18. var _default = sfc({
  19. mixins: [_popup.PopupMixin, _touch.TouchMixin],
  20. props: {
  21. images: Array,
  22. className: null,
  23. lazyLoad: Boolean,
  24. asyncClose: Boolean,
  25. startPosition: Number,
  26. showIndicators: Boolean,
  27. loop: {
  28. type: Boolean,
  29. "default": true
  30. },
  31. overlay: {
  32. type: Boolean,
  33. "default": true
  34. },
  35. showIndex: {
  36. type: Boolean,
  37. "default": true
  38. },
  39. minZoom: {
  40. type: Number,
  41. "default": 1 / 3
  42. },
  43. maxZoom: {
  44. type: Number,
  45. "default": 3
  46. },
  47. overlayClass: {
  48. type: String,
  49. "default": 'van-image-preview__overlay'
  50. },
  51. closeOnClickOverlay: {
  52. type: Boolean,
  53. "default": true
  54. }
  55. },
  56. data: function data() {
  57. return {
  58. scale: 1,
  59. moveX: 0,
  60. moveY: 0,
  61. moving: false,
  62. zooming: false,
  63. active: 0
  64. };
  65. },
  66. computed: {
  67. imageStyle: function imageStyle() {
  68. var scale = this.scale;
  69. var style = {
  70. transition: this.zooming || this.moving ? '' : '.3s all'
  71. };
  72. if (scale !== 1) {
  73. style.transform = "scale3d(" + scale + ", " + scale + ", 1) translate(" + this.moveX / scale + "px, " + this.moveY / scale + "px)";
  74. }
  75. return style;
  76. }
  77. },
  78. watch: {
  79. value: function value() {
  80. this.active = this.startPosition;
  81. },
  82. startPosition: function startPosition(active) {
  83. this.active = active;
  84. }
  85. },
  86. methods: {
  87. onWrapperTouchStart: function onWrapperTouchStart() {
  88. this.touchStartTime = new Date();
  89. },
  90. onWrapperTouchEnd: function onWrapperTouchEnd(event) {
  91. (0, _event.preventDefault)(event);
  92. var deltaTime = new Date() - this.touchStartTime;
  93. var _ref = this.$refs.swipe || {},
  94. _ref$offsetX = _ref.offsetX,
  95. offsetX = _ref$offsetX === void 0 ? 0 : _ref$offsetX,
  96. _ref$offsetY = _ref.offsetY,
  97. offsetY = _ref$offsetY === void 0 ? 0 : _ref$offsetY; // prevent long tap to close component
  98. if (deltaTime < 300 && offsetX < 10 && offsetY < 10) {
  99. var index = this.active;
  100. this.resetScale();
  101. this.$emit('close', {
  102. index: index,
  103. url: this.images[index]
  104. });
  105. if (!this.asyncClose) {
  106. this.$emit('input', false);
  107. }
  108. }
  109. },
  110. startMove: function startMove(event) {
  111. var image = event.currentTarget;
  112. var rect = image.getBoundingClientRect();
  113. var winWidth = window.innerWidth;
  114. var winHeight = window.innerHeight;
  115. this.touchStart(event);
  116. this.moving = true;
  117. this.startMoveX = this.moveX;
  118. this.startMoveY = this.moveY;
  119. this.maxMoveX = Math.max(0, (rect.width - winWidth) / 2);
  120. this.maxMoveY = Math.max(0, (rect.height - winHeight) / 2);
  121. },
  122. startZoom: function startZoom(event) {
  123. this.moving = false;
  124. this.zooming = true;
  125. this.startScale = this.scale;
  126. this.startDistance = getDistance(event.touches);
  127. },
  128. onTouchStart: function onTouchStart(event) {
  129. var touches = event.touches;
  130. var _ref2 = this.$refs.swipe || {},
  131. _ref2$offsetX = _ref2.offsetX,
  132. offsetX = _ref2$offsetX === void 0 ? 0 : _ref2$offsetX;
  133. if (touches.length === 1 && this.scale !== 1) {
  134. this.startMove(event);
  135. }
  136. /* istanbul ignore else */
  137. else if (touches.length === 2 && !offsetX) {
  138. this.startZoom(event);
  139. }
  140. },
  141. onTouchMove: function onTouchMove(event) {
  142. var touches = event.touches;
  143. if (this.moving || this.zooming) {
  144. (0, _event.preventDefault)(event, true);
  145. }
  146. if (this.moving) {
  147. this.touchMove(event);
  148. var moveX = this.deltaX + this.startMoveX;
  149. var moveY = this.deltaY + this.startMoveY;
  150. this.moveX = (0, _utils.range)(moveX, -this.maxMoveX, this.maxMoveX);
  151. this.moveY = (0, _utils.range)(moveY, -this.maxMoveY, this.maxMoveY);
  152. }
  153. if (this.zooming && touches.length === 2) {
  154. var distance = getDistance(touches);
  155. var scale = this.startScale * distance / this.startDistance;
  156. this.scale = (0, _utils.range)(scale, this.minZoom, this.maxZoom);
  157. }
  158. },
  159. onTouchEnd: function onTouchEnd(event) {
  160. /* istanbul ignore else */
  161. if (this.moving || this.zooming) {
  162. var stopPropagation = true;
  163. if (this.moving && this.startMoveX === this.moveX && this.startMoveY === this.moveY) {
  164. stopPropagation = false;
  165. }
  166. if (!event.touches.length) {
  167. this.moving = false;
  168. this.zooming = false;
  169. this.startMoveX = 0;
  170. this.startMoveY = 0;
  171. this.startScale = 1;
  172. if (this.scale < 1) {
  173. this.resetScale();
  174. }
  175. }
  176. if (stopPropagation) {
  177. (0, _event.preventDefault)(event, true);
  178. }
  179. }
  180. },
  181. onChange: function onChange(active) {
  182. this.resetScale();
  183. this.active = active;
  184. this.$emit('change', active);
  185. },
  186. resetScale: function resetScale() {
  187. this.scale = 1;
  188. this.moveX = 0;
  189. this.moveY = 0;
  190. }
  191. },
  192. render: function render(h) {
  193. var _this = this;
  194. if (!this.value) {
  195. return;
  196. }
  197. var active = this.active,
  198. images = this.images;
  199. var Index = this.showIndex && h("div", {
  200. "class": bem('index')
  201. }, [this.slots('index') || active + 1 + "/" + images.length]);
  202. var Images = h(_swipe["default"], {
  203. "ref": "swipe",
  204. "attrs": {
  205. "loop": this.loop,
  206. "indicatorColor": "white",
  207. "initialSwipe": this.startPosition,
  208. "showIndicators": this.showIndicators
  209. },
  210. "on": {
  211. "change": this.onChange
  212. }
  213. }, [images.map(function (image, index) {
  214. var props = {
  215. "class": bem('image'),
  216. style: index === active ? _this.imageStyle : null,
  217. on: {
  218. touchstart: _this.onTouchStart,
  219. touchmove: _this.onTouchMove,
  220. touchend: _this.onTouchEnd,
  221. touchcancel: _this.onTouchEnd
  222. }
  223. };
  224. return h(_swipeItem["default"], [_this.lazyLoad ? h("img", (0, _babelHelperVueJsxMergeProps["default"])([{
  225. "directives": [{
  226. name: "lazy",
  227. value: image
  228. }]
  229. }, props])) : h("img", (0, _babelHelperVueJsxMergeProps["default"])([{
  230. "attrs": {
  231. "src": image
  232. }
  233. }, props]))]);
  234. })]);
  235. return h("transition", {
  236. "attrs": {
  237. "name": "van-fade"
  238. }
  239. }, [h("div", {
  240. "class": [bem(), this.className],
  241. "on": {
  242. "touchstart": this.onWrapperTouchStart,
  243. "touchend": this.onWrapperTouchEnd,
  244. "touchcancel": this.onWrapperTouchEnd
  245. }
  246. }, [Index, Images])]);
  247. }
  248. });
  249. exports["default"] = _default;