three.js实现3d球体树状结构布局——树状结构的实现

目录

    • 系列文章
    • 安装依赖
    • 基本分析
    • 实体类
      • 场景
      • 相机
      • 渲染器
      • 辅助线
      • 环境光
      • 点光源
      • 球形几何体
      • 球形几何体的材质
      • 线几何体
      • 线几何体的材质
      • 物体
      • 文本
      • 轨道控制
    • 实现效果
    • 实现源码
    • 参考文档

系列文章

    three.js实现3d球体树状结构布局——添加入场、出场、点击放大等动画

安装依赖

npm i three three-spritetext three.meshline

    three-spritetext: 用来绘制文字。THREE.TextGeometry绘制文字存在模糊问题,而且转动camera时three-spritetext不需要手动处理让文字始终面向camera。
    three.meshline: 用来绘制线。THREE.LineBasicMaterial绘制线存在linewidth无效问题。
    下面是此次案例版本

"three": "^0.150.1"
"three-spritetext": "^1.8.0"
"three.meshline": "^1.4.0"
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import SpriteText from 'three-spritetext';
import { MeshLine, MeshLineMaterial } from 'three.meshline'

基本分析

    如题three.js实现3d球体树状结构布局是我们此次案例要实现的目标,那我们需要的实体有球、线、文本,以及场景、相机、渲染器、辅助线、灯光等实体。下面我们按照实体一步步来实现。

实体类

场景

const createScene = () => {
    return new THREE.Scene();
}

相机

本例以透视投影相机PerspectiveCamera为例

const createPerspectiveCamera = ({ fov, aspect, near, far }) => {
    // fov — 摄像机视锥体垂直视野角度
    // aspect — 摄像机视锥体长宽比
    // near — 摄像机视锥体近端面
    // far — 摄像机视锥体远端面
    return new THREE.PerspectiveCamera(fov, aspect, near, far);
}

渲染器

const createWebGLRenderer = ({ dom, width, height }) => {
    // renderDom — dom
    // width — 渲染宽度 一般取domclientWidth
    // height — 渲染高度 一般取clientHeight
    if (width === undefined) {
        width = dom.clientWidth;
    }
    if (height === undefined) {
        height = dom.clientHeight;
    }
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    dom.appendChild(renderer.domElement);

    return renderer;
}

辅助线

const createAxesHelper = (length) => {
    return new THREE.AxesHelper(length)
}

环境光

const createAmbientLight = ({ color, intensity }) => {
    // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
    // intensity - (可选参数) 光照强度。 缺省值 1。
    return new THREE.AmbientLight(color, intensity);
}

点光源

// 环境光
const createPointLight = ({ color, intensity, distance, decay }) => {
    // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
    // intensity - (可选参数) 光照强度。 缺省值 1。
    // distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
    // decay - 沿着光照距离的衰退量。缺省值 2。
    return new THREE.PointLight(color, intensity, distance, decay);
}

球形几何体

const createSphereGeometry = ({
    radius,
    widthSegments,
    heightSegments,
    phiStart,
    phiLength,
    thetaStart,
    thetaLength
}) => {
    /*
        radius — 球体半径,默认为1。
        widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。
        heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。
        phiStart — 指定水平(经线)起始角度,默认值为0。。
        phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。
        thetaStart — 指定垂直(纬线)起始角度,默认值为0。
        thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。
    */
    return new THREE.SphereGeometry(
        radius,
        widthSegments,
        heightSegments,
        phiStart,
        phiLength,
        thetaStart,
        thetaLength
    );
}

球形几何体的材质

当然也可使用其他材质,本例使用MeshLambertMaterial

const createMeshLambertMaterial = (data) => {
    return new THREE.MeshLambertMaterial(data);
}

线几何体

const createLineGeometry = (points) => {
    const pointsVector3 = [];
    for (let i = 0; i < points.length; i++) {
        pointsVector3.push(new THREE.Vector3(points[i].x, points[i].y, points[i].z));
    }
    const geometry = new THREE.BufferGeometry().setFromPoints(pointsVector3);
    const line = new MeshLine();
    line.setGeometry(geometry);
    return line
}

线几何体的材质

const createMeshLineMaterial = (data) => {
    return new MeshLineMaterial({
        lineWidth: data.linewidth,
        color: data.color || "white",
        dashArray: data.dashArray || 0,
        transparent: true,
    })
}

物体

const createMesh = (geometry, materialBasic) => {
    return new THREE.Mesh(geometry, materialBasic);
}

文本

const createText = ({text, size, color}) => {
    let textClass = new SpriteText(text, size);
    textClass.color = color;
    return textClass
}

轨道控制

const createControl = (camera, dom) => {
    return new OrbitControls(camera, dom);
}

实现效果

在这里插入图片描述

实现源码

本案例以vue3编写

<script setup>
import { onMounted, ref, onBeforeUnmount, computed, reactive } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import SpriteText from "three-spritetext";
import { MeshLine, MeshLineMaterial } from "three.meshline";

// 渲染dom
let treeDom = ref(null);
// 场景
const createScene = () => {
    return new THREE.Scene();
};
// 相机(透视投影相机)
const createPerspectiveCamera = ({ fov, aspect, near, far }) => {
    /* 
        fov — 摄像机视锥体垂直视野角度
        aspect — 摄像机视锥体长宽比
        near — 摄像机视锥体近端面
        far — 摄像机视锥体远端面
    */
    return new THREE.PerspectiveCamera(fov, aspect, near, far);
};
// 渲染器
const createWebGLRenderer = ({ dom, width, height }) => {
    /* 
        renderDom — dom
        width — 渲染宽度 一般取domclientWidth
        height — 渲染高度 一般取clientHeight
    */
    if (width === undefined) {
        width = dom.clientWidth;
    }
    if (height === undefined) {
        height = dom.clientHeight;
    }
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    dom.appendChild(renderer.domElement);

    return renderer;
};
// 辅助线
const createAxesHelper = (length) => {
    return new THREE.AxesHelper(length);
};
// 环境光
const createAmbientLight = ({ color, intensity }) => {
    // color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
    // intensity - (可选参数) 光照强度。 缺省值 1。
    return new THREE.AmbientLight(color, intensity);
};
// 点光
const createPointLight = ({ color, intensity, distance, decay }) => {
    /*
        color - (可选参数)) 十六进制光照颜色。 缺省值 0xffffff (白色)。
        intensity - (可选参数) 光照强度。 缺省值 1。
        distance - 这个距离表示从光源到光照强度为0的位置。 当设置为0时,光永远不会消失(距离无穷大)。缺省值 0.
        decay - 沿着光照距离的衰退量。缺省值 2。
    */
    return new THREE.PointLight(color, intensity, distance, decay);
};
// 球形几何体
const createSphereGeometry = ({
    radius,
    widthSegments,
    heightSegments,
    phiStart,
    phiLength,
    thetaStart,
    thetaLength,
}) => {
    /*
        radius — 球体半径,默认为1。
        widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。
        heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。
        phiStart — 指定水平(经线)起始角度,默认值为0。。
        phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。
        thetaStart — 指定垂直(纬线)起始角度,默认值为0。
        thetaLength — 指定垂直(纬线)扫描角度大小,默认值为 Math.PI。
    */
    return new THREE.SphereGeometry(
        radius,
        widthSegments,
        heightSegments,
        phiStart,
        phiLength,
        thetaStart,
        thetaLength
    );
};
// 球形几何体的材质
const createMeshLambertMaterial = (data) => {
    return new THREE.MeshLambertMaterial(data);
};
// 线几何体
const createLineGeometry = (points) => {
    const pointsVector3 = [];
    for (let i = 0; i < points.length; i++) {
        pointsVector3.push(
            new THREE.Vector3(points[i].x, points[i].y, points[i].z)
        );
    }
    const geometry = new THREE.BufferGeometry().setFromPoints(pointsVector3);
    const line = new MeshLine();
    line.setGeometry(geometry);
    return line;
};
// 线几何体的材质
const createMeshLineMaterial = (data) => {
    return new MeshLineMaterial({
        lineWidth: data.linewidth,
        color: data.color || "white",
        dashArray: data.dashArray || 0,
        transparent: true,
    });
};
// 物体
const createMesh = (geometry, materialBasic) => {
    return new THREE.Mesh(geometry, materialBasic);
};
// 文本
const createText = ({ text, size, color }) => {
    let textClass = new SpriteText(text, size);
    textClass.color = color;
    return textClass;
};
// 轨道控制
const createControl = (camera, dom) => {
    return new OrbitControls(camera, dom);
};

// 3d树布局算法 灵感来源 梯形/三角形转换为圆锥
const computedDataWeight = (data) => {
    let weight = 0;
    for (let i = 0; i < data.length; i++) {
        let item = data[i];
        if (item?.children?.length) {
            item.weight = computedDataWeight(item.children);
            weight += item.weight;
        } else {
            item.weight = 1;
            weight += 1;
        }
    }
    return weight;
};
const computedArcRArr = (data, pointInterval) => {
    let ArcRArr = [];
    let ArcData = [];
    let ArcWeight = [];
    formatTreeToArcData(data, ArcData);

    for (let i = 0; i < ArcData.length; i++) {
        let item = ArcData[i];
        let weight = 0;
        for (let j = 0; j < item.length; j++) {
            weight += item[j].weight;
        }
        ArcWeight.push(weight);
    }
    let R = computedArcR(pointInterval, ArcWeight[0]);

    // 半径算法
    for (let i = 0; i < ArcData.length; i++) {
        let item = ArcData[i];
        if (ArcWeight[i] < ArcWeight[0]) {
            // 不是完全层
            ArcRArr.push(R);
        } else {
            if (item.length > 1) {
                // 完全层
                let DValue = 0;
                item.forEach((weight) => {
                    DValue += Math.floor(weight.weight / 2);
                });
                ArcRArr.push(((ArcWeight[i] - DValue) / ArcWeight[i]) * R);
            } else {
                ArcRArr.push(0);
            }
        }
    }
    return { ArcRArr, R };
};
const formatTreeToArcData = (data, ArcData, deep = 0) => {
    data.forEach((element) => {
        if (!ArcData[deep]) {
            ArcData[deep] = [];
        }
        ArcData[deep].push({
            label: element.label,
            point_uuid: element.point_uuid,
            weight: element.weight,
        });
        if (element?.children?.length) {
            formatTreeToArcData(element?.children, ArcData, deep + 1);
        }
    });
};
const computedArcR = (pointInterval, points) => {
    if (points === 1) {
        return pointInterval * 2;
    }
    let arcR =
        pointInterval /
        2 /
        Math.cos((Math.PI / 180) * (((points - 2) * 180) / points / 2));
    if (arcR < pointInterval) {
        arcR = pointInterval * 2;
    }
    return arcR;
};
const computedTreeStyleAuto = (style, ArcRArr, R) => {
    if (style.yr === "auto") {
        style.yr = ArcRArr.length === 1 ? R : R / (ArcRArr.length - 1);
    }
    style.startPositionY =
        ((ArcRArr.length - 1) / 2) * style.yr + style.centerXYZ[1];
};
const computedPointPosition = (
    data,
    style,
    ArcRArr,
    startAngle = 0,
    endAngle = Math.PI * 2,
    deep = 0
) => {
    let totalWight = 0;
    for (let i = 0; i < data.length; i++) {
        totalWight += data[i].weight;
    }
    let AngleScope = endAngle - startAngle;
    let curAngle = startAngle;
    for (let i = 0; i < data.length; i++) {
        let item = data[i];
        let ratioAngle = (item.weight / totalWight) * AngleScope;
        item.position = {
            x:
                Math.sin(curAngle + ratioAngle / 2) * ArcRArr[deep] +
                style.centerXYZ[0],
            y:
                style.startPositionY -
                deep * (style.yr || 0) +
                style.centerXYZ[1],
            z:
                Math.cos(curAngle + ratioAngle / 2) * ArcRArr[deep] +
                style.centerXYZ[2],
        };
        if (item?.children?.length) {
            computedPointPosition(
                item?.children,
                style,
                ArcRArr,
                curAngle,
                curAngle + ratioAngle,
                deep + 1
            );
        }
        curAngle += ratioAngle;
    }
};

// 计算camera初始位置
const computedCameraStyle = (style, dom, treeStyle, R) => {
    if (style.position === "auto") {
        style.position = {
            x: 0,
            y: treeStyle.yr * 1.5,
            z: R * 3,
        };
    }
    if (style.data === "auto") {
        style.data = {
            fov: 45,
            aspect: dom.clientWidth / dom.clientHeight,
            near: 0.1,
            far: R * R,
        };
    }
    if (style.lookAt === "auto") {
        style.lookAt = JSON.parse(JSON.stringify(treeStyle.centerXYZ));
    }
};

const treeStyle = {
    centerXYZ: [0, 0, 0],
    yr: "auto",
    pointInterval: 10,
};
const cameraStyle = {
    position: "auto",
    data: "auto",
    lookAt: "auto",
};
const sphereMeshStyle = {
    geometry: {
        radius: 1,
        widthSegments: 320,
        heightSegments: 160,
    },
    material: {
        color: "#ffffff",
        wireframe: false, //是否将几何体渲染为线框,默认值为false(即渲染为平面多边形)
    },
};
const lineMeshStyle = {
    material: {
        color: "#ffffff",
        linewidth: 0.2,
    },
};
const textMeshStyle = {
    material: {
        size: 0.5,
        color: "#ffffff",
    },
};
let scene = null;
let camera = null;
let renderer = null;
const init = (rendererDom) => {
    let data = [
        {
            name: "顶点",
            children: [
                {
                    name: "0",
                    children: [
                        {
                            name: "0-0",
                            children: [
                                {
                                    name: "0-0-0",
                                },
                                {
                                    name: "0-0-1",
                                    children: [
                                        {
                                            name: "0-0-1-0",
                                        },
                                    ],
                                },
                                {
                                    name: "0-0-2",
                                },
                            ],
                        },
                        {
                            name: "0-1",
                        },
                        {
                            name: "0-2",
                            children: [
                                {
                                    name: "0-2-0",
                                },
                                {
                                    name: "0-2-1",
                                },
                            ],
                        },
                    ],
                },
                {
                    name: "1",
                    children: [
                        {
                            name: "1-0",
                        },
                        {
                            name: "1-1",
                        },
                        {
                            name: "1-2",
                            children: [
                                {
                                    name: "1-2-0",
                                },
                                {
                                    name: "1-2-1",
                                },
                            ],
                        },
                    ],
                },
                {
                    name: "2",
                    children: [
                        {
                            name: "2-0",
                            children: [
                                {
                                    name: "2-0-0",
                                },
                                {
                                    name: "2-0-1",
                                },
                                {
                                    name: "2-0-2",
                                },
                            ],
                        },
                        {
                            name: "2-1",
                            children: [
                                {
                                    name: "2-1-0",
                                },
                                {
                                    name: "2-1-1",
                                },
                            ],
                        },
                        {
                            name: "2-2",
                        },
                    ],
                },
            ]
        }
    ];

    computedDataWeight(data);
    let { ArcRArr, R } = computedArcRArr(data, treeStyle.pointInterval);
    computedTreeStyleAuto(treeStyle, ArcRArr, R);
    computedPointPosition(data, treeStyle, ArcRArr);

    computedCameraStyle(cameraStyle, rendererDom, treeStyle, R);

    scene = createScene();
    camera = createPerspectiveCamera(cameraStyle.data);
    camera.position.set(
        cameraStyle.position.x,
        cameraStyle.position.y,
        cameraStyle.position.z
    );
    camera.lookAt(
        cameraStyle.lookAt[0],
        cameraStyle.lookAt[1],
        cameraStyle.lookAt[2]
    );
    renderer = createWebGLRenderer({
        dom: rendererDom,
    });

    createControl(camera, rendererDom);

    const axes = createAxesHelper(R);
    scene.add(axes);

    const ambientLight = createAmbientLight({ color: "#fff", intensity: 0.2 });
    scene.add(ambientLight);

    const pointLight = createPointLight({ color: "#fff", intensity: 1 });
    pointLight.position.set(R * 10, R * 10, R * 10);
    scene.add(pointLight);

    const sphereGeometrys = [];
    const textGeometrys = [];
    const lineGeometrys = [];
    initGeometrys(data, sphereGeometrys, textGeometrys, lineGeometrys);
    scene.add(...sphereGeometrys);
    scene.add(...textGeometrys);
    scene.add(...lineGeometrys);

    render();
};
const initGeometrys = (data, sphereGeometrys, textGeometrys, lineGeometrys, parentPosition) => {
    for (let i = 0; i < data.length; i++) {
        let item = data[i];

        const geometry = createSphereGeometry(sphereMeshStyle.geometry);
        const material = createMeshLambertMaterial(sphereMeshStyle.material);
        const mesh = createMesh(geometry, material);
        mesh.position.set(item.position.x, item.position.y, item.position.z);
        sphereGeometrys.push(mesh);

        const text = createText({
            text: item.name,
            size: textMeshStyle.material.size,
            color: textMeshStyle.material.color,
        });
        text.position.x = item.position.x;
        text.position.y = item.position.y + sphereMeshStyle.geometry.radius * 2;
        text.position.z = item.position.z;
        textGeometrys.push(text);

        if (parentPosition) {
            const lineGeometry = createLineGeometry([
                parentPosition,
                { x: item.position.x, y: item.position.y, z: item.position.z },
            ]);
            const lineMaterial = createMeshLineMaterial(lineMeshStyle.material);
            const lineMesh = createMesh(lineGeometry, lineMaterial);
            lineGeometrys.push(lineMesh);
        }

        if (item?.children?.length) {
            initGeometrys(
                item.children,
                sphereGeometrys,
                textGeometrys,
                lineGeometrys,
                { x: item.position.x, y: item.position.y, z: item.position.z }
            );
        }
    }
};
// 渲染
const render = () => {
    //循环调用
    requestAnimationFrame(render);
    renderer.render(scene, camera);
};

onMounted(() => {
    let rendererDom = treeDom.value;
    init(rendererDom);
});
</script>

<template>
    <div class="tree-new-page">
        <div class="tree-new" ref="treeDom"></div>
    </div>
</template>

<style scoped lang="scss">
.tree-new-page {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: #000;
    position: relative;
    .tree-new {
        width: 100%;
        height: 100%;
    }
}
</style>

参考文档

three.js官方文档
three-spritetext文档
three.meshline文档

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

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

相关文章

Adaptive AUTOSAR——Time Synchronization(VRTE 3.0 R21-11)

15 Time Synchronization 15.1 What is Time Synchronization? 时间同步是自适应平台基础中的一个功能集群。时间同步通过库向应用程序提供C API&#xff0c;该库作为RTA-VRTE入门套件的一部分提供&#xff0c;并与应用程序链接以访问该功能。 本版本包含非常少量的时间同步…

ASIC-WORLD Verilog(1)一日Verilog

写在前面 在自己准备写一些简单的verilog教程之前&#xff0c;参考了许多资料----asic-world网站的这套verilog教程即是其一。这套教程写得极好&#xff0c;奈何没有中文&#xff0c;在下只好斗胆翻译过来&#xff08;加了自己的理解&#xff09;分享给大家。 这是网站原文&…

Helm学习笔记

文章目录概念定义helm组件helm的工作流程helm安装helm仓库helm部署应用helm应用的更新或回退或卸载概念 定义 学习helm首先得了解helm是什么&#xff0c;我们先来看一下helm的定义&#xff1a;helm是将kubernetes的各种资源对象打包&#xff0c;类似于Linux中的yum工具&#…

【HTML系列】第六章 · 框架标签、HTML实体、HTML全局属性和meta元信息

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

【前端面试题——微信小程序】

目录1.请谈谈wxml与标准的html的异同&#xff1f;2.请谈谈WXSS和CSS的异同&#xff1f;3.请谈谈微信小程序主要目录和文件的作用&#xff1f;4.请谈谈小程序的双向绑定和vue的异同&#xff1f;5.简单描述下微信小程序的相关文件类型&#xff1f;6.微信小程序有哪些传值(传递数据…

jsp+javaEE+mysql校园物品租赁系统dzkf5294程序

1&#xff0e;物品信息管理&#xff1a;管理员发布物品信息后&#xff0c;普通用户便可以查询到该物品信息&#xff0c;用户选择某个物品信息&#xff0c;查询物品信息&#xff0c;管理员审核添加&#xff0c;或删除物品信息。 2&#xff0e;租赁管理&#xff1a;管理员发布租赁…

ChatGPT大解密:带您探讨机器学习背后的秘密、利用与发展

一、什么是机器学习&#xff1f;二、ChatGPT 的运作原理三、ChatGPT 生活利用1、自然语言处理2、翻译3、自动回复四、ChatGPT vs 其他相关技术五、ChatGPT 的未来1、未来发展2、职业取代3、客服人员4、翻译人员5、语言学家6、机遇与挑战六、结语这篇文章&#xff0c;将带着各位…

ThreeJS-投影、投影模糊(十七)

无投影&#xff1a; 完整的代码&#xff1a; <template> <div id"three_div"></div> </template> <script> import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/Or…

再不转型为ChatGPT程序员,有遭受降维打击的危险

Open AI在演示GPT-4的时候&#xff0c;有这么一个场景&#xff1a;给一个界面草图&#xff0c;就可以生成网页代码。这个演示非常简单&#xff0c;如果界面原型比较复杂呢&#xff1f;像这样&#xff1a;ChatGPT能不能直接生成HTML, CSS,JavaScript代码&#xff0c;把这个网页给…

MongoDB副本集Command failed with error 10107 (NotMaster):on server

问题 通过DataGrip连接的MongoDB节点&#xff0c;之前可以新增或更新数据。某天突然不能新增或更新数据&#xff0c;报错信息如下&#xff1a; 具体的报错信息&#xff1a; Command failed with error 10107 (NotMaster): not master on server 10.19.21.11:30386. The full…

HNU-电路与电子学-实验3

实验三 模型机组合部件的实现&#xff08;二&#xff09;&#xff08;实验报告格式案例&#xff09; 班级 计XXXXX 姓名 wolf 学号 2021080XXXXX 一、实验目的 1&#xff0e;了解简易模型机的内部结构和工作原理。 2&#xff0e;分析模型机的功能&am…

【Linux】LVM与磁盘配额

文章目录1.LVM1.1 LVM概述1.2 LVM机制1.3 LVM管理命令1.4 LVM应用实例2. 磁盘配额2.1 磁盘配额概述2.2 磁盘配额管理2.3 启用磁盘配额支持2.4 磁盘配额应用实例1.LVM 1.1 LVM概述 Logical Volume Manager&#xff0c;逻辑卷管理 ● 能够在保持现有数据不变的情况下动态调整磁盘…

43掌握自动化运维工具 Puppet 的基本用法,包括模块编写、资源管理

Puppet是一种自动化配置管理工具&#xff0c;可以自动化地部署、配置和管理大规模服务器环境。本教程将介绍Puppet的基本用法&#xff0c;包括模块编写和资源管理。 模块编写 在Puppet中&#xff0c;模块是一组相关的类、文件和资源的集合。模块可以用于部署和配置应用程序、服…

图形编辑器:排列移动功能的实现

大家好&#xff0c;我是前端西瓜哥。这次来实现一下图形编辑器排列&#xff08;arrange&#xff09;功能的实现。 先看效果。 有四种移动方式&#xff1a; 置顶&#xff08;Front&#xff09;&#xff1a;将指定的图形移动到顶部&#xff1b;置底&#xff08;Back&#xff09…

嵌入式学深度学习:1、Pytorch框架搭建

嵌入式学深度学习&#xff1a;1、Pytorch框架搭建1、介绍2、Pytorch开发环境搭建2.1、查看GPU是否支持CUDA2.2、安装Miniconda2.3、使用Conda安装pytorch2.4、安装常用库3、简单使用验证1、介绍 深度学习是机器学习的一种&#xff0c;如下图&#xff1a; 目前深度学习应用场景…

MySQL-四大类日志

目录 &#x1f341;MySQL日志分为4大类 &#x1f341;错误日志 &#x1f343;修改系统配置 &#x1f341;二进制日志 &#x1f343;查看二进制日志 &#x1f343;删除二进制日志 &#x1f343;暂时停止二进制日志的功能 &#x1f341;事务日志(或称redo日志) &#x1f341;慢查…

chatgpt3中文辅助写作-gpt2中文文本生成

GPT-3是一种深度学习模型&#xff0c;具有潜在的巨大计算成本和训练麻烦。根据OpenAI公司的官方消息&#xff0c;训练GPT-3是一项昂贵的和耗时的过程&#xff0c;在OpenAI公司&#xff0c;训练GPT-3的成本已经超过了10亿美元。考虑到GPT-3的架构、规模和训练时间&#xff0c;这…

高分子PEG磷酸盐mPEG-phosphoric acid,Phosphate PEG,甲氧基聚乙二醇磷酸,可用于修饰金属氧化物表面

规格单位&#xff1a;g |货期&#xff1a;按照具体的库存进行提供 | 端基取代率&#xff1a;95% 中英文名&#xff1a;mPEG-phosphoric acid|Phosphate PEG|甲氧基聚乙二醇磷酸​ 一、Phosphate PEG化学结构式&#xff1a; 二、产品详情&#xff1a; 外观&#xff1a;灰白…

[oeasy]python0123_中文字符_文字编码_gb2312_激光照排技术_王选

中文编码GB2312 回忆上次内容 上次回顾了 日韩各有 编码格式 日本 有假名 五十音一字节 可以勉强放下 有日本汉字 字符数量超过20000 韩国 有谚文 数量超过500一个字节 放不下 有朝鲜汉字 字符数量超过20000 作为 汉字源头的中国 究竟应该 如何对汉字 进行编码 呢&#x…

操作系统-AOSOA

一、个人感受 1.1 权衡 在我写这份报告的时候&#xff0c;已经是 6 月 30 号了&#xff0c;经历了一个学期的“折磨”&#xff0c;我面对终点&#xff0c;已经没啥感觉了&#xff0c;就想着赶快呼噜完了就完事了。其实做这个项目最大的体会就是“人力有穷&#xff0c;一切皆权…