prodViewImages.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <!-- 商品图片组件 -->
  2. <template>
  3. <div class="products-pic-panel">
  4. <div class="products-pic-all-box" id="PicZoom">
  5. <div class="products-pic-show-box" id="BigPic">
  6. <div class="middle-box" :style="{width: `${boxWidth}px`, height: `${boxHeight}px`}" @mouseenter="isShow = true" @mouseleave="isShow = false" @mousemove="move($event)">
  7. <div class="play" @click="openvideo" v-show="!hide_img && video">
  8. <img src="~/assets/images/icon/play.png">
  9. </div>
  10. <div class="video" v-show="hide_img">
  11. <video controls ref="myvideo" @ended="stop()">
  12. <source :src="video" />
  13. </video>
  14. </div>
  15. <img :src="popThumb || middleImage[curIndex]" :alt="middleImage[curIndex]" v-show="!hide_img">
  16. <div class="move" :style="{width: `${this.glassWidth}px`,height: `${this.glassHeight}px`,top: `${this.glassTop}px`,left: `${this.glassLeft}px`}" v-show="isShow&&!hide_img"></div>
  17. </div>
  18. </div>
  19. <div class="products-pic-small-box">
  20. <span id="products-pic-pre" v-if="smallImage.length>3" @click="goPre"></span>
  21. <span id="products-pic-next" v-if="smallImage.length>3" @click="goNext"></span>
  22. <div id="SmallPicList" class="products-pic-list-box" style="width:80%;">
  23. <ul :style="{width: `${this.ulWidth}px`,marginLeft: `${this.ulMarginLeft}px`}">
  24. <li v-for="(image,index) in smallImage" :key="index" :class="{picCur: curIndex == index}" @mouseenter="closeVideo(index)">
  25. <img :src="image" :alt="image">
  26. </li>
  27. </ul>
  28. </div>
  29. </div>
  30. <div class="b_box" v-if="isShow">
  31. <img :src="popThumb || bigImage[curIndex]" :style="{left: `${bigLeft}px`, top: `${bigTop}px`,width: `${this.bigWidth}px`,height: `${this.bigHeight}px`}">
  32. </div>
  33. </div>
  34. </div>
  35. </template>
  36. <script>
  37. export default {
  38. //组件名称
  39. name: "ProdViewImages",
  40. props: {
  41. video: String,
  42. bigImage: Array,
  43. middleImage: Array,
  44. smallImage: Array,
  45. popThumb: String
  46. },
  47. data() {
  48. return {
  49. hide_img: false,
  50. next_length: 3,
  51. //当前选中商品
  52. curIndex: 0,
  53. //是否显示大图
  54. isShow: false,
  55. //显示盒子的宽度和高度
  56. boxWidth: 400,
  57. boxHeight: 400,
  58. //显示盒子相对于浏览器窗口的偏移
  59. boxOffsetLeft: 0,
  60. boxOffsetTop: 0,
  61. //放大镜的宽度和高度
  62. glassWidth: 100,
  63. glassHeight: 100,
  64. //放大镜的位置
  65. glassLeft: 0,
  66. glassTop: 0,
  67. //大图的宽度和高度
  68. bigWidth: 1000,
  69. bigHeight: 1000,
  70. //大图的位置
  71. bigLeft: 0,
  72. bigTop: 0,
  73. //小图列表盒子的宽度
  74. SmallPicListWidth: 400,
  75. //小图列表li的宽度(加外边距)
  76. liOuterWidth: 110,
  77. //小图列表ul宽度
  78. ulWidth: 460,
  79. //小图列表ul的marginleft
  80. ulMarginLeft: 0
  81. };
  82. },
  83. //初始化
  84. mounted() {
  85. this.$nextTick(() => {
  86. //显示盒子到浏览器窗口最左端的距离
  87. this.boxOffsetLeft = this.getElementLeft(
  88. document.querySelector(".middle-box")
  89. );
  90. //显示盒子到浏览器窗口最顶部的距离
  91. this.boxOffsetTop = this.getElementTop(
  92. document.querySelector(".middle-box")
  93. );
  94. //小图列表ul宽度
  95. if (this.smallImage.length > 3) {
  96. this.ulWidth = this.liOuterWidth * this.smallImage.length - 20;
  97. }
  98. });
  99. },
  100. methods: {
  101. stop() {
  102. this.hide_img = false;
  103. },
  104. closeVideo(index) {
  105. this.curIndex = index;
  106. this.hide_img = false;
  107. this.$emit('removePopThumb')
  108. },
  109. openvideo() {
  110. if (this.video) {
  111. this.hide_img = true;
  112. let myvideo = this.$refs.myvideo;
  113. myvideo.play();
  114. }
  115. },
  116. //放大镜移动
  117. move(event) {
  118. //计算放大镜的位置
  119. //位置= 鼠标指针位置 - 显示盒子在浏览器上的偏移 - 放大镜宽高的一半
  120. this.glassLeft = event.pageX - this.boxOffsetLeft - this.glassWidth / 2;
  121. this.glassTop = event.pageY - this.boxOffsetTop - this.glassHeight / 2;
  122. //放大镜在水平方向上的最大距离
  123. var maxLeft = this.boxWidth - this.glassWidth;
  124. //放大镜在竖直方向上移动的最大距离
  125. var maxTop = this.boxHeight - this.glassHeight;
  126. //限制放大镜在水平方向的距离
  127. if (this.glassLeft < 0) {
  128. this.glassLeft = 0;
  129. } else if (this.glassLeft > maxLeft) {
  130. this.glassLeft = maxLeft;
  131. }
  132. //限制放大镜在竖直方向上的范围
  133. if (this.glassTop < 0) {
  134. this.glassTop = 0;
  135. } else if (this.glassTop > maxTop) {
  136. this.glassTop = maxTop;
  137. }
  138. //计算大图的移动位置
  139. this.bigLeft =
  140. -(this.glassLeft / maxLeft) * (this.bigWidth - this.boxWidth);
  141. this.bigTop =
  142. -(this.glassTop / maxTop) * (this.bigHeight - this.boxHeight);
  143. },
  144. //元素最左端到网页最左端的距离
  145. getElementLeft(element) {
  146. var actualLeft = element.offsetLeft;
  147. var current = element.offsetParent;
  148. while (current !== null) {
  149. actualLeft += current.offsetLeft;
  150. current = current.offsetParent;
  151. }
  152. return actualLeft;
  153. },
  154. //元素最顶端到网页最顶端的距离
  155. getElementTop(element) {
  156. var actualTop = element.offsetTop;
  157. var current = element.offsetParent;
  158. while (current !== null) {
  159. actualTop += current.offsetTop;
  160. current = current.offsetParent;
  161. }
  162. return actualTop;
  163. },
  164. //下一个点击按钮
  165. goNext() {
  166. this.ulMarginLeft = -this.liOuterWidth + this.ulMarginLeft;
  167. },
  168. //上一个点击按钮
  169. goPre() {
  170. if (this.ulMarginLeft > -this.liOuterWidth) {
  171. this.ulMarginLeft = 0;
  172. return;
  173. } else {
  174. this.ulMarginLeft = this.ulMarginLeft + this.liOuterWidth;
  175. }
  176. }
  177. }
  178. };
  179. </script>
  180. <style scoped lang="scss">
  181. .middle-box {
  182. position: relative;
  183. .play {
  184. position: absolute;
  185. left: 20px;
  186. bottom: 20px;
  187. z-index: 999;
  188. cursor: pointer;
  189. }
  190. .video {
  191. position: absolute;
  192. left: 0;
  193. top: 0;
  194. width: 100%;
  195. height: 100%;
  196. z-index: 9999;
  197. video {
  198. width: 100%;
  199. height: 100%;
  200. }
  201. }
  202. }
  203. .products-pic-panel {
  204. width: 100%;
  205. height: 100%;
  206. }
  207. .products-pic-all-box {
  208. position: relative;
  209. width: 100%;
  210. height: 100%;
  211. }
  212. .products-pic-show-box {
  213. position: relative;
  214. overflow: hidden;
  215. width: 100%;
  216. }
  217. .products-pic-show-box img {
  218. width: 100%;
  219. height: 100%;
  220. }
  221. .move {
  222. position: absolute;
  223. background: #fff;
  224. z-index: 99;
  225. filter: alpha(opacity=40);
  226. opacity: 0.4;
  227. cursor: move;
  228. }
  229. .b_box {
  230. position: absolute;
  231. top: 0;
  232. left: 410px;
  233. width: 400px;
  234. height: 400px;
  235. overflow: hidden;
  236. background: #fff;
  237. z-index: 9;
  238. }
  239. .b_box img {
  240. position: absolute;
  241. top: 0;
  242. left: 0;
  243. }
  244. .products-pic-small-box {
  245. position: relative;
  246. overflow: hidden;
  247. width: 100%;
  248. height: auto;
  249. margin-top: 10px;
  250. }
  251. .products-pic-list-box {
  252. overflow: hidden;
  253. width: 460px;
  254. height: 102px;
  255. margin: 0 auto;
  256. }
  257. .products-pic-list-box ul {
  258. overflow: hidden;
  259. width: 100%;
  260. height: 100%;
  261. }
  262. .products-pic-list-box ul li {
  263. float: left;
  264. overflow: hidden;
  265. width: 100px;
  266. height: 100px;
  267. margin-right: 10px;
  268. background: #f2f2f2;
  269. border: 1px solid transparent;
  270. box-sizing: border-box;
  271. cursor: pointer;
  272. }
  273. .products-pic-list-box ul li:last-child {
  274. margin-right: 0;
  275. }
  276. .products-pic-list-box ul li.picCur {
  277. border: 1px solid var(--color);
  278. }
  279. .products-pic-list-box ul li img {
  280. width: 100%;
  281. height: 100%;
  282. }
  283. span#products-pic-pre {
  284. position: absolute;
  285. top: 0;
  286. left: 0;
  287. display: block;
  288. width: 20px;
  289. height: 100px;
  290. cursor: pointer;
  291. background: #f2f2f2 url(../../assets/images/index/banner-btn-pre.png) center
  292. center no-repeat;
  293. }
  294. span#products-pic-next {
  295. position: absolute;
  296. top: 0;
  297. right: 0;
  298. display: block;
  299. width: 20px;
  300. height: 100px;
  301. cursor: pointer;
  302. background: #f2f2f2 url(../../assets/images/index/banner-btn-next.png) center
  303. center no-repeat;
  304. }
  305. span#products-pic-pre:hover {
  306. background: #f2f2f2 url(../../assets/images/products/banner-btn-pre-cur.png)
  307. center center no-repeat;
  308. }
  309. span#products-pic-next:hover {
  310. background: #f2f2f2 url(../../assets/images/products/banner-btn-next-cur.png)
  311. center center no-repeat;
  312. }
  313. </style>