Home_pc.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817
  1. <template>
  2. <div class="wcontainer">
  3. <img class="logo" :src="require(`@/assets/images/logo.png`)" alt="" />
  4. <Loading :barWidth="loadprogress" v-if="!hadLoaded" />
  5. <transition appear name="dm">
  6. <vmenu @clickItem="handleItem" />
  7. </transition>
  8. <transition appear name="dm">
  9. <vintroduce v-if="currentItem == 'info'" />
  10. </transition>
  11. <div class="infobg">
  12. <img :src="require('@/assets/images/info_bg.png')" alt="">
  13. <p>特展馆·二楼<br />镇院之宝展厅</p>
  14. </div>
  15. <div class="right-title">
  16. <img :src="require('@/assets/images/title.png')" alt="">
  17. </div>
  18. <div id="player">
  19. <div class='widgets-doll-labels'> </div>
  20. <canvas></canvas>
  21. </div>
  22. </div>
  23. </template>
  24. <script>
  25. import vmenu from "@/components/menu";
  26. import Loading from "@/components/loading";
  27. import vintroduce from "@/components/introduce";
  28. const transitionTime = 2000
  29. let labelClick = (e) => {
  30. if (e.centerCamePosi) {
  31. console.log(e);
  32. let { x, y, z } = e.centerCamePosi
  33. window.transitions.start(
  34. window.lerp.vector(window.viewer.camera.position,
  35. new window.THREE.Vector3(x, y, z)),
  36. transitionTime,
  37. () => {
  38. e.elem[0].style.display == 'block' && e.elem.addClass('detailShow')
  39. e.elem.siblings().removeClass('detailShow')
  40. e.elem.siblings().css({
  41. "opacity": 0,
  42. "pointer-events": "none"
  43. })
  44. console.log(e.elem.siblings());
  45. let wlmesh = window.viewer.model.getObjectByName("WL48_ping")
  46. wlmesh.material.emissiveMap = e.emissiveTexture;
  47. wlmesh.material.dispose();
  48. window.showWenli = true
  49. // window.viewer.labels.forEach(item => {
  50. // if (centerLabel.title == item.title) {
  51. // this.centerLabel = centerLabel
  52. // }
  53. // else {
  54. // item.elem.removeClass('detailShow')
  55. // }
  56. // })
  57. },
  58. 0/* Delay */,
  59. window.easing.easeInOutQuad,
  60. 'cameraFly');
  61. }
  62. }
  63. let infoLabels = [{ "title": "宝珠钮", "posInModel": [-4.6302, 20.0953, 2.9731] },
  64. { "title": "瓶身", "posInModel": [-11.7969, -1.7939, 3.9055] },
  65. { "title": "瓶盖", "posInModel": [-6.0636, 16.2615, 3.4633] }]
  66. let picLabels = [
  67. {
  68. "title": "竹子",
  69. "entitle": "Diagonal squares pattern",
  70. "infodesc": "清代郑燮咏竹:咬定青山不放松,立根原在破岩中;千磨万击还坚劲,任尔东西南北风。",
  71. "imgsrc": "zhu",
  72. "labeltype": "canShow",
  73. "posInModel": [
  74. -9.9383,
  75. 1.517,
  76. 8.4702
  77. ],
  78. "centerCamePosi": {
  79. x: -0.4650665393060424,
  80. y: 0.0106499843061736,
  81. z: 0.43269467554899155,
  82. },
  83. clickFun: labelClick
  84. },
  85. {
  86. "title": "牡丹",
  87. "entitle": "Diagonal squares pattern",
  88. "infodesc": "唐朝·刘禹锡《赏牡丹》:庭前芍药妖无格,池上芙蕖净少情。唯有牡丹真国色,花开时节动京城。",
  89. "imgsrc": "mudan",
  90. "labeltype": "canShow",
  91. "posi": "right",
  92. "posInModel": [
  93. -10.5926,
  94. -6.1392,
  95. 1.8685
  96. ],
  97. "centerCamePosi": {
  98. x: -0.5357516927819861,
  99. y: -0.3176574374999963,
  100. z: 0.1252552053945424
  101. },
  102. clickFun: labelClick
  103. },
  104. {
  105. "title": "梅",
  106. "entitle": "Diagonal squares pattern",
  107. "labeltype": "canShow",
  108. "infodesc": "元代王冕咏梅:不要人夸好颜色,只留清气满乾坤。",
  109. "imgsrc": "mei",
  110. "posi": "right",
  111. "posInModel": [
  112. 12.4014,
  113. 5.4827,
  114. 2.9209
  115. ],
  116. "centerCamePosi": {
  117. x: 0.5882886392634421,
  118. y: 0.2267149762544653,
  119. z: 0.07836955309150107
  120. },
  121. clickFun: labelClick
  122. },
  123. {
  124. "title": "松",
  125. "entitle": "Diagonal squares pattern",
  126. "labeltype": "canShow",
  127. "infodesc": "唐代白居易咏松:岁暮满山雪,松色郁青苍。彼如君子心,秉操贯冰霜。",
  128. "imgsrc": "song",
  129. "posInModel": [
  130. -5.2427,
  131. 1.903,
  132. -12.1582
  133. ],
  134. "centerCamePosi": {
  135. x: -0.2604583387784285,
  136. y: 0.00816509249833358,
  137. z: -0.5794133027654209
  138. },
  139. clickFun: labelClick
  140. }
  141. ]
  142. export default {
  143. components: { vmenu, Loading, vintroduce },
  144. data() {
  145. return {
  146. scene: null,
  147. camera: null,
  148. renderer: null,
  149. controls: null,
  150. rafId: null,
  151. container: null,
  152. containerW: 0,
  153. containerH: 0,
  154. loadprogress: 0,
  155. hadLoaded: false,
  156. modelLoaded: null,
  157. timer: null,
  158. obj: null,
  159. labelRenderer: null,
  160. label: null,
  161. meshGroup: null,
  162. currentItem: 'info',
  163. centerLabel: null,
  164. fgtimer: null
  165. };
  166. },
  167. methods: {
  168. handleItem(data) {
  169. this.currentItem = data.id
  170. switch (data.id) {
  171. case "info":
  172. this.info()
  173. break;
  174. case "pic":
  175. this.pic()
  176. break;
  177. default:
  178. break;
  179. }
  180. },
  181. // 重置相机位置
  182. resetCameraView() {
  183. window.transitions.start(
  184. window.lerp.vector(window.viewer.camera.rotation,
  185. new window.THREE.Vector3(-6.123233995736765e-17, 0, 0)),
  186. transitionTime,
  187. () => { },
  188. 0/* Delay */,
  189. window.easing.easeInOutQuad,
  190. 'cameraFly');
  191. },
  192. info() {
  193. this.resetCameraView()
  194. window.viewer.removeAllLabels()
  195. window.viewer.model.getObjectByName("wl48_biaochi").visible = true
  196. //模型位置
  197. window.transitions.start(
  198. window.lerp.vector(window.viewer.model.position,
  199. new window.THREE.Vector3(0, 0, 0)),
  200. transitionTime,
  201. () => { },
  202. 0/* Delay */,
  203. window.easing.easeInOutQuad,
  204. 'cameraFly');
  205. //模型旋转角度
  206. window.transitions.start(
  207. window.lerp.vector(window.viewer.model.rotation,
  208. new window.THREE.Vector3(0, 0, 0)),
  209. transitionTime,
  210. () => {
  211. window.viewer.loadLabelsFromData(infoLabels)
  212. window.viewer.control.maxPolarAngle = Math.PI;
  213. window.viewer.control.minPolarAngle = 0;
  214. },
  215. 0/* Delay */,
  216. window.easing.easeInOutQuad,
  217. 'cameraFly');
  218. //相机位置
  219. window.transitions.start(
  220. window.lerp.vector(window.viewer.camera.position,
  221. new window.THREE.Vector3(0, 0, 0.78)),
  222. transitionTime,
  223. () => { },
  224. 0/* Delay */,
  225. window.easing.easeInOutQuad,
  226. 'cameraFly');
  227. },
  228. pic() {
  229. this.resetCameraView()
  230. window.viewer.removeAllLabels()
  231. window.viewer.model.getObjectByName("wl48_biaochi").visible = false
  232. //相机位置
  233. window.transitions.start(
  234. window.lerp.vector(window.viewer.camera.position,
  235. new window.THREE.Vector3(0, 3.8901816405972494e-17, 0.6353148749999993)),
  236. transitionTime,
  237. () => { },
  238. 0/* Delay */,
  239. window.easing.easeInOutQuad,
  240. 'cameraFly');
  241. //模型位置
  242. window.transitions.start(
  243. window.lerp.vector(window.viewer.model.position,
  244. new window.THREE.Vector3(0, 0, 0)),
  245. transitionTime,
  246. () => { },
  247. 0/* Delay */,
  248. window.easing.easeInOutQuad,
  249. 'cameraFly');
  250. //模型旋转角度
  251. window.transitions.start(
  252. window.lerp.vector(window.viewer.model.rotation,
  253. new window.THREE.Vector3(0, 0, 0)),
  254. transitionTime,
  255. () => {
  256. window.viewer.control.maxPolarAngle = Math.PI / 1.5;
  257. window.viewer.control.minPolarAngle = Math.PI / 6;
  258. window.viewer.loadLabelsFromData(picLabels)
  259. // window.showWenli = true
  260. },
  261. 0/* Delay */,
  262. window.easing.easeInOutQuad,
  263. 'cameraFly');
  264. },
  265. // 窗口改变
  266. onresize() {
  267. },
  268. },
  269. watch: {
  270. centerLabel(newVal) {
  271. if (newVal) {
  272. newVal.elem[0].style.display == 'block' && newVal.elem.addClass('detailShow')
  273. let wlmesh = window.viewer.model.getObjectByName("WL48_ping")
  274. wlmesh.material.emissiveMap = this.centerLabel.emissiveTexture;
  275. wlmesh.material.dispose();
  276. }
  277. },
  278. currentItem(newVal) {
  279. if (newVal != 'pix') {
  280. window.showWenli = false
  281. }
  282. }
  283. },
  284. mounted() {
  285. this.timer = setInterval(() => {
  286. if (!this.hadLoaded) {
  287. if (this.loadprogress < 80) {
  288. this.loadprogress += 0.8;
  289. } else {
  290. if (this.modelLoaded) {
  291. if (this.loadprogress <= 100) {
  292. this.loadprogress += 2;
  293. } else {
  294. this.hadLoaded = true;
  295. clearInterval(this.timer);
  296. this.timer = null;
  297. }
  298. }
  299. }
  300. }
  301. }, 10);
  302. window.viewer = new window.Viewer(0, window.$("#player")[0])
  303. window.viewer.addEventListener("hadLoaded", () => {
  304. this.modelLoaded = true
  305. window.viewer.loadLabelsFromData(infoLabels)
  306. window.viewer.control.maxPolarAngle = Math.PI;
  307. window.viewer.control.minPolarAngle = 0;
  308. })
  309. window.viewer.addEventListener("delayUpdate", (e) => {
  310. // setTimeout(() => {
  311. // if (this.currentItem == 'pic') {
  312. // let centerLabel = window.viewer.getCLabel()
  313. // if (centerLabel) {
  314. // window.viewer.labels.forEach(item => {
  315. // if (centerLabel.title == item.title) {
  316. // this.centerLabel = centerLabel
  317. // }
  318. // else {
  319. // item.elem.removeClass('detailShow')
  320. // }
  321. // })
  322. // }
  323. // }
  324. // });
  325. })
  326. },
  327. beforeDestroy() {
  328. },
  329. };
  330. </script>
  331. <style lang="less" scoped>
  332. .wcontainer {
  333. width: 100%;
  334. height: 100%;
  335. position: relative;
  336. background-repeat: no-repeat;
  337. color: #ac5b5b;
  338. .logo {
  339. position: absolute;
  340. top: 50px;
  341. left: 66px;
  342. width: 100px;
  343. z-index: 9999;
  344. }
  345. .infobg {
  346. position: absolute;
  347. bottom: 0;
  348. right: 0;
  349. width: 250px;
  350. height: auto;
  351. >p {
  352. position: absolute;
  353. top: 70%;
  354. left: 50%;
  355. transform: translate(-50%, -50%);
  356. color: rgba(255, 255, 255, 0.8);
  357. font-family: SimSun;
  358. line-height: 1.5;
  359. }
  360. }
  361. .right-title {
  362. position: absolute;
  363. right: 90px;
  364. top: 14%;
  365. width: 150px;
  366. height: auto;
  367. >img {
  368. width: 100%;
  369. }
  370. }
  371. #player {
  372. width: 100%;
  373. height: 100%;
  374. position: absolute;
  375. top: 0;
  376. left: 0;
  377. }
  378. }
  379. .dm-enter {
  380. opacity: 0;
  381. }
  382. .dm-leave-to {
  383. opacity: 0;
  384. }
  385. .dm-enter-active,
  386. .dm-leave-active {
  387. transition: all 2.8s ease;
  388. }
  389. </style>
  390. <style lang="less">
  391. *,
  392. :after,
  393. :before {
  394. box-sizing: border-box;
  395. }
  396. .widgets-doll-labels {
  397. overflow: hidden;
  398. position: absolute;
  399. pointer-events: none;
  400. top: 0;
  401. left: 0;
  402. bottom: 0;
  403. right: 0;
  404. .room-label {
  405. position: absolute;
  406. width: 0;
  407. height: 0;
  408. transform: translateZ(0);
  409. animation: room-label 0.3s ease 0.1s;
  410. animation-fill-mode: both;
  411. cursor: pointer;
  412. &:after {
  413. content: "";
  414. display: block;
  415. position: absolute;
  416. height: 1px;
  417. width: 88px;
  418. // background-image: url("img/labelline.svg");
  419. background-color: #A99979;
  420. background-size: contain;
  421. background-repeat: no-repeat;
  422. bottom: 0;
  423. right: 0;
  424. }
  425. a {
  426. display: block;
  427. position: absolute;
  428. line-height: 2;
  429. top: 50%;
  430. right: 88px;
  431. transform: translateY(-50%);
  432. text-align: center;
  433. white-space: nowrap;
  434. padding: 6px 14px;
  435. pointer-events: auto;
  436. background-repeat: no-repeat;
  437. background-size: 100% 100%;
  438. background-image: url('~@/assets/images/tab.svg');
  439. color: #fff;
  440. box-sizing: border-box;
  441. >p {
  442. margin: 0;
  443. width: 100%;
  444. height: 100%;
  445. }
  446. span {
  447. white-space: nowrap;
  448. user-select: none;
  449. }
  450. }
  451. }
  452. .right {
  453. a {
  454. left: 88px;
  455. right: unset;
  456. }
  457. &:after {
  458. content: "";
  459. display: block;
  460. position: absolute;
  461. bottom: 0;
  462. right: unset;
  463. left: 0;
  464. }
  465. }
  466. .canShow {
  467. &:after {
  468. content: "";
  469. display: block;
  470. position: absolute;
  471. height: 38px;
  472. width: 38px;
  473. background-image: url('~@/assets/images/point.svg');
  474. background-color: transparent;
  475. background-size: cover;
  476. background-repeat: no-repeat;
  477. bottom: 0;
  478. right: 0;
  479. top: 0;
  480. left: 0;
  481. }
  482. &::before {
  483. content: '';
  484. width: 100px;
  485. height: 2px;
  486. display: inline-block;
  487. background-color: #A99979;
  488. position: absolute;
  489. transform: rotate(45deg);
  490. top: -30px;
  491. right: -20px;
  492. }
  493. &:hover {
  494. color: #fff;
  495. &:after {
  496. background-image: url('~@/assets/images/point_active.svg');
  497. content: '';
  498. }
  499. &::before {
  500. content: '';
  501. background-color: #fff !important;
  502. }
  503. a {
  504. >p,
  505. span {
  506. color: #fff;
  507. }
  508. .sline {
  509. background-color: #fff;
  510. }
  511. }
  512. }
  513. a {
  514. display: block;
  515. position: absolute;
  516. line-height: 2;
  517. transition: .1s opacity ease;
  518. top: -103px;
  519. right: 51px;
  520. transform: translateY(0);
  521. text-align: center;
  522. white-space: nowrap;
  523. padding: 6px 14px;
  524. pointer-events: auto;
  525. background-repeat: no-repeat;
  526. background-size: 100% 100%;
  527. background-image: none;
  528. color: #fff;
  529. box-sizing: border-box;
  530. &::after {
  531. content: '';
  532. }
  533. &::before {
  534. content: '';
  535. }
  536. >p {
  537. margin: 0;
  538. width: 100%;
  539. height: 100%;
  540. text-align: left;
  541. }
  542. span {
  543. white-space: nowrap;
  544. padding-right: 30px;
  545. user-select: none;
  546. color: #A99979;
  547. font-size: 16px;
  548. text-align: left;
  549. }
  550. .sline {
  551. width: 100%;
  552. height: 2px;
  553. background-color: #A99979;
  554. }
  555. .enspan {
  556. font-size: 12px;
  557. }
  558. }
  559. &.right {
  560. a {
  561. left: 88px;
  562. right: unset;
  563. }
  564. &::before {
  565. content: '';
  566. width: 100px;
  567. height: 2px;
  568. display: inline-block;
  569. background-color: #A99979;
  570. position: absolute;
  571. transform: rotate(-45deg);
  572. top: -30px;
  573. left: 18px;
  574. right: unset;
  575. }
  576. a {
  577. >p {
  578. text-align: right;
  579. padding-right: 0;
  580. padding-left: 30px;
  581. }
  582. span {
  583. text-align: right;
  584. padding-right: 0;
  585. padding-left: 30px;
  586. }
  587. }
  588. }
  589. &.detailShow {
  590. z-index: 1088 !important;
  591. &:after {
  592. content: "";
  593. background-image: url('~@/assets/images/point_active.svg');
  594. }
  595. &::before {
  596. content: "";
  597. background-color: #fff;
  598. }
  599. a {
  600. opacity: 0;
  601. }
  602. .picdetail {
  603. opacity: 1;
  604. pointer-events: auto;
  605. &::before {
  606. content: '';
  607. background-color: #fff !important;
  608. }
  609. }
  610. &.right {
  611. .picdetail {
  612. top: -254px;
  613. left: 163px;
  614. right: unset;
  615. &::before {
  616. content: '';
  617. display: inline-block;
  618. width: 60px;
  619. height: 2px;
  620. background-color: #A99979;
  621. position: absolute;
  622. left: -60px;
  623. right: unset;
  624. }
  625. }
  626. }
  627. }
  628. }
  629. }
  630. .picdetail {
  631. position: absolute;
  632. z-index: 999;
  633. opacity: 0;
  634. top: -254px;
  635. right: 163px;
  636. width: 300px;
  637. background-image: url('~@/assets/images/pop.png');
  638. background-repeat: no-repeat;
  639. background-size: 100% 100%;
  640. color: #fff;
  641. padding: 30px 36px;
  642. min-height: 378px;
  643. transition: .1s opacity ease;
  644. &::before {
  645. content: '';
  646. display: inline-block;
  647. width: 98px;
  648. height: 2px;
  649. background-color: #A99979;
  650. position: absolute;
  651. right: -98px;
  652. top: 189px;
  653. }
  654. .header {
  655. display: flex;
  656. justify-content: space-between;
  657. align-items: center;
  658. }
  659. .pinfo {
  660. width: 100%;
  661. margin-top: 20px;
  662. >img {
  663. width: 100%;
  664. }
  665. >p {
  666. text-align: justify;
  667. font-size: 14px;
  668. color: rgba(255, 255, 255, 0.8);
  669. margin-top: 10px;
  670. line-height: 1.5;
  671. }
  672. }
  673. }
  674. @-webkit-keyframes room-label {
  675. 0% {
  676. opacity: 0;
  677. margin-top: 8.75px;
  678. }
  679. to {
  680. opacity: 1;
  681. margin-top: 0;
  682. }
  683. }
  684. @keyframes room-label {
  685. 0% {
  686. opacity: 0;
  687. margin-top: 8.75px;
  688. }
  689. to {
  690. opacity: 1;
  691. margin-top: 0;
  692. }
  693. }
  694. </style>