3D知识入门

news2024/11/23 22:32:44

3D场景必备:scene, renderer, light, camera, model
一个基本代码:

 <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r127/three.min.js"></script>
 var scene = new THREE.Scene();
 var camera = new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);
 camera.position.set(0,0,50);
 var aLight = new THREE.AmbientLight(0xffffff,1);
 scene.add(aLight);
 var renderer = new THREE.WebGLRenderer({ });
 renderer.setSize(window.innerWidth,window.innerHeight);
 renderer.setSize(window.innerWidth,window.innerHeight);
 renderer.outputEncoding = THREE.sRGBEncoding;// 编码模式
 document.body.appendChild(renderer.domElement);
 renderer.render(scene,camera);

场景Scene

设置背景颜色背景图:

scene.background = new THREE.Color("#88B9DD");
scene.background = textureLoader.load();

设置背景透明:

var renderer = new THREE.WebGLRenderer( { alpha: true } );
renderer.setClearAlpha(0);

渲染器:

WebGLRenderer
属性:

灯光:

常用类型:

DirectionalLight 方向光

var dLight = new THREE.DirectionalLight(0x888888,1);
dLight.position.set(2,7,0);
dLight.target = box1;
scene.add(dLight)

AmbientLight 环境光

var light = new THREE.AmbientLight( 0x404040, 1.0 ); // soft white light
scene.add( light );

PointLight 点光源

var pLight = new THREE.PointLight(0xfff33f,1);
pLight.position.set(0,7,0);
scene.add(pLight);

相机:

PerspectiveCamera 远景相机

var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000 );

视角fov 宽高比aspect 近裁剪面near 远裁剪面 far

OrthographicCamera 正交相机

let width = window.innerWidth, height = window.innerHeight;
camera = new THREE.OrthographicCamera(-width/2, width/2, height/2, -height/2, 1, 1000);

left(-width/2) right(width/2) top(height/2) bottom(-height/2) near(1) far(1000)
常用于工程图等无需近大远小的项目

模型加载:

3D模型加载器: GLTFLoader, FBXLoader,
纹理加载器:TextureLoader

 const gltfLoader = new GLTFLoader();
 gltfLoader.load(modelUrl,function(gltf){
           const model = gltf.scene;
           model.position.set(0,-30,150);
           model.scale.set(300,300,300);
           model.rotation.set(0.3,0,0);
           scene.add(model);
       });

自己创建模型:

创建3D模型

var textureLoader = new THREE.TextureLoader();
var boxGeo = new THREE.BoxGeometry(1,1,1);
var texture = textureLoader.load('./imgs/1.jpg');
var mat = new THREE.MeshLambertMaterial({map:texture,side: THREE.DoubleSide});
var box = new THREE.Mesh(boxGeo,mat);
scene.add(box);

Box的不同面设置为不同的材质纹理:

var matArr = [mat1,mat2,mat1,mat2,mat1,mat2];
var mesh = new THREE.Mesh(boxGeo,matArr);

自定义材质索引

var matArr2 = [mat1,mat2];
boxGeo.groups[3].materialIndex = 0;
boxGeo.groups[4].materialIndex = 0;
boxGeo.groups[5].materialIndex = 0;
var mesh = new THREE.Mesh(boxGeo,matArr2);

网格Mesh

在这里插入图片描述
获取某个子元素:
getObjectByName, getObjectById,

常用属性:
children, position, scale, rotation(quaternion), name, up, userData
常用方法:
traverse,.traverseVisible,lookAt,.add,.remove,.clone,.getWorldPosition,.getWorldRotation,.getWorldScale
显示与隐藏Layer

材质Material-类型:

基本材质
var matBasic = new THREE.MeshBasicMaterial({color:0xeeff00,wireframe:false});// 不受光照影响,就算没有光也可以显示出来
兰伯特材质
var matLambert = new THREE.MeshLambertMaterial({color:0xeeff00,wireframe:false});// 此材质必须有环境光才能显示出来,只有漫反射
高光材质
var matPhong = new THREE.MeshPhongMaterial({// 此材质必须有光才能显示出来,只有镜面反射
            color:0xeeff00,
            wireframe:false,
            specular:0x11ffee,
            shininess:10
        });// 高光材质 specular高光颜色  shininess 光照强度系数
精灵材质
var spriteMaterial = new THREE.SpriteMaterial({
        map: texture //设置精灵纹理贴图
     });
点材质
const pointMat =  new THREE.PointsMaterial({
         // color: 0xff0000,// 使用顶点颜色数据渲染模型,不需要再定义color属性
         // 属性.vertexColors的默认值是THREE.NoColors,也就是说模型的颜色渲染效果取决于材质属性.color,
         // 如果把材质属性.vertexColors的值设置为THREE.VertexColors,渲染模型时就会使用几何体的顶点颜色数据geometry.attributes.color
         vertexColors: THREE.VertexColors, // 以顶点颜色为准  
         size: 0.2
     });
标准材质:
const material = new THREE.MeshStandardMaterial({
        color: "#ffff00",
        map: doorColorTexture,// 色彩贴图
        alphaMap: doorAplhaTexture,// 透明度贴图,0(黑色)代表完全透明,1(白色)代表完全不透明,0.5(灰色)代表半透明
        transparent: true, 
        aoMap: doorAoTexture,// 环境遮挡贴图,使纹理对光的穿透效果不同
        aoMapIntensity: 1,// 遮挡强度,该值乘以贴图以调整效果
        displacementMap: doorHeightTexture,// 置换贴图,使顶点位置发生位移(设置同时需要把顶点数量segment设置多一些)
        displacementScale: 0.1,// 该值乘以贴图以调整位移距离效果 未设置map似乎无效
        roughness: 1,// 粗糙度设置,1代表完全粗糙,0代表完全光滑 如果同时设置map会乘以map的值以调整map的显示效果
        roughnessMap: roughnessTexture,// 粗糙度贴图 1(白色)代表完全粗糙,0(黑色)代表完全光滑,0.5(灰色)代表半粗糙半光滑
        metalness: 1,// 金属度设置 1代表最强 0 代表最弱,0.5代表中间程度 如果同时设置map会乘以贴图以调整金属度效果
        metalnessMap: metalnessTexture,// 金属度贴图 
        normalMap: normalTexture,// 法线向量(三个数)对应一个色彩值(三个数),用色彩值形成图片代表法线向量 使光线照射上去凹凸位置看起来不同(光线折射方向不同) 不设置将导致金属部分看起来无凹凸感
        opacity: 0.3,
        side: THREE.DoubleSide,
     });

常用属性map,color,side

纹理贴图

var textureLoader = new THREE.TextureLoader();
textureLoader.load('./imgs/1.jpg',function(texture){// 异步,
     var mat = new THREE.MeshLambertMaterial({map:texture,side: THREE.DoubleSide});
     var box = new THREE.Mesh(boxGeo,mat);
     scene.add(box);
 });

属性:

// 纹理贴图重复模式   默认ClampToEdgeWrapping  重复排列:RepeatWrapping  镜像重复排列(重复部分呈现镜像纹理):MirroredRepeatWrapping
 texture1.wrapS = THREE.RepeatWrapping;
 texture1.wrapT = THREE.RepeatWrapping;
 // uv两个方向纹理重复数量
 texture1.repeat.set(1,2);

 // 纹理偏移设置
 // texture1.offset = new THREE.Vector2(0.2,0);
 texture1.offset.set(0.2,0);
 
 texture1.rotation = Math.PI / 4;// 纹理旋转
 texture1.center.set(0.5,0.5);// 纹理旋转中心(默认0,0)

 // texture纹理显示设置 当纹理像素不足以覆盖模型的时候,怎么渲染(使用最近的像素值--会显示方块形像素点/线性渲染--会模糊)
 texture.minFilter = THREE.NearestFilter;
 texture.minFilter = THREE.LinearFilter;

 // texture纹理显示设置 当纹理像素数量多于覆盖像素点的时候,怎么渲染
 texture.magFilter = THREE.NearestFilter;
 texture.magFilter = THREE.LinearFilter;
cube纹理(了解)
const cubeTextureLoader = new THREE.CubeTextureLoader();
const envMap = cubeTextureLoader.load([
     'texture/pisa/px.png',
     'texture/pisa/nx.png',
     'texture/pisa/py.png',
     'texture/pisa/ny.png',
     'texture/pisa/pz.png',
     'texture/pisa/nz.png',
 ]);
 scene.background = envMap;
 scene.environment = envMap;
hdr纹理(了解)
const rgbeLoader = new THREE.RGBELoader();
rgbeLoader.loadAsync('texture/yuanlin.hdr').then(texture => {
    texture.mapping = THREE.EquirectangularReflectionMapping;
    scene.background = texture;
    scene.environment = texture;
});

形状Geometry

类型:BufferGeometry,BoxGeometry,TextGeometry,PlaneGeometry等
在这里插入图片描述

var bufferGeo = new THREE.BufferGeometry();
const positions = new Float32Array([
            0, 0, 0, //顶点1坐标
            0.5, 0, 0, //顶点2坐标
            0, 1, 0, //顶点3坐标

            0, 0, 0, //顶点4坐标
            0, 0, 1, //顶点5坐标
            0.5, 0, 0, //顶点6坐标
        ]);
const colors = new Float32Array([
                 1, 0, 0, //顶点1颜色
                  0, 1, 0, //顶点2颜色
                  0, 0, 1, //顶点3颜色

                  1, 1, 0, //顶点4颜色
                  0, 1, 1, //顶点5颜色
                  1, 0, 1, //顶点6颜色
              ]);
// 物体有漫反射、镜面反射,太阳光照在一个物体表面,物体表面与光线夹角位置不同的区域明暗程度不同
// WebGL中为了计算光线与物体表面入射角,首先要计算物体表面每个位置的法线方向,
// 没有法向量数据,点光源、平行光等带有方向性的光源不会起作用(物体无法参与光照计算)
// 两个三角形表面法线不同,即使光线方向相同,明暗依然不同,在分界位置将有棱角感。
// 顶点法向量数据和顶点位置数据、顶点颜色数据都是一一对应的。
const normals = new Float32Array([
    0, 0, 1, //顶点1法向量
    0, 0, 1, //顶点2法向量
    0, 0, 1, //顶点3法向量

    0, 1, 0, //顶点4法向量
    0, 1, 0, //顶点5法向量
    0, 1, 0, //顶点6法向量
])
// 创建顶点索引数组的时候,可以根据顶点的数量选择类型数组Uint8Array、Uint16Array、Uint32Array。
// 对于顶点索引而言选择整型类型数组,对于非索引的顶点数据,需要使用浮点类型数组Float32Array等
const indexes = new Uint16Array([// 用于解决重复顶点的问题,重复顶点不需要重复设置位置和法线数据,只需要用索引指向对应的数据即可
                    // 0对应第1个顶点位置数据、第1个顶点法向量数据
                    // 1对应第2个顶点位置数据、第2个顶点法向量数据
                    // 索引值3个为一组,表示一个三角形的3个顶点
                    0, 1, 2,
                    0, 2, 3,
                ])
bufferGeo.setAttribute("position", new THREE.BufferAttribute(positions, 3));
bufferGeo.setAttribute('color', new THREE.BufferAttribute(colors, 3));
bufferGeo.setAttribute('normal', new THREE.BufferAttribute(normals,3));
bufferGeo.setAttribute('index', new THREE.BufferAttribute(indexes,1));
const points = [];
points.push( new THREE.Vector3( - 1, 0, 0 ) );
points.push( new THREE.Vector3( 0, 1, 0 ) );
points.push( new THREE.Vector3( 1, 0, 0 ) );
const bufferGeo2 = new THREE.BufferGeometry().setFromPoints( points );// 绑定顶点到空几何体
const rectHalfWidth = 0.5,rectHalfHeight = 1;
const rectShape = new THREE.Shape();
rectShape.moveTo(-rectHalfWidth,rectHalfHeight);
rectShape.lineTo(rectHalfWidth,rectHalfHeight);
rectShape.lineTo(rectHalfWidth,-rectHalfHeight);
rectShape.lineTo(-rectHalfWidth,-rectHalfHeight);
rectShape.lineTo(-rectHalfWidth,rectHalfHeight);
const shapeGeo = new THREE.ShapeGeometry(rectShape);

组Group

在这里插入图片描述

var tags = new THREE.Group();

精灵:

var spriteMaterial = new THREE.SpriteMaterial({
              map: texture //设置精灵纹理贴图
          });
var sprite = new THREE.Sprite(spriteMaterial);
sprite.scale.set(textureScale[0] * 1.5, textureScale[1] * 1.5, textureScale[2] * 1.5);
sprite.position.set(pos.x, 12, pos.z);
sprite.name = name;
model.add(sprite)

模型变换

<script src="js/OrbitControls.js"></script>
var controls = new THREE.OrbitControls(camera)
controls.enableZoom = true
 //controls.autoRotate = true;
 controls.minDistance = 10;
 controls.maxDistance = 300;
 controls.maxPolarAngle = 1.5;
 controls.minPolarAngle = 1.5;
 controls.enablePan = false;
 animate()
 function animate(){
        controls.update()
        requestAnimationFrame(animate);
        renderer.render(scene,camera);
    }

数学工具

向量:

三维向量Vector3,Vector4,Color
类似于js {x: 0, y: 0, z: 0}
方法:
setX,setY,setZ,copy,add,sub,multiplyScalar,divideScalar,dot,normalize,floor,ceil,round,roundToZero,addScalar,divide,min,max,multiply,toArray

欧拉角Euler:

方法:
set,copy,clone,equals

鼠标拾取:Raycaster

let mousePosition = new THREE.Vector2();
mousePosition.x = (touch.x / window.innerWidth) * 2 - 1;
mousePosition.y = -(touch.y / window.innerHeight) * 2 + 1;
var raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mousePosition, camera);
let intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
}

播放动画Amimation

const clock = new THREE.Clock;

const mixer = new THREE.AnimationMixer(fbx);
const action = mixer.clipAction(fbx.animations[0]);
action.play();
timer = setInterval(() => {
  mixer.update(clock.getDelta());
}, 10);

模型规范与案例讲解:

gltf-UnityTestUtil

<!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>gltf模型导出规范工具</title>
    <style>
        *{
            padding: 0;
            margin: 0;
            overflow: hidden;
        }
        .info{
            position: fixed;
            left: 0;
            top: 0;
        }
        .tip{
            color: orange;
        }
    </style>
</head>
<body>
    <div class="info">
        <h3>使用说明:</h3>
        <ol>
            <li> 打开 <a  href="https://blog.csdn.net/qq_34568700/article/details/107139489" target="_blank">链接</a>这个网址根据文章设置浏览器跨域(如已设置请忽略)</li>
            <li>将3D模型放入gltf文件夹</li>
            <li>在当前网址拼接“?name=文件名”,例如:gltfTest.html?name=yu</li>
            <li>鼠标拖动可以移动模型,用于检查移动灵敏度和坐标轴方向;虚拟摇杆旋转3D模型来检查模型的旋转中心点是否正确等问题;鼠标滚轮缩放模型检查缩放速度</li>
        </ol>
        <h3>模型规范检查清单</h3>
        <ul>
            <li>文件夹层级:name/name.gltf </li>
            <li>文件(上述中的name值)命名: 全英文,描述这个3D模型的名字 ,<span class="tip">禁止出现中文,空格,特殊字符</span></li>
            <li>文件导出类型:gltf</li>
            <li>模型初始位置:位于原点(参考红绿线条原点位置)</li>
            <li>模型初始大小:统一单位(cm)大小:可完整显示在浏览器中的合理大小</li>
            <li>模型初始角度:便于观察模型特征的合理角度(所有鱼头方向保持统一方向)</li>
            <li>模型旋转中心点:旋转中心点位置为模型重心位置;</li>
        </ul>
    </div>
    <script src="./js/three.js"></script>
    <script src="./js/loaders/GLTFLoader.js"></script>
    <script>
        (function(){
            var winWidth = window.innerWidth,winHeight = window.innerHeight;
            var name = GetQueryString('name');
            var dirImpulse = [], currModel;
            var mOnDown = false,
                mLastPosition = new THREE.Vector2();

            var scene = new THREE.Scene();
            var camera = new THREE.OrthographicCamera(winWidth / -2, winWidth / 2, winHeight / 2, winHeight/-2, 0.01,500);
            camera.position.z = 200;
            camera.lookAt(new THREE.Vector3(0,0,0))
            scene.add(new THREE.AmbientLight(0xffffff, 1));

            var gltfLoader = new GLTFLoader();
            gltfLoader.load(`./gltf/${name}/${name}.gltf`, (obj) => {
                let m = obj.scene;
                scene.add(m);
                currModel = m;

                let clock = new THREE.Clock();
                let mixer = new THREE.AnimationMixer(m); // 创建混合器
                let AnimationAction = mixer.clipAction(obj.animations[0]); // 返回动画操作对象
                AnimationAction.timeScale = 1.5;
                AnimationAction.play();
                setInterval(() => {
                    mixer.update(clock.getDelta());
                }, 10);
            });

            var axesHelper = new THREE.AxesHelper( 300 );
            scene.add( axesHelper );    

            var renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true,
                // preserveDrawingBuffer: true
            });
            renderer.setSize(winWidth,winHeight);// 不在这里设置,而在css里设置模型将变的模糊
            renderer.outputEncoding = THREE.sRGBEncoding;
            document.body.appendChild(renderer.domElement);
            ani()
            function ani(){
                renderer.render(scene,camera);
                requestAnimationFrame(ani);

                let [x,y] = dirImpulse;
                if (Math.abs(x) > Math.abs(y)) {
                    if (x > 0) {// right
                        currModel.rotation.y -= 0.04;
                    } else if (x < 0) {// left
                        currModel.rotation.y += 0.04;
                    }
                } else {
                    if (y > 0) {// bottom
                        currModel.rotation.x += 0.04;
                    } else if (y < 0) {// top
                        currModel.rotation.x -= 0.04;
                    }
                }
            }


            document.body.addEventListener('mousedown', mouseDown, false);
            document.body.addEventListener('mousemove', mouseMove, false);
            document.body.addEventListener('mouseup', mouseUp, false);
            window.onmousewheel = document.onmousewheel = wheel;
            function mouseDown(e) {
                mOnDown = true;
                mLastPosition.set(e.pageX , e.pageY);
            }
            function mouseMove(e){
                if (mOnDown) {
                    let currX = e.pageX || e.touches[0].pageX;
                    let currY = e.pageY || e.touches[0].pageY;
                    let deltaX = currX - mLastPosition.x;
                    let deltaY = currY - mLastPosition.y;
                    currModel.position.x += deltaX;
                    currModel.position.y -= deltaY;
                    mLastPosition.set(currX,currY);
                }
            }
            function mouseUp(e) {
                //设置bool值
                mOnDown = false;
                mLastPosition.set(0,0);
            }
            function wheel(event){
                var delta = 0;
                if (!event) event = window.event;
                if (event.wheelDelta) {//IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
                    delta = event.wheelDelta/120; 
                    if (window.opera) delta = -delta;//因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
                } else if (event.detail) {//FF浏览器使用的是detail,其值为“正负3”
                    delta = -event.detail/3;
                }
                if (delta)
                    currModel.scale.addScalar(delta);
            }

            initRocker();
            // 绘制摇杆
            function initRocker(){
                let outerDiameter = 100;// 外圆直径
                let innerDiameter = 35;// 内圆直径
                let outerRadius = outerDiameter / 2;
                let innerRadius = innerDiameter / 2;
                let centerNum = (outerDiameter - innerDiameter) / 2;// 内圆位置
                let rockerBox = document.createElement('div');
                setStyle(rockerBox,{
                    width: `${outerDiameter}px`,
                    height: `${outerDiameter}px`,
                    borderRadius: `${outerRadius}px`,
                    position: 'fixed',
                    bottom: '2rem',
                    right: '4rem',
                    zIndex: 100,
                    background: 'url("./imgs/rocker-bg.png") no-repeat center',
                    backgroundSize: 'contain'
                });
                document.body.appendChild(rockerBox);

                let rockerBtn = document.createElement('div');
                setStyle(rockerBtn,{
                    position: 'absolute',
                    width: `${innerDiameter}px`,
                    height: `${innerDiameter}px`,
                    left: `${centerNum}px`,
                    bottom: `${centerNum}px`,
                    borderRadius: `${innerRadius}px`,
                    background: '#fbbb1d',
                });
                rockerBox.appendChild(rockerBtn);

                // 添加移动监控事件
                let startPos = {x:0,y:0};
                let disX = 0,disY = 0;
                function onDown(e){
                    e.stopPropagation();
                    startPos.x = e.clientX || e.touches[0].clientX;
                    startPos.y = e.clientY || e.touches[0].clientY;
                    document.addEventListener('mousemove',onMove,false);
                    document.addEventListener('touchmove',onMove,false);
                }
                function onMove(e){
                    e.stopPropagation();
                    let clientX = e.clientX || e.touches[0].clientX;
                    let clientY = e.clientY || e.touches[0].clientY;
                    let maxNum = centerNum + 5;
                    disX = (clientX - startPos.x) ;
                    disY = (clientY - startPos.y) ;
                    // 圆心位置 (100,100) (div.style.x + 40, div.style.y + 40)
                    disX = disX > maxNum ? maxNum : (disX < -maxNum ? -maxNum : disX);
                    disY = disY > maxNum ? maxNum : (disY < -maxNum ? -maxNum : disY);
                    if ((Math.pow(disX,2) + Math.pow(disY,2)) > Math.pow(maxNum,2)) {
                        if (disY > 0) {
                            disY = Math.sqrt(Math.pow(maxNum, 2) - Math.pow(disX,2));
                        } else if (disY < 0) {
                            disY = -Math.sqrt(Math.pow(maxNum, 2) - Math.pow(disX,2));
                        }
                    }
                    
                    rockerBtn.style.transform = `translate(${disX}px,${disY}px)`;
                }
                rockerUp = function (e){
                    e.stopPropagation();
                    document.removeEventListener('mousemove',onMove,false);
                    document.removeEventListener('touchmove',onMove,false);
                    disX = 0;
                    disY = 0;
                    rockerBtn.style.transform = 'translate(0,0)';
                }

                rockerBtn.addEventListener('mousedown',onDown,false);
                document.body.addEventListener('mouseup',rockerUp,false);

                rockerBtn.addEventListener('touchstart',onDown,false);
                document.body.addEventListener('touchend',rockerUp,false);

                function moveFrame(){
                    requestAnimationFrame(moveFrame);
                    dirImpulse = [disX, disY];
                }
                moveFrame();
            };

            // 工具函数         
            function setStyle(dom,options,fn){
                new Promise(function(resolve,reject){
                    for (let key in options){
                        dom.style[key] = options[key];
                    }
                    resolve();
                }).then(res => {
                    if (fn) {
                        fn()
                    }
                }).catch(err => {
                    console.log(err)
                })
            }   

            function GetQueryString(name) {
                var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
                var r = window.location.search.substr(1).match(reg);
                if (r != null)
                    return r[2];     //注意这里不能用js里面的unescape方法
                return null;
            }

        }())
    </script>
</body>
</html>

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

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

相关文章

【EKS】基于Amazon EKS搭建kubernetes集群

文章目录 前言 | 亚马逊云科技 re:Invent前沿资讯一、介绍篇&#x1f3a8;什么是AWS 云计算什么是Amazon EKS 二、部署篇&#x1f528;1、创建集群VPC2、创建集群子网3、创建IGW网关4、创建路由表与子网绑定5、EKS集群创建6、创建kubeconfig配置文件7、添加计算节点组8、查看EK…

IC卡水表大多都用在什么项目上?有什么功能特点吗?

IC卡水表是一种先进的计量仪表&#xff0c;广泛应用于许多项目&#xff0c;其功能特点使其在许多领域得到广泛应用。 首先&#xff0c;IC卡水表可以应用于自来水的计量&#xff0c;它可以高精度地测量水的流量&#xff0c;提供给用户准确的用水量信息&#xff0c;从而有助于用户…

分片架构,Redis Cluster 分析

分片架构解决的问题 通过堆机器&#xff0c;提升读写性能&#xff0c;与存储性能 分片架构设计要点 分片规则 选择Cardinality大的作为分片键&#xff0c;尽可能保证数据分布均匀 常见分片键&#xff1a; 基于主键&#xff08;业务型数据&#xff09;&#xff0c;基于时间…

JavaScript高级四、高阶技巧

零、文章目录 JavaScript高级四、高阶技巧 1、深浅拷贝 首先浅拷贝和深拷贝只针对引用类型 &#xff08;1&#xff09;浅拷贝 浅拷贝&#xff1a;拷贝对象的属性的值&#xff08;简单类型存的值就是值本身&#xff0c;引用类型存的值是对象的堆地址&#xff09;&#xff0c…

windows里怎么杀死一个进程?

我们可以使用 taskkill 命令&#xff0c;可以使用该工具按照进程 ID (PID) 或映像名称终止任务。 显示帮助消息&#xff1a; taskkill /?参数列表&#xff1a; /S&#xff1a;system&#xff1a;指定要连接的远程系统。/U&#xff1a;[domain\]user&#xff1a;指定应该在哪…

【ESP-01S / ESP8266 AT指令连接阿里云物联网平台】

ESP-01S / ESP8266 AT指令连接阿里云物联网平台 阿里云物联网平台新建设备获取AT参数 AT指令介绍连接阿里云AT指令介绍MQTT固件固件下载硬件连接固件烧录 串口助手调试硬件连接测试指令 AT_Command移植总结问题排查 源码获取 关注星标公众号&#xff0c;不错过精彩内容 作者 | …

【简单实用框架】【十大排序算法直接调用】【可移植】

☀️博客主页&#xff1a;CSDN博客主页&#x1f4a8;本文由 萌萌的小木屋 原创&#xff0c;首发于 CSDN&#x1f4a2;&#x1f525;学习专栏推荐&#xff1a;面试汇总❗️游戏框架专栏推荐&#xff1a;游戏实用框架专栏⛅️点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd;&#…

JeecgBoot企业级开发中实现自定义导出EXCEL的前端表格字段功能

文章目录 如何在后端实现导出前端列表字段到Excel功能需求前端的实现1. 提供一个导出的点击函数2.引入组件中的userMethod3.tableProps中导出中添加对应的查询参数4. 编写导出函数 后端逻辑的实现1.Controller层2.创建Modal类3.Sevice层 检验成果总结 如何在后端实现导出前端列…

【Android Gradle 插件】更新依赖方式,同时解决github三方库引用无法使用问题

首先看一下完整的 settings.gradle 依赖介绍 /* pluginManagement 脚本块,用于配置Gradle插件的Maven仓库,配置的是构建过程中,使用的仓库 ; pluginManagement 脚本块中的 repositories 配置 , 对应之前的 buildscript 中的 repositories 配置 ; */ pluginManagement {reposit…

技术分享 | 一文了解 MySQL Optimizer Trace 的神奇功效

作者&#xff1a;Mutlis CSDN & 阿里云 & 知乎 等平台优质作者&#xff0c;擅长Oracle & MySQL等主流数据库系统的维护和管理等 本文来源&#xff1a;原创投稿 前言 对于 MySQL 5.6 以及之前的版本来说&#xff0c;查询优化器就像是一个黑盒子一样&#xff0c;…

迪赛智慧数——柱状图(基本柱状图):购买雪糕考虑的因素

效果图 冰淇淋季节来袭&#xff0c;因其细腻凉爽的口感和浓郁的口味被广大消费者所钟爱&#xff0c;近年来已经从一款传统的解暑冷冻饮品转变为一种原料丰富、口味多元、追求健康、愉悦和高品质生活方式的休闲食品。据数据显示&#xff0c;82.2&#xff05;女性、82.3%男性消费…

chatgpt赋能python:Python中乘方的介绍

Python中乘方的介绍 在Python中&#xff0c;乘方运算指数运算&#xff0c;常用符号为“”&#xff08;例如2的3次方为23&#xff09;。使用乘方运算可以快速地进行数值计算&#xff0c;尤其是在科学和工程领域中。 为什么要使用乘方运算&#xff1f; 乘方运算主要用于处理大…

NeRF算法

Instant-ngp Instant-ngp简单介绍 Instant-ngp论文链接 英伟达实现的github链接 taichi实现Instant-ngp taichi实现的github链接 渲染 采用体素渲染方法&#xff0c;从相机光线出发&#xff0c;逐步采样3D场景中的三维坐标点的颜色&#xff0c;即可渲染出3D画面。如果直接将3…

进阶神册,Redis+Nginx+设计模式+Spring全家桶+Dubbo核心技术笔记

最近花了很长的时间去搜罗Java核心技术好文&#xff0c;我把每个Java核心技术的优选文章都整理成了一个又一个的文档。昨天也是终于全部整理好了&#xff0c;今天就把这些东西分享给老铁们&#xff0c;也能为老铁们省去不少麻烦&#xff0c;想学什么技能了&#xff0c;遇到哪方…

vue3组件通信详解

vue3组件通信方式有以下几种&#xff1a;porps&#xff0c;$emit&#xff0c; bus&#xff0c;v-model&#xff0c;useAttrs&#xff0c;$ref/$parent&#xff0c;provide/inject&#xff0c;pinia&#xff0c;slot。下面将逐一讲解。 目录 1.porps&#xff1a;实现父子组件通…

V7.0_增加消息队列功能

一&#xff0c;功能描述 增加消息队列&#xff1b;使用自定义copy功能时&#xff0c;子进程copy结束后向父进程发送消息&#xff08;通过消息队列&#xff09;然后exit&#xff1b;此时因wait&#xff08;&#xff09;而处于阻塞态的父进程终于解除了阻塞并且从队列中读取到消…

【云原生-K8s-1】kubeadm搭建k8s集群(一主两从)完整教程及kubernetes简介

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录 Kubernetes简介1 kubernetes架构1.1m…

清凉一夏小风扇-React版

这里写目录标题 前言 一、效果二、代码分享三、总结 前言 本片文章主要是做一个小练习&#xff0c;通过react来制作一个风扇练习css动画。 vue3实现部分看这里–> 一、效果 二、代码分享 1、主体框架 “react”: “^18.2.0” “sass”: “^1.62.1” 2、主要技术点 使用事…

企业上云容灾如何实现碳中和?

随着能源成本的增加和数据消费的激增&#xff0c;“电耗”和“碳排放”成为今年世界移动通信大会热议的话题。目前&#xff0c;ICT行业耗电量约占全球用电量的7%。预计到2040年&#xff0c;ICT行业碳排放量占全球排放量的比例将上升至14%。 容灾是企业为了在灾难时保证业务继续…

基于html+css的图展示99

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…