前端效果积累 | 酷炫、实用3D地球路径飞行效果实现

news2024/11/15 8:32:49

📌个人主页:个人主页
​🧀 推荐专栏:前端开发成神之路 --【这是一个为想要入门和进阶前端开发专门开启的精品专栏!从个人到商业的全套开发教程,实打实的干货分享,确定不来看看? 😻😻】
📝作者简介从web开发,再到大数据算法,踩过了无数的坑,用心总结经验教训,助你在技术生涯一臂之力!若想获取更多精彩内容,敬请订阅专栏或者关注😁😂🤣😃😆😉😊😋😍😘🥰
⭐️您的小小关注是我持续输出的动力!⭐️


干货内容推荐

🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :

  • 《小程序开发必备功能的吐血整理【个人中心界面样式大全】》
  • 《微信小程序 | 动手实现双十一红包雨》
  • 《微信小程序 | 人脸识别的最终解决方案》
  • 《来接私活吧?小程序接私活必备功能-婚恋交友【附完整代码】》
  • 《吐血整理的几十款小程序登陆界面【附完整代码】》

文章目录

  • 干货内容推荐
    • 一、效果预览
    • 二、技术要点及用途
    • 三、完整代码


一、效果预览

请添加图片描述

二、技术要点及用途

这样的3D地球飞行线效果,其主要的应用场景在于酷炫的数据报表大屏!

在日常的开发工作中,搭建数据大屏其实是很多前端工程师都必须经历的一个基础需求!可能你觉得这不就是拿百度的Eachart组件搭建一下不就可以了!这放在过去几年,这个需求说不定还存在!

大哥,现在都是2023年了,数字孪生这个热词被炒的沸沸扬扬。可以见的现在的数据大屏报表需求逐步往3D化、场景可视化、从操控一体化的方向发展了!所以说,现在要搞定酷炫的数据可视化仅仅是一个前端工程师加一个UI设计可能已经是跟不上配置了!一个数字孪生效果的建立,可能需要用到建模师、工程测量、电子工程师等依托于场景的各类专业技术人才!详细的数据可视化技术积累可以看我另一篇文章:超干货!数据可视化最全解决方案!酷炫效果分分钟拿捏!【附全网高质量学习资料】

本文中的技术要点无非是:Three.js。通过three.js构建3D空间效果,同时设置不同的点,再将不同的点用线进行连接!

三、完整代码

<div id="container"></div>
<script src="https://wow.techbrood.com/uploads/user_upload/56822/three.r111.js"></script>
<script src="https://wow.techbrood.com/uploads/user_upload/56822/OrbitControls.js"></script>

<script id="vertex-shader" type="x-shader/x-vertex">
    attribute float percent;
    uniform float time;
    uniform float number;
    uniform float speed;
    uniform float length;
    varying float opacity;
    uniform float size;

    void main()
    {
        float l = clamp(1.0-length, 0.0, 1.0);

        gl_PointSize = clamp(fract(percent*number + l - time*number*speed)-l, 0.0, 1.) * size * (1./length);

        opacity = gl_PointSize/size;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
</script>

<script id="fragment-shader" type="x-shader/x-fragment">
    varying float opacity;
    uniform vec3 color;

    void main(){
        if (opacity <=0.2){
            discard;
        }
        gl_FragColor = vec4(color, 1.0);
    }
</script>


<script type="text/javascript">
    var container = document.getElementById('container');
var scene, camera, renderer;
var globeMesh = undefined;
var groupDots, groupLines, groupAnimDots;
var controls;

var _PI2 = Math.PI * 2; // 弧度的取值为0-2π

// 配置参数
var params = {
    globeRadius: 100, // 地球半径
    pointsLength: 20, // 点数
}
var commonUniforms = {
    time: {
        value: 0
    },
    number: {
        value: 1
    },
    speed: {
        value: 0.5
    },
    length: {
        value: 0.4
    },
    size: {
        value: 4
    }
};

var vertexShader = document.getElementById('vertex-shader').innerHTML;
var fragmentShader = document.getElementById('fragment-shader').innerHTML;

// 预制件
var Prefab = {
    Sphere: (function() {
        var instance;
        return function(clone = true) {
            if (!instance) {
                instance = new createSphere();
            }
            if (clone) return instance.clone();
            else return instance;
        }
    })()
}

init();
update();

function init() {
    // 场景
    scene = new THREE.Scene();
    groupDots = new THREE.Group();
    groupLines = new THREE.Group();
    groupAnimDots = new THREE.Group();
    scene.add(groupDots, groupLines, groupAnimDots);

    // 相机
    camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 10000);
    camera.position.x = -200;
    camera.position.y = 200;
    camera.position.z = -200;
    camera.lookAt(scene.position);

    // 渲染器
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(window.devicePixelRatio);
    container.appendChild(renderer.domElement);

    // 光
    var light = new THREE.HemisphereLight(0xffffff, 0xffffff, 1);
    scene.add(light);

    // 控制器
    controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.minDistance = 200;
    controls.maxDistance = 400;
    controls.rotateSpeed = 0.5;
    controls.enableDamping = true;
    controls.enablePan = false;

    initGlobe();
    initFlyLines();

    window.addEventListener('resize', onWindowResize, false);
}

function update() {
    requestAnimationFrame(update);
    renderer.render(scene, camera);

    commonUniforms.time.value += 0.01;

    controls.update();
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
}

function initGlobe() {
    // 地球
    var geo = new THREE.SphereGeometry(params.globeRadius, 32, 32);
    var texture = new THREE.TextureLoader().load('https://wow.techbrood.com/uploads/user_upload/56822/earth.jpg');
    texture.minFilter = THREE.LinearFilter;
    var material = new THREE.MeshPhongMaterial({
        map: texture,
        // wireframe: true
    });

    globeMesh = new THREE.Mesh(geo, material);
    scene.add(globeMesh);
}

// 地球飞线和点
function initFlyLines() {
    // 球面随机点
    for (let i = 0; i < params.pointsLength; i++) {
        addPoints(groupDots, params.globeRadius);
    }

    // 点到点生成曲线
    groupDots.children.forEach(function(elem, index) {
        if (elem != groupDots.children[0]) {
            addLines(groupDots.children[index - 1].position, elem.position);
        }
    });
}

// 3d球面取点
function getEarthPos(radius, a, b) {
    var x = radius * Math.sin(a) * Math.cos(b);
    var y = radius * Math.sin(a) * Math.sin(b);
    var z = radius * Math.cos(a);
    return {
        x, y, z
    };
}

// 添加随机点
function addPoints(group, radius) {
    var mesh = new Prefab.Sphere();
    var pos = getEarthPos(radius, _PI2 * Math.random(), _PI2 * Math.random());
    mesh.position.set(pos.x, pos.y, pos.z);
    group.add(mesh);
}

function addLines(v0, v3) {
    var angle = v0.angleTo(v3);

    var vtop = v0.clone().add(v3);
    vtop = vtop.normalize().multiplyScalar(params.globeRadius);

    var n;

    if (angle <= 1) {
        n = params.globeRadius / 5 * angle;
    } else if (angle > 1 && angle < 2) {
        n = params.globeRadius / 5 * Math.pow(angle, 2);
    } else {
        n = params.globeRadius / 5 * Math.pow(angle, 1.5);
    }

    var v1 = v0.clone().add(vtop).normalize().multiplyScalar(params.globeRadius + n);
    var v2 = v3.clone().add(vtop).normalize().multiplyScalar(params.globeRadius + n);

    // addLineHelper(globeMesh.position, v1);
    // addLineHelper(globeMesh.position, v2);
    // addLineHelper(globeMesh.position, vtop)

    // 三维三次贝塞尔曲线(v0起点,v1第一个控制点,v2第二个控制点,v3终点)
    var curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
    var points = curve.getPoints(500);
    var geometry = new THREE.BufferGeometry().setFromPoints(points);

    let length = points.length;
    var percents = new Float32Array(length);
    for (let i = 0; i < length; i += 1) {
        percents[i] = (i / length);
    }
    geometry.setAttribute('percent', new THREE.BufferAttribute(percents, 1));

    var material = createLineMaterial();
    var flyLine = new THREE.Points(geometry, material);
    groupLines.add(flyLine);
}

function createLineMaterial() {
    let uniforms = {
        time: commonUniforms.time,
        number: commonUniforms.number,
        speed: commonUniforms.speed,
        length: commonUniforms.length,
        size: commonUniforms.size,
        color: {
            value: new THREE.Color(Math.random(), Math.random(), Math.random())
        }
    };

    var material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        transparent: true,
        blending: THREE.AdditiveBlending,
    });

    return material;
}

// 小球
function createSphere() {
    var geometry = new THREE.SphereBufferGeometry(1);
    var material = new THREE.MeshBasicMaterial({
        color: 0x00ffff
    });
    var mesh = new THREE.Mesh(geometry, material);
    return mesh;
}

// 贝塞尔曲线辅助点
function addPointHelper(pos) {
    var mesh = new Prefab.Sphere();
    mesh.material = new THREE.MeshBasicMaterial({
        color: 0xff0000
    });
    mesh.position.copy(pos);
    scene.add(mesh);
}

// 贝塞尔曲线辅助线
function addLineHelper(pos1, pos2) {
    var material = new THREE.LineBasicMaterial({
        color: 0x0000ff
    });

    var geometry = new THREE.Geometry();
    geometry.vertices.push(pos1, pos2);
    var line = new THREE.Line(geometry, material);
    scene.add(line);
}
</script>



<style type="text/css">
    
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0;
            overflow: hidden;
        }

</style>

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

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

相关文章

【C语言进阶】自定义类型之结构体

目录一&#xff1a;结构体1.1&#xff1a;结构的基础知识&#xff1a; 1.2&#xff1a;结构的声明&#xff1a; 1.3&#xff1a;特殊声明&#xff08;匿名结构体&#xff09;&#xff1a; 1.4&#xff1a;结构的自引用&#xff1a; 1.5&#xff1a;结构体变量的定义和初始化&am…

springboot 项目自定义log日志文件提示系统找不到指定的文件

自己尝试搭建了一个springboot项目&#xff0c;自定义了log日志文件&#xff0c;启动后报错 Logging system failed to initialize using configuration from logback-spring.xml java.io.FileNotFoundException: E:\code_demo\xxxx\logback-spring.xml (系统找不到指定的文件…

Elasticsearch(二)--Elasticsearch客户端讲解

一、前言 在上一章我们大致了解了下elasticsearch,虽说上次的内容全是八股文&#xff0c;但是很多东西还是非常有用的&#xff0c;这些哪怕往小说作为面试&#xff0c;往大说是可以帮你很快的理解es是个什么玩意儿&#xff0c;所以还是非常推荐大家去看一下上一章内容。 这一章…

【C++】map和set的使用

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;关联式容…

码二哥的技术专栏 总入口

已发表的技术专栏&#xff08;订阅即可观看所有专栏&#xff09; 0  grpc-go、protobuf、multus-cni 技术专栏 总入口 1  grpc-go 源码剖析与实战  文章目录 2  Protobuf介绍与实战 图文专栏  文章目录 3  multus-cni   文章目录(k8s多网络实现方案) 4  gr…

JVM整理笔记之测试工具JCStress的使用及其注解的应用

文章目录前言如何使用JCStress测试代码JCStress 注解说明前言 如果要研究高并发&#xff0c;一般会借助高并发工具来进行测试。JCStress&#xff08;Java Concurrency Stress&#xff09;它是OpenJDK中的一个高并发测试工具&#xff0c;它可以帮助我们研究在高并发场景下JVM&a…

RecyclerView 倒计时和正计时方案

本章内容一.方案制定二.设计三.编码相信不少同学都会在这里栽跟头&#xff0c;在思考这个问题设计了两套方案&#xff0c;而我的项目需求中需要根据业务是否反馈来进行倒计时和正计时的操作。一.方案制定 1.在Adapter中使用CountDownTimer 2.修改数据源更新数据 3.只修改页面展…

leetcode--各种数据结构相关的题

数据结构1.数组&#xff08;1&#xff09;找到所有数组中消失的数字(448)&#xff08;2&#xff09;旋转图像(48)&#xff08;3&#xff09;搜索二维矩阵 II(240)&#xff08;4&#xff09;最多能完成排序的块(769)2.栈和队列&#xff08;1&#xff09;用栈实现队列(232)&#…

“链引擎”(PBC)计划 | 太保集团长安链应用展示

引言 长安链“链引擎”计划&#xff08;Powered by Chainmaker&#xff09;(简称&#xff1a;PBC计划)是由长安链生态联盟发起的一项应用赋能计划&#xff0c;旨在以长安链技术体系为核心支撑&#xff0c;汇聚产业各方力量&#xff0c;为应用方提供技术、品牌、生态等支持&…

面试干货!初级软件测试面试题及答案题库一起奉上

软件测试工程师面试通常要经历技术面以及HR面&#xff0c;HR面一般都是日常问题&#xff0c;面试人可以临场发挥过去&#xff0c;但关乎岗位职责的技术面&#xff0c;可就没那么容易了&#xff0c;尤其是对于很多初次去面试测试岗位的没有任何测试岗位面试经验的转行人员&#…

Java并发面试题

基础知识 并发编程的优缺点 为什么要使用并发编程&#xff08;并发编程的优点&#xff09; 充分利用多核CPU的计算能力&#xff1a;通过并发编程的形式可以将多核CPU的计算能力发挥到极致&#xff0c;性能得到提升方便进行业务拆分&#xff0c;提升系统并发能力和性能&#…

【网络安全】内网介绍+windows信息收集(含命令)

目录 前言 一、内网渗透测试是什么&#xff1f; 1.介绍 2.内外网区别 3.工作组是什么&#xff1f; 4.域是什么&#xff1f; 5.域的知识点 6.活动目录 7.活动目录主要功能 8.域权限 二、windows信息收集 &#xff08;1&#xff09;系统信息 &#xff08;2&#xff0…

【pandas】17 数据处理和绘图

【pandas】17 数据处理和绘图 2023.1.16 pandas数据处理方法和绘图&#xff1a;读取数据、更改数据、时间数据等 主要参考&#xff1a;https://mofanpy.com/tutorials/data-manipulation/pandas/time 17.1运算方法 17.1.1 筛选赋值运算 就是用前面的方法对数据进行筛选&#…

AI中Deepfake的部分研究前沿与文献综述

AI中Deepfake的部分研究前沿与文献综述一、研究现状二、典型算法&#xff1a;三、存在问题四、未来的研究热点参考文献&#xff1a;一、研究现状 由于Deepfake其潜在的安全威胁&#xff0c;它已经引起了学术界和工业界的研究兴趣。为了减轻这种风险&#xff0c;人们提出了许多…

【Nginx01】Ngnix入门

1.版本 Nginx开源版Nginx plus商业版OpenrestyTengine 2.Nginx开源版安装 2.1下载 2.2编译安装 如果本身没有c语言的编译器 命令&#xff1a; yum install -y gcc 解压Nginx 命令&#xff1a; tar -zxvf nginx-1.22.1.tar.gz 安装perl库 命令&#xff1a; yum install -y p…

广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”

文章目录广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署”服务 Docker 构建及部署代码支持服务打包&构建服务部署广告业务系统 之 敏捷交付 —— “基于 Docker 容器同机部署” 服务 Docker 构建及部署 在 ADX 系统中&#xff0c;全链路涉及 大大小小的微服务…

SpringBoot+VUE前后端分离项目学习笔记 - 【22 权限菜单 下】

本节主要实现用户角色菜单分配功能&#xff0c;并且实现前端的动态渲染以及动态路由 数据库&#xff1a; sys_user表增加role字段; sys_role增加flag字段;sys_menu表增加page_path字段。前两者表示用户角色标识&#xff0c;后者是前端页面vue路径&#xff0c;用以实现动态路由 …

verilog学习笔记- 13)呼吸灯实验

目录 简介&#xff1a; 实验任务&#xff1a; 硬件设计&#xff1a; 程序设计&#xff1a; 下载验证&#xff1a; 简介&#xff1a; 呼吸灯采用 PWM 的方式&#xff0c;在固定的频率下&#xff0c;通过调整占空比的方式来控制 LED 灯亮度的变化。PWM即脉冲宽度调制&#x…

2021年帆软杯一等奖作品 |《基于数据可视化的中国编程岗位需求分析》

# 作品主题 #——基于数据可视化的中国编程岗位需求分析一、团队介绍 团队名称&#xff1a;汪汪队立大功 团队成员&#xff1a;乔好鑫、许春阳、窦晨辉 指导老师&#xff1a;施金妹 团队的三位成员均是来自于海南科技职业大学大数据技术与应用专业&#xff0c;专业课主修了pyt…

SpringBoot+2次MD5登录密码加密+MyBatisPlus+Thymeleaf+Bootstrap简单实现登录功能,一文轻松搞定!

这里写目录标题一、演示GIF二、开发前期准备1、数据库2、依赖POM.XML3、idea结构目录三、后端1、实体类2、mapper接口3、mapper.xml4、Servicce接口5、Impl实现6、Controller控制器7、全局异常处理类GlobalExceptionGlobalExceptionHandler8、工具类MD5UtilUUIDUtilCookieUtilV…