main.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. const modelViewerParameters = document.querySelector("model-viewer#sphere")
  2. const ecButton = document.querySelector("#ec-button")
  3. const strengthButton = document.querySelector("#strength-button")
  4. const splitBox = document.querySelector(".splitBox")
  5. const container = document.querySelector("#container")
  6. const buttonBox = document.querySelector(".buttonBox")
  7. const txtBox = document.querySelector('.txt')
  8. let isMobile = false
  9. // 需要切换的贴图
  10. let bmTexture = null
  11. let bmTexture2 = null
  12. // 金属度粗糙度贴图
  13. let mRTexture = null
  14. // 当前贴图
  15. let material = null
  16. // 进入页面,加载好贴图
  17. modelViewerParameters.addEventListener("load", () => {
  18. isMobile = /Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)
  19. strengthButton.style.display = "block"
  20. ecButton.style.display = "block"
  21. material = modelViewerParameters.model.materials[0]
  22. // 设置金属度粗糙度
  23. // material.pbrMetallicRoughness.setMetallicFactor(0);
  24. // material.pbrMetallicRoughness.setRoughnessFactor(0.66)
  25. // 设置baseColor贴图
  26. bmTexture = material.pbrMetallicRoughness.baseColorTexture.texture
  27. // 设置金属度粗糙度贴图
  28. modelViewerParameters.createTexture("./static/gltf-13/2_r-4k.jpg").then((texture) => {
  29. material.pbrMetallicRoughness.metallicRoughnessTexture.setTexture(texture)
  30. mRTexture = texture
  31. })
  32. modelViewerParameters.createTexture("./static/gltf-13/bm-color.jpg").then((texture) => {
  33. bmTexture2 = texture
  34. })
  35. modelViewerParameters.createTexture("./static/gltf-13/color_normal.jpg").then((texture) => {
  36. material.normalTexture.setTexture(texture)
  37. })
  38. })
  39. // 创建第二个模型
  40. const modelViewerParameters2 = modelViewerParameters.cloneNode(true)
  41. modelViewerParameters2.id = "sphere2"
  42. modelViewerParameters2.style.display = "none"
  43. modelViewerParameters2.querySelector('.txt').innerHTML = '微痕增强'
  44. const txtBox2 = modelViewerParameters2.querySelector('.txt')
  45. document.querySelector("#container").appendChild(modelViewerParameters2)
  46. startSync()
  47. // 加载第二个模型
  48. modelViewerParameters2.addEventListener("load", () => {
  49. const material2 = modelViewerParameters2.model.materials[0]
  50. modelViewerParameters2.createTexture("./static/gltf-13/2_r-4k.jpg").then((texture) => {
  51. material2.pbrMetallicRoughness.metallicRoughnessTexture.setTexture(texture)
  52. })
  53. modelViewerParameters2.createTexture("./static/gltf-13/bm-color.jpg").then((texture) => {
  54. material2.pbrMetallicRoughness.baseColorTexture.setTexture(texture)
  55. })
  56. material2.pbrMetallicRoughness.setBaseColorFactor([0.3137, 0.3137, 0.3137])
  57. console.log(material2)
  58. })
  59. const closeCompare = () => {
  60. modelViewerParameters2.style.display = "none"
  61. modelViewerParameters.style.width = "100%"
  62. modelViewerParameters.style.height = "100%"
  63. modelViewerParameters.style.maxWidth = "100%"
  64. splitBox.style.display = "none"
  65. ecButton.style.backgroundColor = "#f0f0f0"
  66. container.style.flexDirection = "row"
  67. txtBox.style.display = 'none'
  68. txtBox2.style.display = 'none'
  69. isEcClick = true
  70. }
  71. const openComparePC = () => {
  72. modelViewerParameters2.style.display = "block"
  73. txtBox.style.display = 'block'
  74. txtBox2.style.display = 'block'
  75. modelViewerParameters.style.width = "49.5%"
  76. modelViewerParameters.style.maxWidth = "80%"
  77. splitBox.style.display = "flex"
  78. ecButton.style.backgroundColor = "#ccc"
  79. isEcClick = false
  80. }
  81. const openCompareM = () => {
  82. modelViewerParameters2.style.display = "block"
  83. txtBox.style.display = 'block'
  84. txtBox2.style.display = 'block'
  85. modelViewerParameters2.style.width = "100%"
  86. modelViewerParameters2.style.height = "0%"
  87. modelViewerParameters.style.height = "50%"
  88. container.style.flexDirection = "column"
  89. ecButton.style.backgroundColor = "#ccc"
  90. txtBoxRotate(modelViewerParameters2.querySelector('.txt'))
  91. isEcClick = false
  92. }
  93. // 点击切换展示第二个模型
  94. let isEcClick = true
  95. ecButton.addEventListener("click", () => {
  96. if (isEcClick) {
  97. if (isMobile) {
  98. openCompareM()
  99. } else {
  100. openComparePC()
  101. }
  102. } else {
  103. closeCompare()
  104. }
  105. })
  106. // 点击增强按钮切换贴图
  107. let isStrengthClick = true
  108. strengthButton.addEventListener("click", () => {
  109. console.log("点击了")
  110. if (isStrengthClick) {
  111. material.pbrMetallicRoughness.baseColorTexture.setTexture(bmTexture2)
  112. material.pbrMetallicRoughness.setBaseColorFactor([0.3137, 0.3137, 0.3137])
  113. strengthButton.style.backgroundColor = "#ccc"
  114. isStrengthClick = false
  115. closeCompare()
  116. } else {
  117. material.pbrMetallicRoughness.baseColorTexture.setTexture(bmTexture)
  118. material.pbrMetallicRoughness.setBaseColorFactor([1, 1, 1])
  119. strengthButton.style.backgroundColor = "#f0f0f0"
  120. isStrengthClick = true
  121. }
  122. })
  123. // 拖动分割线
  124. splitBox.addEventListener("mousedown", (e) => {
  125. e.preventDefault() // 阻止默认行为
  126. const containerWidth = container.offsetWidth
  127. const startX = e.clientX
  128. const startWidth = modelViewerParameters.offsetWidth
  129. // 保存事件处理函数的引用以便后续移除
  130. const onMouseMove = (e) => {
  131. const moveX = e.clientX
  132. const moveWidth = moveX - startX
  133. const newWidth = startWidth + moveWidth
  134. // 更新左右面板的宽度
  135. modelViewerParameters.style.width = newWidth + "px"
  136. modelViewerParameters2.style.width = (containerWidth - newWidth) + "px"
  137. }
  138. const onMouseUp = () => {
  139. document.removeEventListener("mousemove", onMouseMove)
  140. document.removeEventListener("mouseup", onMouseUp)
  141. }
  142. document.addEventListener("mousemove", onMouseMove)
  143. document.addEventListener("mouseup", onMouseUp)
  144. })
  145. // 实时同步
  146. function startSync() {
  147. modelViewerParameters.addEventListener('mousemove', () => {
  148. modelViewerParameters.addEventListener('camera-change', handleCameraChange)
  149. modelViewerParameters2.removeEventListener('camera-change', handleCameraChange2)
  150. })
  151. modelViewerParameters2.addEventListener('mousemove', () => {
  152. modelViewerParameters2.addEventListener('camera-change', handleCameraChange2)
  153. modelViewerParameters.removeEventListener('camera-change', handleCameraChange)
  154. })
  155. // 兼容移动端
  156. modelViewerParameters.addEventListener('touchmove', () => {
  157. modelViewerParameters.addEventListener('camera-change', handleCameraChange)
  158. modelViewerParameters2.removeEventListener('camera-change', handleCameraChange2)
  159. })
  160. modelViewerParameters2.addEventListener('touchmove', () => {
  161. modelViewerParameters2.addEventListener('camera-change', handleCameraChange2)
  162. modelViewerParameters.removeEventListener('camera-change', handleCameraChange)
  163. })
  164. // 兼容鼠标滚轮
  165. modelViewerParameters.addEventListener('wheel', () => {
  166. modelViewerParameters.addEventListener('camera-change', handleCameraChange)
  167. modelViewerParameters2.removeEventListener('camera-change', handleCameraChange2)
  168. })
  169. modelViewerParameters2.addEventListener('wheel', () => {
  170. modelViewerParameters2.addEventListener('camera-change', handleCameraChange2)
  171. modelViewerParameters.removeEventListener('camera-change', handleCameraChange)
  172. })
  173. }
  174. // 相机变化处理
  175. function handleCameraChange() {
  176. // 如果正在同步中,则不处理此次事件,避免循环触发
  177. modelViewerParameters2.removeEventListener('camera-change', handleCameraChange2)
  178. // 获取相机参数
  179. const orbit = modelViewerParameters.getCameraOrbit()
  180. const targetPoint = modelViewerParameters.getCameraTarget()
  181. const fov = modelViewerParameters.getFieldOfView()
  182. // 添加文字显示控制
  183. modelViewerParameters.querySelector('.txt').style.opacity = fov < 28 ? 0 : 1
  184. modelViewerParameters2.querySelector('.txt').style.opacity = fov < 28 ? 0 : 1
  185. // 设置到目标viewer
  186. modelViewerParameters2.cameraOrbit = orbit.toString()
  187. modelViewerParameters2.cameraTarget = targetPoint.toString()
  188. modelViewerParameters2.fieldOfView = `${fov}deg`
  189. modelViewerParameters2.jumpCameraToGoal()
  190. }
  191. function handleCameraChange2() {
  192. modelViewerParameters.removeEventListener('camera-change', handleCameraChange)
  193. // 获取相机参数
  194. const orbit = modelViewerParameters2.getCameraOrbit()
  195. const targetPoint = modelViewerParameters2.getCameraTarget()
  196. const fov = modelViewerParameters2.getFieldOfView()
  197. // 添加文字显示控制
  198. modelViewerParameters.querySelector('.txt').style.opacity = fov < 28 ? 0 : 1
  199. modelViewerParameters2.querySelector('.txt').style.opacity = fov < 28 ? 0 : 1
  200. // 设置到目标viewer
  201. modelViewerParameters.cameraOrbit = orbit.toString()
  202. modelViewerParameters.cameraTarget = targetPoint.toString()
  203. modelViewerParameters.fieldOfView = `${fov}deg`
  204. modelViewerParameters.jumpCameraToGoal()
  205. }
  206. // 页面旋转和缩放处理函数
  207. function handleOrientationChange() {
  208. const screenWidth = document.documentElement.clientWidth
  209. const screenHeight = document.documentElement.clientHeight
  210. console.log(screenWidth, screenHeight)
  211. if (screenWidth <= screenHeight) {
  212. // 竖屏模式
  213. console.log('竖屏模式')
  214. isMobile = true
  215. modelViewerParameters.orientation = '-90deg 0deg 0deg'
  216. modelViewerParameters2.orientation = '-90deg 0deg 0deg'
  217. splitBox.style.display = 'none'
  218. buttonBox.style.transform = "rotate(90deg) translate(-10px, -10px)"
  219. buttonBox.style.transformOrigin = "center"
  220. buttonBox.style.bottom = "10px"
  221. buttonBox.style.top = "auto"
  222. buttonBox.style.zIndex = "1"
  223. txtBoxRotate(txtBox)
  224. } else {
  225. isMobile = false
  226. modelViewerParameters.orientation = '0deg 0deg 0deg'
  227. modelViewerParameters2.orientation = '0deg 0deg 0deg'
  228. }
  229. }
  230. const txtBoxRotate = (dom) => {
  231. dom.style.transform = "rotate(90deg) translate(50%,-100%)"
  232. dom.style.transformOrigin = "top right"
  233. dom.style.left = "60%"
  234. dom.style.top = "50%"
  235. }
  236. // 页面加载完成后初始化
  237. window.addEventListener('load', () => {
  238. handleOrientationChange()
  239. })
  240. // 监听窗口大小变化
  241. window.addEventListener('resize', handleOrientationChange)