Bladeren bron

feat(mobile): 移动端开发

lanxin 8 maanden geleden
bovenliggende
commit
e85ab97296

+ 2 - 1
package.json

@@ -4,6 +4,7 @@
   "private": true,
   "dependencies": {
     "@ant-design/cssinjs": "^1.5.6",
+    "@dage/krpano": "^3.0.0",
     "@testing-library/jest-dom": "^5.16.5",
     "@testing-library/react": "^13.4.0",
     "@testing-library/user-event": "^13.5.0",
@@ -61,4 +62,4 @@
     "react-app-rewired": "^2.2.1"
   },
   "homepage": "."
-}
+}

BIN
public/images/VR.png


+ 18 - 0
public/showa/js/loadCAD.js

@@ -50,6 +50,11 @@ window.grendCAD = (function grendCAD() {
         height: 100%;
       }
 
+      #cad path {
+        stroke-width: 0.3;
+        color: #fff;
+      }
+
       @media only screen and (max-width: 600px) {
         .cad {
             position: absolute;
@@ -61,6 +66,19 @@ window.grendCAD = (function grendCAD() {
             border-radius: 5px;
         }
       }
+
+      @media only screen and (max-width: 1000px) {
+        .cad {
+            position: absolute;
+            right: 0;
+        left: auto;
+        top: 0 !important;
+            width: 180px !important;
+            height: 150px !important;
+            background: rgba(0, 0, 0, .3);
+            border-radius: 5px;
+        }
+      }
     `
 
     document.documentElement.appendChild(style)

+ 11 - 4
src/pages/A0base/component/Intro.tsx

@@ -1,20 +1,27 @@
 import React from 'react'
 import styles from './index.module.scss'
 import base from '../image/base.png'
+import baseMobile from '../image/M_base.png'
 import close from '../image/close.png'
+import classNames from 'classnames'
+import isMobile from '@/utils/isMobile'
 
 export function Intro({ handleIntroClick }: { handleIntroClick: (isShow: boolean) => void }) {
   return (
-    <div className={styles.intro}>
+    <div className={classNames(styles.intro, isMobile() && styles.introMobile)}>
       <div className='intro-content'>
         <div className='intro-title'>
           <span>前海院区基本概况</span>
           <span>
-            <img src={close} onClick={() => handleIntroClick(false)} alt='' />
+            <img
+              src={isMobile() ? require('../image/close_white.png') : require('../image/close.png')}
+              onClick={() => handleIntroClick(false)}
+              alt=''
+            />
           </span>
         </div>
         <div className='intro-base'>
-          <img src={base} alt='' />
+          {!isMobile() ? <img src={base} alt='' /> : <img src={baseMobile} alt='' />}
         </div>
         <div className='intro-base-text-container'>
           <div className='intro-base-text'>
@@ -53,7 +60,7 @@ export function Intro({ handleIntroClick }: { handleIntroClick: (isShow: boolean
 
 export function MapIntro({ handleIntroClick }: { handleIntroClick: (isShow: boolean) => void }) {
   return (
-    <div className={styles.mapIntro}>
+    <div className={classNames(styles.mapIntro, isMobile() && styles.mapIntroMobile)}>
       <div className='mapIntro-content'>
         <img
           src={close}

+ 7 - 3
src/pages/A0base/component/Preview.tsx

@@ -2,6 +2,8 @@ import React, { useState } from 'react'
 import styles from './index.module.scss'
 import { SliderList } from './Slider'
 import store from '@/store'
+import isMobile from '@/utils/isMobile'
+import classNames from 'classnames'
 
 const TextContainer = ({ type }: { type: string }) => {
   const textListBao = [
@@ -18,7 +20,7 @@ const TextContainer = ({ type }: { type: string }) => {
     {
       label: '空间分布:',
       content:
-        '有1间报告厅,7间会议室,5间智慧教室,2间研讨室以及阅读室和近25间共独立办公室,满足师生研究及办公。'
+        '有1间报告厅,7间会议室,5间智慧教室,2间研讨室以及阅读室和近25间共独立办公室,满足师生研究及办公。'
     },
     {
       label: '承载人数:',
@@ -94,7 +96,7 @@ export function Preview({
 
   return (
     <>
-      <div className={styles.preview}>
+      <div className={classNames(styles.preview, isMobile() && styles.previewMobile)}>
         <div className='preview-close' onClick={handleCloseClick}>
           <img src={require('../image/close_white.png')} alt='' />
         </div>
@@ -112,7 +114,7 @@ export function Preview({
                 currentIndex === imgArr.length - 1 ? { opacity: 0.4, cursor: 'not-allowed' } : {}
               }
             ></div>
-            <div className='preview-title'>{imgArr[currentIndex].title}</div>
+            {!isMobile() && <div className='preview-title'>{imgArr[currentIndex].title}</div>}
             <div className='preview-base-container'>
               <div
                 className='preview-base'
@@ -129,6 +131,8 @@ export function Preview({
                 <img src={require(`../image/${type}/${imgArr[currentIndex].src}`)} alt='' />
               </div>
             </div>
+
+            {isMobile() && <div className='preview-title'>{imgArr[currentIndex].title}</div>}
           </div>
         </div>
         {/* index为0,特殊处理 */}

+ 4 - 2
src/pages/A0base/component/Slider.tsx

@@ -1,5 +1,7 @@
 import React, { useState } from 'react'
 import styles from './index.module.scss'
+import isMobile from '@/utils/isMobile'
+import classNames from 'classnames'
 
 export function Slider({
   imgIndex,
@@ -18,7 +20,7 @@ export function Slider({
 }) {
   return (
     <div
-      className={styles.slider}
+      className={classNames(styles.slider, isMobile() && styles.sliderMobile)}
       onClick={() => onSliderClick(imgIndex)}
       style={{ border: imgIndex === selectedIndex ? '3px solid #0081fa' : 'none' }}
     >
@@ -42,7 +44,7 @@ export const SliderList = ({
   type: string
 }) => {
   return (
-    <div className={styles.sliderList}>
+    <div className={classNames(styles.sliderList, isMobile() && styles.sliderListMobile)}>
       {imgArr.map((item, index) => (
         <Slider
           key={index}

+ 151 - 24
src/pages/A0base/component/index.module.scss

@@ -70,6 +70,52 @@
   }
 }
 
+.introMobile {
+  background-color: rgba(0, 0, 0, 0.8);
+  :global {
+    .intro-content {
+      height: 100%;
+      background-color: transparent;
+      .intro-title {
+        font-size: 20px;
+        height: 100px;
+        color: #fff;
+        > span {
+          img {
+            width: 28px;
+            height: 28px;
+          }
+        }
+      }
+      .intro-base {
+        width: 100%;
+        height: 200px;
+        margin: 0;
+        img {
+          object-fit: cover;
+        }
+      }
+      .intro-base-text-container {
+        height: 100%;
+        gap: 16px;
+        .intro-base-text {
+          flex-direction: column;
+          width: 85%;
+          gap: 6px;
+          .intro-base-text-label {
+            font-size: 14px;
+            color: #fff;
+          }
+          .intro-base-text-content {
+            font-size: 14px;
+            color: rgba(255, 255, 255, 0.6);
+          }
+        }
+      }
+    }
+  }
+}
+
 .mapIntro {
   width: 100%;
   height: 100%;
@@ -110,6 +156,20 @@
   }
 }
 
+.mapIntroMobile {
+  :global {
+    .mapIntro-content {
+      width: 85%;
+      height: 80%;
+      padding: 12px 0;
+      .mapIntro-text {
+        overflow: auto;
+        font-size: 14px;
+      }
+    }
+  }
+}
+
 .preview {
   width: 100%;
   height: 100%;
@@ -118,6 +178,7 @@
   justify-content: flex-start;
   align-items: center;
   flex-direction: column;
+  padding: 6px 0;
   :global {
     .preview-close {
       cursor: pointer;
@@ -218,6 +279,92 @@
   }
 }
 
+.previewMobile {
+  justify-content: space-between;
+  :global {
+    .preview-close {
+      width: 28px;
+      height: 28px;
+      z-index: 10;
+    }
+    .preview-container {
+      width: 100%;
+      height: 100%;
+      max-height: 294px;
+      .preview-content {
+        .preview-arrow-left {
+          left: 2px;
+          top: 53%;
+        }
+        .preview-arrow-right {
+          right: 2px;
+          top: 53%;
+        }
+        .preview-title {
+          font-size: 18px;
+          padding: 12px;
+        }
+        .preview-base-container {
+          width: 100%;
+          margin-top: 40px;
+          .preview-base {
+            height: 240px;
+            background-color: rgba(0, 0, 0, 0.3);
+          }
+        }
+      }
+    }
+    .preview-base-text-container {
+      gap: 6px;
+      width: 100%;
+      padding: 0;
+      padding-bottom: 6px;
+      .preview-base-text {
+        padding: 0 12px;
+        flex-direction: column;
+        gap: 6px;
+        .preview-base-text-label {
+          font-size: 14px;
+          color: #fff;
+        }
+        .preview-base-text-content {
+          font-size: 14px;
+        }
+      }
+    }
+  }
+}
+
+.sliderScroll {
+  width: 100%;
+  overflow: hidden;
+  background-color: rgba(0, 0, 0, 0.5);
+  display: flex;
+  align-items: center;
+  margin-bottom: 12px;
+  ::-webkit-scrollbar {
+    display: none;
+  }
+}
+
+.sliderList {
+  height: 180px;
+  display: flex;
+  justify-content: left;
+  align-items: center;
+  gap: 12px;
+  flex-wrap: nowrap;
+  min-width: fit-content;
+
+  :global {
+    flex: 0 0 auto;
+  }
+}
+
+.sliderListMobile {
+  height: 120px;
+}
+
 .slider {
   position: relative;
   width: 200px;
@@ -257,28 +404,8 @@
   }
 }
 
-.sliderScroll {
-  width: 100%;
-  overflow: hidden;
-  background-color: rgba(0, 0, 0, 0.5);
-  display: flex;
-  align-items: center;
-  margin-bottom: 12px;
-  ::-webkit-scrollbar {
-    display: none;
-  }
-}
-
-.sliderList {
-  height: 180px;
-  display: flex;
-  justify-content: left;
-  align-items: center;
-  gap: 12px;
-  flex-wrap: nowrap;
-  min-width: fit-content;
-
-  :global {
-    flex: 0 0 auto;
-  }
+.sliderMobile {
+  width: 150px;
+  height: 100px;
+  margin: 0;
 }

BIN
src/pages/A0base/image/M_D_taohuayuan.png


BIN
src/pages/A0base/image/M_D_xingtong.png


BIN
src/pages/A0base/image/M_base.png


BIN
src/pages/A0base/image/M_bg_floor.png


BIN
src/pages/A0base/image/M_bg_map.png


+ 47 - 0
src/pages/A0base/index.module.scss

@@ -49,6 +49,26 @@
   }
 }
 
+.A0baseMobile {
+  :global {
+    .A0_iconBar {
+      width: 45px;
+      top: 68%;
+      left: 85%;
+      flex-direction: column;
+      gap: 0;
+      .A0_icon {
+        div {
+          white-space: nowrap;
+        }
+        .addLike {
+          bottom: 130px;
+        }
+      }
+    }
+  }
+}
+
 .diagram {
   position: relative;
   width: 355px;
@@ -62,6 +82,9 @@
       &:hover {
         scale: 1.1;
       }
+      &:active {
+        scale: 1.1;
+      }
     }
     .diagram-address {
       position: fixed;
@@ -70,6 +93,7 @@
       }
     }
     .diagram-text {
+      font-family: 'PingFang SC', '微软雅黑', sans-serif;
       display: inline-block;
       font-size: 24px;
       line-height: 24px;
@@ -82,6 +106,21 @@
   }
 }
 
+.diagramMobile {
+  width: 200px;
+  height: 150px;
+  :global {
+    .diagram-text {
+      font-size: 16px;
+      line-height: 16px;
+      width: 90px;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+    }
+  }
+}
+
 .layout {
   :global {
     .back {
@@ -150,3 +189,11 @@
     }
   }
 }
+
+.layoutMobile {
+  :global {
+    .layout-container {
+      left: 9%;
+    }
+  }
+}

+ 92 - 37
src/pages/A0base/index.tsx

@@ -4,19 +4,20 @@ import classNames from 'classnames'
 import http from '@/utils/http'
 import { useHistory } from 'react-router-dom'
 import taohuanyuan from './image/D_taohuayuan.png'
+import taohuanyuanMobile from './image/M_D_taohuayuan.png'
 import xingtong from './image/D_xingtong.png'
+import xingtongMobile from './image/M_D_xingtong.png'
 import xuni from './image/D_xuni.png'
 import address from './image/D_address.png'
 import like from './image/icon_like.png'
 import share from './image/icon_share.png'
 import intro from './image/icon_intro.png'
-import floor from './image/bg_floor.png'
-import map from './image/bg_map.png'
 import arrow from './image/arrow.png'
 
 import { message } from 'antd'
 import { Intro, MapIntro } from './component/Intro'
 import { Preview } from './component/Preview'
+import isMobile from '@/utils/isMobile'
 
 const imgArrTemp = [
   { src: 'Bao-0.png', title: '基本情况' },
@@ -49,24 +50,36 @@ function Diagram({
   addressLeft,
   addressTop,
   text,
-  handleClick
+  handleClick,
+  textLeft,
+  textTop
 }: {
   imgSrc: any
   left: number
   top: number
   addressLeft: number
   addressTop: number
+  textLeft?: number
+  textTop?: number
   text: string
   handleClick: () => void
 }) {
   console.log(imgSrc)
   console.log(taohuanyuan)
   return (
-    <div className={styles.diagram} style={{ left: `${left}%`, top: `${top}%` }}>
+    <div
+      className={classNames(styles.diagram, isMobile() && styles.diagramMobile)}
+      style={{ left: `${left}%`, top: `${top}%` }}
+    >
       <img className='diagram-img' src={imgSrc} onClick={handleClick} alt='' />
+      {isMobile() && (
+        <div className='diagram-text' style={{ left: `${textLeft}%`, top: `${textTop}%` }}>
+          {text}
+        </div>
+      )}
       <div className='diagram-address' style={{ left: `${addressLeft}%`, top: `${addressTop}%` }}>
         <img src={address} alt='' />
-        <div className='diagram-text'>{text}</div>
+        {!isMobile() && <div className='diagram-text'>{text}</div>}
       </div>
     </div>
   )
@@ -75,7 +88,7 @@ function Diagram({
 function Layout({ setIsFloor }: { setIsFloor: (isFloor: boolean) => void }) {
   const history = useHistory()
   return (
-    <div className={styles.layout}>
+    <div className={classNames(styles.layout, isMobile() && styles.layoutMobile)}>
       <div className='back' onClick={() => setIsFloor(false)}>
         <img src={require('./image/back.png')} alt='' />
       </div>
@@ -83,7 +96,7 @@ function Layout({ setIsFloor }: { setIsFloor: (isFloor: boolean) => void }) {
         <div
           className='floor-1'
           onClick={() => {
-            history.push('/home?m=SG-dwRgbFq7Fiz')
+            history.push('/home?m=SG-NqtcxoVBj5C')
             setTimeout(() => {
               window.location.reload()
             }, 200)
@@ -142,8 +155,16 @@ function A0Base() {
   }
   return (
     <div
-      className={styles.A0base}
-      style={{ backgroundImage: isFloor ? `url(${floor})` : `url(${map})` }}
+      className={classNames(styles.A0base, isMobile() && styles.A0baseMobile)}
+      style={{
+        backgroundImage: isFloor
+          ? isMobile()
+            ? `url(${require('./image/M_bg_floor.png')})`
+            : `url(${require('./image/bg_floor.png')})`
+          : isMobile()
+          ? `url(${require('./image/M_bg_map.png')})`
+          : `url(${require('./image/bg_map.png')})`
+      }}
     >
       {showIntro &&
         (isFloor ? (
@@ -155,33 +176,64 @@ function A0Base() {
 
       {!isFloor && !showIntro && !isPreview[0] && (
         <>
-          <Diagram
-            imgSrc={taohuanyuan}
-            left={13.6}
-            top={8.2}
-            addressLeft={30.4}
-            addressTop={6}
-            text='桃花园科技创新生态园'
-            handleClick={() => setIsPreview([true, 'baoan'])}
-          />
-          <Diagram
-            imgSrc={xingtong}
-            left={9.6}
-            top={5}
-            addressLeft={25.6}
-            addressTop={73}
-            text='星通大厦'
-            handleClick={() => setIsFloor(true)}
-          />
-          <Diagram
-            imgSrc={xuni}
-            left={47.5}
-            top={-22}
-            addressLeft={55.5}
-            addressTop={85}
-            text='深圳虚拟大学园'
-            handleClick={() => setIsPreview([true, 'nanshang'])}
-          />
+          {!isMobile() ? (
+            <Diagram
+              imgSrc={taohuanyuan}
+              left={13.6}
+              top={8.2}
+              addressLeft={30.4}
+              addressTop={6}
+              text='桃花园科技创新生态园'
+              handleClick={() => setIsPreview([true, 'baoan'])}
+            />
+          ) : (
+            <Diagram
+              imgSrc={taohuanyuanMobile}
+              left={9.6}
+              top={8.2}
+              addressLeft={47.2}
+              addressTop={4}
+              text='桃花园科技创新生态园'
+              textLeft={50}
+              textTop={100}
+              handleClick={() => setIsPreview([true, 'baoan'])}
+            />
+          )}
+
+          {!isMobile() ? (
+            <Diagram
+              imgSrc={xingtong}
+              left={9.6}
+              top={5}
+              addressLeft={25.6}
+              addressTop={73}
+              text='星通大厦'
+              handleClick={() => setIsFloor(true)}
+            />
+          ) : (
+            <Diagram
+              imgSrc={xingtongMobile}
+              left={20.6}
+              top={31}
+              addressLeft={13.2}
+              addressTop={66.5}
+              text='星通大厦'
+              textLeft={70}
+              textTop={110}
+              handleClick={() => setIsFloor(true)}
+            />
+          )}
+          {!isMobile() && (
+            <Diagram
+              imgSrc={xuni}
+              left={47.5}
+              top={-22}
+              addressLeft={55.5}
+              addressTop={85}
+              text='深圳虚拟大学园'
+              handleClick={() => setIsPreview([true, 'nanshang'])}
+            />
+          )}
         </>
       )}
 
@@ -192,7 +244,10 @@ function A0Base() {
           type={isPreview[1]}
         />
       )}
-      <div className='A0_iconBar' style={{ display: isPreview[0] ? 'none' : 'flex' }}>
+      <div
+        className='A0_iconBar'
+        style={{ display: isPreview[0] || (isMobile() && showIntro) ? 'none' : 'flex' }}
+      >
         <div className='A0_icon' onClick={() => handleLikeClick()}>
           <div
             className={classNames(isLike ? 'addLikeAc' : '', 'addLike')}

+ 10 - 0
src/pages/A2main/components/A24drawerList/index.module.scss

@@ -4,6 +4,16 @@
 //   }
 // }
 
+.A24drawerListMobile {
+  height: 160px;
+  #drawer {
+    top: 20% !important;
+    .frame-container {
+      height: 160px !important;
+    }
+  }
+}
+
 // .A24logo{
 //   :global{
 

+ 45 - 4
src/pages/A2main/index.module.scss

@@ -47,14 +47,17 @@
     #gui-modes-map {
       #pullTab,
       .A2hotIcon,
+      #play,
+      #pause,
+      #next,
       #gui-modes-inside,
       #gui-modes-dollhouse,
       #gui-modes-floorplan {
         width: var(--pcIconWidth);
         height: var(--pcIconWidth);
-        margin-left: 18px;
         background-color: transparent !important;
         position: relative;
+        margin-left: 12px;
         img {
           width: 100%;
           height: 100%;
@@ -94,7 +97,7 @@
 
     // 底部的位置
     .pinBottom {
-      bottom: 34px;
+      bottom: 20px;
     }
     .pinBottom.playing {
       bottom: 50px !important;
@@ -174,6 +177,7 @@
         width: 100%;
         text-align: center;
         text-shadow: 1px 1px 1px #fcda99;
+        color: #fff;
       }
     }
 
@@ -275,6 +279,9 @@
       .hoveImg {
         display: none !important;
       }
+      .A2_share_text {
+        display: none !important;
+      }
       #play,
       #pause {
         width: var(--appIconWidthH);
@@ -313,13 +320,20 @@
 
     @media screen and (max-width: 600px) {
       #gui-modes-map {
+        height: 260px;
+        justify-content: flex-end;
+        gap: 6px;
+        #play,
+        #pause,
+        #next,
         #pullTab,
         .A2hotIcon,
         #gui-modes-inside,
         #gui-modes-dollhouse,
         #gui-modes-floorplan {
-          margin-left: 0;
-          margin-top: 5px;
+          margin: 0;
+          width: 45px;
+          height: 45px;
         }
       }
       .likeBox,
@@ -331,6 +345,33 @@
       .pinBottom.right {
         right: 10px;
       }
+
+      .rightViewContainer {
+        display: flex;
+        justify-content: flex-end;
+        align-items: center;
+        flex-direction: column;
+        height: 260px;
+        gap: 6px;
+        .likeBox,
+        #vr,
+        #volume,
+        .A2_share_box {
+          width: 45px;
+          height: 45px;
+          margin: 0;
+        }
+      }
+
+      #drawer-container {
+        #thumb-container {
+          width: fit-content !important;
+          .thumbImg {
+            width: 105px;
+            height: 75px;
+          }
+        }
+      }
     }
   }
 }

+ 38 - 36
src/pages/A2main/index.tsx

@@ -88,35 +88,35 @@ function A2main() {
                 />
               </a>
             </div>
-            <div id='play' className='ui-icon' rel='tooltip' data-original-title='播放'>
-              {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
-              <a>
-                <img src='images/play.png' alt='' />
-              </a>
-              {/* 鼠标移入 */}
-              <div className='hoveImg'>自动导览</div>
-            </div>
-            <div id='pause' className='ui-icon' style={{ display: 'none' }}>
-              {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
-              <a>
-                <img rel='tooltip' src='images/pause.png' alt='' />
-              </a>
-              {/* 鼠标移入 */}
-              <div className='hoveImg'>暂停导览</div>
-            </div>
-            <div id='next' className='next desktop-only ui-icon wide' style={{ display: 'none' }}>
-              {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
-              <a>
-                <i
-                  rel='tooltip'
-                  title=''
-                  className='icon icon-dpad-right'
-                  data-original-title='下一个'
-                ></i>
-              </a>
-            </div>
 
             <div id='gui-modes-map' className='ui-icon double active'>
+              <div id='play' className='ui-icon' rel='tooltip' data-original-title='播放'>
+                {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
+                <a>
+                  <img src='images/play.png' alt='' />
+                </a>
+                {/* 鼠标移入 */}
+                <div className='hoveImg'>自动导览</div>
+              </div>
+              <div id='pause' className='ui-icon' rel='tooltip' style={{ display: 'none' }}>
+                {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
+                <a>
+                  <img src='images/pause.png' alt='' />
+                </a>
+                {/* 鼠标移入 */}
+                <div className='hoveImg'>暂停导览</div>
+              </div>
+              <div id='next' className='next desktop-only ui-icon wide' style={{ display: 'none' }}>
+                {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
+                <a>
+                  <i
+                    rel='tooltip'
+                    title=''
+                    className='icon icon-dpad-right'
+                    data-original-title='下一个'
+                  ></i>
+                </a>
+              </div>
               <div data-original-title='导览' id='pullTab' rel='tooltip' title=''>
                 <img className='icon icon-inside' src='images/auto.png' alt='' />
                 {/* 鼠标移入 */}
@@ -165,15 +165,7 @@ function A2main() {
                 {/* 鼠标移入 */}
                 <div className='hoveImg'>平面视觉</div>
               </div>
-              <div
-                data-original-title='VR'
-                id='vr'
-                rel='tooltip'
-                title=''
-                style={{ display: 'none' }}
-              >
-                <img className='icon icon-inside' src='images/VR.png' title='VR' alt='' />
-              </div>
+
               <div
                 data-original-title='消除外壳'
                 id='gui-remove-face'
@@ -219,6 +211,16 @@ function A2main() {
               <div className={classNames('likeMove', like ? 'likeMoveAc' : '')}>+1</div>
             </div>
 
+            <div
+              data-original-title='VR'
+              id='vr'
+              rel='tooltip'
+              title=''
+              style={{ display: 'none' }}
+            >
+              <img className='icon icon-inside' src='images/VR.png' title='VR' alt='' />
+            </div>
+
             <div id='volume' className='ui-icon wide'>
               {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
               <a>

+ 3 - 0
src/utils/isMobile.ts

@@ -0,0 +1,3 @@
+export default function isMobile() {
+  return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
+}

+ 34 - 1
yarn.lock

@@ -1315,6 +1315,15 @@
   resolved "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz#b6c75a56a1947cc916ea058772d666a2c8932f31"
   integrity sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==
 
+"@dage/krpano@^3.0.0":
+  version "3.0.0"
+  resolved "http://192.168.20.245:4873/@dage/krpano/-/krpano-3.0.0.tgz#86c4f55f96e79b5554bb4b2bac275c28e6ddc8b4"
+  integrity sha512-LlQoemNJXkmAhB7XOx+BSvFMWCQRXn1amDV7EMijWBWAY09IcNkcH1A3RpCGii3ARVlG/Ll7tOu7ky2RApA3LA==
+  dependencies:
+    escape-html "^1.0.3"
+    mobx "^6.13.2"
+    mobx-react "^9.1.1"
+
 "@emotion/hash@^0.8.0":
   version "0.8.0"
   resolved "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
@@ -4546,7 +4555,7 @@ escalade@^3.1.1:
   resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
   integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
 
-escape-html@~1.0.3:
+escape-html@^1.0.3, escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
   integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
@@ -7046,6 +7055,25 @@ mkdirp@~0.5.1:
   dependencies:
     minimist "^1.2.6"
 
+mobx-react-lite@^4.1.0:
+  version "4.1.0"
+  resolved "http://192.168.20.245:4873/mobx-react-lite/-/mobx-react-lite-4.1.0.tgz#6a03ed2d94150848213cfebd7d172e123528a972"
+  integrity sha512-QEP10dpHHBeQNv1pks3WnHRCem2Zp636lq54M2nKO2Sarr13pL4u6diQXf65yzXUn0mkk18SyIDCm9UOJYTi1w==
+  dependencies:
+    use-sync-external-store "^1.4.0"
+
+mobx-react@^9.1.1:
+  version "9.2.0"
+  resolved "http://192.168.20.245:4873/mobx-react/-/mobx-react-9.2.0.tgz#c1e4d1ed406f6664d9de0787c948bac3a7ed5893"
+  integrity sha512-dkGWCx+S0/1mfiuFfHRH8D9cplmwhxOV5CkXMp38u6rQGG2Pv3FWYztS0M7ncR6TyPRQKaTG/pnitInoYE9Vrw==
+  dependencies:
+    mobx-react-lite "^4.1.0"
+
+mobx@^6.13.2:
+  version "6.13.7"
+  resolved "http://192.168.20.245:4873/mobx/-/mobx-6.13.7.tgz#70e5dda7a45da947f773b3cd3b065dfe7c8a75de"
+  integrity sha512-aChaVU/DO5aRPmk1GX8L+whocagUUpBQqoPtJk+cm7UOXUk87J4PeWCh6nNmTTIfEhiR9DI/+FnA8dln/hTK7g==
+
 ms@2.0.0:
   version "2.0.0"
   resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -10148,6 +10176,11 @@ use-sync-external-store@^1.0.0, use-sync-external-store@^1.2.0:
   resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
   integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
 
+use-sync-external-store@^1.4.0:
+  version "1.5.0"
+  resolved "http://192.168.20.245:4873/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0"
+  integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
+
 util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
   version "1.0.2"
   resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"