• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Three.js--》实现3d地球模型展示

武飞扬头像
亦世凡华、
帮助1

目录

项目搭建

实现网页简单布局

初始化three.js基础代码

创建环境背景

加载地球模型

实现光柱效果

添加月球模型


今天简单实现一个three.js的小Demo,加强自己对three知识的掌握与学习,只有在项目中才能灵活将所学知识运用起来,话不多说直接开始。

项目搭建

本案例还是借助框架书写three项目,借用vite构建工具搭建vue项目,vite这个构建工具如果有不了解的朋友,可以参考我之前对其讲解的文章:vite脚手架的搭建与使用 。搭建完成之后,用编辑器打开该项目,在终端执行 npm i 安装一下依赖,安装完成之后终端在安装 npm i three 即可。

因为我搭建的是vue3项目,为了便于代码的可读性,所以我将three.js代码单独抽离放在一个组件当中,在App根组件中进入引入该组件。具体如下:

  1.  
    <template>
  2.  
    <!-- 3D地球 -->
  3.  
    <CoolEarth></CoolEarth>
  4.  
    </template>
  5.  
     
  6.  
    <script setup>
  7.  
    import CoolEarth from './components/CoolEarth.vue';
  8.  
    </script>
  9.  
     
  10.  
    <style lang="less">
  11.  
    *{
  12.  
    margin: 0;
  13.  
    padding: 0;
  14.  
    }
  15.  
    </style>
学新通

实现网页简单布局

在HTML布局处进行设置一个loading效果,并通过一个loading.glf动态图使loading效果更加具体,相关代码样式如下:

  1.  
    <template>
  2.  
    <div class="home">
  3.  
    <div class="canvas-container" ref="screenDom"></div>
  4.  
    <div class="loading" v-if="progress != 100"></div>
  5.  
    <div class="progress" v-if="progress != 100">
  6.  
    <img src="../assets/loading.gif" alt="" />
  7.  
    <span>地球加载中:{{ progress }}%</span>
  8.  
    </div>
  9.  
    <div class="title">酷炫3D地球</div>
  10.  
    </div>
  11.  
    </template>
  12.  
     
  13.  
    <style>
  14.  
    body {
  15.  
    background-color: #000;
  16.  
    }
  17.  
    .canvas-container {
  18.  
    width: 100vw;
  19.  
    height: 100vh;
  20.  
    }
  21.  
    .home {
  22.  
    width: 100vw;
  23.  
    height: 100vh;
  24.  
    transform-origin: 0 0;
  25.  
    }
  26.  
    .loading {
  27.  
    position: fixed;
  28.  
    top: 0;
  29.  
    left: 0;
  30.  
    width: 1920px;
  31.  
    height: 1080px;
  32.  
    background-image: url(../assets/loading.jpg);
  33.  
    background-size: cover;
  34.  
    filter: blur(50px);
  35.  
    z-index: 100;
  36.  
    }
  37.  
    .progress {
  38.  
    position: fixed;
  39.  
    top: 0;
  40.  
    left: 0;
  41.  
    width: 1920px;
  42.  
    height: 1080px;
  43.  
    z-index: 101;
  44.  
    display: flex;
  45.  
    justify-content: center;
  46.  
    align-items: center;
  47.  
    font-size: 20px;
  48.  
    color: #fff;
  49.  
    }
  50.  
    .progress > img {
  51.  
    padding: 0 15px;
  52.  
    }
  53.  
     
  54.  
    .title {
  55.  
    width: 380px;
  56.  
    height: 40px;
  57.  
    position: fixed;
  58.  
    right: 100px;
  59.  
    top: 50px;
  60.  
    background-color: rgba(0, 0, 0, 0.5);
  61.  
    line-height: 40px;
  62.  
    text-align: center;
  63.  
    color: #fff;
  64.  
    border-radius: 5px;
  65.  
    z-index: 110;
  66.  
    }
  67.  
    </style>
学新通

初始化three.js基础代码

three.js开启必须用到的基础代码如下:

导入three库

import * as THREE from 'three'

初始化场景

const scene = new THREE.Scene()

初始化相机

  1.  
    const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
  2.  
    camera.position.set(0,50,300)

初始化渲染器

  1.  
    const renderer = new THREE.WebGLRenderer({ antialias: true })
  2.  
    renderer.setSize(window.innerWidth,window.innerHeight)

监听屏幕大小的改变,修改渲染器的宽高和相机的比例

  1.  
    window.addEventListener("resize",()=>{
  2.  
    renderer.setSize(window.innerWidth,window.innerHeight)
  3.  
    camera.aspect = window.innerWidth/window.innerHeight
  4.  
    camera.updateProjectionMatrix()
  5.  
    })

设置渲染函数

  1.  
    const render = () =>{
  2.  
    controls.update();
  3.  
    requestAnimationFrame(render);
  4.  
    renderer.render(scene, camera);
  5.  
    }

进行挂载

  1.  
    onMounted(()=>{
  2.  
    // 设置进度
  3.  
    THREE.DefaultLoadingManager.onProgress = function (item, loaded, total) {
  4.  
    progress.value = new Number((loaded / total) * 100).toFixed(2);
  5.  
    };
  6.  
    // 将画布添加到页面中
  7.  
    screenDom.value.appendChild(renderer.domElement)
  8.  
    render()
  9.  
    })

ok,写完基础代码之后,接下来开始具体的Demo实操。

创建环境背景

这里通过TextureLoader加载各种类型的纹理图像,包括JPEG、PNG、GIF等。通过TextureLoader,开发人员可以轻松地将纹理加载到自己的Three.js场景中,从而为场景增加更多的细节和视觉效果。

  1.  
    // 创建星空的背景颜色
  2.  
    scene.background = new THREE.Color(0x030311);
  3.  
    // 加载点材质纹理
  4.  
    const starsTexture = new THREE.TextureLoader().load("./images/stars.png");
  5.  
    const starsMaterial = new THREE.PointsMaterial({
  6.  
    size: 2,
  7.  
    sizeAttenuation: true, // 尺寸衰减
  8.  
    color: 0x4d76cf,
  9.  
    transparent: true,
  10.  
    opacity: 1,
  11.  
    map: starsTexture,
  12.  
    });

接下来通过点材质创建星空效果,setAttribute方法可以用于向这些BufferAttribute对象中设置顶点属性数据,BufferAttribute是在Three.js等WebGL引擎中用于描述几何体或粒子的渲染数据结构,也是WebGL中顶点缓存对象(VBO)中存储顶点数据的方式之一:

  1.  
    // 使用点材质创建星空效果
  2.  
    const vertices = [];
  3.  
    for (let i = 0; i < 500; i ) {
  4.  
    const vertex = new THREE.Vector3();
  5.  
    vertex.x = 800 * Math.random() - 400;
  6.  
    vertex.y = 800 * Math.random() - 400;
  7.  
    vertex.z = 800 * Math.random() - 400;
  8.  
    vertices.push(vertex.x, vertex.y, vertex.z);
  9.  
    }
  10.  
     
  11.  
    // 星空效果
  12.  
    let starsGeometry = new THREE.BufferGeometry();
  13.  
    starsGeometry.setAttribute(
  14.  
    "position",
  15.  
    new THREE.BufferAttribute(new Float32Array(vertices), 3)
  16.  
    );
  17.  
    let stars = new THREE.Points(starsGeometry, starsMaterial);
  18.  
    scene.add(stars);
学新通

学新通

加载地球模型

接下来依然通过TextureLoader加载各种类型的纹理图像:

  1.  
    // 创建地球
  2.  
    let earthGeometry = new THREE.SphereGeometry(50, 32, 32);
  3.  
    let earthTexture = new THREE.TextureLoader().load("./images/map.jpg");
  4.  
    let earthMaterial = new THREE.MeshBasicMaterial({
  5.  
    map: earthTexture,
  6.  
    });
  7.  
    let earth = new THREE.Mesh(earthGeometry, earthMaterial);
  8.  
    scene.add(earth);

学新通

接下来在原有地球的基础上再加一层发光球体的壳,使地球更具有美感:

  1.  
    // 发光地球
  2.  
    let lightTexture = new THREE.TextureLoader().load("./images/earth.jpg");
  3.  
    let lightEarthGeometry = new THREE.SphereGeometry(53, 32, 32);
  4.  
    let lightEarthMaterial = new THREE.MeshBasicMaterial({
  5.  
    map: lightTexture,
  6.  
    alphaMap: lightTexture,
  7.  
    blending: THREE.AdditiveBlending,
  8.  
    transparent: true,
  9.  
    });
  10.  
    let lightEarth = new THREE.Mesh(lightEarthGeometry, lightEarthMaterial);
  11.  
    scene.add(lightEarth);

学新通

接下来通过 Sprite 将Sprite 对象图像资源打包在一张贴图上,然后在需要渲染Sprite 的时候使用不同的纹理坐标选取对应的图像片段进行绘制。

  1.  
    // 添加地球内外发光精灵
  2.  
    let spriteTexture = new THREE.TextureLoader().load("./images/glow.png");
  3.  
    let spriteMaterial = new THREE.SpriteMaterial({
  4.  
    map: spriteTexture,
  5.  
    color: 0x4d76cf,
  6.  
    transparent: true,
  7.  
    depthWrite: false,
  8.  
    depthTest: false,
  9.  
    blending: THREE.AdditiveBlending,
  10.  
    });
  11.  
    let sprite = new THREE.Sprite(spriteMaterial);
  12.  
    sprite.scale.set(155, 155, 0);
  13.  
    scene.add(sprite);

学新通

接下来接着使用该函数使其内发光:

  1.  
    // 内发光
  2.  
    let spriteTexture1 = new THREE.TextureLoader().load("./images/innerGlow.png");
  3.  
    let spriteMaterial1 = new THREE.SpriteMaterial({
  4.  
    map: spriteTexture1,
  5.  
    color: 0x4d76cf,
  6.  
    transparent: true,
  7.  
    depthWrite: false,
  8.  
    depthTest: false,
  9.  
    blending: THREE.AdditiveBlending,
  10.  
    });
  11.  
    let sprite1 = new THREE.Sprite(spriteMaterial1);
  12.  
    sprite1.scale.set(128, 128, 0);
  13.  
    scene.add(sprite1);
  14.  
    let scale = new THREE.Vector3(1, 1, 1);

学新通

实现光柱效果

通过for循环实现30个光柱效果的展示,这里依然通过TextureLoader加载各种类型的纹理图像:

  1.  
    for (let i = 0; i < 30; i ) {
  2.  
    // 实现光柱
  3.  
    let lightPillarTexture = new THREE.TextureLoader().load(
  4.  
    "./images/light_column.png"
  5.  
    );
  6.  
    let lightPillarGeometry = new THREE.PlaneGeometry(3, 20);
  7.  
    let lightPillarMaterial = new THREE.MeshBasicMaterial({
  8.  
    color: 0xffffff,
  9.  
    map: lightPillarTexture,
  10.  
    alphaMap: lightPillarTexture,
  11.  
    transparent: true,
  12.  
    blending: THREE.AdditiveBlending,
  13.  
    side: THREE.DoubleSide,
  14.  
    depthWrite: false,
  15.  
    });
  16.  
    let lightPillar = new THREE.Mesh(lightPillarGeometry, lightPillarMaterial);
  17.  
    lightPillar.add(lightPillar.clone().rotateY(Math.PI / 2));
  18.  
     
  19.  
    // 设置光柱的位置
  20.  
    let lat = Math.random() * 180 - 90;
  21.  
    let lon = Math.random() * 360 - 180;
  22.  
    let position = lon2xyz(60, lon, lat);
  23.  
    lightPillar.position.set(position.x, position.y, position.z);
  24.  
     
  25.  
    lightPillar.quaternion.setFromUnitVectors(
  26.  
    new THREE.Vector3(0, 1, 0),
  27.  
    position.clone().normalize()
  28.  
    );
  29.  
    scene.add(lightPillar);
  30.  
    }
学新通

学新通

接下来利用贴图给地球的每个光柱添加光圈效果,这里利用gsap动画库实现:

  1.  
    // 创建波纹扩散效果
  2.  
    let circlePlane = new THREE.PlaneGeometry(6, 6);
  3.  
    let circleTexture = new THREE.TextureLoader().load("./images/label.png");
  4.  
    let circleMaterial = new THREE.MeshBasicMaterial({
  5.  
    color: 0xffffff,
  6.  
    map: circleTexture,
  7.  
    transparent: true,
  8.  
    blending: THREE.AdditiveBlending,
  9.  
    depthWrite: false,
  10.  
    side: THREE.DoubleSide,
  11.  
    });
  12.  
    let circleMesh = new THREE.Mesh(circlePlane, circleMaterial);
  13.  
    circleMesh.rotation.x = -Math.PI / 2;
  14.  
    circleMesh.position.set(0, -7, 0);
  15.  
     
  16.  
    lightPillar.add(circleMesh);
  17.  
     
  18.  
    gsap.to(circleMesh.scale, {
  19.  
    duration: 1 Math.random() * 0.5,
  20.  
    x: 2,
  21.  
    y: 2,
  22.  
    z: 2,
  23.  
    repeat: -1,
  24.  
    delay: Math.random() * 0.5,
  25.  
    yoyo: true,
  26.  
    ease: "power2.inOut",
  27.  
    });
学新通

学新通

添加月球模型

接下来依然通过TextureLoader加载各种类型的纹理图像:

  1.  
    // 绕地球运行的月球
  2.  
    let moonTexture = new THREE.TextureLoader().load("./images/moon.jpg");
  3.  
    let moonMaterial = new THREE.MeshStandardMaterial({
  4.  
    map: moonTexture,
  5.  
    emissive: 0xffffff,
  6.  
    emissiveMap: moonTexture,
  7.  
    });
  8.  
    let moonGeometry = new THREE.SphereGeometry(5, 32, 32);
  9.  
    let moon = new THREE.Mesh(moonGeometry, moonMaterial);
  10.  
    moon.position.set(150, 0, 0);
  11.  
    scene.add(moon);

学新通

接下来实现月球环模型:

  1.  
    // 创建月球环
  2.  
    let moonRingTexture = new THREE.TextureLoader().load("./images/moon_ring.png");
  3.  
    let moonRingMaterial = new THREE.MeshBasicMaterial({
  4.  
    map: moonRingTexture,
  5.  
    transparent: true,
  6.  
    blending: THREE.AdditiveBlending,
  7.  
    side: THREE.DoubleSide,
  8.  
    depthWrite: false,
  9.  
    opacity: 0.5,
  10.  
    });
  11.  
    let moonRingGeometry = new THREE.RingGeometry(145, 155, 64);
  12.  
    let moonRing = new THREE.Mesh(moonRingGeometry, moonRingMaterial);
  13.  
    moonRing.rotation.x = -Math.PI / 2;
  14.  
    scene.add(moonRing);

学新通

接下来通过gsap动画库当月球顺时针绕地球无限匀速旋转运动下去:

  1.  
    let time = {
  2.  
    value: 0,
  3.  
    };
  4.  
    gsap.to(time, {
  5.  
    value: 1,
  6.  
    duration: 10,
  7.  
    repeat: -1,
  8.  
    ease: "linear",
  9.  
    onUpdate: () => {
  10.  
    moon.position.x = 150 * Math.cos(time.value * Math.PI * 2);
  11.  
    moon.position.z = 150 * Math.sin(time.value * Math.PI * 2);
  12.  
    moon.rotation.y = time.value * Math.PI * 8;
  13.  
    },
  14.  
    });

学新通

效果完成之后,我们在一开始设置的挂载时显示进度也就有效果了,如下:

学新通

demo做完,给出本案例的完整代码:(获取素材也可以私信博主)

  1.  
    <template>
  2.  
    <div class="home">
  3.  
    <div class="canvas-container" ref="screenDom"></div>
  4.  
    <div class="loading" v-if="progress != 100"></div>
  5.  
    <div class="progress" v-if="progress != 100">
  6.  
    <img src="../assets/loading.gif" alt="" />
  7.  
    <span>地球加载中:{{ progress }}%</span>
  8.  
    </div>
  9.  
    <div class="title">酷炫3D地球</div>
  10.  
    </div>
  11.  
    </template>
  12.  
     
  13.  
    <script setup>
  14.  
    import * as THREE from 'three'
  15.  
    import { ref,onMounted } from 'vue'
  16.  
    import { gsap } from 'gsap'
  17.  
    import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
  18.  
     
  19.  
    let screenDom = ref(null)
  20.  
    let progress = ref(0);
  21.  
     
  22.  
    // 经纬度转换函数
  23.  
    const lon2xyz = (R,longitude,latitude) =>{
  24.  
    let lon = ( longitude * Math.PI ) / 180 // 转弧度值
  25.  
    const lat = (latitude * Math.PI) / 180 // 转弧度值
  26.  
    lon = -lon // js坐标系z坐标轴对应经度-90度,而不是90度
  27.  
     
  28.  
    // 经纬度坐标转球面坐标计算公式
  29.  
    const x = R * Math.cos(lat) * Math.cos(lon)
  30.  
    const y = R * Math.sin(lat)
  31.  
    const z = R * Math.cos(lat) * Math.sin(lon)
  32.  
    // 返回球面坐标
  33.  
    return new THREE.Vector3(x,y,z)
  34.  
    }
  35.  
    // 创建场景
  36.  
    const scene = new THREE.Scene()
  37.  
    // 创建相机
  38.  
    const camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
  39.  
    camera.position.set(0,50,300)
  40.  
    // 创建渲染器
  41.  
    const renderer = new THREE.WebGLRenderer({ antialias: true })
  42.  
    renderer.setSize(window.innerWidth,window.innerHeight)
  43.  
     
  44.  
    // 创建控制器
  45.  
    const controls = new OrbitControls(camera,renderer.domElement)
  46.  
    controls.autoRotate = true
  47.  
     
  48.  
    window.addEventListener("resize",()=>{
  49.  
    renderer.setSize(window.innerWidth,window.innerHeight)
  50.  
    camera.aspect = window.innerWidth/window.innerHeight
  51.  
    camera.updateProjectionMatrix()
  52.  
    })
  53.  
     
  54.  
    // 创建渲染函数
  55.  
    const render = () =>{
  56.  
    controls.update();
  57.  
    requestAnimationFrame(render);
  58.  
    renderer.render(scene, camera);
  59.  
    }
  60.  
     
  61.  
    onMounted(()=>{
  62.  
    // 设置进度
  63.  
    THREE.DefaultLoadingManager.onProgress = function (item, loaded, total) {
  64.  
    progress.value = new Number((loaded / total) * 100).toFixed(2);
  65.  
    };
  66.  
    // 将画布添加到页面中
  67.  
    screenDom.value.appendChild(renderer.domElement)
  68.  
    render()
  69.  
    })
  70.  
     
  71.  
    // 创建星空的背景颜色
  72.  
    scene.background = new THREE.Color(0x030311);
  73.  
    // 加载点材质纹理
  74.  
    const starsTexture = new THREE.TextureLoader().load("./images/stars.png");
  75.  
    const starsMaterial = new THREE.PointsMaterial({
  76.  
    size: 2,
  77.  
    sizeAttenuation: true, // 尺寸衰减
  78.  
    color: 0x4d76cf,
  79.  
    transparent: true,
  80.  
    opacity: 1,
  81.  
    map: starsTexture,
  82.  
    });
  83.  
     
  84.  
    // 使用点材质创建星空效果
  85.  
    const vertices = [];
  86.  
    for (let i = 0; i < 500; i ) {
  87.  
    const vertex = new THREE.Vector3();
  88.  
    vertex.x = 800 * Math.random() - 400;
  89.  
    vertex.y = 800 * Math.random() - 400;
  90.  
    vertex.z = 800 * Math.random() - 400;
  91.  
    vertices.push(vertex.x, vertex.y, vertex.z);
  92.  
    }
  93.  
     
  94.  
    // 星空效果
  95.  
    let starsGeometry = new THREE.BufferGeometry();
  96.  
    starsGeometry.setAttribute(
  97.  
    "position",
  98.  
    new THREE.BufferAttribute(new Float32Array(vertices), 3)
  99.  
    );
  100.  
    let stars = new THREE.Points(starsGeometry, starsMaterial);
  101.  
    scene.add(stars);
  102.  
     
  103.  
     
  104.  
    // 创建地球
  105.  
    let earthGeometry = new THREE.SphereGeometry(50, 32, 32);
  106.  
    let earthTexture = new THREE.TextureLoader().load("./images/map.jpg");
  107.  
    let earthMaterial = new THREE.MeshBasicMaterial({
  108.  
    map: earthTexture,
  109.  
    });
  110.  
    let earth = new THREE.Mesh(earthGeometry, earthMaterial);
  111.  
    scene.add(earth);
  112.  
     
  113.  
    // 发光地球
  114.  
    let lightTexture = new THREE.TextureLoader().load("./images/earth.jpg");
  115.  
    let lightEarthGeometry = new THREE.SphereGeometry(53, 32, 32);
  116.  
    let lightEarthMaterial = new THREE.MeshBasicMaterial({
  117.  
    map: lightTexture,
  118.  
    alphaMap: lightTexture,
  119.  
    blending: THREE.AdditiveBlending,
  120.  
    transparent: true,
  121.  
    });
  122.  
    let lightEarth = new THREE.Mesh(lightEarthGeometry, lightEarthMaterial);
  123.  
    scene.add(lightEarth);
  124.  
     
  125.  
    // 添加地球内外发光精灵
  126.  
    let spriteTexture = new THREE.TextureLoader().load("./images/glow.png");
  127.  
    let spriteMaterial = new THREE.SpriteMaterial({
  128.  
    map: spriteTexture,
  129.  
    color: 0x4d76cf,
  130.  
    transparent: true,
  131.  
    depthWrite: false,
  132.  
    depthTest: false,
  133.  
    blending: THREE.AdditiveBlending,
  134.  
    });
  135.  
    let sprite = new THREE.Sprite(spriteMaterial);
  136.  
    sprite.scale.set(155, 155, 0);
  137.  
    scene.add(sprite);
  138.  
     
  139.  
    // 内发光
  140.  
    let spriteTexture1 = new THREE.TextureLoader().load("./images/innerGlow.png");
  141.  
    let spriteMaterial1 = new THREE.SpriteMaterial({
  142.  
    map: spriteTexture1,
  143.  
    color: 0x4d76cf,
  144.  
    transparent: true,
  145.  
    depthWrite: false,
  146.  
    depthTest: false,
  147.  
    blending: THREE.AdditiveBlending,
  148.  
    });
  149.  
    let sprite1 = new THREE.Sprite(spriteMaterial1);
  150.  
    sprite1.scale.set(128, 128, 0);
  151.  
    scene.add(sprite1);
  152.  
    let scale = new THREE.Vector3(1, 1, 1);
  153.  
     
  154.  
    for (let i = 0; i < 30; i ) {
  155.  
    // 实现光柱
  156.  
    let lightPillarTexture = new THREE.TextureLoader().load(
  157.  
    "./images/light_column.png"
  158.  
    );
  159.  
    let lightPillarGeometry = new THREE.PlaneGeometry(3, 20);
  160.  
    let lightPillarMaterial = new THREE.MeshBasicMaterial({
  161.  
    color: 0xffffff,
  162.  
    map: lightPillarTexture,
  163.  
    alphaMap: lightPillarTexture,
  164.  
    transparent: true,
  165.  
    blending: THREE.AdditiveBlending,
  166.  
    side: THREE.DoubleSide,
  167.  
    depthWrite: false,
  168.  
    });
  169.  
    let lightPillar = new THREE.Mesh(lightPillarGeometry, lightPillarMaterial);
  170.  
    lightPillar.add(lightPillar.clone().rotateY(Math.PI / 2));
  171.  
     
  172.  
    // 设置光柱的位置
  173.  
    let lat = Math.random() * 180 - 90;
  174.  
    let lon = Math.random() * 360 - 180;
  175.  
    let position = lon2xyz(60, lon, lat);
  176.  
    lightPillar.position.set(position.x, position.y, position.z);
  177.  
     
  178.  
    lightPillar.quaternion.setFromUnitVectors(
  179.  
    new THREE.Vector3(0, 1, 0),
  180.  
    position.clone().normalize()
  181.  
    );
  182.  
    scene.add(lightPillar);
  183.  
     
  184.  
    // 创建波纹扩散效果
  185.  
    let circlePlane = new THREE.PlaneGeometry(6, 6);
  186.  
    let circleTexture = new THREE.TextureLoader().load("./images/label.png");
  187.  
    let circleMaterial = new THREE.MeshBasicMaterial({
  188.  
    color: 0xffffff,
  189.  
    map: circleTexture,
  190.  
    transparent: true,
  191.  
    blending: THREE.AdditiveBlending,
  192.  
    depthWrite: false,
  193.  
    side: THREE.DoubleSide,
  194.  
    });
  195.  
    let circleMesh = new THREE.Mesh(circlePlane, circleMaterial);
  196.  
    circleMesh.rotation.x = -Math.PI / 2;
  197.  
    circleMesh.position.set(0, -7, 0);
  198.  
     
  199.  
    lightPillar.add(circleMesh);
  200.  
     
  201.  
    gsap.to(circleMesh.scale, {
  202.  
    duration: 1 Math.random() * 0.5,
  203.  
    x: 2,
  204.  
    y: 2,
  205.  
    z: 2,
  206.  
    repeat: -1,
  207.  
    delay: Math.random() * 0.5,
  208.  
    yoyo: true,
  209.  
    ease: "power2.inOut",
  210.  
    });
  211.  
    }
  212.  
     
  213.  
    // 绕地球运行的月球
  214.  
    let moonTexture = new THREE.TextureLoader().load("./images/moon.jpg");
  215.  
    let moonMaterial = new THREE.MeshStandardMaterial({
  216.  
    map: moonTexture,
  217.  
    emissive: 0xffffff,
  218.  
    emissiveMap: moonTexture,
  219.  
    });
  220.  
    let moonGeometry = new THREE.SphereGeometry(5, 32, 32);
  221.  
    let moon = new THREE.Mesh(moonGeometry, moonMaterial);
  222.  
    moon.position.set(150, 0, 0);
  223.  
    scene.add(moon);
  224.  
     
  225.  
    // 创建月球环
  226.  
    let moonRingTexture = new THREE.TextureLoader().load("./images/moon_ring.png");
  227.  
    let moonRingMaterial = new THREE.MeshBasicMaterial({
  228.  
    map: moonRingTexture,
  229.  
    transparent: true,
  230.  
    blending: THREE.AdditiveBlending,
  231.  
    side: THREE.DoubleSide,
  232.  
    depthWrite: false,
  233.  
    opacity: 0.5,
  234.  
    });
  235.  
    let moonRingGeometry = new THREE.RingGeometry(145, 155, 64);
  236.  
    let moonRing = new THREE.Mesh(moonRingGeometry, moonRingMaterial);
  237.  
    moonRing.rotation.x = -Math.PI / 2;
  238.  
    scene.add(moonRing);
  239.  
     
  240.  
    let time = {
  241.  
    value: 0,
  242.  
    };
  243.  
    gsap.to(time, {
  244.  
    value: 1,
  245.  
    duration: 10,
  246.  
    repeat: -1,
  247.  
    ease: "linear",
  248.  
    onUpdate: () => {
  249.  
    moon.position.x = 150 * Math.cos(time.value * Math.PI * 2);
  250.  
    moon.position.z = 150 * Math.sin(time.value * Math.PI * 2);
  251.  
    moon.rotation.y = time.value * Math.PI * 8;
  252.  
    },
  253.  
    });
  254.  
     
  255.  
    </script>
  256.  
     
  257.  
    <style>
  258.  
    body {
  259.  
    background-color: #000;
  260.  
    }
  261.  
    .canvas-container {
  262.  
    width: 100vw;
  263.  
    height: 100vh;
  264.  
    }
  265.  
    .home {
  266.  
    width: 100vw;
  267.  
    height: 100vh;
  268.  
    transform-origin: 0 0;
  269.  
    }
  270.  
    .loading {
  271.  
    position: fixed;
  272.  
    top: 0;
  273.  
    left: 0;
  274.  
    width: 1920px;
  275.  
    height: 1080px;
  276.  
    background-image: url(../assets/loading.jpg);
  277.  
    background-size: cover;
  278.  
    filter: blur(50px);
  279.  
    z-index: 100;
  280.  
    }
  281.  
    .progress {
  282.  
    position: fixed;
  283.  
    top: 0;
  284.  
    left: 0;
  285.  
    width: 1920px;
  286.  
    height: 1080px;
  287.  
    z-index: 101;
  288.  
    display: flex;
  289.  
    justify-content: center;
  290.  
    align-items: center;
  291.  
    font-size: 20px;
  292.  
    color: #fff;
  293.  
    }
  294.  
    .progress > img {
  295.  
    padding: 0 15px;
  296.  
    }
  297.  
     
  298.  
    .title {
  299.  
    width: 380px;
  300.  
    height: 40px;
  301.  
    position: fixed;
  302.  
    right: 100px;
  303.  
    top: 50px;
  304.  
    background-color: rgba(0, 0, 0, 0.5);
  305.  
    line-height: 40px;
  306.  
    text-align: center;
  307.  
    color: #fff;
  308.  
    border-radius: 5px;
  309.  
    z-index: 110;
  310.  
    }
  311.  
    </style>
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhfiebga
系列文章
更多 icon
同类精品
更多 icon
继续加载