js实现3d拖拽环绕旋转

news2024/9/19 10:45:12

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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2080864.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cypress第二次安装遇到的问题

问题一&#xff1a;吐血&#xff0c;谁会想到node.js的官网访问不了呢&#xff01; 中文网站&#xff1a;http://url.nodejs.cn/download/ 官网&#xff1a;https://nodejs.org/zh-cn nodejs安装的两种方法(官网、NVM安装-node版本切换)不知道这种方式是否可行&#xff0c;还…

Android UI绘制原理:UI的绘制流程是怎么样呢?为什么子线程不能刷新UI呢?讲解大体的流程是怎么样的

目录&#xff1a; 为什么子线程不能刷新UI呢&#xff0c;原因是什么&#xff1f;UI绘制原理 2.1 创建Activity 实例和view的树型结构 2.2 管理绘制的类&#xff1a;ViewRootImpl 2.3 是如何触发刷新View的&#xff1f; 2.4 View的绘制流程&#xff1a;测量(Measure) 2.5 View的…

1998-2023年上市公司研发投入数据

1998-2023年上市公司研发投入数据 1、时间&#xff1a;1998-2023年 2、来源&#xff1a;上市公司年报 3、指标&#xff1a;证券代码、统计截止日期、数据来源、报表类型、研发人员数量&#xff08;人&#xff09;、研发人员数量占比(%)、研发投入金额&#xff08;元&#xf…

MyBatis一级缓存和二级缓存以及 mybatis架构

缓存 数据缓存&#xff0c;让数据离我们执行的程序更近一点&#xff0c;让程序能够快速的获取到数据 缓存的作用就是减轻数据库的压力&#xff0c;提高查询性能。缓存实现的原理是从数据库中查询出来的对象在使用完后不要销毁&#xff0c;而是存储在内内&#xff08;缓存&…

亚马逊无货源店群模式是什么?2024年还能做吗?

相信众多的电商卖家&#xff0c;对店群模式并不陌生。近年来国内电商的店群模式竞争激烈&#xff0c;近乎饱和。那么&#xff0c;在国际知名的跨境电商平台亚马逊上&#xff0c;店群模式又是如何运作呢&#xff1f;到了2024年&#xff0c;亚马逊的店群模式还值得做吗&#xff1…

EAST文本检测

原文:EAST文本检测 - 知乎 (zhihu.com) 一、文本检测 论文: https://arxiv.org/pdf/1704.03155.pdf​arxiv.org/pdf/1704.03155.pdf 一般的文本检测模型会分多个阶段(multi-stage)进行,在训练时需要把文本检测切割成多个阶段(stage)来进行学习,这种把完整文本行先分…

表达式求值问题的实现

这是C算法基础-数据结构专栏的第二十二篇文章&#xff0c;专栏详情请见此处。 引入 相信大家都会做如1(23)*4/5-6这样的算式&#xff0c;而我们今天要学习让计算机通过表达式求它的值&#xff0c;这就是表达式求值问题。 下面我们就来讲表达式求值问题的实现。 定义 表达式求值…

mysql的聚簇索引、非聚簇索引、回表

1.聚簇索引和非聚簇索引 聚簇索引&#xff08;聚集索引&#xff09;&#xff1a;数据和索引放在一起&#xff0c;B树的叶子节点存放了整行数据&#xff0c;有且只有一个。 【主键索引和唯一索引&#xff0c;主键唯一&#xff0c;存放的是主键对应的整行数据】非聚簇索引&#…

[CR]厚云填补_Diffusion Enhancement for CR

Diffusion Enhancement for Cloud Removal in Ultra-Resolution Remote Sensing Imagery Abstract 云层的存在严重影响了光学遥感图像的质量和有效性。然而&#xff0c;现有的基于深度学习(DL)的云移除(CR)技术&#xff0c;通常以保真度驱动的损失作为约束&#xff0c;例如L1或…

USB3.2 摘录(11)

系列文章目录 USB3.2 摘录&#xff08;一&#xff09; USB3.2 摘录&#xff08;二&#xff09; USB3.2 摘录&#xff08;三&#xff09; USB3.2 摘录&#xff08;四&#xff09; USB3.2 摘录&#xff08;五&#xff09; USB3.2 摘录&#xff08;六&#xff09; USB3.2 摘录&…

OpenAI神秘“草莓”项目 计划最早今年秋季推出

据科技媒体The Information报道&#xff0c;OpenAI神秘“草莓”项目&#xff0c;计划最早今年秋季推出&#xff01;上个月&#xff0c;OpenAI的内部团队被曝出正开发的“草莓”&#xff08;Strawberry&#xff09;项目&#xff0c;目的是增强OpenAI的模型的推理能力&#xff0c…

大模型从入门到精通—— LLM 应用评估(一)

如何评估 LLM 应用 1. 简介 在使用大型语言模型&#xff08;LLM&#xff09;构建应用程序时&#xff0c;评估的思路往往与传统的 AI 开发有所不同。传统 AI 的评估可能依赖于大规模的标注数据集和精细的性能指标&#xff0c;而 LLM 的开发则更注重迭代验证&#xff0c;并在开发…

python从入门到精通:异常操作、模块操作及包操作

目录 1、异常概念 2、异常的捕获方法 3、异常的传递 4、python模块 4.1、模块的导入 4.2、自定义模块 5、python包 5.1、自定义python包 5.2、安装第三方包 1、异常概念 当检测到一个错误时&#xff0c;python解释器会无法执行&#xff0c;反而出现一些错误的提示&a…

视频中间件:大华视频设备接入管理应用

前言 上篇博文介绍了视频中间件&#xff1a;海康视频设备的接入管理&#xff1f;&#xff0c;今天给大家带来大华视频设备的接入管理&#xff0c;视频中间件平台支持大华Sdk、大华主动注册、Onvif、Rtsp、Gb28181等方式对大华视频设备的接入管理。同时视频中间件可支持协议互转…

离子交换技术在含银废水处理中的创新应用

随着科技的不断进步&#xff0c;金属制品在各行各业中扮演着越来越重要的角色。其中&#xff0c;镀银工艺作为一种提高金属制品性能的重要手段&#xff0c;其环境影响也日益受到关注。镀银过程中产生的含银废水含有多种有害物质&#xff0c;对环境构成潜在风险。因此&#xff0…

百度:未来or现在 顾此失彼?

用AI押注未来&#xff0c;却丢了现在 国内AI先行者百度 走到哪了&#xff1f; 作为这个星球最热门的概念&#xff0c;AI无疑是个好故事&#xff0c;不只是百度&#xff0c;美股的一众科技公司几乎都在讲述自己的AI投入及发展成果&#xff0c;市值也随着AI预期坐过山车。而市场…

Datawhale AI夏令营第五期CV方向-城市管理违规行为智能识别-Task1

赛题解析 城市管理违规行为智能识别 初赛任务是根据给定的城管视频监控数据集&#xff0c;进行城市违规行为的检测。违规行为主要包括垃圾桶满溢、机动车违停、非机动车违停等。 选手需要能够从视频中分析并标记出违规行为&#xff0c;提供违规行为发生的时间和位置信息。 数…

ArkTS--状态管理

一、概述 在声明式UI编程范式中&#xff0c;UI是应用程序状态的函数&#xff0c;应用程序状态的修改会更新相应的UI界面。ArkUI采用了MVVM模式&#xff0c;其中ViewModel将数据与视图绑定在一起&#xff0c;更新数据的时候直接更新视图。如下图所示&#xff1a; ArkUI提供了一系…

Day49 | 53. 寻宝 prim算法 与kruskal算法

语言 Java 53. 寻宝 53. 寻宝&#xff08;第七期模拟笔试&#xff09; 题目 题目描述 在世界的某个区域&#xff0c;有一些分散的神秘岛屿&#xff0c;每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路&#xff0c;方便运输。 不同岛屿之间&#xff0c…

【MATLAB学习笔记】绘图——自定义标记(Marker)形状,实现与MATLAB自带标记基本一致的功能(自适应缩放、自适应裁剪)

目录 前言自定义标记函数自定义标记函数的说明纵横比调整将图形大小按磅数设置平移标记点绘制标记点边界标记点不裁剪 拓展功能——标记点自适应绘图区的缩放绘图区缩放回调函数标记点大小自适应标记点裁剪自适应 示例基本绘图自定义标记函数的使用 总代码主函数自定义标记函数…