image.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. <template>
  2. <div class="hotspot" v-if="!isMobile">
  3. <img
  4. class="vhotspot"
  5. :src="require(`@/assets/images/project/kuangti/hotspot_${theme}.png`)"
  6. alt=""
  7. />
  8. <div class="brightness"></div>
  9. <img
  10. @click="$emit('close')"
  11. class="close"
  12. :src="require('@/assets/images/project/icon/close.png')"
  13. alt=""
  14. />
  15. <div class="vhotspotcon">
  16. <div class="vtitle" v-html="hotspot.title"></div>
  17. <div class="hotspotcon">
  18. <div class="img-con">
  19. <img
  20. class="aa"
  21. v-if="hotspot.images.length > 1"
  22. :src="require('@/assets/images/project/icon/hotspot_l.png')"
  23. alt=""
  24. @click="handlePage('prev')"
  25. />
  26. <div class="imgmain" :class="{bigImg: !hotspot.content}">
  27. <img id="map" :src="hotspot.images[active]" alt="" />
  28. </div>
  29. <img
  30. class="aa"
  31. v-if="hotspot.images.length > 1"
  32. :src="require('@/assets/images/project/icon/hotspot_r.png')"
  33. alt=""
  34. @click="handlePage('next')"
  35. />
  36. </div>
  37. <div class="pagna" v-if="hotspot.images.length > 1">
  38. <span>{{ active + 1 }}</span>
  39. /
  40. <span>{{ hotspot.images.length }}</span>
  41. </div>
  42. <div class="desc" v-html="handleContent(hotspot.contents[active])"></div>
  43. </div>
  44. </div>
  45. </div>
  46. <div v-else class="mbhotspot">
  47. <img
  48. class="vhotspot"
  49. :src="require(`@/assets/images/mobile/kuangti/hotspot_${theme}.png`)"
  50. alt=""
  51. />
  52. <div class="brightness"></div>
  53. <img
  54. @click="$emit('close')"
  55. class="close"
  56. :src="require('@/assets/images/project/icon/close.png')"
  57. alt=""
  58. />
  59. <div class="title" v-html="hotspot.title"></div>
  60. <div class="mbhcon" :class="{ single: hotspot.images.length <= 1 }">
  61. <div class="swcon" v-swiper:mySwiper="swiperOption">
  62. <ul class="swiper-wrapper swiper-wrapper-n">
  63. <div
  64. class="swiper-slide"
  65. v-for="(item, index) in hotspot.images"
  66. :key="index"
  67. >
  68. <div class="sl-item">
  69. <img v-viewer :src="item" />
  70. </div>
  71. </div>
  72. </ul>
  73. <div
  74. class="swiper-pagination pagination"
  75. v-if="hotspot.images.length > 1"
  76. slot="pagination"
  77. ></div>
  78. </div>
  79. <div v-if="hotspot.content" class="desc">
  80. <div v-html="handleContent(hotspot.contents[mbactive], 14)"></div>
  81. </div>
  82. </div>
  83. </div>
  84. </template>
  85. <script>
  86. import { directive } from "vue-awesome-swiper";
  87. // import style (<= Swiper 5.x)
  88. import "swiper/css/swiper.css";
  89. import Panzoom from '@panzoom/panzoom'
  90. export default {
  91. directives: {
  92. swiper: directive,
  93. },
  94. props: ["hotspot", "type"],
  95. data() {
  96. return {
  97. panzoom:'',
  98. active: 0,
  99. mbactive: 0,
  100. };
  101. },
  102. methods: {
  103. handlePage(type) {
  104. if (type === "next") {
  105. console.log(this.hotspot.images.length);
  106. if (this.active >= this.hotspot.images.length - 1) {
  107. this.active = 0;
  108. return;
  109. }
  110. this.active += 1;
  111. } else {
  112. if (this.active == 0) {
  113. this.active = this.hotspot.images.length - 1;
  114. return;
  115. }
  116. this.active -= 1;
  117. }
  118. },
  119. },
  120. computed: {
  121. swiperOption() {
  122. let that = this
  123. return {
  124. slidesPerView: "auto",
  125. autoplay: false,
  126. centeredSlides: true,
  127. watchSlidesProgress: true,
  128. loop: this.hotspot.images.length > 1,
  129. pagination: {
  130. el: ".swiper-pagination",
  131. },
  132. on: {
  133. slideChangeTransitionEnd: function() {
  134. that.mbactive = this.realIndex
  135. }
  136. },
  137. };
  138. },
  139. },
  140. mounted(){
  141. const elem = document.getElementById('map')
  142. this.panzoom = Panzoom(elem, {
  143. maxScale: 10
  144. })
  145. this.panzoom.pan(10, 10)
  146. this.panzoom.zoom(1, { animate: true })
  147. elem.addEventListener('wheel', this.panzoom.zoomWithWheel)
  148. }
  149. };
  150. </script>
  151. <style lang="less" scoped>
  152. .noshow {
  153. opacity: 0 !important;
  154. pointer-events: none !important;
  155. }
  156. @w: 82%;
  157. @fixw: 8px;
  158. .hotspot {
  159. width: @w;
  160. position: relative;
  161. margin: 10px auto 0;
  162. .vhotspot {
  163. width: 100%;
  164. position: relative;
  165. pointer-events: none;
  166. }
  167. .brightness {
  168. position: absolute;
  169. width: 100%;
  170. height: 101%;
  171. left: 0;
  172. top: 0;
  173. z-index: -1;
  174. clip-path: polygon(1% 11%, 10% 2%, 99% 2%, 99% 89%, 92% 99%, 1% 99%);
  175. }
  176. .close {
  177. position: absolute;
  178. top: 40px;
  179. right: 30px;
  180. width: 20px;
  181. cursor: pointer;
  182. z-index: 1000;
  183. }
  184. .vhotspotcon {
  185. position: absolute;
  186. top: 0;
  187. transform: translateX(-50%);
  188. left: 50%;
  189. width: 100%;
  190. height: 100%;
  191. text-align: center;
  192. .vtitle {
  193. position: absolute;
  194. top: 24px;
  195. left: 130px;
  196. z-index: 99;
  197. font-size: 20px;
  198. }
  199. .hotspotcon {
  200. width: 90%;
  201. top: 50%;
  202. left: 50%;
  203. transform: translate(-50%, -50%);
  204. position: absolute;
  205. .img-con {
  206. display: flex;
  207. align-items: center;
  208. justify-content: space-between;
  209. position: relative;
  210. .imgmain {
  211. width: 90%;
  212. max-height: 60vh;
  213. overflow-x: hidden;
  214. overflow-y: auto;
  215. position: relative;
  216. margin: 0 auto;
  217. img {
  218. cursor: pointer;
  219. max-width: 100%;
  220. max-height: 60vh;
  221. }
  222. }
  223. @h:72vh;
  224. .bigImg{
  225. max-height: @h;
  226. >img{
  227. max-height: @h;
  228. }
  229. }
  230. .aa {
  231. width: 30px;
  232. height: auto;
  233. cursor: pointer;
  234. }
  235. }
  236. .pagna {
  237. text-align: center;
  238. z-index: 999;
  239. font-size: 18px;
  240. margin-top: 10px;
  241. color: rgba(255, 255, 255, 0.8);
  242. }
  243. .desc {
  244. width: 90%;
  245. font-size: 16px;
  246. text-align: justify;
  247. line-height: 1.8;
  248. max-height: 120px;
  249. margin: 10px auto 0;
  250. padding-right: 14px;
  251. overflow-y: auto;
  252. }
  253. }
  254. }
  255. }
  256. .mbhotspot {
  257. width: 96%;
  258. margin: 60px auto 0;
  259. position: relative;
  260. .vhotspot {
  261. width: 100%;
  262. position: relative;
  263. pointer-events: none;
  264. }
  265. .brightness {
  266. position: absolute;
  267. width: 100%;
  268. height: 100%;
  269. left: 0;
  270. top: 0;
  271. z-index: -1;
  272. clip-path: polygon(1% 11%, 10% 2%, 99% 2%, 99% 89%, 92% 99%, 1% 99%);
  273. }
  274. .close {
  275. position: absolute;
  276. top: 26px;
  277. right: 16px;
  278. width: 14px;
  279. z-index: 1000;
  280. }
  281. .title {
  282. position: absolute;
  283. top: 14px;
  284. left: 40px;
  285. display: inline-block;
  286. font-size: 16px;
  287. margin: 0px auto;
  288. width: 50vw;
  289. }
  290. .mbhcon {
  291. position: absolute;
  292. top: 0;
  293. width: 100%;
  294. left: 0;
  295. .swcon {
  296. position: relative;
  297. margin: 60px auto 0;
  298. width: 92%;
  299. .swiper-wrapper {
  300. padding: 0;
  301. .swiper-slide {
  302. width: 100%;
  303. transform-style: preserve-3d;
  304. position: relative;
  305. height: 100%;
  306. margin: 0 auto;
  307. transform: translate3d(0, 0, 0);
  308. .sl-item {
  309. width: 100%;
  310. text-align: center;
  311. > img {
  312. max-height: 44vh;
  313. max-width: 100%;
  314. }
  315. }
  316. }
  317. }
  318. .pagination {
  319. position: static;
  320. margin-top: 4px;
  321. z-index: 999;
  322. & /deep/ .swiper-pagination-bullet,
  323. & /deep/ .swiper-pagination-bullet-active {
  324. background-color: #fff !important;
  325. }
  326. & /deep/ .swiper-pagination-bullet-active {
  327. background: #fff !important;
  328. }
  329. }
  330. }
  331. .desc {
  332. text-align: justify;
  333. width: 85%;
  334. padding-right: 14px;
  335. margin: 10px auto 0;
  336. p {
  337. font-size: 16px;
  338. font-weight: bold;
  339. }
  340. div {
  341. font-size: 14px;
  342. margin-top: 10px;
  343. line-height: 1.5;
  344. max-height: 15vh;
  345. padding-right: 4px;
  346. overflow-y: auto;
  347. }
  348. }
  349. }
  350. .single {
  351. top: 46%;
  352. transform: translateY(-50%);
  353. }
  354. }
  355. </style>