index.vue 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <template>
  2. <transition name="msgbox-fade">
  3. <div class="preview-mask pub-scroll-box" v-if="visible" @click="visible = false">
  4. <i class="el-icon-close" @click.stop="visible = false"></i>
  5. <img class="img" :src="imgUrl" alt="" ref="image"
  6. :style="{transform:`translate(${picLeft}px,${picTop}px) scale(${picScale})`}" @click.stop>
  7. </div>
  8. </transition>
  9. </template>
  10. <script>
  11. import { isMobile } from '@/util/util'
  12. import Hammer from 'hammerjs'
  13. export default {
  14. name: 'imgPreview',
  15. data () {
  16. return {
  17. isClick: false, // 用作识别pc点击和拖拽
  18. isMobile: isMobile(),
  19. picW: 0, // 图片宽
  20. picH: 0, // 图片高
  21. picScale: 1, // 缩放比例
  22. picScaleMid: 1, // 缩放比例
  23. picInitTop: 0, // 最初top
  24. picInitLeft: 0, // 最初left
  25. picTop: 0,
  26. picLeft: 0,
  27. picTransform: '',
  28. image: null, // target图
  29. disX: 0,
  30. disY: 0
  31. }
  32. },
  33. methods: {
  34. initEvent () {
  35. if (this.isMobile) {
  36. this.handleH5()
  37. } else {
  38. this.handleDragPC()
  39. this.handleScalePC()
  40. }
  41. },
  42. removeEvent () {
  43. },
  44. // pc拖拽
  45. handleDragPC () {
  46. this.image.onmousedown = (ev) => {
  47. this.isClick = true
  48. this.dragStart(ev)
  49. if (this.image.setCapture) this.image.setCapture()
  50. document.addEventListener('mousemove', this.drag)
  51. document.addEventListener('mouseup', this.dragAfter)
  52. return false
  53. }
  54. },
  55. // pc缩放
  56. handleScalePC () {
  57. document.body.addEventListener('mousewheel', this.scale)
  58. },
  59. // h5拖拽、缩放
  60. handleH5 () {
  61. const mc = new Hammer.Manager(this.image)
  62. const tap = new Hammer.Tap({ pointers: 1 })
  63. const pan = new Hammer.Pan({ pointers: 1 })
  64. const pinch = new Hammer.Pinch({ pointers: 2 })
  65. mc.add([tap, pan, pinch])
  66. // 监听-tab
  67. mc.on(`tap`, (ev) => {
  68. // ev.preventDefault()
  69. this.visible = false
  70. })
  71. // 监听-拖拽
  72. mc.on(`panstart panmove panend tap, multitap`, (ev) => {
  73. // ev.preventDefault()
  74. if (ev.type == 'panstart') this.dragStart(ev)
  75. else if (ev.type == 'panmove') this.drag(ev)
  76. else if (ev.type == 'panend') this.dragAfter(ev)
  77. })
  78. // 监听-缩放
  79. mc.on(`pinchmove pinchin pinchout pinchend`, (ev) => {
  80. // ev.preventDefault()
  81. this.picScale = (this.picScaleMid * ev.scale).toFixed(2)
  82. if (ev.type == 'pinchend') {
  83. if (this.picScale < 1) this.picScale = 1
  84. this.picScaleMid = this.picScale
  85. }
  86. })
  87. },
  88. dragStart (ev) {
  89. if (this.isMobile) {
  90. this.disY = ev.deltaY
  91. this.disX = ev.deltaX
  92. } else {
  93. this.disY = ev.clientY
  94. this.disX = ev.clientX
  95. }
  96. },
  97. // 拖拽
  98. drag (ev) {
  99. this.isClick = false
  100. if (this.isMobile) {
  101. // 移动端
  102. this.picTop = ev.deltaY - this.disY
  103. this.picLeft = ev.deltaX - this.disX
  104. } else {
  105. // pc
  106. this.picTop = ev.clientY - this.disY
  107. this.picLeft = ev.clientX - this.disX
  108. }
  109. },
  110. dragAfter () {
  111. document.removeEventListener('mousemove', this.drag)
  112. document.removeEventListener('mouseup', this.dragAfter)
  113. if (this.image.releaseCapture) {
  114. this.image.releaseCapture()
  115. }
  116. // pc
  117. if (!this.isMobile && this.isClick) {
  118. this.visible = false
  119. this.isClick = false
  120. }
  121. this.picTop = this.picInitTop
  122. this.picLeft = this.picInitLeft
  123. },
  124. // 缩放
  125. scale (ev) {
  126. let picScale = this.picScale
  127. ev = ev || window.event
  128. if (ev.deltaY > 0) {
  129. this.picScale = picScale > 0.2 ? picScale - 0.1 : picScale
  130. } else {
  131. this.picScale += 0.1
  132. }
  133. }
  134. },
  135. mounted () {
  136. this.image = this.$refs.image
  137. // 先尝试从链接拿尺寸数据
  138. let img = new Image()
  139. img.src = this.imgUrl
  140. img.onload = () => {
  141. this.initEvent()
  142. }
  143. },
  144. destroyed () {
  145. }
  146. }
  147. </script>
  148. <style lang="scss" scoped>
  149. .preview-mask{
  150. position: fixed;
  151. left: 0;
  152. right: 0;
  153. top: 0;
  154. bottom: 0;
  155. z-index: 999;
  156. background-color: rgba($color: #000000, $alpha: .8);
  157. text-align: center;
  158. overflow: hidden;
  159. &::after{
  160. content: '';
  161. display: inline-block;
  162. height: 100%;
  163. vertical-align: middle;
  164. }
  165. }
  166. .img{
  167. max-width: 100%;
  168. max-height: 100%;
  169. }
  170. .el-icon-close{
  171. position: absolute;
  172. right: 6px;
  173. top: 6px;
  174. font-size: 30px;
  175. cursor: pointer;
  176. z-index: 1000;
  177. color: #ffffff;
  178. }
  179. .h5-wrap {
  180. .preview-mask{
  181. background-color: #000000;
  182. }
  183. }
  184. </style>