three.js 纹理动画实现
需求:
1、使用一张长图、分别播放这张长图的不同位置 来达到动态内容的目的
解决方案:
1、纹理创建并指定重复方向:this.texture.wrapS = this.texture.wrapT = THREE.RepeatWrapping;
2、设定纹理显示范围(就是你的图片要显示的一格动画范围):texture.repeat.set( 1 / this.tilesHorizontal宽, 1 / this.tilesVertical高 );
3、然后就是更改 texture.offset.x 、texture.offset.y 的事情了
一般的动画的话 可以直接在动画函数体内直接更改这两个参数值、
当然这个自带的动画更新函数是很快的、要不想播放的这么快怎么解决呢、
4、这个就要涉及函数类了、先创建一个类、然后创建纹理的时候 new 继承一份类型、 然后在这个类里面加一个方法、去更新继承的这个类的参数、最后在场景动画里面调取的时候去处理就可以了。
不用参考我下面的写法、我这个就是直接copy过来的、这些都可以根据实际的场景去自定义一套自己的规则。
Addtexture(){ this.texture = new THREE.TextureLoader().load(this.path+"btn/c.png")// this.texture.repeat.set(1/4, 1/6); this.test = new this.TextureAnimator(this.texture, 4, 6, 16, 55) // this.updatetexture() }, update(){ var delta = this.clock.getDelta(); this.test.update(1000*delta) }, TextureAnimator(texture, tilesHoriz, tilesVert, numTiles, tileDispDuration) { // note: texture passed by reference, will be updated by the update function. this.tilesHorizontal = tilesHoriz; this.tilesVertical = tilesVert; // how many images does this spritesheet contain? // usually equals tilesHoriz * tilesVert, but not necessarily, // if there at blank tiles at the bottom of the spritesheet. this.numberOfTiles = numTiles; texture.wrapS = texture.wrapT = THREE.RepeatWrapping; texture.repeat.set( 1 / this.tilesHorizontal, 1 / this.tilesVertical ); // how long should each image be displayed? this.tileDisplayDuration = tileDispDuration; // how long has the current image been displayed? this.currentDisplayTime = 0; // which image is currently being displayed? this.currentTile = 0; this.update = function( milliSec ) { this.currentDisplayTime += milliSec; while (this.currentDisplayTime > this.tileDisplayDuration) { this.currentDisplayTime -= this.tileDisplayDuration; this.currentTile--; if (this.currentTile == this.numberOfTiles) this.currentTile = 0; var currentColumn = this.currentTile % this.tilesHorizontal; texture.offset.x = currentColumn / this.tilesHorizontal; var currentRow = Math.floor( this.currentTile / this.tilesHorizontal ); texture.offset.y = currentRow / this.tilesVertical; } }; }, AddPlaneBuffer(spot) {// 方向按键模型 var geometry = new THREE.PlaneBufferGeometry(2, 5, 32); var material = new THREE.MeshBasicMaterial({ map: this.texture, side: THREE.DoubleSide, transparent: true, // 调整黑色背景问题。 }); var plane = new THREE.Mesh(geometry, material); plane.name = spot.name; plane.ivt = spot.ivt; plane.modeltype = spot.type; plane.XYZ = spot.cpoint plane.size = spot.size plane.position.set(spot.spot.x,spot.spot.y,spot.spot.z); plane.lookAt(0, 999, 0); this.scene.add(plane); }, animate() { // 实时更新动画函数 this.renderer.render(this.scene, this.camera); window.requestAnimationFrame(() => this.animate()); this.orbitControls.update(); this.update() TWEEN.update(); },
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义