mui.imageViewer.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /**
  2. * 图片预览组件
  3. * varstion 0.4.0
  4. * by Houfeng
  5. * Houfeng@DCloud.io
  6. */
  7. (function($, document) {
  8. $.init({
  9. gestureConfig: {
  10. tap: true, //默认为true
  11. doubletap: true, //默认为false
  12. longtap: true, //默认为false
  13. swipe: true, //默认为true
  14. drag: true, //默认为true
  15. hold: true, //默认为false,不监听
  16. release: true //默认为false,不监听
  17. }
  18. });
  19. var touchSupport = ('ontouchstart' in document);
  20. var tapEventName = touchSupport ? 'tap' : 'click';
  21. var enterEventName = touchSupport ? 'tap' : 'click';
  22. var imageClassName = $.className('image');
  23. //创建DOM (此函数是否可放在 mui.js 中)
  24. $.dom = function(str) {
  25. if (!$.__create_dom_div__) {
  26. $.__create_dom_div__ = document.createElement('div');
  27. }
  28. $.__create_dom_div__.innerHTML = str;
  29. return $.__create_dom_div__.childNodes;
  30. };
  31. //图片预览组件类
  32. var ImageViewer = $.ImageViewer = $.Class.extend({
  33. //构造函数
  34. init: function(selector, options) {
  35. var self = this;
  36. self.options = options || {};
  37. self.selector = selector || 'img';
  38. if (self.options.dbl) {
  39. enterEventName = touchSupport ? 'doubletap' : 'dblclick';
  40. }
  41. self.findAllImage();
  42. self.createViewer();
  43. self.bindEvent();
  44. },
  45. //创建图片预览组件的整体 UI
  46. createViewer: function() {
  47. var self = this;
  48. self.viewer = $.dom("<div class='mui-imageviewer'><div class='mui-imageviewer-mask'></div><div class='mui-imageviewer-header'><i class='mui-icon mui-icon-closeempty mui-imageviewer-close'></i><span class='mui-imageviewer-state'></span></div><i class='mui-icon mui-icon-arrowleft mui-imageviewer-left'></i><i class='mui-icon mui-icon-arrowright mui-imageviewer-right'></i></div>");
  49. self.viewer = self.viewer[0] || self.viewer;
  50. //self.viewer.style.height = screen.height;
  51. self.closeButton = self.viewer.querySelector('.mui-imageviewer-close');
  52. self.state = self.viewer.querySelector('.mui-imageviewer-state');
  53. self.leftButton = self.viewer.querySelector('.mui-imageviewer-left');
  54. self.rightButton = self.viewer.querySelector('.mui-imageviewer-right');
  55. self.mask = self.viewer.querySelector('.mui-imageviewer-mask');
  56. document.body.appendChild(self.viewer);
  57. },
  58. //查找所有符合的图片
  59. findAllImage: function() {
  60. var self = this;
  61. self.images = [].slice.call($(self.selector));
  62. },
  63. //检查图片是否为启动预览的图片
  64. checkImage: function(target) {
  65. var self = this;
  66. if (target.tagName !== 'IMG') return false;
  67. return self.images.some(function(image) {
  68. return image == target;
  69. });
  70. },
  71. //绑定事件
  72. bindEvent: function() {
  73. var self = this;
  74. //绑定图片 tap 事件
  75. document.addEventListener(enterEventName, function(event) {
  76. if (!self.viewer) return;
  77. var target = event.target;
  78. if (!self.checkImage(target)) return;
  79. self.viewer.style.display = 'block';
  80. setTimeout(function() {
  81. self.viewer.style.opacity = 1;
  82. }, 0);
  83. self.index = self.images.indexOf(target);
  84. self.currentItem = self.createImage(self.index);
  85. }, false);
  86. //关系按钮事件
  87. self.closeButton.addEventListener(tapEventName, function(event) {
  88. self.viewer.style.opacity = 0;
  89. setTimeout(function() {
  90. self.viewer.style.display = 'none';
  91. self.disposeImage(true);
  92. }, 600);
  93. event.preventDefault();
  94. event.cancelBubble = true;
  95. }, false);
  96. //处理左右按钮
  97. self.leftButton.addEventListener(tapEventName, function() {
  98. self.prev();
  99. }, false);
  100. self.rightButton.addEventListener(tapEventName, function() {
  101. self.next();
  102. }, false);
  103. //处理划动
  104. self.mask.addEventListener($.EVENT_MOVE, function(event) {
  105. event.preventDefault();
  106. event.cancelBubble = true;
  107. }, false);
  108. self.viewer.addEventListener('swipeleft', function(event) {
  109. if (self.scaleValue == 1) self.next();
  110. event.preventDefault();
  111. event.cancelBubble = true;
  112. }, false);
  113. self.viewer.addEventListener('swiperight', function(event) {
  114. if (self.scaleValue == 1) self.prev();
  115. event.preventDefault();
  116. event.cancelBubble = true;
  117. }, false);
  118. //处理缩放开始
  119. self.viewer.addEventListener($.EVENT_START, function(event) {
  120. var touches = event.touches;
  121. if (touches.length == 2) {
  122. var p1 = touches[0];
  123. var p2 = touches[1];
  124. var x = p1.pageX - p2.pageX; //x1-x2
  125. var y = p1.pageY - p2.pageY; //y1-y2
  126. self.scaleStart = Math.sqrt(x * x + y * y);
  127. self.isMultiTouch = true;
  128. } else if (touches.length = 1) {
  129. self.dragStart = touches[0];
  130. }
  131. }, false);
  132. self.viewer.addEventListener($.EVENT_MOVE, function(event) {
  133. var img = self.currentItem.querySelector('img');
  134. var touches = event.changedTouches;
  135. if (touches.length == 2) {
  136. event.preventDefault();
  137. event.cancelBubble = true;
  138. var p1 = touches[0];
  139. var p2 = touches[1];
  140. var x = p1.pageX - p2.pageX;
  141. var y = p1.pageY - p2.pageY;
  142. self.scaleEnd = Math.sqrt(x * x + y * y);
  143. self._scaleValue = (self.scaleValue * (self.scaleEnd / self.scaleStart));
  144. //self.state.innerText = self._scaleValue;
  145. img.style.webkitTransform = "scale(" + self._scaleValue + "," + self._scaleValue + ") "; // + " translate(" + self.dragX || 0 + "px," + self.dragY || 0 + "px)";
  146. } else if (!self.isMultiTouch && touches.length == 1 && self.scaleValue != 1) {
  147. event.preventDefault();
  148. event.cancelBubble = true;
  149. self.dragEnd = touches[0];
  150. self._dragX = self.dragX + (self.dragEnd.pageX - self.dragStart.pageX);
  151. self._dragY = self.dragY + (self.dragEnd.pageY - self.dragStart.pageY);
  152. img.style.marginLeft = self._dragX + 'px';
  153. img.style.marginTop = self._dragY + 'px';
  154. //img.style.transform = "translate(" + self._dragX + "px," + self._dragY + "px) " + " scale(" + self.scaleValue || 1 + "," + self.scaleValue || 1 + ")";
  155. }
  156. }, false);
  157. self.viewer.addEventListener($.EVENT_END, function() {
  158. self.scaleValue = self._scaleValue || self.scaleValue;
  159. self._scaleValue = null;
  160. self.dragX = self._dragX;
  161. self.dragY = self._dragY;
  162. self._dragX = null;
  163. self._dragY = null;
  164. var touches = event.touches;
  165. self.isMultiTouch = (touches.length != 0);
  166. });
  167. // doubletap 好像不能用
  168. self.viewer.addEventListener('doubletap', function() {
  169. var img = self.currentItem.querySelector('img');
  170. if (self.scaleValue === 1) {
  171. self.scaleValue = 2;
  172. } else {
  173. self.scaleValue = 1;
  174. }
  175. self.dragX = 0;
  176. self.dragY = 0;
  177. img.style.marginLeft = self.dragX + 'px';
  178. img.style.marginTop = self.dragY + 'px';
  179. img.style.webkitTransform = "scale(" + self.scaleValue + "," + self.scaleValue + ") "; //+ " translate(" + self.dragX || 0 + "px," + self.dragY || 0 + "px)";
  180. self.viewer.__tap_num = 0;
  181. }, false);
  182. //处理缩放结束
  183. },
  184. //下一张图片
  185. next: function() {
  186. var self = this;
  187. self.mask.style.display = 'block';
  188. self.index++;
  189. var newItem = self.createImage(self.index, 'right');
  190. setTimeout(function() {
  191. self.currentItem.classList.remove('mui-imageviewer-item-center');
  192. self.currentItem.classList.add('mui-imageviewer-item-left');
  193. newItem.classList.remove('mui-imageviewer-item-right');
  194. newItem.classList.add('mui-imageviewer-item-center');
  195. self.oldItem = self.currentItem;
  196. self.currentItem = newItem;
  197. // TODO: 临时,稍候将调整
  198. setTimeout(function() {
  199. self.disposeImage();
  200. self.mask.style.display = 'none';
  201. }, 600);
  202. }, 25);
  203. },
  204. //上一张图片
  205. prev: function() {
  206. var self = this;
  207. self.mask.style.display = 'block';
  208. self.index--;
  209. var newItem = self.createImage(self.index, 'left');
  210. setTimeout(function() {
  211. self.currentItem.classList.remove('mui-imageviewer-item-center');
  212. self.currentItem.classList.add('mui-imageviewer-item-right');
  213. newItem.classList.remove('mui-imageviewer-item-left');
  214. newItem.classList.add('mui-imageviewer-item-center');
  215. self.oldItem = self.currentItem;
  216. self.currentItem = newItem;
  217. // TODO: 临时,稍候将调整
  218. setTimeout(function() {
  219. self.disposeImage();
  220. self.mask.style.display = 'none';
  221. }, 600);
  222. }, 25);
  223. },
  224. //释放不显示的图片
  225. disposeImage: function(all) {
  226. var sel = '.mui-imageviewer-item-left,.mui-imageviewer-item-right';
  227. if (all) sel += ",.mui-imageviewer-item";
  228. var willdisposes = $(sel);
  229. willdisposes.each(function(i, item) {
  230. if (item.parentNode && item.parentNode.removeChild)
  231. item.parentNode.removeChild(item, true);
  232. });
  233. },
  234. //创建一个图片
  235. createImage: function(index, type) {
  236. var self = this;
  237. type = type || 'center';
  238. if (index < 0) index = self.images.length - 1;
  239. if (index > self.images.length - 1) index = 0;
  240. self.index = index;
  241. var item = $.dom("<div class='mui-imageviewer-item'></div>")[0];
  242. item.appendChild($.dom('<span><img src="' + self.images[self.index].src + '"/></span>')[0]);
  243. item.classList.add('mui-imageviewer-item-' + type);
  244. self.viewer.appendChild(item);
  245. self.state.innerText = (self.index + 1) + "/" + self.images.length;
  246. //重置初始缩放比例
  247. self.scaleValue = 1;
  248. self.dragX = 0;
  249. self.dragY = 0;
  250. return item;
  251. }
  252. });
  253. $.imageViewer = function(selector, options) {
  254. return new ImageViewer(selector, options);
  255. };
  256. $.ready(function() {
  257. $.imageViewer('.' + imageClassName);
  258. });
  259. }(mui, document));