index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. "use strict";
  2. exports.__esModule = true;
  3. exports.default = void 0;
  4. var _utils = require("../utils");
  5. var _style = require("../utils/dom/style");
  6. var _event = require("../utils/dom/event");
  7. var _raf = require("../utils/dom/raf");
  8. var _number = require("../utils/format/number");
  9. var _touch = require("../mixins/touch");
  10. var _relation = require("../mixins/relation");
  11. var _bindEvent = require("../mixins/bind-event");
  12. // Utils
  13. // Mixins
  14. var _createNamespace = (0, _utils.createNamespace)('swipe'),
  15. createComponent = _createNamespace[0],
  16. bem = _createNamespace[1];
  17. var _default = createComponent({
  18. mixins: [_touch.TouchMixin, (0, _relation.ParentMixin)('vanSwipe'), (0, _bindEvent.BindEventMixin)(function (bind, isBind) {
  19. bind(window, 'resize', this.resize, true);
  20. bind(window, 'orientationchange', this.resize, true);
  21. bind(window, 'visibilitychange', this.onVisibilityChange);
  22. if (isBind) {
  23. this.initialize();
  24. } else {
  25. this.clear();
  26. }
  27. })],
  28. props: {
  29. width: [Number, String],
  30. height: [Number, String],
  31. autoplay: [Number, String],
  32. vertical: Boolean,
  33. lazyRender: Boolean,
  34. indicatorColor: String,
  35. loop: {
  36. type: Boolean,
  37. default: true
  38. },
  39. duration: {
  40. type: [Number, String],
  41. default: 500
  42. },
  43. touchable: {
  44. type: Boolean,
  45. default: true
  46. },
  47. initialSwipe: {
  48. type: [Number, String],
  49. default: 0
  50. },
  51. showIndicators: {
  52. type: Boolean,
  53. default: true
  54. },
  55. stopPropagation: {
  56. type: Boolean,
  57. default: true
  58. }
  59. },
  60. data: function data() {
  61. return {
  62. rect: null,
  63. offset: 0,
  64. active: 0,
  65. deltaX: 0,
  66. deltaY: 0,
  67. swiping: false,
  68. computedWidth: 0,
  69. computedHeight: 0
  70. };
  71. },
  72. watch: {
  73. children: function children() {
  74. this.initialize();
  75. },
  76. initialSwipe: function initialSwipe() {
  77. this.initialize();
  78. },
  79. autoplay: function autoplay(_autoplay) {
  80. if (_autoplay > 0) {
  81. this.autoPlay();
  82. } else {
  83. this.clear();
  84. }
  85. }
  86. },
  87. computed: {
  88. count: function count() {
  89. return this.children.length;
  90. },
  91. maxCount: function maxCount() {
  92. return Math.ceil(Math.abs(this.minOffset) / this.size);
  93. },
  94. delta: function delta() {
  95. return this.vertical ? this.deltaY : this.deltaX;
  96. },
  97. size: function size() {
  98. return this[this.vertical ? 'computedHeight' : 'computedWidth'];
  99. },
  100. trackSize: function trackSize() {
  101. return this.count * this.size;
  102. },
  103. activeIndicator: function activeIndicator() {
  104. return (this.active + this.count) % this.count;
  105. },
  106. isCorrectDirection: function isCorrectDirection() {
  107. var expect = this.vertical ? 'vertical' : 'horizontal';
  108. return this.direction === expect;
  109. },
  110. trackStyle: function trackStyle() {
  111. var style = {
  112. transitionDuration: (this.swiping ? 0 : this.duration) + "ms",
  113. transform: "translate" + (this.vertical ? 'Y' : 'X') + "(" + this.offset + "px)"
  114. };
  115. if (this.size) {
  116. var mainAxis = this.vertical ? 'height' : 'width';
  117. var crossAxis = this.vertical ? 'width' : 'height';
  118. style[mainAxis] = this.trackSize + "px";
  119. style[crossAxis] = this[crossAxis] ? this[crossAxis] + "px" : '';
  120. }
  121. return style;
  122. },
  123. indicatorStyle: function indicatorStyle() {
  124. return {
  125. backgroundColor: this.indicatorColor
  126. };
  127. },
  128. minOffset: function minOffset() {
  129. return (this.vertical ? this.rect.height : this.rect.width) - this.size * this.count;
  130. }
  131. },
  132. mounted: function mounted() {
  133. this.bindTouchEvent(this.$refs.track);
  134. },
  135. methods: {
  136. // initialize swipe position
  137. initialize: function initialize(active) {
  138. if (active === void 0) {
  139. active = +this.initialSwipe;
  140. }
  141. if (!this.$el || (0, _style.isHidden)(this.$el)) {
  142. return;
  143. }
  144. clearTimeout(this.timer);
  145. var rect = {
  146. width: this.$el.offsetWidth,
  147. height: this.$el.offsetHeight
  148. };
  149. this.rect = rect;
  150. this.swiping = true;
  151. this.active = active;
  152. this.computedWidth = +this.width || rect.width;
  153. this.computedHeight = +this.height || rect.height;
  154. this.offset = this.getTargetOffset(active);
  155. this.children.forEach(function (swipe) {
  156. swipe.offset = 0;
  157. });
  158. this.autoPlay();
  159. },
  160. // @exposed-api
  161. resize: function resize() {
  162. this.initialize(this.activeIndicator);
  163. },
  164. onVisibilityChange: function onVisibilityChange() {
  165. if (document.hidden) {
  166. this.clear();
  167. } else {
  168. this.autoPlay();
  169. }
  170. },
  171. onTouchStart: function onTouchStart(event) {
  172. if (!this.touchable) return;
  173. this.clear();
  174. this.touchStartTime = Date.now();
  175. this.touchStart(event);
  176. this.correctPosition();
  177. },
  178. onTouchMove: function onTouchMove(event) {
  179. if (!this.touchable || !this.swiping) return;
  180. this.touchMove(event);
  181. if (this.isCorrectDirection) {
  182. (0, _event.preventDefault)(event, this.stopPropagation);
  183. this.move({
  184. offset: this.delta
  185. });
  186. }
  187. },
  188. onTouchEnd: function onTouchEnd() {
  189. if (!this.touchable || !this.swiping) return;
  190. var size = this.size,
  191. delta = this.delta;
  192. var duration = Date.now() - this.touchStartTime;
  193. var speed = delta / duration;
  194. var shouldSwipe = Math.abs(speed) > 0.25 || Math.abs(delta) > size / 2;
  195. if (shouldSwipe && this.isCorrectDirection) {
  196. var offset = this.vertical ? this.offsetY : this.offsetX;
  197. var pace = 0;
  198. if (this.loop) {
  199. pace = offset > 0 ? delta > 0 ? -1 : 1 : 0;
  200. } else {
  201. pace = -Math[delta > 0 ? 'ceil' : 'floor'](delta / size);
  202. }
  203. this.move({
  204. pace: pace,
  205. emitChange: true
  206. });
  207. } else if (delta) {
  208. this.move({
  209. pace: 0
  210. });
  211. }
  212. this.swiping = false;
  213. this.autoPlay();
  214. },
  215. getTargetActive: function getTargetActive(pace) {
  216. var active = this.active,
  217. count = this.count,
  218. maxCount = this.maxCount;
  219. if (pace) {
  220. if (this.loop) {
  221. return (0, _number.range)(active + pace, -1, count);
  222. }
  223. return (0, _number.range)(active + pace, 0, maxCount);
  224. }
  225. return active;
  226. },
  227. getTargetOffset: function getTargetOffset(targetActive, offset) {
  228. if (offset === void 0) {
  229. offset = 0;
  230. }
  231. var currentPosition = targetActive * this.size;
  232. if (!this.loop) {
  233. currentPosition = Math.min(currentPosition, -this.minOffset);
  234. }
  235. var targetOffset = offset - currentPosition;
  236. if (!this.loop) {
  237. targetOffset = (0, _number.range)(targetOffset, this.minOffset, 0);
  238. }
  239. return targetOffset;
  240. },
  241. move: function move(_ref) {
  242. var _ref$pace = _ref.pace,
  243. pace = _ref$pace === void 0 ? 0 : _ref$pace,
  244. _ref$offset = _ref.offset,
  245. offset = _ref$offset === void 0 ? 0 : _ref$offset,
  246. emitChange = _ref.emitChange;
  247. var loop = this.loop,
  248. count = this.count,
  249. active = this.active,
  250. children = this.children,
  251. trackSize = this.trackSize,
  252. minOffset = this.minOffset;
  253. if (count <= 1) {
  254. return;
  255. }
  256. var targetActive = this.getTargetActive(pace);
  257. var targetOffset = this.getTargetOffset(targetActive, offset); // auto move first and last swipe in loop mode
  258. if (loop) {
  259. if (children[0] && targetOffset !== minOffset) {
  260. var outRightBound = targetOffset < minOffset;
  261. children[0].offset = outRightBound ? trackSize : 0;
  262. }
  263. if (children[count - 1] && targetOffset !== 0) {
  264. var outLeftBound = targetOffset > 0;
  265. children[count - 1].offset = outLeftBound ? -trackSize : 0;
  266. }
  267. }
  268. this.active = targetActive;
  269. this.offset = targetOffset;
  270. if (emitChange && targetActive !== active) {
  271. this.$emit('change', this.activeIndicator);
  272. }
  273. },
  274. // @exposed-api
  275. prev: function prev() {
  276. var _this = this;
  277. this.correctPosition();
  278. this.resetTouchStatus();
  279. (0, _raf.doubleRaf)(function () {
  280. _this.swiping = false;
  281. _this.move({
  282. pace: -1,
  283. emitChange: true
  284. });
  285. });
  286. },
  287. // @exposed-api
  288. next: function next() {
  289. var _this2 = this;
  290. this.correctPosition();
  291. this.resetTouchStatus();
  292. (0, _raf.doubleRaf)(function () {
  293. _this2.swiping = false;
  294. _this2.move({
  295. pace: 1,
  296. emitChange: true
  297. });
  298. });
  299. },
  300. // @exposed-api
  301. swipeTo: function swipeTo(index, options) {
  302. var _this3 = this;
  303. if (options === void 0) {
  304. options = {};
  305. }
  306. this.correctPosition();
  307. this.resetTouchStatus();
  308. (0, _raf.doubleRaf)(function () {
  309. var targetIndex;
  310. if (_this3.loop && index === _this3.count) {
  311. targetIndex = _this3.active === 0 ? 0 : index;
  312. } else {
  313. targetIndex = index % _this3.count;
  314. }
  315. if (options.immediate) {
  316. (0, _raf.doubleRaf)(function () {
  317. _this3.swiping = false;
  318. });
  319. } else {
  320. _this3.swiping = false;
  321. }
  322. _this3.move({
  323. pace: targetIndex - _this3.active,
  324. emitChange: true
  325. });
  326. });
  327. },
  328. correctPosition: function correctPosition() {
  329. this.swiping = true;
  330. if (this.active <= -1) {
  331. this.move({
  332. pace: this.count
  333. });
  334. }
  335. if (this.active >= this.count) {
  336. this.move({
  337. pace: -this.count
  338. });
  339. }
  340. },
  341. clear: function clear() {
  342. clearTimeout(this.timer);
  343. },
  344. autoPlay: function autoPlay() {
  345. var _this4 = this;
  346. var autoplay = this.autoplay;
  347. if (autoplay > 0 && this.count > 1) {
  348. this.clear();
  349. this.timer = setTimeout(function () {
  350. _this4.next();
  351. _this4.autoPlay();
  352. }, autoplay);
  353. }
  354. },
  355. genIndicator: function genIndicator() {
  356. var _this5 = this;
  357. var h = this.$createElement;
  358. var count = this.count,
  359. activeIndicator = this.activeIndicator;
  360. var slot = this.slots('indicator');
  361. if (slot) {
  362. return slot;
  363. }
  364. if (this.showIndicators && count > 1) {
  365. return h("div", {
  366. "class": bem('indicators', {
  367. vertical: this.vertical
  368. })
  369. }, [Array.apply(void 0, Array(count)).map(function (empty, index) {
  370. return h("i", {
  371. "class": bem('indicator', {
  372. active: index === activeIndicator
  373. }),
  374. "style": index === activeIndicator ? _this5.indicatorStyle : null
  375. });
  376. })]);
  377. }
  378. }
  379. },
  380. render: function render() {
  381. var h = arguments[0];
  382. return h("div", {
  383. "class": bem()
  384. }, [h("div", {
  385. "ref": "track",
  386. "style": this.trackStyle,
  387. "class": bem('track', {
  388. vertical: this.vertical
  389. })
  390. }, [this.slots()]), this.genIndicator()]);
  391. }
  392. });
  393. exports.default = _default;