index.tsx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import React, { useState, useRef } from 'react'
  2. import styles from './index.module.scss'
  3. import { isMobileFu } from '@/utils/history'
  4. import { Swiper, SwiperSlide } from 'swiper/react'
  5. import 'swiper/css'
  6. import 'swiper/css/effect-coverflow'
  7. import 'swiper/css/pagination'
  8. import 'swiper/css/navigation'
  9. import { EffectCoverflow, Pagination, Navigation } from 'swiper/modules'
  10. function Look({
  11. style,
  12. setIsHideSider
  13. }: {
  14. style: React.CSSProperties
  15. setIsHideSider: (isHideSider: boolean) => void
  16. }) {
  17. const [hoveredIndex, setHoveredIndex] = useState<number | null>(null)
  18. const [selectIndex, setSelectIndex] = useState<number | null>(null)
  19. const swiperRef = useRef<any>(null)
  20. const iframeRef = useRef<HTMLIFrameElement>(null)
  21. // 添加全屏切换函数
  22. const toggleFullscreen = () => {
  23. if (!iframeRef.current) return
  24. const iframe = iframeRef.current
  25. // 检查是否已经全屏
  26. if (!document.fullscreenElement) {
  27. // 直接请求iframe元素全屏(而非内部文档)
  28. if (iframe.requestFullscreen) {
  29. iframe
  30. .requestFullscreen()
  31. .then(() => { })
  32. .catch(err => {
  33. console.error('进入全屏失败:', err)
  34. })
  35. }
  36. } else {
  37. // 退出全屏
  38. if (document.exitFullscreen) {
  39. document
  40. .exitFullscreen()
  41. .then(() => { })
  42. .catch(err => {
  43. console.error('退出全屏失败:', err)
  44. })
  45. }
  46. }
  47. }
  48. return (
  49. <div className={styles.look} style={style}>
  50. {/* 顶部仅在pc端显示 */}
  51. <div className='top'>
  52. <div className='logo'>
  53. <img src={require('@/assets/img/sceneLogo.png')} alt='' />
  54. </div>
  55. <div className='title'>矿石赏析</div>
  56. </div>
  57. {selectIndex === null ? (
  58. <div className='content'>
  59. {/* 移动端 */}
  60. {isMobileFu() && (
  61. <Swiper
  62. ref={swiperRef}
  63. loopPreventsSliding={false}
  64. effect={'coverflow'}
  65. grabCursor={true}
  66. centeredSlides={true}
  67. slidesPerView={'1'}
  68. coverflowEffect={{
  69. rotate: 0,
  70. stretch: 0,
  71. depth: 180,
  72. modifier: 4
  73. }}
  74. pagination={{ el: '.swiper-pagination', clickable: true }}
  75. modules={[EffectCoverflow, Pagination, Navigation]}
  76. className='swiper_container'
  77. // 添加Swiper尺寸观察器
  78. observer={true}
  79. observeParents={true}
  80. // 初始化后强制更新布局
  81. onInit={(swiper: any) => {
  82. setTimeout(() => {
  83. swiper.update()
  84. }, 0)
  85. }}
  86. >
  87. {/* 保持原有的slide渲染代码不变 */}
  88. {oreData.map((item, index) => (
  89. <SwiperSlide key={index}>
  90. <div
  91. className='itemCard'
  92. key={index}
  93. // onMouseEnter={() => setHoveredIndex(index)}
  94. // onMouseLeave={() => setHoveredIndex(null)}
  95. onClick={() => {
  96. setSelectIndex(index)
  97. setIsHideSider(true)
  98. }}
  99. >
  100. <div className='itemImage'>
  101. <img
  102. src={hoveredIndex === index ? item.activeImg : item.img}
  103. alt={item.title}
  104. />
  105. </div>
  106. <div className='viewButton'>查看详情</div>
  107. </div>
  108. </SwiperSlide>
  109. ))}
  110. </Swiper>
  111. )}
  112. {/* pc端 */}
  113. {!isMobileFu() &&
  114. oreData.map((item, index) => (
  115. <div
  116. className='itemCard pcItem'
  117. key={index}
  118. onMouseEnter={() => setHoveredIndex(index)}
  119. onMouseLeave={() => setHoveredIndex(null)}
  120. onClick={() => {
  121. setSelectIndex(index)
  122. setIsHideSider(true)
  123. }}
  124. >
  125. <div className='itemImage'>
  126. <img
  127. src={hoveredIndex === index ? item.activeImg : item.img}
  128. alt={item.title}
  129. />
  130. </div>
  131. <div className='viewButton'>查看详情</div>
  132. </div>
  133. ))}
  134. </div>
  135. ) : (
  136. <>
  137. <div
  138. className='back'
  139. onClick={() => {
  140. setSelectIndex(null)
  141. setIsHideSider(false)
  142. }}
  143. >
  144. <img src={require('@/assets/img/back.png')} alt='' />
  145. </div>
  146. <div className='detail'>
  147. <div className='left'>
  148. <div className='fullscreen' onClick={toggleFullscreen}>
  149. <img src={require('@/assets/img/enlarge_on.png')} alt='' />
  150. </div>
  151. <iframe
  152. ref={iframeRef}
  153. title='3D Model'
  154. src={selectIndex !== null ? oreData[selectIndex].modelSrc : ''}
  155. allow='src'
  156. />
  157. </div>
  158. <div className='right'>
  159. <div className='oreTitle'>
  160. {selectIndex !== null ? oreData[selectIndex].title : ''}
  161. </div>
  162. <div className='intro' dangerouslySetInnerHTML={{ __html: selectIndex !== null ? oreData[selectIndex].text : '' }}>
  163. </div>
  164. </div>
  165. </div>
  166. </>
  167. )}
  168. </div>
  169. )
  170. }
  171. const MemoLook = React.memo(Look)
  172. export default MemoLook