js实现3d拖拽环绕旋转

js实现拖动节点围绕圆心转动在这里插入图片描述

1.使用transform属性,将圆环放倒展示为椭圆

圆环上有不同的色彩,在转动的同时,需要让圆环也转动,所以圆环不能是椭圆,而是圆形,这样在转动的时候,改变rotate,可以让圆环绕中间转动

<div class="home-cirque-hidden">
      <div class="home-cirque-div" :style="`transform: rotateX(76deg) rotateZ(${theta * -1}deg);`"></div>
 </div>
 .home-cirque{
    width: 1560px;
    height: 1560px;
    position: absolute;
    left: 55px;
    top: -773px;
    transform-style: preserve-3d;
    perspective: 3000px;
  }
  .home-cirque-div{
    width: 1560px;
    height: 1560px;
    position: absolute;
    left: 0;
    top: -638px;
    background: url('../assets/home/circle1.png') no-repeat center;
    background-size: contain;
  }
  .home-cirque-hidden{
    width: 1560px;
    height: 371px;
    position: absolute;
    left: 0;
    top: 629px;
    overflow: hidden;
    transform-style: preserve-3d;
    perspective: 3000px;
  }

2.将12个节点绘制上去,并且进行旋转

12个节点的圆心设置到外部,在转动的时候可以围绕一个圆心点转动,形成3d旋转,但是点位不能旋转,所以在旋转的同时,需要让点位自转,抵消掉父元素围绕圆心的转动

<div class="home-ellipse" @mousedown="turnDown" @mousemove="turnMove">
   <div :style="`transform: translateZ(800px) rotateY(${theta + item.num}deg);`" :class="`home-dot home-dot${item.index}`" v-for="item in dotList" :key="item.index">
       <div class="home-dot-line" :style="`transform: rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);height:${scaleFun(item)==1.3?93:64}px;`"></div>
       <div :style="`transform: rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);`" class="home-dot-box"><div></div></div>
       <div :style="`transform:translateZ(1px) translateX(-50%) rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);`" :class="`home-list home-list${item.index}`">
           <div :style="`transform: translateX(-50%) translateY(${scaleFun(item)==1.3?-50:0}%);`" :class="scaleFun(item)==1.3?'home-list-active':'home-list-bg'">
              {{ item.title }}
           </div>
       </div>
    </div>
</div>
.home-ellipse{
    width: 280px;
    height: 400px;
    position: absolute;
    left: 697px;
    top: -192px;
    transform-style: preserve-3d;
    transform: rotateX(-13deg) rotateY(0deg);
    perspective: 7000px;
  }
 .home-dot{
    width: 100%;
    height: 100%;
    position: absolute;
    transform-origin: center center -750px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    z-index: 100;
    transform-style: preserve-3d;
    perspective: 10000px;
  }
  .home-dot-box{
    width: 52px;
    height: 52px;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    z-index: 1;
    background: url('../assets/home/dot.png') no-repeat center;
    background-size: contain;
  }
  .home-dot-line{
    width: 1px;
    height: 64px;
    position: absolute;
    left: 0;
    right: 0;
    margin: 0 auto;
    bottom: 56%;
    background: url('../assets/home/dot-line.png') no-repeat center top;
    background-size: cover;
  }
  .home-list{
    position: absolute;
    width: 199px;
    height: 98px;
    left: 50%;
    top: calc(50% - 170px);
    z-index: 2;
    transform: translateX(-50%);
  }
  .home-list div{
    position: absolute;
    left: 50%;
    top: 0;
    z-index: 2;
    text-align: center;
    text-wrap: balance;
    transition: transform 0.3s;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .home-list-bg{
    font-size: 16px;
    width: 229px;
    height: 98px;
    padding: 20px 20px;
    background: url('../assets/home/list-bg.png') no-repeat center;
    background-size: 100%;
  }
  .home-list-active{
    width: 405px;
    height: 197px;
    font-size: 22px;
    line-height: 26px;
    padding: 47px 61px;
    font-weight: bold;
    background: url('../assets/home/list-active.png') no-repeat center;
    background-size: 100%;
  }

3.全部源码

<style scoped>

  .home{
    width: 100%;
    height: 100%;
    position: relative;
    overflow: hidden;
    background-color: #0a4662;
    color: #fff;
  }
  .home-content{
    width: 1623px;
    height: 683px;
    position: absolute;
    bottom: -79px;
    left: 204px;
  }
  
  .home-ellipse{
    width: 280px;
    height: 400px;
    position: absolute;
    left: 697px;
    top: -192px;
    transform-style: preserve-3d;
    transform: rotateX(-13deg) rotateY(0deg);
    perspective: 7000px;
  }
  .home-cirque{
    width: 1560px;
    height: 1560px;
    position: absolute;
    left: 55px;
    top: -773px;
    transform-style: preserve-3d;
    perspective: 3000px;
  }
  .home-cirque-div{
    width: 1560px;
    height: 1560px;
    position: absolute;
    left: 0;
    top: -638px;
    background: url('../assets/home/circle1.png') no-repeat center;
    background-size: contain;
  }
  .home-cirque-hidden{
    width: 1560px;
    height: 371px;
    position: absolute;
    left: 0;
    top: 629px;
    overflow: hidden;
    transform-style: preserve-3d;
    perspective: 3000px;
  }
  .home-dot{
    width: 100%;
    height: 100%;
    position: absolute;
    transform-origin: center center -750px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    z-index: 100;
    transform-style: preserve-3d;
    perspective: 10000px;
  }
  .home-dot-box{
    width: 52px;
    height: 52px;
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    z-index: 1;
    background: url('../assets/home/dot.png') no-repeat center;
    background-size: contain;
  }
  .home-dot-line{
    width: 1px;
    height: 64px;
    position: absolute;
    left: 0;
    right: 0;
    margin: 0 auto;
    bottom: 56%;
    background: url('../assets/home/dot-line.png') no-repeat center top;
    background-size: cover;
  }
  .home-list{
    position: absolute;
    width: 199px;
    height: 98px;
    left: 50%;
    top: calc(50% - 170px);
    z-index: 2;
    transform: translateX(-50%);
  }
  .home-list div{
    position: absolute;
    left: 50%;
    top: 0;
    z-index: 2;
    text-align: center;
    text-wrap: balance;
    transition: transform 0.3s;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .home-list-bg{
    font-size: 16px;
    width: 229px;
    height: 98px;
    padding: 20px 20px;
    background: url('../assets/home/list-bg.png') no-repeat center;
    background-size: 100%;
  }
  .home-list-active{
    width: 405px;
    height: 197px;
    font-size: 22px;
    line-height: 26px;
    padding: 47px 61px;
    font-weight: bold;
    background: url('../assets/home/list-active.png') no-repeat center;
    background-size: 100%;
  }
  .home-line{
    width: 1500px;
    height: 1500px;
    position: absolute;
    left: 77px;
    top: -700px;
    transform-style: preserve-3d;
    perspective: 5000px;
    transform: rotateX(-12.7deg);
  }
  .home-line-box{
    width: 1600px;
    height: 393px;
    position: absolute;
    left: 0;
    top: 597px;
    overflow: hidden;
    background: url('../assets/home/line-1.png') no-repeat center;
    background-size: contain;
  }
  .home-point{
    width: 7px;
    height: 7px;
    position: absolute;
    transform-origin: center center -750px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    background-color: rgba(255, 255, 255, 0.4);
    border-radius: 500%;
  }
  .home-title{
    position: absolute;
    height: 13px;
    transform-origin: center center -750px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    transform-style: preserve-3d;
    perspective: 500px;
  }
  .home-title div{
    position: absolute;
    width: 93px;
    height: 13px;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    margin: auto;
    font-size: 12px;

  }
</style>
<template>
  <div class="home" @mouseup="turnUp">
    <div class="home-content">
      <div class="home-light"></div>
      <div class="home-line">
        <div class="home-line-box"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + (-13.7)}deg);`"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + 115}deg);`"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + 147}deg);`"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + 241.7}deg);`"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + 284.5}deg);`"></div>
        <div class="home-point" :style="`transform: translateZ(790px) rotateY(${theta + 322.6}deg);`"></div>
        <div class="home-title home-title1" :style="`transform: translateY(-2px) translateZ(810px) rotateY(${theta + 49}deg) scale(1)`"><div :style="`transform: rotateY(${titleComput(49,'+')}deg);`">测试环绕文字1</div></div>
        <div class="home-title home-title3" :style="`transform: translateY(-2px) translateZ(810px) rotateY(${theta + 137.1}deg) scale(1);`"><div :style="`transform: rotateY(${titleComput(137.1,'+')}deg);`">测试环绕文字2</div></div>
        <div class="home-title home-title6" :style="`transform: translateY(-2px) translateZ(810px) rotateY(${theta + 307.5}deg) scale(1);`"><div :style="`transform: rotateY(${titleComput(307.5,'+')}deg);`">测试环绕文字4</div></div>
        <div class="home-title home-title7" :style="`transform: translateY(-2px) translateZ(810px) rotateY(${theta + 338}deg) scale(1);`"><div :style="`transform: rotateY(${titleComput(338,'+')}deg);`">测试环绕文字5</div></div>
        <div class="home-title home-title8" :style="`transform: translateY(-2px) translateZ(810px) rotateY(${theta + 272}deg) scale(1);`"><div :style="`transform: rotateY(${titleComput(272,'+')}deg);`">测试环绕文字3</div></div>
        
      </div>
      <div class="home-cirque">
        <div class="home-cirque-hidden">
          <div class="home-cirque-div" :style="`transform: rotateX(76deg) rotateZ(${theta * -1}deg);`"></div>
        </div>
      </div>
      <div class="home-ellipse" @mousedown="turnDown" @mousemove="turnMove">
        <div :style="`transform: translateZ(800px) rotateY(${theta + item.num}deg);`" :class="`home-dot home-dot${item.index}`" v-for="item in dotList" :key="item.index">
          <div class="home-dot-line" :style="`transform: rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);height:${scaleFun(item)==1.3?93:64}px;`"></div>
          <div :style="`transform: rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);`" class="home-dot-box"></div>
          <div :style="`transform:translateZ(1px) translateX(-50%) rotateY(${item.index==10?(theta*-1):rotateYfun(item.num)}deg);`" :class="`home-list home-list${item.index}`">
            <div :style="`transform: translateX(-50%) translateY(${scaleFun(item)==1.3?-50:0}%);`" :class="scaleFun(item)==1.3?'home-list-active':'home-list-bg'">
              {{ item.title }}
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
export default{
  data(){
    return{
      isdown:false,
      startX:0,
      startY:0,
      upspin:0,
      theta:-0.5,  //一版本每个点位角度32.7  现在是27.8
      dotList:[
        { index:10, num:0,title:'点位文字1'},
        { index:11, num:32.7,title:'点位文字2'},
        { index:1, num:65.4,title:'点位文字3'},
        { index:2, num:98.1,title:'点位文字4'},
        { index:3, num:130.8,title:'点位文字5'},
        { index:4, num:163.5,title:'点位文字6'},
        { index:5, num:196.2,title:'点位文字7'},
        { index:6, num:228.9,title:'点位文字8'},
        { index:7, num:261.6,title:'点位文字9'},
        { index:8, num:294.3,title:'点位文字10'},
        { index:9, num:327,title:'点位文字11'},
      ],
      isItem:{}
    }
  },
  mounted(){
    
    
  },
  methods:{
    titleComput(data,symbol){
      if(symbol=='-'){
        return ((Math.abs(this.theta - data) % 360>100)&&(Math.abs(this.theta - data) % 360<300)?180:0)
      }else{
        return ((Math.abs(this.theta + data) % 360>100)&&(Math.abs(this.theta + data) % 360<300)?180:0)
      }
    },
    rotateYfun(data){
      return (this.theta + data)<=0?Math.abs(this.theta + data):(-1 * Math.abs(this.theta + data))
    },
    scaleFun(data){
      if((Math.abs(this.theta + data.num)%360)<=10||(Math.abs(this.theta + data.num)%360)>=350){
        this.isItem = data.num
      }
      return (Math.abs(this.theta + data.num)%360)<=7||(Math.abs(this.theta + data.num)%360)>=353?1.3:1
    },
    turnDown(e){
      this.isdown = true
      this.startX = e.clientX
      this.startY = e.clientY
    },
    async turnMove(e){
      if(this.isdown){
        this.theta = (this.upspin + (e.clientX - this.startX) / 10) % 360
      }
    },
    turnUp(){
      this.isdown = false
      this.upspin = this.theta
      // 计算
      if((Math.abs(this.theta + this.isItem)%360)<=7||(Math.abs(this.theta + this.isItem)%360)>=353){
        this.theta = 0-this.isItem
        this.upspin = this.theta
      }
    }
  }
}
</script>

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现3D球状拖动旋转效果可以使用Three.js库来创建一个3D场景。下面是一个简单的示例代码,可以将其用作起点: ```javascript // 创建场景 var scene = new THREE.Scene(); // 创建相机 var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); camera.position.z = 5; // 创建渲染器 var renderer = new THREE.WebGLRenderer(); renderer.setSize( window.innerWidth, window.innerHeight ); document.body.appendChild( renderer.domElement ); // 创建球体 var geometry = new THREE.SphereGeometry( 2, 32, 32 ); var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); var sphere = new THREE.Mesh( geometry, material ); scene.add( sphere ); // 添加鼠标拖动控制 var controls = new THREE.OrbitControls( camera, renderer.domElement ); controls.enableDamping = true; controls.dampingFactor = 0.25; controls.enableZoom = false; // 渲染场景 function render() { requestAnimationFrame( render ); renderer.render( scene, camera ); } render(); ``` 上述代码创建了一个简单的场景,其中包含一个白色的球体,并使用OrbitControls库添加了鼠标拖动控制。你可以通过拖动鼠标左键或右键来旋转球体。 如果你想要在球体上添加纹理或其他材质,可以创建一个THREE.TextureLoader对象,加载一个纹理图像,并将其传递给MeshBasicMaterial。例如: ```javascript var texture = new THREE.TextureLoader().load( 'texture.jpg' ); var material = new THREE.MeshBasicMaterial( { map: texture } ); ``` 你可以自己尝试更改代码来实现你想要的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值