使用JS实现3D模型的旋转效果

580 阅读2分钟

一、效果图

先上效果图

GIF 2023-11-7 17-03-55.gif

二、前言

通过实现图片跟随鼠标的移动而旋转,使用JS实现3D模型的旋转效果。

**原理:**就是通过鼠标事件和鼠标定位,鼠标位置的不断改变,通过计算属性来不断地切换图片。

三、代码实现

1、编写一个容器包裹着图片,并给容器添加鼠标监听事件


<div @mousemove="onMouseMove" id="animationContainer" ref="container">
    <img :src="currentImageSrc" id="animatedImage" />
    <div class="imgName">{{ currentImageSrc }}</div>
  </div>
  

2、让容器全屏,并添加定位,让图片居中。

绝对定位,让图片在容器中居中对齐样式

position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

#animationContainer {

  width: 100vw;

  height: 100vh;

  background-color: #75aabb;

  position: relative;

  overflow: hidden;

  cursor: pointer;

}


#animatedImage {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

}

.imgName{

  position: absolute;

  top: 75%;

  left: 50%;

  transform: translate(-50%, -50%);

}

3、引入vue的ref和computed和定义参数

import { ref, computed } from 'vue'

const totalFrames = 360 //图片总数

const imagePrefix = '1_0' //图片的前缀名,完整的名称为1_0001.jpg  1_0025.jpg  1_0164.jpg

const imageExtension = '.jpg' //图片后缀名

const animationSpeed = 100 // 调整这个值以控制动画速度

const maxAngle = 30 // 最大角度(可根据需求调整)

  


const currentFrame = ref(1)

const mouseX = ref(0)

const containerWidth = ref(0)

let animationInterval

let container = ref()

let frameToShow = ref(1)

4、添加鼠标的监听事件

getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。

event.clientX 以浏览器窗口左上顶角为原点,定位 x 轴坐标。


// 监听鼠标位置变化

const onMouseMove = (event) => {

  const containerRect = container.value.getBoundingClientRect()

  mouseX.value = event.clientX - containerRect.left

  containerWidth.value = containerRect.width

}


5、通过计算属性,来显示要显示的图片

const mousePercentage = mouseX.value / containerWidth.value 计算出当前的x坐标占整个容器的份数。


**// 计算角度并显示对应的图片

const currentImageSrc = computed(() => {

  const mousePercentage = mouseX.value / containerWidth.value

  const angle = maxAngle * (2 * mousePercentage - 1)

  frameToShow.value = Math.floor(((angle / maxAngle + 1) * totalFrames) / 2) + 1

  let str = frameToShow.value.toString()

  if (str.length == 1) {

    frameToShow.value = `00${frameToShow.value}`

  } else if (str.length == 2) {

    frameToShow.value = `0${frameToShow.value}`

  }

  if (!frameToShow.value) {

    frameToShow.value = 1

    let url = `${imagePrefix}00${frameToShow.value}${imageExtension}`

    return new URL(`/src/components/canvas/${url}`, import.meta.url).href

  } else {

    let url = `${imagePrefix}${frameToShow.value}${imageExtension}`

    return new URL(`/src/components/canvas/${url}`, import.meta.url).href

  }

})
**

四、完整代码


<template>

  <div @mousemove="onMouseMove" id="animationContainer" ref="container">

    <img :src="currentImageSrc" id="animatedImage" />

    <div class="imgName">{{ currentImageSrc }}</div>

  </div>

</template>

<script setup>

import { ref, computed } from 'vue'

const totalFrames = 360 //图片总数

const imagePrefix = '1_0' //图片的前缀名,完整的名称为1_0001.jpg  1_0025.jpg  1_0164.jpg

const imageExtension = '.jpg'  //图片后缀名

const animationSpeed = 100 // 调整这个值以控制动画速度

const maxAngle = 30 // 最大角度(可根据需求调整)

  


const currentFrame = ref(1)

const mouseX = ref(0)

const containerWidth = ref(0)

let animationInterval

let container = ref()

let frameToShow = ref(1)

// 监听鼠标位置变化

const onMouseMove = (event) => {

  const containerRect = container.value.getBoundingClientRect()

  mouseX.value = event.clientX - containerRect.left

  containerWidth.value = containerRect.width

}

// 计算角度并显示对应的图片

// 通过容器的大小和鼠标的x坐标来实现图片的监听

const currentImageSrc = computed(() => {

  const mousePercentage = mouseX.value / containerWidth.value

  const angle = maxAngle * (2 * mousePercentage - 1)

  frameToShow.value = Math.floor(((angle / maxAngle + 1) * totalFrames) / 2) + 1

  let str = frameToShow.value.toString()

  if (str.length == 1) {

    frameToShow.value = `00${frameToShow.value}`

  } else if (str.length == 2) {

    frameToShow.value = `0${frameToShow.value}`

  }

  if (!frameToShow.value) {

    frameToShow.value = 1

    let url = `${imagePrefix}00${frameToShow.value}${imageExtension}`

    return new URL(`/src/components/canvas/${url}`, import.meta.url).href

  } else {

    console.log(frameToShow.value)

    let url = `${imagePrefix}${frameToShow.value}${imageExtension}`


    return new URL(`/src/components/canvas/${url}`, import.meta.url).href

  }

})

</script>

<style>

#animationContainer {

  width: 100vw;

  height: 100vh;

  background-color: #75aabb;

  position: relative;

  overflow: hidden;

  cursor: pointer;

}

#animatedImage {

  position: absolute;

  top: 50%;

  left: 50%;

  transform: translate(-50%, -50%);

}

.imgName{

  position: absolute;

  top: 75%;

  left: 50%;

  transform: translate(-50%, -50%);

}

</style>