在threejs制作鼠标交互的网页banner之前,需要准备好产品三维模型,三维模型文件格式为.gltf格式,同时准备好产品缩略图。建议三维模型使用threejs的编辑器进行重新调整材质,因为使用三维建模软件导出的.gltf格式文件导入到threejs,材质经常加载失败,使用threejs的编辑器进行重新调整材质可以避免这样的问题。
html文件中添加部分样式:
<style type="text/css">
    .productsList img {
      padding: 5px;
      border: 4px solid rgba(255, 255, 255, 0.3);
      width: 70px;
      height: 70px;
      margin: 0 10px;
      scale: 1;
      transition: all 0.3s;
    }

    .productsList img:hover {
      scale: 1.1;
    }

    .productDetails a {
      display: inline-block;
      padding: 5px 60px;
      border: 4px solid rgba(255, 255, 255, 0.3);
      background-color: rgba(4, 64, 150, 0);
      border-radius: 10px;
      color: white;
      transition: all 0.5s;
      scale: 1;
    }

    .productDetails a:hover {
      scale: 1.1;
      background-color: rgba(4, 64, 150, 1);
      border: 4px solid rgba(255, 255, 255, 1);
    }
</style>

同时,需要在html页面上准备id为app的div,用于展示模型:
<div id="app"> </div>
 

在执行主程序之前,还需要导入importmap文件:
<script type="importmap">
  {
    "imports": {
      "three": "https://unpkg.com/three@0.138.0/build/three.module.js",
      "gLTFLoader": "https://unpkg.com/three@0.138.0/examples/jsm/loaders/GLTFLoader.js"
    }
  }
</script>

导入模块化程序:
<script type="module">
    import * as THREE from 'three';
    import { GLTFLoader } from 'gLTFLoader';

    const w = window.innerWidth
    const h = window.innerHeight - 80
    var textureLoader = new THREE.TextureLoader();
    var backgroundTexture = textureLoader.load('bgix5.jpg');

    // 3D容器--scene(场景)
    const scene = new THREE.Scene()
    scene.background = backgroundTexture


    // 坐标系
    const axes = new THREE.AxesHelper(2, 2, 2)
    scene.add(axes)

    // 产品数据数组,包含产品名称、模型文件路径、缩略图url、产品参数、产品详情url
    let productsData = [
      { 'name': 'TXZC2型智能压力开关', 'model': '/files/txzc.gltf', 'imgUrl': 'https://cz-tianli.com/files/slt1.png', 'parameter': '测量范围:-0.1~100MPa<br/>工作温度:-25℃~80℃<br>显示:四位LCD<br>供电电源:DC24V或AC220V<br/>防护等级:IP65<br/>防爆等级:Exd Ⅱ CT6 Gb', 'productLink': 'https://cz-tianli.com/txzcdzylkg/135.html' },
      { 'name': 'TL0202机械压力开关', 'model': '/files/ylkg.gltf', 'imgUrl': 'https://cz-tianli.com/files/slt1.png', 'parameter': '测量范围:-0.1~2.5MPa<br>工作温度:-40℃~80℃<br>防护等级:IP65或IP54<br>防爆等级:Exd Ⅱ CT4~T6 Gb', 'productLink': 'https://cz-tianli.com/ptxjxylkg/383.html' }
    ]


    const loader = new GLTFLoader()

    let product = 'product'
    let isRotate = true
    let isDragging = false
    // 导入产品模型
    function loadModel(productIndex = 0) {
      loader.load(
        productsData[productIndex]['model'],
        (gltf) => {
          product = gltf.scene

          // 初始位置和缩放调整
          product.scale.set(0.5, 0.5, 0.5)
          product.position.y = 1.5
          scene.add(product)
        }
      )
      isRotate = true
    }
    loadModel()

    // 光线
    const light = new THREE.AmbientLight(0xffffff)
    light.position.set(1, 3, 6)
    scene.add(light)

    const diectLight = new THREE.DirectionalLight(0xffffff, 1)
    diectLight.position.set(15, 10, 15)
    scene.add(diectLight)

    const diectLight1 = new THREE.DirectionalLight(0xffffff, 1)
    diectLight1.position.set(-15, 10, 15)
    scene.add(diectLight1)

    const diectLight2 = new THREE.DirectionalLight(0xffffff, 1)
    diectLight2.position.set(-15, 10, -15)
    scene.add(diectLight2)

    const diectLight3 = new THREE.DirectionalLight(0xffffff, 1)
    diectLight3.position.set(15, 10, -15)
    scene.add(diectLight3)


    // 相机
    const canema = new THREE.PerspectiveCamera(75, w / h, 0.1, 1500)
    canema.position.set(0, 0, 10)
    canema.lookAt(0, 0, 0)

    // 渲染器
    const renderer = new THREE.WebGLRenderer({
      antialias:true
    })
    renderer.setSize(w, h)
    renderer.render(scene, canema)

    document.querySelector('#app').append(renderer.domElement)

    // 模型鼠标交互
    let preX = 0
    let preY = 0
    let currentX = 0
    let currentY = 0
    let totalX = 0
    let totalY = 0
    let deltaX = 0
    let deltaY = 0
    document.querySelector('#app').addEventListener('mousedown', function (e) {
      isRotate = false
      isDragging = true
      preX = e.clientX
      preY = e.clientY
      deltaX = 0
      deltaY = 0
    })
    document.querySelector('#app').addEventListener('mouseup', function (e) {
      isDragging = false
    })
    document.querySelector('#app').addEventListener('mousemove', function (e) {
      if (isDragging) {
        currentX = e.clientX
        currentY = e.clientY
        product.children.forEach(kg => {
          totalX += (deltaX) * 0.001
          totalY += (deltaY) * 0.001
          kg.rotation.y = totalX
          kg.rotation.x = totalY
        })
        deltaX = currentX - preX
        deltaY = currentY - preY
        preX = currentX
        preY = currentY
      }
    })

    // 创建一个HTML元素用于显示产品标题文本
    let textElement = document.createElement('div')
    textElement.style.position = 'absolute'
    textElement.style.color = 'white'
    textElement.style.top = h * 0.6 + 'px'
    textElement.style.left = w * 0.15 + 'px'
    textElement.style.fontSize = '30px'
    textElement.style.fontWeight = 'bold'
    document.body.appendChild(textElement)

    // 创建一个HTML元素用于显示产品参数文本
    let textElement1 = document.createElement('div')
    textElement1.style.position = 'absolute'
    textElement1.style.color = 'white'
    textElement1.style.top = h * 0.6 + 50 + 'px'
    textElement1.style.left = w * 0.15 + 'px'
    textElement1.style.fontSize = '20px'
    document.body.appendChild(textElement1)

    // 创建一个HTML元素用于跳转产品详情页面
    let textElement2 = document.createElement('div')
    textElement2.className = 'productDetails'
    textElement2.style.position = 'absolute'
    textElement2.style.top = h * 0.6 + 240 + 'px'
    textElement2.style.left = w * 0.15 + 'px'
    textElement2.style.fontSize = '20px'

    document.body.appendChild(textElement2)

    // 底部产品导航
    let productsNav = document.createElement('div')
    productsNav.className = 'productsList'
    productsNav.style.position = 'absolute'
    productsNav.style.bottom = '30px'
    productsNav.style.width = '100%'
    productsNav.style.textAlign = 'center'
    document.body.appendChild(productsNav)


    let imgstr = ''
    for (let img in productsData) {
      imgstr += '<img src="' + productsData[img]['imgUrl'] + '" />'
    }
    productsNav.innerHTML = imgstr

    // 更新初始文字
    textElement.innerHTML = productsData[0]['name']
    textElement1.innerHTML = productsData[0]['parameter']
    textElement2.innerHTML = '<a href="' + productsData[0]['productLink'] + '">产品详情</a>'

    let productsListenList = document.querySelectorAll('.productsList img')
    for (let productIndex = 0; productIndex < productsListenList.length; productIndex++) {
      productsListenList[productIndex].addEventListener('click', function (e) {
        textElement.innerHTML = productsData[productIndex]['name']
        textElement1.innerHTML = productsData[productIndex]['parameter']
        textElement2.innerHTML = '<a href="' + productsData[0]['productLink'] + '">产品详情</a>'
        scene.remove(product)
        loadModel(productIndex)
        product = productsData[productIndex]['name']
      })
    }

    // 运动方式requestAnimationFrame,尽可能接近1/60秒的刷新频率
    function tick() {
      const time = clock.getElapsedTime()
      if (typeof (product) === 'objct') {
        product.rotation.z = time
      }
      if (typeof (product) != 'string' && isRotate === true) {
        product.children.forEach(kg => {
          totalX = time * 0.5
          kg.rotation.y = totalX
        })
      }

      renderer.render(scene, canema)
      requestAnimationFrame(tick)


    }
    // clock是threejs考虑刷新率之后进行优化的频率,优先考虑这种方式
    const clock = new THREE.Clock()
    tick()

  </script>
评论
头像
验证码:
相关推荐

threejs制作鼠标交互的网页banner

如何让男人感觉失去你了

对付男人冷落你方法10个




如果未经特殊说明,本站内容皆为原创,转载内容如果侵犯了您的权益,如有侵权请联系管理员删除
联系QQ:2380712278

备案号:皖ICP备19012824号