ImagePreview.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Utils
  2. import { bem, createComponent } from './shared'; // Mixins
  3. import { PopupMixin } from '../mixins/popup';
  4. import { TouchMixin } from '../mixins/touch';
  5. import { BindEventMixin } from '../mixins/bind-event'; // Components
  6. import Icon from '../icon';
  7. import Swipe from '../swipe';
  8. import ImagePreviewItem from './ImagePreviewItem';
  9. export default createComponent({
  10. mixins: [TouchMixin, PopupMixin({
  11. skipToggleEvent: true
  12. }), BindEventMixin(function (bind) {
  13. bind(window, 'resize', this.resize, true);
  14. bind(window, 'orientationchange', this.resize, true);
  15. })],
  16. props: {
  17. className: null,
  18. closeable: Boolean,
  19. asyncClose: Boolean,
  20. overlayStyle: Object,
  21. showIndicators: Boolean,
  22. images: {
  23. type: Array,
  24. default: function _default() {
  25. return [];
  26. }
  27. },
  28. loop: {
  29. type: Boolean,
  30. default: true
  31. },
  32. overlay: {
  33. type: Boolean,
  34. default: true
  35. },
  36. minZoom: {
  37. type: [Number, String],
  38. default: 1 / 3
  39. },
  40. maxZoom: {
  41. type: [Number, String],
  42. default: 3
  43. },
  44. transition: {
  45. type: String,
  46. default: 'van-fade'
  47. },
  48. showIndex: {
  49. type: Boolean,
  50. default: true
  51. },
  52. swipeDuration: {
  53. type: [Number, String],
  54. default: 300
  55. },
  56. startPosition: {
  57. type: [Number, String],
  58. default: 0
  59. },
  60. overlayClass: {
  61. type: String,
  62. default: bem('overlay')
  63. },
  64. closeIcon: {
  65. type: String,
  66. default: 'clear'
  67. },
  68. closeOnPopstate: {
  69. type: Boolean,
  70. default: true
  71. },
  72. closeIconPosition: {
  73. type: String,
  74. default: 'top-right'
  75. }
  76. },
  77. data: function data() {
  78. return {
  79. active: 0,
  80. rootWidth: 0,
  81. rootHeight: 0,
  82. doubleClickTimer: null
  83. };
  84. },
  85. mounted: function mounted() {
  86. this.resize();
  87. },
  88. watch: {
  89. startPosition: 'setActive',
  90. value: function value(val) {
  91. var _this = this;
  92. if (val) {
  93. this.setActive(+this.startPosition);
  94. this.$nextTick(function () {
  95. _this.resize();
  96. _this.$refs.swipe.swipeTo(+_this.startPosition, {
  97. immediate: true
  98. });
  99. });
  100. } else {
  101. this.$emit('close', {
  102. index: this.active,
  103. url: this.images[this.active]
  104. });
  105. }
  106. }
  107. },
  108. methods: {
  109. resize: function resize() {
  110. if (this.$el && this.$el.getBoundingClientRect) {
  111. var rect = this.$el.getBoundingClientRect();
  112. this.rootWidth = rect.width;
  113. this.rootHeight = rect.height;
  114. }
  115. },
  116. emitClose: function emitClose() {
  117. if (!this.asyncClose) {
  118. this.$emit('input', false);
  119. }
  120. },
  121. emitScale: function emitScale(args) {
  122. this.$emit('scale', args);
  123. },
  124. setActive: function setActive(active) {
  125. if (active !== this.active) {
  126. this.active = active;
  127. this.$emit('change', active);
  128. }
  129. },
  130. genIndex: function genIndex() {
  131. var h = this.$createElement;
  132. if (this.showIndex) {
  133. return h("div", {
  134. "class": bem('index')
  135. }, [this.slots('index', {
  136. index: this.active
  137. }) || this.active + 1 + " / " + this.images.length]);
  138. }
  139. },
  140. genCover: function genCover() {
  141. var h = this.$createElement;
  142. var cover = this.slots('cover');
  143. if (cover) {
  144. return h("div", {
  145. "class": bem('cover')
  146. }, [cover]);
  147. }
  148. },
  149. genImages: function genImages() {
  150. var _this2 = this;
  151. var h = this.$createElement;
  152. return h(Swipe, {
  153. "ref": "swipe",
  154. "attrs": {
  155. "lazyRender": true,
  156. "loop": this.loop,
  157. "duration": this.swipeDuration,
  158. "initialSwipe": this.startPosition,
  159. "showIndicators": this.showIndicators,
  160. "indicatorColor": "white"
  161. },
  162. "class": bem('swipe'),
  163. "on": {
  164. "change": this.setActive
  165. }
  166. }, [this.images.map(function (image) {
  167. return h(ImagePreviewItem, {
  168. "attrs": {
  169. "src": image,
  170. "show": _this2.value,
  171. "active": _this2.active,
  172. "maxZoom": _this2.maxZoom,
  173. "minZoom": _this2.minZoom,
  174. "rootWidth": _this2.rootWidth,
  175. "rootHeight": _this2.rootHeight
  176. },
  177. "on": {
  178. "scale": _this2.emitScale,
  179. "close": _this2.emitClose
  180. }
  181. });
  182. })]);
  183. },
  184. genClose: function genClose() {
  185. var h = this.$createElement;
  186. if (this.closeable) {
  187. return h(Icon, {
  188. "attrs": {
  189. "role": "button",
  190. "name": this.closeIcon
  191. },
  192. "class": bem('close-icon', this.closeIconPosition),
  193. "on": {
  194. "click": this.emitClose
  195. }
  196. });
  197. }
  198. },
  199. onClosed: function onClosed() {
  200. this.$emit('closed');
  201. },
  202. // @exposed-api
  203. swipeTo: function swipeTo(index, options) {
  204. if (this.$refs.swipe) {
  205. this.$refs.swipe.swipeTo(index, options);
  206. }
  207. }
  208. },
  209. render: function render() {
  210. var h = arguments[0];
  211. return h("transition", {
  212. "attrs": {
  213. "name": this.transition
  214. },
  215. "on": {
  216. "afterLeave": this.onClosed
  217. }
  218. }, [this.shouldRender ? h("div", {
  219. "directives": [{
  220. name: "show",
  221. value: this.value
  222. }],
  223. "class": [bem(), this.className]
  224. }, [this.genClose(), this.genImages(), this.genIndex(), this.genCover()]) : null]);
  225. }
  226. });