SimpleImagePreview.vue 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. <template>
  2. <Modal
  3. :class="prefixCls"
  4. v-model="modalIsShow"
  5. title="图片预览"
  6. fullscreen
  7. footer-hide
  8. @on-visible-change="visibleChange"
  9. >
  10. <div slot="header"></div>
  11. <div :class="[`${prefixCls}-close`]" @click="cancel">
  12. <i class="el-icon-circle-close"></i>
  13. <Icon type="ios-close" />
  14. </div>
  15. <div :class="[`${prefixCls}-body`]" ref="ReviewBody" @click="cancel">
  16. <div
  17. :class="[`${prefixCls}-guide`, `${prefixCls}-guide-prev`]"
  18. @click.stop="showPrev"
  19. >
  20. <Icon type="ios-arrow-back" />
  21. </div>
  22. <div
  23. :class="[`${prefixCls}-guide`, `${prefixCls}-guide-next`]"
  24. @click.stop="showNext"
  25. >
  26. <Icon type="ios-arrow-forward" />
  27. </div>
  28. <div
  29. :class="[
  30. `${prefixCls}-imgs`,
  31. { [`${prefixCls}-imgs-nosition`]: nosition }
  32. ]"
  33. :style="styles"
  34. v-show="!loading && curImage.imgSrc"
  35. v-if="modalIsShow"
  36. >
  37. <img
  38. :src="curImage.imgSrc"
  39. :alt="curImage.name"
  40. ref="PreviewImgDetail"
  41. />
  42. </div>
  43. <div :class="[`${prefixCls}-none`]" v-if="!curImage.imgSrc">
  44. <Icon type="md-image" />
  45. <p>暂无数据</p>
  46. </div>
  47. </div>
  48. <div :class="[`${prefixCls}-footer`]">
  49. <ul>
  50. <li title="旋转" @click.stop="toRotate">
  51. <Icon type="ios-refresh-circle" />
  52. </li>
  53. </ul>
  54. </div>
  55. <div :class="[`${prefixCls}-loading`]" v-show="loading">
  56. <Icon class="ivu-load-loop" type="ios-loading" />
  57. </div>
  58. </Modal>
  59. </template>
  60. <script>
  61. const prefixCls = "cc-image-preview";
  62. export default {
  63. name: "simple-image-preview",
  64. props: {
  65. curImage: {
  66. type: Object,
  67. default() {
  68. return {};
  69. }
  70. }
  71. },
  72. data() {
  73. return {
  74. prefixCls,
  75. modalIsShow: false,
  76. styles: { width: "", height: "", top: "", left: "", transform: "" },
  77. initWidth: 500,
  78. transform: {
  79. scale: 1,
  80. rotate: 0
  81. },
  82. loading: false,
  83. loadingSetT: null,
  84. nosition: false
  85. };
  86. },
  87. // watch: {
  88. // "curImage.imgSrc": {
  89. // handler(val) {
  90. // if (val) this.loading = true;
  91. // }
  92. // }
  93. // },
  94. methods: {
  95. visibleChange(visible) {
  96. if (!visible) return;
  97. // this.loading = true;
  98. this.$nextTick(() => {
  99. this.registfileLoad();
  100. });
  101. },
  102. registfileLoad() {
  103. const imgDom = this.$refs.PreviewImgDetail;
  104. imgDom.onload = () => {
  105. this.rezizeImage(imgDom);
  106. };
  107. },
  108. rezizeImage(imgDom) {
  109. const { naturalWidth, naturalHeight } = imgDom;
  110. const imageSize = this.getImageSizePos({
  111. win: {
  112. width: this.$refs.ReviewBody.clientWidth,
  113. height: this.$refs.ReviewBody.clientHeight
  114. },
  115. img: {
  116. width: naturalWidth,
  117. height: naturalHeight
  118. },
  119. rotate: 0
  120. });
  121. this.styles = Object.assign(this.styles, {
  122. width: imageSize.width + "px",
  123. height: imageSize.height + "px",
  124. top: imageSize.top + "px",
  125. left: imageSize.left + "px",
  126. transform: ""
  127. });
  128. this.transform = {
  129. scale: 1,
  130. rotate: 0
  131. };
  132. // this.loading = false;
  133. console.log(11);
  134. setTimeout(() => {
  135. this.nosition = false;
  136. }, 100);
  137. },
  138. getImageSizePos({ win, img, rotate }) {
  139. const imageSize = {
  140. width: 0,
  141. height: 0,
  142. top: 0,
  143. left: 0
  144. };
  145. const isHorizontal = !!(rotate % 180);
  146. const rateWin = isHorizontal
  147. ? win.height / win.width
  148. : win.width / win.height;
  149. const hwin = isHorizontal
  150. ? {
  151. width: win.height,
  152. height: win.width
  153. }
  154. : win;
  155. const rateImg = img.width / img.height;
  156. if (rateImg <= rateWin) {
  157. imageSize.height = Math.min(hwin.height, img.height);
  158. imageSize.width = Math.floor(
  159. (imageSize.height * img.width) / img.height
  160. );
  161. } else {
  162. imageSize.width = Math.min(hwin.width, img.width);
  163. imageSize.height = Math.floor(
  164. (imageSize.width * img.height) / img.width
  165. );
  166. }
  167. imageSize.left = (win.width - imageSize.width) / 2;
  168. imageSize.top = (win.height - imageSize.height) / 2;
  169. return imageSize;
  170. },
  171. cancel() {
  172. this.modalIsShow = false;
  173. this.$emit("on-close");
  174. },
  175. open() {
  176. this.modalIsShow = true;
  177. },
  178. showPrev() {
  179. this.$emit("on-prev");
  180. // this.initData();
  181. },
  182. showNext() {
  183. this.$emit("on-next");
  184. // this.initData();
  185. },
  186. // dome-move
  187. setStyleTransform() {
  188. const { scale, rotate } = this.transform;
  189. this.styles.transform = `scale(${scale}, ${scale}) rotate(${rotate}deg)`;
  190. },
  191. toRotate() {
  192. this.transform.rotate = this.transform.rotate + 90;
  193. this.setStyleTransform();
  194. // 调整图片尺寸
  195. const { naturalWidth, naturalHeight } = this.$refs.PreviewImgDetail;
  196. const imageSize = this.getImageSizePos({
  197. win: {
  198. width: this.$refs.ReviewBody.clientWidth,
  199. height: this.$refs.ReviewBody.clientHeight
  200. },
  201. img: {
  202. width: naturalWidth,
  203. height: naturalHeight
  204. },
  205. rotate: this.transform.rotate
  206. });
  207. this.styles = Object.assign(this.styles, {
  208. width: imageSize.width + "px",
  209. height: imageSize.height + "px",
  210. top: imageSize.top + "px",
  211. left: imageSize.left + "px"
  212. });
  213. // 360度无缝切换到0度
  214. if (this.transform.rotate >= 360) {
  215. setTimeout(() => {
  216. this.nosition = true;
  217. this.transform.rotate = 0;
  218. this.setStyleTransform();
  219. setTimeout(() => {
  220. this.nosition = false;
  221. }, 100);
  222. }, 200);
  223. }
  224. }
  225. }
  226. };
  227. </script>