前端小练习——星辰宇宙(JS没有上限!!!)

        前言:在刚开始学习前端的时候,我们会学习到前端三件套中的JavaScript,可能那时候读者没有觉得JavaScript这个语言有多么的牛逼,本篇文章将会使用一个炫酷的案例来刷新你对JavaScript这个语言的认知与理解。


✨✨✨这里是秋刀鱼不做梦的BLOG

✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客

先让我们看一下最终的结果:

在开始讲解这个炫酷的案例之前,先让我们了解一下本案例所需的前置知识:

  1. Three.js:一个用于创建和显示3D图形的JavaScript库。代码中导入了Three.js的核心库和轨道控制库(OrbitControls),用于处理3D场景的创建和相机控制。

  2. WebGL:用于在网页中绘制3D图形的底层API。Three.js封装了WebGL,使得3D渲染变得更简单。

  3. 模块化 JavaScript:使用 ES6 的模块导入语法 (import) 引入外部库,使代码结构更加清晰。

  4. 着色器编程:自定义顶点和片段着色器,通过 onBeforeCompile 方法替换默认着色器,控制点的大小、颜色和运动效果。

  5. 缓冲几何体:使用 BufferGeometry 来管理大量点的性能,提升渲染效率。

  6. 动画循环:利用 setAnimationLoop 实现流畅的渲染动画,每帧更新控制器状态和场景渲染。

  7. 响应式设计:通过 resize 事件监听器,动态调整相机和渲染器的尺寸,以适应浏览器窗口的变化。

        ——在文章的最后,我们给出了实现这个案例的全部代码,读者可以直接复制后在自己的编译器上执行一下!!!

        那么现在正式开始我们的讲解:

目录

1.导入库和清理控制台

2.创建场景和相机

3.创建渲染器

4. 处理窗口大小变化

5. 控制器设置

6. 创建全局uniform变量和点的属性

7. 创建点的顶点数组

 8. 添加围绕的点

9. 创建几何体和材质

10. 创建点云并添加到场景

11. 渲染循环

——全部代码


1.导入库和清理控制台

        开始我们要先导入库和清理控制台:

import * as THREE from "https://cdn.skypack.dev/three@0.136.0"; // 导入三维模型库
import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls"; // 导入轨道控制库
console.clear(); // 清除控制台

        注释:这部分代码导入了Three.js库及其轨道控制功能,并清理了控制台,以便后续输出信息更清晰。

2.创建场景和相机

        在导入库和清理控制台后,我们就需要创建场景和相机:

let scene = new THREE.Scene(); // 创建场景
scene.background = new THREE.Color(0x160016); // 设置场景背景颜色

let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000); // 创建相机
camera.position.set(0, 4, 21); // 设置相机位置

        注释:这部分代码创建了一个场景和一个透视相机,设置了相机的位置和背景颜色,为后续的渲染准备基础环境。

3.创建渲染器

        其后我们需要为其创建一个渲染器:

let renderer = new THREE.WebGLRenderer(); // 创建渲染器
renderer.setSize(innerWidth, innerHeight); // 设置渲染器大小
document.body.appendChild(renderer.domElement); // 把渲染器加入到页面中

        注释:这里创建了一个WebGL渲染器,并设置其大小为窗口的宽高,最后将渲染器的DOM元素添加到网页中,以显示渲染结果。

4. 处理窗口大小变化

        在创建完渲染器之后,我们需要对后续的窗口的大小的变化进行处理:

window.addEventListener("resize", event => {
    camera.aspect = innerWidth / innerHeight; // 更新相机的长宽比
    camera.updateProjectionMatrix(); // 更新相机的投影矩阵
    renderer.setSize(innerWidth, innerHeight); // 设置渲染器大小
});

        注释:这一部分代码监听窗口的大小变化,动态调整相机的长宽比和渲染器的大小,确保在窗口大小变化时,场景仍能正确显示。

5. 控制器设置

        处理完窗口大小的变化之后,我们就需要对控制器进行设置了!

let controls = new OrbitControls(camera, renderer.domElement); // 创建控制器
controls.enableDamping = true; // 开启阻尼效果
controls.enablePan; // 禁用平移(此行未完成)

        注释:这部分代码创建了一个轨道控制器,允许用户通过鼠标控制相机旋转和缩放,增强用户交互体验。注意,这里 enablePan 需要完整设置。

6. 创建全局uniform变量和点的属性

        接下来让哦我们对全局的uniform变量和点的属性进行设置:

let gu = {
    time: { value: 0 }
}; // 创建全局uniform变量

let sizes = []; // 点的大小数组
let shift = []; // 点的移动数组

let pushShift = () => { // 创建移动函数
    shift.push(
        Math.random() * Math.PI,
        Math.random() * Math.PI * 2,
        (Math.random() * 0.9 + 0.1) * Math.PI * 0.1,
        Math.random() * 0.9 + 0.1
    ); // 随机生成位置信息
};

        注释:定义了一个全局uniform变量 gu 用于时间控制,并初始化了两个数组 sizesshift 用于存储点的大小和位置信息。同时,定义了一个函数 pushShift,用于生成随机的位移数据。

7. 创建点的顶点数组

        接下来让我们创建点的顶点数组:

let pts = new Array(50000).fill().map(p => {
    sizes.push(Math.random() * 1.5 + 0.5); // 添加随机大小
    pushShift(); // 添加位置信息
    return new THREE.Vector3().randomDirection().multiplyScalar(Math.random() * 0.5 + 9.5); // 返回随机方向的点
});

        注释:这里创建了一个包含5万个点的数组 pts,每个点都有随机的大小和方向。通过 randomDirection() 方法生成随机方向的向量,模拟球体内的点。

 8. 添加围绕的点

        创建完点的顶点数组之后,让我们添加其围绕的点:       

for (let i = 0; i < 100000; i++) {
    let r = 10, R = 40; // 定义内外半径
    let rand = Math.pow(Math.random(), 1.5); // 生成随机数
    let radius = Math.sqrt(R * R * rand + (1 - rand) * r * r); // 计算随机半径
    pts.push(new THREE.Vector3().setFromCylindricalCoords(radius, Math.random() * 2 * Math.PI, (Math.random() - 0.5) * 2)); // 生成点
    sizes.push(Math.random() * 1.5 + 0.5); // 添加随机大小
    pushShift(); // 添加位置信息
}

        注释:这部分代码在已有的点基础上,再添加10万个点。使用极坐标系生成点,使其在一定范围内均匀分布,丰富了场景中的点的数量和分布。

9. 创建几何体和材质

        接下来让我们设置一下几何体和其材质样式:

let g = new THREE.BufferGeometry().setFromPoints(pts); // 创建几何体
g.setAttribute("sizes", new THREE.Float32BufferAttribute(sizes, 1)); // 设置sizes属性
g.setAttribute("shift", new THREE.Float32BufferAttribute(shift, 4)); // 设置shift属性

let m = new THREE.PointsMaterial({ // 创建点材质
    size: 0.125, // 点的大小
    transparent: true, // 透明材质
    depthTest: false, // 禁用深度测试
    blending: THREE.AdditiveBlending, // 添加混合模式
    onBeforeCompile: shader => { // 自定义着色器
        shader.uniforms.time = gu.time; // 设置uniform变量
        shader.vertexShader = `
            uniform float time;
            attribute float sizes;
            attribute vec4 shift;
            varying vec3 vColor;
            ${shader.vertexShader}
        `; // 修改顶点着色器

        // 更新点的大小、颜色和移动逻辑
        shader.vertexShader = shader.vertexShader
            .replace(`gl_PointSize = size;`, `gl_PointSize = size * sizes;`)
            .replace(`#include <color_vertex>`, `#include <color_vertex> float d = length(abs(position)/vec3(40.,10.,40)); d=clamp(d,0.,1.); vColor = mix(vec3(227.,155.,0.),vec3(100.,50.,255.),d)/255.;`)
            .replace(`#include <begin_vertex>`, `#include <begin_vertex> float t = time; float moveT = mod(shift.x + shift.z * t,PI2); float moveS = mod(shift.y + shift.z * t,PI2); transformed += vec3(cos(moveS) * sin(moveT), cos(moveT), sin(moveS) * sin(moveT)) * shift.w;`);
        
        // 修改片元着色器
        shader.fragmentShader = `
            varying vec3 vColor;
            ${shader.fragmentShader}
        `.replace(`#include <clipping_planes_fragment>`, `#include <clipping_planes_fragment> float d = length(gl_PointCoord.xy - 0.5);`)
          .replace(`vec4 diffuseColor = vec4( diffuse, opacity );`, `vec4 diffuseColor = vec4( vColor, smoothstep(0.5, 0.1, d));`);
    }
});

        注释:在这部分代码中,创建了一个缓冲几何体并设置了点的大小和移动信息。还定义了一个点材质,使用自定义着色器来控制点的大小、颜色和移动效果,提供了动态的视觉效果。

10. 创建点云并添加到场景

        接下来让我们创建点云并添加到场景:

let p = new THREE.Points(g, m); // 创建点云
p.rotation.order = "ZYX"; // 设置旋转顺序
p.rotation.z = 0.2; // 设置初始旋转角度
scene.add(p); // 将点云添加到场景中

        注释:这里将创建的几何体和材质结合成一个点云对象,并设置其旋转顺序和初始旋转角度,最后将其添加到场景中以进行渲染。

11. 渲染循环

        最后让我们渲染一下环境:

let clock = new THREE.Clock(); // 创建时钟对象
renderer.setAnimationLoop(() => { // 设置渲染循环
    controls.update(); // 更新控制器
    let t = clock.getElapsedTime() * 0.5; // 获取流逝时间
    gu.time.value = t * Math.PI; // 更新时间
    p.rotation.y = t * 0.05; // 更新点云的旋转角度
    renderer.render(scene, camera); // 渲染场景和相机
});

        注释:最后,这段代码设置了渲染循环,利用时钟对象控制动画的时间,并不断更新控制器和点云的旋转,最终渲染场景。

        通过上述的分层讲解之后,我们就大致的了解每一步都是如何操作并且为什么这么操作的了,为了使读者能更好的理解上述流程,这里我们在进行总结一下:

  1. 导入库

    • 使用Three.js库和OrbitControls模块,准备进行三维场景的创建和交互。

  2. 场景和相机设置

    • 创建一个三维场景并设置背景颜色。

    • 创建透视相机,设定相机的位置,准备从特定角度观察场景。

  3. 渲染器初始化

    • 创建WebGL渲染器,设置其大小与窗口相同,并将其添加到网页中以显示内容。

  4. 窗口大小自适应

    • 添加事件监听器,以确保在窗口大小变化时,自动调整相机的长宽比和渲染器的大小,保持渲染效果。

  5. 控制器设置

    • 创建轨道控制器,允许用户通过鼠标控制相机的旋转和缩放,增强用户交互体验。

  6. 全局变量和点属性初始化

    • 定义用于控制动画的全局变量和点的大小、位移数组,准备生成点的运动效果。

  7. 点的生成

    • 生成大量随机位置的点,包括中心球体内的点和周围分布的点,以增加视觉复杂度。

  8. 几何体和材质设置

    • 创建缓冲几何体,设置点的大小和位移信息。

    • 定义点的材质,使用自定义着色器来控制点的大小、颜色和移动效果。

  9. 点云创建和添加到场景

    • 将几何体和材质组合成点云对象,并设置初始旋转,最后将其添加到场景中以进行渲染。

  10. 渲染循环

    • 使用时钟对象进行动画控制,在每一帧中更新控制器、点云的旋转和动画时间,并渲染场景。

        ——至此,我们就讲解完了上述案例的所以步骤了!!!

——全部代码

        最后在让我们看一下最终的效果,(JavaScript没有极限!!!)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>秋刀鱼不做梦</title>
    <style>
        body {
            overflow: hidden;
            margin: 0;
        }
    </style>
</head>

<body>
    <script type="module">
        // 导入三维模型库
        import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
        // 导入轨道控制库
        import { OrbitControls } from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls";
        // 清除控制台
        console.clear()
        // 创建场景
        let scene = new THREE.Scene()
        // 设置场景背景颜色
        scene.background = new THREE.Color(0x160016)

        // 创建相机
        let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000)
        // 设置相机位置
        camera.position.set(0, 4, 21)

        // 创建渲染器
        let renderer = new THREE.WebGLRenderer()
        // 设置渲染器大小
        renderer.setSize(innerWidth, innerHeight)
        // 把渲染器加入到页面中
        document.body.appendChild(renderer.domElement)
        // 监听窗口大小变化事件
        window.addEventListener("resize", event => {
            camera.aspect = innerWidth / innerHeight
            camera.updateProjectionMatrix()
            renderer.setSize(innerWidth, innerHeight)
        })

        // 创建控制器
        let controls = new OrbitControls(camera, renderer.domElement)
        // 开启阻尼效果
        controls.enableDamping = true
        // 禁用面板
        controls.enablePan
        // 创建全局uniform
        let gu = {
            time: { value: 0 }
        }
        // 创建点的大小数组和移动数组
        let sizes = []
        let shift = []

        // 创建移动函数
        let pushShift = () => {
            shift.push(
                Math.random() * Math.PI,
                Math.random() * Math.PI * 2,
                (Math.random() * 0.9 + 0.1) * Math.PI * 0.1,
                Math.random() * 0.9 + 0.1
            )
        }

        // 创建点的顶点数组(中间的球体)
        // 创建一个长度为5万的数组pts并y用Array.prototype.map()方法遍历数组并对每个元素进行操作
        let pts = new Array(50000).fill().map(p => {
            // 每次遍历中,会向sizes数组中添加一个随机大小
            sizes.push(Math.random() * 1.5 + 0.5)
            // 调用pushShift()函数添加位置信息,并返回一个随机方向的THREE.Vector对象
            pushShift()
            return new THREE.Vector3().randomDirection().multiplyScalar(Math.random() * 0.5 + 9.5)
            //
        })

        // 添加更多的点(旁边围绕的)
        // 先循环生成十万个点
        // 每次循环中生成一个随机数rand,再生成一个随机半径radius

        for (let i = 0; i < 100000; i++) {
            let r = 10, R = 40;
            let rand = Math.pow(Math.random(), 1.5);
            let radius = Math.sqrt(R * R * rand + (1 - rand) * r * r);
            // 使用new THREE.Vector3().setFromCylindricalCoords()生成一个点。
            pts.push(new THREE.Vector3().setFromCylindricalCoords(radius, Math.random() * 2 * Math.PI, (Math.random() - 0.5) * 2));
            sizes.push(Math.random() * 1.5 + 0.5);
            pushShift();
        }
        // 生成一个点g,同时将点的大小和位置信息添加到sizes和shift数组中
        let g = new THREE.BufferGeometry().setFromPoints(pts)
        // 创建了一个缓冲几何体并设置sizes和shift属性
        // 注意这里的F要大写Float32BufferAttribute
        g.setAttribute("sizes", new THREE.Float32BufferAttribute(sizes, 1))
        g.setAttribute("shift", new THREE.Float32BufferAttribute(shift, 4))
        // 创建点材质
        let m = new THREE.PointsMaterial({
            // 表示点的大小
            size: 0.125,
            // 设置材质为透明
            transparent: true,
            // 表示禁用深度测试,使点可以叠加
            depthTest: false,
            // 使用假发混合模式
            blending: THREE.AdditiveBlending,
            // 在材质编译之前修改颜色器,在这里,它用来替换顶点着色器和片元着色器,添加uniform
            // 和attribute,以鸡自定义颜色和移动
            onBeforeCompile: shader => {
                shader.uniforms.time = gu.time
                // 首先,它为着色器设置了一个uniform变量time,该变量是在点材质中定义的,用来追踪时间
                // 然后它定义了两个attribute变量sizes和shift,这两个变量是在缓冲几何体中定义的,用来控制点的大小和移动
                // 最后使用replace方法来替换顶点着色器中的代码
                shader.vertexShader = `
                uniform float time;
                attribute float sizes;
                attribute vec4 shift;
                varying vec3 vColor;
                ${shader.vertexShader}
                `
                    // 注意上面的 ` 不要漏掉了
                    // 使用replace来替换着色器中的代码
                    // 更新点的大小
                    .replace(
                        `gl_PointSize = size;`,
                        `gl_PointSize = size * sizes;`
                    )
                    // 更新点的颜色
                    .replace(
                        `#include <color_vertex>`,
                        `#include <color_vertex>
                    float d = length(abs(position)/vec3(40.,10.,40));
                    d=clamp(d,0.,1.);
                    vColor = mix(vec3(227.,155.,0.),vec3(100.,50.,255.),d)/255.;`
                    )
                    // 记得加上分号
                    // 更新点的移动
                    .replace(
                        `#include <begin_vertex>`,
                        `#include <begin_vertex>
                            float t = time;
                            float moveT = mod(shift.x + shift.z * t,PI2);
                            float moveS = mod(shift.y + shift.z * t,PI2);
                            transformed += vec3(cos(moveS) * sin(moveT),cos(moveT),sin(moveS)*sin(moveT)) * shift.w;
                            `
                    )
                // 修改片元着色器,用来让点的边缘更加圆滑

                // 首先,定义一个varying变量vColor,这个变量是在顶点着色器中定义的,用来传递点的颜色到片段着色器
                // 然后使用replace方法来替换片段着色器的代码
                shader.fragmentShader = `
                    varying vec3 vColor;
                    ${shader.fragmentShader}
                `.replace(
                    `#include <clipping_planes_fragment>`,
                    `#include <clipping_planes_fragment>
                        float d = length(gl_PointCoord.xy - 0.5);
                    `
                ).replace(
                    // 记得加上空格
                    `vec4 diffuseColor = vec4( diffuse, opacity );`,
                    `vec4 diffuseColor = vec4( vColor, smoothstep(0.5, 0.1, d)/* * 0.5+0.5*/);`
                );
            }

        })
        // 创建点云并将其添加到场景中,并设置渲染循环
        let p = new THREE.Points(g, m)
        // 旋转顺序为"ZYX"
        p.rotation.order = "ZYX"
        // 旋转角度 0.2
        p.rotation.z = 0.2
        // 把对象(p)添加到场景(scene)中
        scene.add(p)
        // 创建一个时钟对象clock
        let clock = new THREE.Clock()
        // 渲染循环,每次循环中会更新控制器,更新p的旋转角度,更新时间
        renderer.setAnimationLoop(() => {
            // 更新控制器
            controls.update()
            // 获取时钟对象(clock)的已经流逝的时间(t)并将他乘0.5
            // 先把时钟关了
            let t = clock.getElapsedTime() * 0.5
            // 将gu.time.value 设置为t*Math.PI
            gu.time.value = t * Math.PI
            // 将对象(p)的旋转角度y设置为t*0.05
            p.rotation.y = t * 0.05
            // 渲染场景(scene)和相机(camera)
            renderer.render(scene, camera)
        })
    </script>
</body>

</html>


以上就是本篇文章的全部内容了!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript 生成二维码

我试过了&#xff0c;这一款js库支持中英文混合。 进入网站后&#xff0c;可以直接点击运行哟&#xff5e; https://andi.cn/page/621821.html

Vue全栈开发旅游网项目(6)-接口开发

1.景点详情接口开发 1.设计响应数据结构 文件地址&#xff1a;sight/serializers.py 创建类&#xff1a; class SightDetailSerializers(BaseSerializer):#景点详情def to_dict(self):obj self.objreturn {id: obj.id,name: obj.name,desc: obj.desc,img: obj.banner_img.…

【嵌入式】STM32中的SPI通信

SPI是由摩托罗拉公司开发的一种通用数据总线&#xff0c;其中由四根通信线&#xff0c;支持总线挂载多设备&#xff08;一主多从&#xff09;&#xff0c;是一种同步全双工的协议。主要是实现主控芯片和外挂芯片之间的交流。这样可以使得STM32可以访问并控制各种外部芯片。本文…

微服务系列一:基础拆分实践

目录 前言 一、认识微服务 1.1 单体架构 VS 微服务架构 1.2 微服务的集大成者&#xff1a;SpringCloud 1.3 微服务拆分原则 1.4 微服务拆分方式 二、微服务拆分入门步骤 &#xff1a;以拆分商品模块为例 三、服务注册订阅与远程调用&#xff1a;以拆分购物车为例 3.1 …

密码学简要介绍

密码学是研究编制密码和破译密码的技术科学&#xff0c;它研究密码变化的客观规律&#xff0c;主要包括编码学和破译学两大部分。 一、定义与起源 定义&#xff1a;密码学是研究如何隐密地传递信息的学科&#xff0c;在现代特别指对信息以及其传输的数学性研究&#xff0c;常被…

苄基异喹啉类生物碱的微生物合成-文献精读77

苄基异喹啉类生物碱的微生物合成研究进展及挑战 摘要 微生物发酵是一种经济高效、可持续的生产方式&#xff0c;可替代植物种植和化学合成来生产多种植物来源的药物。苄基异喹啉类生物碱作为植物来源生物碱的典型代表&#xff0c;具有多种重要的生理活性&#xff0c;已成为极具…

Centos安装配置Jenkins

下载安装 注意&#xff1a;推荐的LTS版本对部分插件不适配&#xff0c;直接用最新的版本&#xff0c;jenkins还需要用到git和maven&#xff0c;服务器上已经安装&#xff0c;可查看参考文档[1]、[2]&#xff0c;本次不再演示 访问开始使用 Jenkins 下载jenkins 上传至服务器…

【进度猫-注册/登录安全分析报告】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞…

【前端基础】盒子模型

目标&#xff1a;掌握盒子模型组成部分&#xff0c;使用盒子模型布局网页区域 01-选择器 结构伪类选择器 基本使用 作用&#xff1a;根据元素的结构关系查找元素。 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8">…

Webserver(2.8)守护进程

目录 守护进程案例 守护进程案例 每隔2s获取系统时间&#xff0c;将这个时间写入到磁盘文件中 #include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<unistd.h> #include<fcntl.h> #include<sys/time.h> #include<…

基于SpringBoot+微信小程序+协同过滤算法+二维码订单位置跟踪的农产品销售平台-新

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; “农产品商城”小程序…

Windows 10 安装使用Docker踩过的坑和解决-31/10/2024

目录 环境版本 一、Docker Desktop双击启动没反应&#xff0c;open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified. 二、Docker Desktop运行run命令时显示错误HTTP code 500 并且错误大意是服务器拒绝访问 三、Docker Engine stopped/启动…

AG32( MCU + FPGA)实现多串口(15个UART)的应用

AG32 的引脚定义 AG32只有模拟相关的IO是固定的&#xff0c;其它数字IO接口可以任意分配。 QFN-32Pin nameAG32VFxxxKAGRV2KQ321PIN_1IO/RTCIO_GB2PIN_2IO/OSC_INIO3PIN_3IO/OSC_OUTIO4NRSTNRSTNRST5PIN_5IO_ADC_IN12IO6VDDA33VDDA33VDDA337PIN_7IO_WKUP_ADC_IN0_CMP_PA0IO8PI…

CSS基础知识六(浮动的高度塌陷问题及解决方案)

目录 1.浮动高度塌陷概念 2.下面是几种解决高度塌陷的几种方案&#xff1a; 解决方案一&#xff1a; 解决方案二&#xff1a; 解决方案三&#xff1a; 1.浮动高度塌陷概念 在CSS中&#xff0c;高度塌陷问题指的是父元素没有正确地根据其内部的浮动元素或绝对定位元素来计…

014:无人机遥控器操作

摘要&#xff1a;本文详细介绍了无人机遥控器及其相关操作。首先&#xff0c;解释了油门、升降舵、方向舵和副翼的概念、功能及操作方式&#xff0c;这些是控制无人机飞行姿态的关键部件。其次&#xff0c;介绍了美国手、日本手和中国手三种不同的操作模式&#xff0c;阐述了遥…

GitHub | 发布到GitHub仓库并联文件夹的方式

推送到Github 推送步骤如果你只想更新单个文件&#xff0c;只需在第 4 步中指定该文件的路径即可。可能问题一 效果 推送步骤 更新 GitHub 仓库中的文件通常涉及以下步骤&#xff1a; 克隆仓库&#xff1a; 首先&#xff0c;你需要将 GitHub 上的仓库克隆到本地。使用 git …

qt QCloseEvent详解

1、概述 QCloseEvent 是 Qt 框架中用于处理窗口关闭事件的一个类。当用户尝试关闭一个窗口&#xff08;例如&#xff0c;通过点击窗口的关闭按钮&#xff0c;或者通过调用窗口的 close() 方法&#xff09;时&#xff0c;Qt 会生成一个 QCloseEvent 对象&#xff0c;并将其发送…

《JVM第5课》虚拟机栈

无痛快速学习入门JVM&#xff0c;欢迎订阅本免费专栏 Java虚拟机栈&#xff08;Java Virtual Machine Stack&#xff0c;简称JVM栈&#xff0c;又称Java方法栈&#xff09;是 JVM 运行时数据区的一部分&#xff0c;主要用于支持Java方法的执行。每当一个新线程被创建时&#xf…

数据迁移: 安全高效转移数据, 满足企业业务需求和技术改进

天津鸿萌科贸发展有限公司从事数据安全服务二十余年&#xff0c;致力于为各领域客户提供专业的数据存储、数据恢复、数据备份、数据迁移等解决方案与服务&#xff0c;并针对企业面临的数据安全风险&#xff0c;提供专业的相关数据安全培训。 鸿萌数据迁移业务为众多企业顺利高效…

w~自动驾驶~合集4

我自己的原文哦~ https://blog.51cto.com/whaosoft/12451789 #基于深度学习的端到端自动驾驶 最新的端到端自动驾驶综述刚刚出炉&#xff0c;话说论文一作卡内基梅隆大学的Apoorv Singh今年产出了七篇综述&#xff0c;都和自动驾驶相关&#xff0c;推荐给大家。就一个字&…