【Three.js基础学习】22.New project structure

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

这里将使用全新的项目结构,将不同工具分层,区分开使用。


一、结构目录

二、对应文件

1.script.js

获取画布,引入样式和功能。

/* 课程要点:1. 类和模块import  /   expore defaultcalss 类名 {constructor(){}}new 类名() // 实例化calss 类 extends 类 { // 继承contructor(){super() // 基于类的引用} } 2.新项目建立一个时间,尺寸类的函数。EventEmitter.js回调如何在Camera.js使用尺寸大小,画布等1.全局变量2.传参3.保存实例化,在引入 在Experience.js保存this ,在Camera中引入Experience.js 再次实例化时判断instance是否已经实例化,若是则不创建新的 (使用这个)*/import './style.css'
import Experience from './Experience/Experience'const experience = new Experience(document.querySelector('canvas.webgl'))

2.Experience.js

2-1 Experience.js

总览功能,初始化创建实例,引入各个类,创建实例,监听页面大小,定时刷新渲染,执行各个类的方法,实现功能

import * as THREE from 'three'
import Sizes from './Utils/Sizes.js'
import Time from './Utils/Time.js'
import Camera from './Camera.js'
import Renderer from './Renderer.js'
import World from './World/World.js'
import Resources from './Utils/Resources.js'
import Debug from './Utils/Debug.js'
import sources from './sources.js' // 资源 s没有大写let instance = null
export default class Experience{constructor(canvas){if(instance){ // 很重要,其他引入时,可以拿到同一个实例内容return instance}instance = this// Global accesswindow.experience = this// Optionsthis.canvas = canvas// Setupthis.debug = new Debug()this.sizes = new Sizes() // 尺寸类this.time = new Time() // 时间类this.scene = new THREE.Scene() // 场景this.resources = new Resources(sources) // 资源类 加载器在这里已经加载完成this.camera = new Camera() // 照相机this.renderer = new Renderer() // 渲染类this.world = new World() // 将展示的3D 在此处 环境贴图,资源用在此处// Sizes resize eventthis.sizes.on('resize',()=>{ // 监听页面大小,更新canvasthis.resize()})// Time tick evnet/* 继承关系: Time 类继承自 EventEmitter,因此 Time 类实例拥有 EventEmitter 中定义的 trigger() 方法。trigger('tick') 的作用:this.trigger('tick') 会在 EventEmitter 中寻找并调用已注册到 tick 事件的所有回调函数。事件注册 :在 Experience 类的构造函数中,this.time.on('tick', () => { this.update() }) 注册了 tick 事件的回调函数(this.update() 方法)。on() 方法会将该回调添加到 EventEmitter 的 callbacks 中。事件触发:当 tick() 方法中的 this.trigger('tick') 被调用时,EventEmitter 的 trigger() 方法会找到所有与tick 事件关联的回调并依次执行它们,因此Experience 中的 update() 方法也会被调用*/this.time.on('tick',()=>{ // 定时更新,刷新帧this.update()})}resize(){this.camera.resize()this.renderer.resize()}update(){this.camera.update()this.world.update()this.renderer.update()}destroy(){ // 销毁this.time.off('tick')this.time.off('resize')// 遍历 scenethis.scene.traverse((child)=>{if(child instanceof THREE.Mesh){child.geometry.dispose()for(const key in child.material){const value = child.material[key]if(value && typeof value.dispose === 'function'){ // 判断某个值有功能 就销毁value.dispose()}}}})this.camera.controls.dispose()this.renderer.instance.dispose()if(this.debug.active)this.debug.ui.destroy()}
}

2-2 Camera.js

创建照相机和轨道控制器,resize更新尺寸,update更新轨道,在experience.js中使用

import * as THREE from 'three'
import { OrbitControls } from "three/examples/jsm/controls/orbitcontrols";
import Experience from "./Experience.js";
export default class Camera {constructor(){this.experience = new Experience()this.sizes = this.experience.sizesthis.scene = this.experience.scenethis.canvas = this.experience.canvasthis.setInstance()this.setObitControls()}setInstance(){ // 创建照相机this.instance = new THREE.PerspectiveCamera(75,this.sizes.width / this.sizes.height,0.1,100)this.instance.position.set(6,4,8)this.scene.add(this.instance)}setObitControls(){ // 轨道控制器this.controls = new OrbitControls(this.instance,this.canvas)this.controls.enableDamping = true}resize(){console.log('update camera for canvas')this.instance.aspect = this.sizes.width/this.sizes.heightthis.instance.updateProjectionMatrix()}update(){this.controls.update()}
}

2-3 Renderer.js

创建渲染,设置对应属性。

import * as THREE from 'three'
import Experience from './Experience.js'export default class Renderer
{constructor(){this.experience = new Experience() // 初始化实例获取数据this.canvas = this.experience.canvasthis.sizes = this.experience.sizesthis.scene = this.experience.scenethis.camera = this.experience.camerathis.setInstance()}setInstance(){this.instance = new THREE.WebGLRenderer({canvas:this.canvas,antialias:true,})this.instance.physicallyCorrectLights = truethis.instance.outputEncoding = THREE.sRGBEncodingthis.instance.toneMapping = THREE.CineonToneMappingthis.instance.toneMappingExposure = 1.75this.instance.shadowMap.enabled = truethis.instance.shadowMap.type = THREE.PCFSoftShadowMapthis.instance.setClearColor('#211d20')this.instance.setSize(this.sizes.width,this.sizes.height)this.instance.setPixelRatio(this.sizes.pixelRatio)}resize(){this.instance.setSize(this.sizes.width,this.sizes.height)this.instance.setPixelRatio(this.sizes.pixelRatio)}update(){this.instance.render(this.scene,this.camera.instance)}
}

2-4 sources.js

资源地址,environmentMapTexture为环境贴图,texture贴图,foxModel模型

export default [{name: 'environmentMapTexture',type: 'cubeTexture',path:['textures/environmentMap/px.jpg','textures/environmentMap/nx.jpg','textures/environmentMap/py.jpg','textures/environmentMap/ny.jpg','textures/environmentMap/pz.jpg','textures/environmentMap/nz.jpg']},{name: 'grassColorTexture',type: 'texture',path: 'textures/dirt/color.jpg'},{name: 'grassNormalTexture',type: 'texture',path: 'textures/dirt/normal.jpg'},{name: 'foxModel',type: 'gltfModel',path: 'models/Fox/glTF/Fox.gltf'}
]

3.Utils 

3-1 Sizes.js

监听页面,获取尺寸,暴露执行this.trigger(resize)

import EventEmitter from "./EventEmitter"
export default class Sizes extends EventEmitter{constructor(){super()// setupthis.width = window.innerWidththis.height = window.innerHeightthis.pixelRatio = Math.min(window.devicePixelRatio,2)// Resize eventwindow.addEventListener('resize',()=>{this.width = window.innerWidththis.height = window.innerHeightthis.pixelRatio = Math.min(window.devicePixelRatio,2)this.trigger('resize')})}
}

3-2 Time.js

获取上一秒和这一秒,花了多少时间,帧率

import EventEmitter from "./EventEmitter.js";
export default class Time extends EventEmitter{constructor(){super()// Setupthis.start = Date.now()this.current = this.startthis.elapsed = 0this.delta = 16 // 60FPS下,每帧增量时间16毫秒window.requestAnimationFrame(()=>{ // 这里等上一秒执行 因为当前时间和上次时间减为0 所以第一帧就是0this.tick()})}tick(){const currentTime = Date.now()this.delta = currentTime - this.current // 当前时间 - 上次时间this.current = currentTime // 更新this.elapsed = this.current - this.start // 花了多少时间this.trigger('tick') // 计时器触发 ,回调触发tick回调的所有函数window.requestAnimationFrame(()=>{ // 保留上下文this.tick()})}
}

3-3 EventEmitter.js

提供on,trigger方法 回调函数  on方法添加有对应名称的方法,trigger 会执行所有callbacks中所有的方法

export default class EventEmitter
{constructor(){this.callbacks = {}this.callbacks.base = {}}on(_names, callback){// Errorsif(typeof _names === 'undefined' || _names === ''){console.warn('wrong names')return false}if(typeof callback === 'undefined'){console.warn('wrong callback')return false}// Resolve namesconst names = this.resolveNames(_names)// Each namenames.forEach((_name) =>{// Resolve nameconst name = this.resolveName(_name)// Create namespace if not existif(!(this.callbacks[ name.namespace ] instanceof Object))this.callbacks[ name.namespace ] = {}// Create callback if not existif(!(this.callbacks[ name.namespace ][ name.value ] instanceof Array))this.callbacks[ name.namespace ][ name.value ] = []// Add callbackthis.callbacks[ name.namespace ][ name.value ].push(callback)})// console.log(names,this.callbacks,'eeee')return this}off(_names){// Errorsif(typeof _names === 'undefined' || _names === ''){console.warn('wrong name')return false}// Resolve namesconst names = this.resolveNames(_names)// Each namenames.forEach((_name) =>{// Resolve nameconst name = this.resolveName(_name)// Remove namespaceif(name.namespace !== 'base' && name.value === ''){delete this.callbacks[ name.namespace ]}// Remove specific callback in namespaceelse{// Defaultif(name.namespace === 'base'){// Try to remove from each namespacefor(const namespace in this.callbacks){if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array){delete this.callbacks[ namespace ][ name.value ]// Remove namespace if emptyif(Object.keys(this.callbacks[ namespace ]).length === 0)delete this.callbacks[ namespace ]}}}// Specified namespaceelse if(this.callbacks[ name.namespace ] instanceof Object && this.callbacks[ name.namespace ][ name.value ] instanceof Array){delete this.callbacks[ name.namespace ][ name.value ]// Remove namespace if emptyif(Object.keys(this.callbacks[ name.namespace ]).length === 0)delete this.callbacks[ name.namespace ]}}})return this}trigger(_name, _args){// Errorsif(typeof _name === 'undefined' || _name === ''){console.warn('wrong name')return false}let finalResult = nulllet result = null// Default argsconst args = !(_args instanceof Array) ? [] : _args// Resolve names (should on have one event)let name = this.resolveNames(_name)// Resolve namename = this.resolveName(name[ 0 ])// Default namespaceif(name.namespace === 'base'){// Try to find callback in each namespacefor(const namespace in this.callbacks){if(this.callbacks[ namespace ] instanceof Object && this.callbacks[ namespace ][ name.value ] instanceof Array){this.callbacks[ namespace ][ name.value ].forEach(function(callback){result = callback.apply(this, args)if(typeof finalResult === 'undefined'){finalResult = result}})}}}// Specified namespaceelse if(this.callbacks[ name.namespace ] instanceof Object){if(name.value === ''){console.warn('wrong name')return this}this.callbacks[ name.namespace ][ name.value ].forEach(function(callback){result = callback.apply(this, args)if(typeof finalResult === 'undefined')finalResult = result})}return finalResult}resolveNames(_names){let names = _namesnames = names.replace(/[^a-zA-Z0-9 ,/.]/g, '')names = names.replace(/[,/]+/g, ' ')names = names.split(' ')return names}resolveName(name){const newName = {}const parts = name.split('.')newName.original  = namenewName.value     = parts[ 0 ]newName.namespace = 'base' // Base namespace// Specified namespaceif(parts.length > 1 && parts[ 1 ] !== ''){newName.namespace = parts[ 1 ]}return newName}
}

3-4 Resources.js

加载器初始化gltfLoader,textLoader,cubeTextureLoader

import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/gltfloader";
import EventEmitter from "./EventEmitter";export default class Resources extends EventEmitter{constructor(sources){super()// Optionsthis.sources = sourcesthis.items = {} // 资源this.toLoad = this.sources.length // 全部资源长度this.loaded = 0 // 资源初始this.setLoaders()this.startLoading()}setLoaders(){this.loaders = {} // 加载器this.loaders.gltfLoader = new GLTFLoader()this.loaders.textureLoader = new THREE.TextureLoader()this.loaders.cubeTextureLoader = new THREE.CubeTextureLoader()}startLoading(){ // 要加载的资源// load are sourcefor(const source of this.sources){if(source.type === 'gltfModel'){this.loaders.gltfLoader.load(source.path,(file)=>{this.sourceLoaded(source,file)})}else if(source.type === 'texture'){this.loaders.textureLoader.load(source.path,(file)=>{this.sourceLoaded(source,file)})}else if(source.type === 'cubeTexture'){this.loaders.cubeTextureLoader.load(source.path,(file)=>{this.sourceLoaded(source,file)})}}}sourceLoaded(source,file){this.items[source.name] = file // 存储this.loaded++ // 资源加载if(this.loaded === this.toLoad){ // 判断资源是否加载完成this.trigger('ready')}}
}

3-5 Debug.js

lil-GUI调试

import * as dat from 'lil-gui'
export default class Debug{constructor(){this.active = window.location.hash === '#debug'if(this.active){this.ui = new dat.GUI()}}
}

4.World

4-1 World.js

加载对应的资源,如模型 环境 和贴图等

import Experience from '../Experience.js'
import Environment from './Environment.js'
import Floor from './Floor.js'
import Fox from './Fox.js'export default class World
{constructor(){this.experience = new Experience()this.scene = this.experience.scenethis.resources = this.experience.resources // 资源// const testMesh = new THREE.Mesh( // 创建网格//     new THREE.BoxGeometry(1,1,1),//     new THREE.MeshStandardMaterial()// )// this.scene.add(testMesh)this.resources.on('ready',()=>{ // 判断是否完成资源加载 ,然后使用this.floor = new Floor() // 先添加底部 ,因为环境贴图若更改强度,地板没加载则无法适应强度this.fox = new Fox() // 狐狸模型this.environment = new Environment() // 环境类})}update(){if(this.fox){this.fox.update()}}
}

4-2 Environment.js

环境类 阳光设置,环境贴图等属性设置

import * as THREE from 'three'
import Experience from '../Experience.js'export default class Environment
{constructor(){this.experience = new Experience()this.scene = this.experience.scenethis.resources = this.experience.resources // 环境类要加载资源 当然要使用this.debug = this.experience.debug// Debugif(this.debug.active){this.debugFolder = this.debug.ui.addFolder('environment')}this.setSunLight() this.setEnvironmentMap() // 设置环境贴图}setSunLight(){ // 设置太阳光 ,光线this.sunLight = new THREE.DirectionalLight(0xffffff,0.5)this.sunLight.castShadow = truethis.sunLight.shadow.camera.far = 15this.sunLight.shadow.mapSize.set(1024,1024) // 数值越大 阴影越清晰this.sunLight.shadow.normalBias = 0.05 // 偏移this.sunLight.position.set(3.5,2,-1.25)this.scene.add(this.sunLight)// Debugif(this.debug.active){this.debugFolder.add(this.sunLight,'intensity').name('sunLightIntensity').min(0).max(10).step(0.001)this.debugFolder.add(this.sunLight.position,'x').name('sunLightX').min(-5).max(5).step(0.001)this.debugFolder.add(this.sunLight.position,'y').name('sunLightY').min(-5).max(5).step(0.001)this.debugFolder.add(this.sunLight.position,'z').name('sunLightZ').min(-5).max(5).step(0.001)}}setEnvironmentMap(){ // 环境贴图this.environmentMap = {}this.environmentMap.intensity = 0.4 // 环境贴图强度this.environmentMap.texture = this.resources.items.environmentMapTexturethis.environmentMap.texture.encoding = THREE.sRGBEncodingthis.scene.environment = this.environmentMap.texture // 环境为场景添加灯光this.environmentMap.updateMaterials = () =>{this.scene.traverse((child)=>{ // 更新环境贴图if(child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial){child.material.envmap = this.environmentMap.texturechild.material.envMapIntensity = this.environmentMap.intensitychild.material.needsUpdate = true}})}this.environmentMap.updateMaterials()// Debugif(this.debug.active){this.debugFolder.add(this.environmentMap,'intensity').name('envMapIntensity').min(0).max(4).step(0.001).onChange(this.environmentMap.updateMaterials)}}
}

4-3 Floor.js

地板创建,设置贴图(加载器已经加载完成直接设置),创建材质,创建网格,添加到场景

import * as THREE from 'three'
import Experience from '../Experience.js'export default class Floor
{constructor(){this.experience = new Experience()this.scene = this.experience.scenethis.resources = this.experience.resourcesthis.setGeometry()this.setTextures()this.setMaterial()this.setMesh()}setGeometry(){this.geometry = new THREE.CircleGeometry(5,64)}setTextures(){this.textures = {}this.textures.color = this.resources.items.grassColorTexturethis.textures.color.encoding = THREE.sRGBEncoding // 编码this.textures.color.repeat.set(1.5,1.5)this.textures.color.wrapS = THREE.RepeatWrapping;this.textures.color.wrapT = THREE.RepeatWrapping;this.textures.normal = this.resources.items.grassNormalTexturethis.textures.normal.repeat.set(1.5,1.5)this.textures.normal.wrapS = THREE.RepeatWrapping;this.textures.normal.wrapT = THREE.RepeatWrapping;}setMaterial(){this.material = new THREE.MeshStandardMaterial({map:this.textures.color,normalMap:this.textures.normal,})}setMesh(){this.mesh = new THREE.Mesh(this.geometry,this.material)this.mesh.rotation.x = - Math.PI * 0.5this.mesh.receiveShadow = truethis.scene.add(this.mesh)}
}

4-4 Fox.js

同上,不过是设置模型(模型加载器已经加载)

import * as THREE from 'three'
import Experience from '../Experience.js'export default class Fox
{constructor(){this.experience = new Experience()this.scene = this.experience.scenethis.resources = this.experience.resourcesthis.time = this.experience.timethis.debug = this.experience.debug // 调试面板if(this.debug.active){this.debugFolder = this.debug.ui.addFolder('fox') // addFolder 以层级形式创建新的GUI}// set upthis.resources = this.resources.items.foxModelthis.setModel()this.setAnimation()}setModel(){this.model = this.resources.scene // 整个模型this.model.scale.set(0.02,0.02,0.02) // 设置模型位置this.scene.add(this.model)this.model.traverse((child)=>{ // 遍历if(child instanceof THREE.Mesh){child.castShadow = true}})}setAnimation(){this.animation = {}this.animation.mixer = new  THREE.AnimationMixer(this.model)this.animation.actions = {}this.animation.actions.idle = this.animation.mixer.clipAction(this.resources.animations[0])this.animation.actions.walking = this.animation.mixer.clipAction(this.resources.animations[1])this.animation.actions.runing = this.animation.mixer.clipAction(this.resources.animations[2])this.animation.actions.current = this.animation.actions.idlethis.animation.actions.current.play()// 开始 同时需要在更新时间时候 更新关键帧this.animation.play = (name) => { // 如何实现动画之间的平稳过渡 const newAction = this.animation.actions[name] // 新动画const oldAction = this.animation.actions.current // 旧动画newAction.reset()newAction.play()newAction.crossFadeFrom(oldAction, 1)this.animation.actions.current = newAction}// Debugif(this.debug.active){const debugObject = {playIdle:()=>{this.animation.play('idle')},playWalking:()=>{this.animation.play('walking')},playRuning:()=>{this.animation.play('runing')},}this.debugFolder.add(debugObject,'playIdle')this.debugFolder.add(debugObject,'playWalking')this.debugFolder.add(debugObject,'playRuning')}}update(){this.animation.mixer.update(this.time.delta * 0.001) // 提供增量时间,更新}
}

5. new Experience()

其中这段代码可以保证引入Experience.js的文件可以使用它内部的变量。以word.js举例

this.scene = this.experience.scene

        this.resources = this.experience.resources // 资源

是可以使用的

let instance = null
export default class Experience{constructor(canvas){if(instance){ // 很重要,其他引入时,可以拿到同一个实例内容return instance}instance = this}
import Experience from '../Experience.js'export default class World
{constructor(){this.experience = new Experience()}

三,效果

three.js基础学习 新的结构 狐狸


总结

在项目中如何运用,以及对应的结构区分方式方法不止这一种,择优而用!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI风向标|算力与通信的完美融合,SRM6690解锁端侧AI的智能密码

当前,5G技术已经成为推动数字经济和实体经济深度融合的关键驱动力,进入5G发展的下半场,5G与AI的融合正推动诸多行业的数字化转型和创新发展,终端侧AI和端云混合式AI将广泛应用于各类消费终端和各行各业。 在推动5G和AI与各行业场…

【WPF】Prism学习(二)

Prism Commands 1.命令(Commanding) 1.1. ViewModel的作用: ViewModel不仅提供在视图中显示或编辑的数据,还可能定义一个或多个用户可以执行的动作或操作。这些用户可以通过用户界面(UI)执行的动作或操作…

智慧建造-运用Trimble技术将梦幻水族馆变为现实【上海沪敖3D】

项目概述 西雅图水族馆耗资1.6亿美元对海洋馆进行扩建。该项目包括建造三个大型栖息地,每个建筑物几乎都没有直边,其中一个主栖息地由520立方米混凝土和355吨钢筋组成。特纳建筑公司的混凝土团队通过强大的贸易合作伙伴和创新的数字制造技术,…

kubesphere环境-本地Harbor仓库+k8s集群(单master 多master)+Prometheus监控平台部署

前言:半月前在公司生产环境上离线部署了k8s集群Victoria Metrics(二开版)自研版夜莺 监控平台的搭建,下面我租用3台华为云服务器演示部署kubesphere环境-本地Harbor仓库k8s集群(单master节点 & 单master节点)Prometheus监控部…

java 随机生成验证码

1.需求 实现随机生成验证码,验证码可能是大小写字母和数字 2.实现 写一个getCode方法实现 public static String getCode(int n){//1. 定义一个字符串,字符串中包含大小写字母和数字String str "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrs…

Unity图形学之Blend指令

1.渲染流程:Blend 决定了要渲染的像素和Gbuffer里像素到底怎么取舍 2.Blend 公式: 3.factor可以取值的内容有: One 1 Zero :0 SrcColor : 要渲染的像素 SrcAlpha : 要渲染像素的 a 通道。 DstColor : 已经渲染在gbuffer…

林曦词典|养生

“林曦词典”是在水墨画家林曦的课堂与访谈里,频频邂逅的话语,总能生发出无尽的思考。那些悠然轻快的、微妙纷繁的,亦或耳熟能详的词,经由林曦老师的独到解析,意蕴无穷,让人受益。于是,我们将诸…

生成自签名证书并配置 HTTPS 使用自签名证书

生成自签名证书 1. 运行 OpenSSL 命令生成证书和私钥 在终端中输入以下命令,生成自签名证书和私钥文件: sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout self_signed.key -out self_signed.pem-x509:生成自签名证书。…

物料数据对接:轻易云助力聚水潭与金蝶云星空集成方案

聚水潭数据集成到金蝶云星空:物料对接方案 在企业信息化系统中,数据的高效流动和准确对接是业务运营的关键。本文将聚焦于一个具体的技术案例——如何通过轻易云数据集成平台实现聚水潭与金蝶云星空之间的物料数据对接。 本次集成任务主要涉及两个核心…

阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_作战无人机和察打无人机图鉴

文献基本信息 题名作者来源发表时间2020年国外先进军用无人机技术发展综述 袁成;董晓琳;朱超磊 飞航导弹 2021-01-14 2021年国外军用无人机装备技术发展综述 朱超磊 ;袁成;杨佳会;飞航导弹 战术导弹技术2022-02-112022年国外军用无人机装备技术发展综述 朱超磊;金钰;王靖…

【C#设计模式(11)——外观模式(Facade Pattern)】

前言 外观模式隐藏了子系统的复杂性,简化了客户端与子系统之间的交互。 代码 public class Facade{private CommunicationModel communicationModel;private AcquisitionModel acquisitionModel;private ToolModel toolModel;public Facade(){communicationModel n…

学习日记_20241115_聚类方法(层次聚类)

前言 提醒: 文章内容为方便作者自己后日复习与查阅而进行的书写与发布,其中引用内容都会使用链接表明出处(如有侵权问题,请及时联系)。 其中内容多为一次书写,缺少检查与订正,如有问题或其他拓展…

力扣 LeetCode 239. 滑动窗口最大值(Day5:栈与队列)

解题思路: 始终维护deque的头元素为最大值,后面来的值更大就会逐一清除前面比它小的值 可以把 peek() 改为 peekFirst() ,虽然是一个意思,但看起来更加清楚,对于双端队列能更清晰地表述具体操作 class Solution {pu…

基于GPU器件行为的创新分布式功能安全机制为智能驾驶保驾护航

作者:商瑞 陈娇 随着汽车智能化程度的快速提高,大量新的处理器和系统级芯片(SoC)被广泛引入到车辆中,无论是在驾驶还是座舱等场景,无论采用域控制器模式还是新兴的中央控制单元模式,都无一例外…

高美GULMAY高压发生器维修X射线源维修CF160

GULMAY高压发生器维修规格系列包括:CF,FC,CP等系列 维修类别:仪器仪表/无损检测仪器/其他无损检测仪器 GULMAY公司作为世界上X的工业X射线高压系统制造厂家之一,GULMAY公司拥有30多年的研发和制造经验,不但为XX射线探伤X域的用户提供种类繁多的标准型号…

动态规划-背包问题——[模版]完全背包问题

1.题目解析 题目来源 [模版]完全背包_牛客题霸_牛客 测试用例 2.算法原理 1.状态表示 与01背包相同,这里的完全背包也是需要一个二维dp表来表示最大价值,具体如下 求最大价值dp[i][j]:在[1,i]区间选择物品,此时总体积不大于j时的最大价值 求…

Android音视频直播低延迟探究之:WLAN低延迟模式

Android WLAN低延迟模式 Android WLAN低延迟模式是 Android 10 引入的一种功能,允许对延迟敏感的应用将 Wi-Fi 配置为低延迟模式,以减少网络延迟,启动条件如下: Wi-Fi 已启用且设备可以访问互联网。应用已创建并获得 Wi-Fi 锁&a…

Android setTheme设置透明主题无效

【问题现象】 1、首先&#xff0c;你在AndroidManifest.xml中声明一个activity&#xff0c;不给application或者activity设置android:theme, 例如这样&#xff1a; <applicationandroid:allowBackup"true"android:icon"mipmap/ic_launcher"android:lab…

基于Spring Boot的在线性格测试系统设计与实现(源码+定制+开发)智能性格测试与用户个性分析平台、在线心理测评系统的开发、性格测试与个性数据管理系统

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…