three.js官方案例webgl_loader_fbx.html学习

目录

1.1 添加库引入

1.2 添加必要的组件scene,camera,webrenderer等

1.3 模型加载

1.4 半球光

1.5 动画

1.6 换个自己的fbx模型

1.7 fbx模型和fbx动画关联

1.7 html脚本全部如下

1.8 fbx.js全部脚本如下


1.1 添加库引入

import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
 //控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 //fbx模型加载器
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';

1.2 添加必要的组件scene,camera,webrenderer等

      先创建必要的场景scene,相机camera,渲染器webrenderer,控制器controls和灯光DirectionalLight.   性能检测stars,  地面, 网格

自定义属性

let camera, scene, renderer, stats;

	function init() {

				const container = document.createElement( 'div' );
				document.body.appendChild( container );
                //相机
				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
				camera.position.set( 100, 200, 300 );
                //场景
				scene = new THREE.Scene();
				scene.background = new THREE.Color( 0xa0a0a0 );
				scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );//雾
            
                //灯 模拟太阳光
				const dirLight = new THREE.DirectionalLight( 0xffffff, 5 );
				dirLight.position.set( 0, 200, 100 );
				dirLight.castShadow = true;//此属性设置为 true 灯光将投射阴影 注意:这样做的代价比较高,需要通过调整让阴影看起来正确。 查看 DirectionalLightShadow 了解详细信息。 默认值为 false
                //dirLight.shadow 为DirectionalLightShadow 对象,用于计算该平行光产生的阴影
                //.camera 在光的世界里。这用于生成场景的深度图;从光的角度来看,其他物体背后的物体将处于阴影中
				dirLight.shadow.camera.top = 180;
				dirLight.shadow.camera.bottom = - 100;
				dirLight.shadow.camera.left = - 120;
				dirLight.shadow.camera.right = 120;
				scene.add( dirLight );

				

				// ground  地面
				const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
				mesh.rotation.x = - Math.PI / 2;
				mesh.receiveShadow = true;
				scene.add( mesh );
                //网格
				const grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
				grid.material.opacity = 0.2;
				grid.material.transparent = true;
				scene.add( grid );


                //WEBGL渲染器
				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.shadowMap.enabled = true;//
				container.appendChild( renderer.domElement );
                //控制器
				const controls = new OrbitControls( camera, renderer.domElement );
				controls.target.set( 0, 100, 0 );
				controls.update();
              
				// stats 性能检测
				stats = new Stats();
				container.appendChild( stats.dom );
   
			}

1.3 模型加载

function fbxLoad(path){
     // model  加载模型
	const loader = new FBXLoader();
	loader.load( path, function ( object ) {
    console.log(object);
    //动画混合器
	mixer = new THREE.AnimationMixer( object );
    // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称
	const action = mixer.clipAction( object.animations[ 0 ] );
	action.play();//动画播放

	object.traverse( function ( child ) {

		if ( child.isMesh ) {

		child.castShadow = true;//对象是否被渲染到阴影贴图中。默认值为false
		child.receiveShadow = true;//材质是否接收阴影。默认值为false

		}

		} );

	scene.add( object );

	} );
}

打印的模型信息如下:

1.4 半球光

HemisphereLight( skyColor : Integer, groundColor : Integer, intensity : Float )

skyColor -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 Color 对象。
groundColor -(可选)一个表示颜色的 Color 的实例、字符串或数字,默认为一个白色(0xffffff)的 Color 对象。
intensity -(可选)光照强度。默认值为 1

//灯 半球光
//光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444, 5 );
hemiLight.position.set( 0, 200, 0 );
scene.add( hemiLight );

加上这个光后,模型明显变量了。

1.5 动画

function animate() {

requestAnimationFrame( animate );
//获取自 .oldTime 设置后到当前的秒数。 同时将 .oldTime 设置为当前时间。
//如果 .autoStart 设置为 true 且时钟并未运行,则该方法同时启动时钟
				const delta = clock.getDelta();//

if ( mixer ) mixer.update( delta );//动画更新

renderer.render( scene, camera );

stats.update();//性能监视器更新

}
init();
animate();

1.6 换个自己的fbx模型

 fbxLoad('../Models/ren/Arisa/Arisa.fbx');

这里模型加载进去小,所以进行了放大100

      function fbxLoad(path){
                // model  加载模型
				const loader = new FBXLoader();
				loader.load( path, function ( object ) {
                    console.log(object);
                    //动画混合器
					mixer = new THREE.AnimationMixer( object );
                   // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称
                   if(object.animations>0){
                    const action = mixer.clipAction( object.animations[ 0 ] );
					action.play();//动画播放
                   }
					
					object.traverse( function ( child ) {

						if ( child.isMesh ) {

							child.castShadow = true;//对象是否被渲染到阴影贴图中。默认值为false
							child.receiveShadow = true;//材质是否接收阴影。默认值为false

						}

					} );
                    object.position.set(0,0,0);
					object.scale.set(100,100,100);
					scene.add( object );

				} );
            }

注意:需要把贴图和fbx放入同一个文件下

1.7 fbx模型和fbx动画关联

如果模型和动画不在一个文件里,比如模型是一个fbx,动画是另一个fbx,需要这么加载:

function fbxLoad(path,aniPath){
                // model  加载模型
				const loader = new FBXLoader();
				loader.load( path, function ( object ) {
                    console.log(object);
                    //动画混合器
					mixer = new THREE.AnimationMixer( object );
                   // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称
                //    if(object.animations>0){
                //     const action = mixer.clipAction( object.animations[ 0 ] );
				// 	action.play();//动画播放
                //    }
					
					object.traverse( function ( child ) {

						if ( child.isMesh ) {

							child.castShadow = true;//对象是否被渲染到阴影贴图中。默认值为false
							child.receiveShadow = true;//材质是否接收阴影。默认值为false

						}

					} );
                    object.position.set(0,0,0);
					//object.scale.set(100,100,100);
					scene.add( object );

                     
					const clips={};
					const actions={};
					//加载动画
					loader.load(aniPath,(animations)=>{
						console.log(animations);
						animations.animations.forEach((clip)=>{
							clips[clip.name]=clip;
							actions[clip.name]=mixer.clipAction(clip);
						});
						actions['Take 001'].play(); 
					}) ;  
					             
				} );
            }

针对后缀的anim的动画文件,目前是需要这么解决

我找了个之前Unity工程里用的人物模型,一个fbx里包含了8种风格的人物 和他的6个动作fbx:

为了切换不同人物和不同的动画,增加了一个UI模块:

把模型和动画加载的函数重构了下:

 // model  加载模型
            function fbxLoad(path,aniPath,type){
				 //移除已有的
				 while ( root.children.length > 0 ) {

					const object = root.children[ 0 ];
					object.parent.remove( object );

				}                				
				container.style.display='block';
				percenDiv.style.width=0+"px";//进度条元素长度0
				percenDiv.style.textIndent=0+5+"px";//缩进元素中的首行文本0
				percenDiv.innerHTML=Math.floor(0) +"%";//进度百分比0
				//开始加载
				loader.load( path, function ( object ) {
                    console.log(object);					
					container.style.display='none';					
                    //动画混合器
					mixer = new THREE.AnimationMixer(object);
                   // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称
                  //    if(object.animations>0){
                  //     const action = mixer.clipAction( object.animations[ 0 ] );
				  // 	action.play();//动画播放
                   //    }
				   object.position.set(0,0,0);
				   //object.scale.set(100,100,100);
				   root.add( object );

				   ChangePerson2(currenPersonType);
					// object.traverse( function ( child ) {                       
					// 	if ( child.isMesh ) {
					// 		ChangePerson(child,currenPersonType);
					// 		child.castShadow = true;//对象是否被渲染到阴影贴图中。默认值为false
					// 		child.receiveShadow = true;//材质是否接收阴影。默认值为false
							
					// 	}						
					// } );
                 					
					//加载动画
					LoadPersonAnimation(aniPath);
					// loader.load(aniPath,(animations)=>{
					// 	let clipName;
					// 	console.log(animations);
					// 	animations.animations.forEach((clip)=>{
					// 		clips[clip.name]=clip;
					// 		actions[clip.name]=mixer.clipAction(clip);
					// 		clipName=clip.name;
					// 	});
					// 	actions[clipName].play(); 
					// }) ;  
					             
				},function(xhr){
					const percent=xhr.loaded/xhr.total;  
					percenDiv.style.width=percent*400+"px";//进度条元素长度
					percenDiv.style.textIndent=percent*400+5+"px";//缩进元素中的首行文本
					percenDiv.innerHTML=Math.floor(percent*100) +"%";//进度百分比
				} );
            }

			 //加载动画fbx
			 function LoadPersonAnimation(aniPath){
				mixer.stopAllAction ();//停用混合器上所有预定的动作
				loader.load(aniPath,(animations)=>{
					let clipName;
					console.log(animations);
					animations.animations.forEach((clip)=>{
						clips[clip.name]=clip;
						//clipAction返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。如果不存在符合传入的剪辑和根对象这两个参数的动作, 该方法将会创建一个。传入相同的参数多次调用将会返回同一个剪辑实例。
						actions[clip.name]=mixer.clipAction(clip);
						clipName=clip.name;
					});
					actions[clipName].play(); 
				}) ;  
			 }

UI监听的两函数:

1.7 html脚本全部如下

   里面加了一个进度条,这部分我也不是很了解,脚本如下:

<!DOCTYPE html>
<html lang="en">
	<head>
		<title>three.js webgl - FBX loader</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<link type="text/css" rel="stylesheet" href="../three.js-r163/examples/main.css">



		<style>
/* 进度条css样式*/
#container{
		   position: absolute;
		   width: 400px;
		   height: 16px;
		   top: 50%;
		   left: 50%;
		   margin-left: -200px;
		   margin-top: -8px;
		   border-radius: 8px;
		   border: 1px solid #009999;
		   overflow: hidden;

	   }
	   #per{
		   height: 100px;
		   width: 0px;
		   background: #00ffff;
		   color: #00ffff;
		   line-height: 15px;
	   }
		</style>
		


	</head>

	<body>
		<div id="info">
			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> - FBXLoader<br />
			Character and animation from <a href="https://www.mixamo.com/" target="_blank" rel="noopener">Mixamo</a>
		</div>

		<div id="container">
			<!--进度条-->
			<div id="per"></div>
		</div>
		
		<script type="importmap">
			{
				"imports": {
                    "three": "../three.js-r163/build/three.module.js",  
                    "three/addons/":"../three.js-r163/examples/jsm/"  
				}
			}
		</script>

		<script type="module" src="fbx.js">
        </script>
    </body>
</html>

1.8 fbx.js全部脚本如下

import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
 //控制器
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
 //fbx模型加载器
import { FBXLoader } from 'three/addons/loaders/FBXLoader.js';
 //引入ui库
 import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

			let camera, scene, renderer, stats;

			const clock = new THREE.Clock();//该对象用于跟踪时间

			let mixer;//动画混合器
            let gui;//ui
			let root;//模型的父物体
			const percenDiv=document.getElementById('per');//获取进度条元素
			const container=document.getElementById('container');//获取进度条元素背景
			//不同人物对象
				 const Persons = {
					'人物1': '01',
					'人物2': '02',
					'人物3': '03',
					'人物4': '04',
					'人物5': '05',
					'人物6': '06',
					'人物7': '07',
					'人物8': '08',				
				};
	
				const params = {
					molecule: '01',
					currentAni:'idle',
				};

				//不同的动画
                const PersonAnis={
					'idle':'idle',
					'Asking Question':'Asking Question',
					'Clapping':'Clapping',
					'Running':'Running',
					'sit':'sit',
					'sit_Clapping':'sit_Clapping',
					'Waving':'Waving'
				}
				
				let  currenPersonType='01';;//当前人物
				let  currentPersonAni='idle';//当前动画
	
			const loader = new FBXLoader();//模型加载器
			const clips={};
			const actions={};

			function init() {
				
				const container = document.createElement( 'div' );
				document.body.appendChild( container );
                //相机
				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
				camera.position.set( 100, 200, 300 );
                //场景
				scene = new THREE.Scene();
				scene.background = new THREE.Color( 0xa0a0a0 );
				scene.fog = new THREE.Fog( 0xa0a0a0, 200, 1000 );//雾
            
                //灯 模拟太阳光
				const dirLight = new THREE.DirectionalLight( 0xffffff, 5 );
				dirLight.position.set( 0, 200, 100 );
				dirLight.castShadow = true;//此属性设置为 true 灯光将投射阴影 注意:这样做的代价比较高,需要通过调整让阴影看起来正确。 查看 DirectionalLightShadow 了解详细信息。 默认值为 false
                //dirLight.shadow 为DirectionalLightShadow 对象,用于计算该平行光产生的阴影
                //.camera 在光的世界里。这用于生成场景的深度图;从光的角度来看,其他物体背后的物体将处于阴影中
				dirLight.shadow.camera.top = 180;
				dirLight.shadow.camera.bottom = - 100;
				dirLight.shadow.camera.left = - 120;
				dirLight.shadow.camera.right = 120;
				scene.add( dirLight );

				root=new THREE.Group();
                scene.add(root);
				

				// ground  地面
				const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
				mesh.rotation.x = - Math.PI / 2;
				mesh.receiveShadow = true;//接收阴影
				scene.add( mesh );
                //网格
				const grid = new THREE.GridHelper( 2000, 20, 0x000000, 0x000000 );
				grid.material.opacity = 0.2;
				grid.material.transparent = true;
				scene.add( grid );


                //WEBGL渲染器
				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.shadowMap.enabled = true;//
				container.appendChild( renderer.domElement );
                //控制器
				const controls = new OrbitControls( camera, renderer.domElement );
				controls.target.set( 0, 100, 0 );
				controls.update();
              
				// stats 性能检测
				stats = new Stats();
				container.appendChild( stats.dom );

				//                   //窗口大小更改监听
             	window.addEventListener( 'resize', onWindowResize );

                //fbxLoad('../Models/Arisa/Arisa.fbx');

				fbxLoad('../Models/ren/man.fbx','../Models/ren/idle.fbx','01');
			   

                             //灯 半球光
                             //光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色
				const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444, 5 );
				hemiLight.position.set( 0, 200, 0 );
				scene.add( hemiLight );
                //scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );

                //ui部分
				gui=new GUI();
				gui.add( params, 'molecule', Persons).onChange( ChangePerson2 );//切换不同的人物模型
				gui.add( params, 'currentAni', PersonAnis).onChange( ChangePersonAni );//切换不同的人物模型
				gui.open(); 
			}

         
           
            // model  加载模型
            function fbxLoad(path,aniPath,type){
				 //移除已有的
				 while ( root.children.length > 0 ) {

					const object = root.children[ 0 ];
					object.parent.remove( object );

				}                				
				container.style.display='block';
				percenDiv.style.width=0+"px";//进度条元素长度0
				percenDiv.style.textIndent=0+5+"px";//缩进元素中的首行文本0
				percenDiv.innerHTML=Math.floor(0) +"%";//进度百分比0
				//开始加载
				loader.load( path, function ( object ) {
                    console.log(object);					
					container.style.display='none';					
                    //动画混合器
					mixer = new THREE.AnimationMixer(object);
                   // 返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称
                  //    if(object.animations>0){
                  //     const action = mixer.clipAction( object.animations[ 0 ] );
				  // 	action.play();//动画播放
                   //    }
				   object.position.set(0,0,0);
				   //object.scale.set(100,100,100);
				   root.add( object );

				   ChangePerson2(currenPersonType);
					// object.traverse( function ( child ) {                       
					// 	if ( child.isMesh ) {
					// 		ChangePerson(child,currenPersonType);
					// 		child.castShadow = true;//对象是否被渲染到阴影贴图中。默认值为false
					// 		child.receiveShadow = true;//材质是否接收阴影。默认值为false
							
					// 	}						
					// } );
                 					
					//加载动画
					LoadPersonAnimation(aniPath);
					// loader.load(aniPath,(animations)=>{
					// 	let clipName;
					// 	console.log(animations);
					// 	animations.animations.forEach((clip)=>{
					// 		clips[clip.name]=clip;
					// 		actions[clip.name]=mixer.clipAction(clip);
					// 		clipName=clip.name;
					// 	});
					// 	actions[clipName].play(); 
					// }) ;  
					             
				},function(xhr){
					const percent=xhr.loaded/xhr.total;  
					percenDiv.style.width=percent*400+"px";//进度条元素长度
					percenDiv.style.textIndent=percent*400+5+"px";//缩进元素中的首行文本
					percenDiv.innerHTML=Math.floor(percent*100) +"%";//进度百分比
				} );
            }

			 //加载动画fbx
			 function LoadPersonAnimation(aniPath){
				mixer.stopAllAction ();//停用混合器上所有预定的动作
				loader.load(aniPath,(animations)=>{
					let clipName;
					console.log(animations);
					animations.animations.forEach((clip)=>{
						clips[clip.name]=clip;
						//clipAction返回所传入的剪辑参数的AnimationAction, 根对象参数可选,默认值为混合器的默认根对象。第一个参数可以是动画剪辑(AnimationClip)对象或者动画剪辑的名称。如果不存在符合传入的剪辑和根对象这两个参数的动作, 该方法将会创建一个。传入相同的参数多次调用将会返回同一个剪辑实例。
						actions[clip.name]=mixer.clipAction(clip);
						clipName=clip.name;
					});
					actions[clipName].play(); 
				}) ;  
			 }

			function onWindowResize() {
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();
				renderer.setSize( window.innerWidth, window.innerHeight );
			}

			//
			function animate() {
				requestAnimationFrame( animate );
              //获取自 .oldTime 设置后到当前的秒数。 同时将 .oldTime 设置为当前时间。
//如果 .autoStart 设置为 true 且时钟并未运行,则该方法同时启动时钟
				const delta = clock.getDelta();//
				if ( mixer ) mixer.update( delta );//推进混合器时间并更新动画
				renderer.render( scene, camera );
				stats.update();//性能监视器更新
			}
            init();
			animate();


			// function ChangePerson(child,type){
			// 	currenPersonType=type;
			// 	//fbxLoad('../Models/ren/man.fbx','../Models/ren/'+currentPersonAni+'.fbx',type);
			// 	if(child.name.includes(type)){
			// 		console.log(child.name);

			// 		//这里如果是clone  导致切换时不显示
			// 		child.copy(child).visible=true;
			// 	}else{
			// 		child.visible=false;
			// 	}
			// }

            //切换人物
			function ChangePerson2(type){
				currenPersonType=type;           
				root.traverse( function ( child ) {                       
					if ( child.isMesh ) {
						//ChangePerson(child,type);
						if(child.name.includes(type)){
							console.log(child.name);
							//这里如果是clone  导致切换时不显示
							child.copy(child).visible=true;
						}else{
							child.visible=false;
						}											
					}						
				} );
			}
            //切换人物动画
			function ChangePersonAni(Anitype){
				currentPersonAni=Anitype;
				LoadPersonAnimation('../Models/ren/'+Anitype+'.fbx');								
			}

		

运行结果:

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

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

相关文章

算法简单笔记2

5月26号&#xff0c;之前学了两天算法烦了&#xff0c;去学了几天鸿蒙&#xff0c;今天又回来看一下算法&#xff0c;距离6月1日国赛还有6天&#xff0c;哈哈真是等死咯...... 一、蓝桥杯第13届国赛第1题填空题&#xff1a;重合次数 &#xff08;半难不难&#xff0c;写编程难…

张大哥笔记:赚钱高手养成计划---如何将一份时间产生N份收入?

我们常说的赚钱的四种境界有哪些&#xff1f; 1.靠体力挣钱 2.靠技能挣钱 3.靠知识挣钱 4.靠平台钱生钱 所以对应的收入的模式就会是下面4种模式&#xff1a; 1.一份时间卖1次 2.一份时间卖N次 3.一份时间溢价卖N次 4.购买他人时间为自己所用 时间对于每个人都是相同的…

vs code怎么补全路径,怎么快捷输入文件路径

安装插件&#xff1a; 链接&#xff1a;https://marketplace.visualstudio.com/items?itemNamejakob101.RelativePath 使用 按住 Ctrl Shift H&#xff0c;弹出窗口&#xff0c;输入文件补全&#xff0c;回车就可以了 排除文件 如果你的项目下文件太多&#xff0c;它会…

Java单元测试

单元测试一 一、单选题 1 public class Test{public static void main(String[] args){int i1;switch(i){case 0:System.out.println("1"(i));case 1:System.out.println("2"(i));break;case 2:System.out.println("3"(i));default…

【程序员如何送外卖】

嘿&#xff0c;咱程序员要在美团送外卖&#xff0c;那还真有一番说道呢。 先说说优势哈&#xff0c;咱程序员那逻辑思维可不是盖的&#xff0c;规划送餐路线什么的&#xff0c;简直小菜一碟。就像敲代码找最优解一样&#xff0c;能迅速算出怎么送最省时间最有效率。而且咱平时…

雷军-2022.8小米创业思考-9-爆品模式:产品力超群,具有一流口碑,最终实现海量长销的产品。人人都向往;做减法;重组创新;小白模式

第九章 爆品模式 小米方法论的第三个关键词&#xff0c;就是一切以产品为出发点&#xff0c;打造爆品模式。 大多数人对“爆品”的着眼点仅在于“爆”&#xff0c;也就是产品卖得好。希望产品大卖这没有错&#xff0c;但是“爆”是“品”的结果&#xff0c;爆品是打造出来的&…

内网穿透--Frp-简易型(速成)-上线

免责声明:本文仅做技术交流与学习... 目录 frp项目介绍: 一图通解: ​编辑 1-下载frp 2-服务端(server)开启frp口 3-kali客户端(client)连接frp服务器 4-kali生成马子 5-kali监听 6-马子执行-->成功上线 frp项目介绍: GitHub - fatedier/frp: A fast reverse proxy…

react 下拉框内容回显

需要实现效果如下 目前效果如下 思路 : 将下拉框选项的value和label一起存储到state中 , 初始化表单数据时 , 将faqType对应的label查找出来并设置到Form.Item中 , 最后修改useEffect 旧代码 //可以拿到faqType为0 但是却没有回显出下拉框的内容 我需要faqType为0 回显出下拉…

超详细避坑指南!OrangpiAIPro转换部署模型全流程!

目录 OrangepiPro初体验 前述&#xff1a; 一、硬件准备 二、安装CANN工具链&#xff08;虚拟机&#xff09; 三、配置模型转换环境&#xff08;虚拟机&#xff09; 1.安装miniconda 。 2.创建环境。 3.安装依赖包 四、转换模型 1. 查看设备号&#xff08;开发板&…

【AD21】坐标文件的输出

坐标文件通常发给贴片厂&#xff0c;该文件提供了每个元件、每个测试点等在PCB上的精确位置&#xff0c;可以用于指导和优化PCB制造和组装过程中元件和孔位的精确定位。 在PCB源文件页面&#xff0c;菜单栏中点击文件->装配输出->Generates pick and place files。 在新…

【搜索方法推荐】高效信息检索方法和实用网站推荐

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

【软件设计师】——9.UML建模

目录 9.1概述 9.2 结构图 9.2.1 对象图 9.2.2 类图 9.2.3 构件/组件图 9.2.3 部署图 9.2.4 制品图 9.2.5 组合结构图 9.3 行为图 9.3.1 用例图 9.3.2 协作图 9.3.3 顺序/序列/时序图 9.3.4 活动图 9.3.5 状态图 9.3.6 通信图 9.4 交互图 9.1概述 基本概念 UML统…

30.哀家要长脑子了!---栈与队列

1.388. 文件的最长绝对路径 - 力扣&#xff08;LeetCode&#xff09; 其实看懂了就还好 用一个栈来保存所遍历过最大的文件的绝对路径的长度&#xff0c;栈顶元素是文件的长度&#xff0c;栈中元素的个数是该文件目录的深度&#xff0c;非栈顶元素就是当时目录的长度 检查此…

2.冒泡排序

样例输入 5 8 3 6 4 9 样例输出 3 4 6 8 9 以下是解题答案&#xff1a; class demo1{public static void main(String[] args) {Scanner scnnew Scanner(System.in);int[] array new int[scn.nextInt()];if(array.length>0&&array.length<200){for(int…

“按摩”科技?

都说A股股民是特别善于学习的&#xff0c;这不市场又现新概念——“按摩科技”&#xff0c;成立仅6年&#xff0c;把上门按摩干到35亿营收也是没谁了&#xff0c;现在号称有1000万用户&#xff0c;3万家入驻商户数的按摩平台&#xff0c;难道就凭借2.5万名女技师&#xff0c;活…

数据库|基于T-SQL创建数据表(练习笔记)

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 前边学习了如何用T-SQL创建数据库《数据库|基于T-SQL创建数据库》 今天继续学习基于T-SQL在数据库中创建数据表。 以下为学习笔记。 01 创建Author数据表 创建一个作者表&#xff0c;表名称为Author,包含作者编号&am…

SARscape5.7已经支持3米陆探一号(LT-1)数据处理

SARsacpe5.6.2.1版本已经开始支持LT-1的数据处理&#xff0c;由于当时只获取了12米的条带模式2&#xff08;STRIP2&#xff09;例子数据&#xff0c;对3米条带模式1&#xff08;STRIP1&#xff09;数据的InSAR处理轨道误差挺大&#xff0c;可能会造成干涉图异常。 SARsacpe5.7最…

Go程序出问题了?有pprof!

什么情况下会关注程序的问题&#xff1f; 一是没事儿的时候 二是真有问题的时候 哈哈哈&#xff0c;今天我们就来一起了解一下Go程序的排查工具&#xff0c;可以说即简单又优雅&#xff0c;它就是pprof。 在 Go 中&#xff0c;pprof 工具提供了一种强大而灵活的机制来分析 …

【ARMv8/v9 异常模型入门及渐进 10 -- WFI 与 WFE 使用详细介绍 1】

请阅读【ARMv8/v9 ARM64 System Exception】 文章目录 WFI 与 WFE等待事件&#xff08;WFE&#xff09;发送事件&#xff08;SEV&#xff09;本地发送事件&#xff08;SEVL&#xff09;WFE 唤醒事件 WFE 使用场景举例与代码实现wfe睡眠函数sev 事件唤醒函数全局监视器和自旋锁 …

推荐丨免费一年期SSL证书在哪里可以申请到?

当然&#xff0c;申请HTTPS证书的流程可以简化为三个主要步骤&#xff0c;以便理解&#xff1a; 第一步&#xff1a;选择证书类型和认证机构 1. 确定证书类型&#xff1a;首先&#xff0c;你需要确定适合你网站的SSL证书类型。常见的有三种&#xff1a; - 域名验证型&#xff0…