threejs 贴图动画总结
引言
在三维可视化中,会涉及到很多动画,其中贴图动画是其中很重要的一种,本文介绍几种贴图动画的思路,供大家一起探讨。
流动动画
流动动画通过设置贴图的repeat属性,并不断改变贴图对象的offset让贴图产生流动效果。 这种动画不难实现,首先加载贴图,如下所示:
let img = new Image();
img.src = './images/path.png';
let texture = new eg.Texture(img);
img.onload = function () {
texture.needsUpdate = true;
}
texture.repeat.set(100,1);
tube.material.map= texture;
function render(){
tube.material.map.wrapS = eg.RepeatWrapping;
tube.material.map.offset.set(offset,0);
tube.material.map.needsUpdate = true;
offset += 0.01;
}
上面代码,实现了一个tube(管道),然后给管道加了一个贴图texture。 在渲染的时候,不断更新texture对象的offset的值,此时就可以生产流动的动画。如下图所示:
雪碧图动画(Sprite Sheet)
图集也就是常说的雪碧图,就是把一系列小图按照一定的布局放到一张大图上面。 在使用的时候,截取大图的一部分来获取某个小图。 这在web端是一种常用的手段,通常用于减少图片数量,从而降低网络请求数量。
通过雪碧图的方式,可以把动画的系列动作的每一帧都布局在雪碧图上。 然后通过雪碧图创建texture对象,设置贴图的repeat和offset,让每次绘制获取雪碧图上的某一帧图像,不断改变offset,就可以形成绘制不同帧的动画效果。比如下面的图片:
下面这个threejs的demo,就是这样的效果,所以此处不再赘述代码,有兴趣的读者可以查看demo的源代码。
https://stemkoski.github.io/Three.js/Texture-Animation.html 效果如下图所示:
GIF动画
gif图片本身自带动画,如果gif放到Image对象上,动画会自动播放,只是当把gif作为贴图对象的图片的时候。 不会自动播放动画。
要自动播放gif动画,需要使用解析gif的库,把gif图片的每一帧解析出来, 并把每一帧图像绘制到一个canvas上,把canvas作为贴图对象的图片。大致代码如下:
加载gif图片,并解析图片。其中解析图片用到了一个库omggif,利用里面的GifReader可以解析gif图片的帧数据:
import { GifReader } from 'omggif';
const loader = new FileLoader(this.manager);
loader.setPath(this.path);
loader.setResponseType('arraybuffer');
loader.load(url, (response) => {
const gifData = new Uint8Array(response);
const reader = new GifReader(gifData);
if (onLoad) onLoad(reader);
}, onProgress, onError);
然后不断的更新贴图的图像:
draw() {
if (!this.reader) {
return;
}
const { reader, image, context } = this;
const { width, height } = image;
const frameNum = ++this.frameNumber % reader.numFrames();
const frameInfo = reader.frameInfo(frameNum);
if (frameNum === 0) {
// always clear canvas to start
context.clearRect(0, 0, width, height);
} else if (this.previousFrameInfo && this.previousFrameInfo.disposal === 2) {
// disposal was "restore to background" which is essentially "restore to transparent"
context.clearRect(this.previousFrameInfo.x,
this.previousFrameInfo.y,
this.previousFrameInfo.width,
this.previousFrameInfo.height);
}
const imageData = context.getImageData(0, 0, width, height);
reader.decodeAndBlitFrameRGBA(frameNum, imageData.data);
context.putImageData(imageData, 0, 0);
this.needsUpdate = true;
this.previousFrameInfo = frameInfo;
this.timeoutId = setTimeout(this.draw.bind(this), (frameInfo.delay || 2) * 10);
}
最终的gif贴图效果如下图所示
APNG动画
APNG图片和gif图片是类似的,也是动画图片。 不过相对于gif来说。APNG可以设置半透明,边缘锯齿不严重,所以使用APNG的图片的效果要优于gif图片。
原理上类似,也是解析APNG图片,然后把没一帧一次绘制到canvas上,并不断更新texture对象。 解析APNG图片,使用了一个开源库,APNG-canvas。 有兴趣读者可以自行研究,此处不重点讲述。
解析完成后,可以把解析的帧集合进行绘制,代码如下:
draw() {
if (!this.reader) {
return;
}
const { reader, image, context } = this;
const { width, height } = image;
const frameNum = ++this.frameNumber % reader.numFrames;
const frameInfo = reader.frames[frameNum];
if (frameNum === 0) {
// always clear canvas to start
context.clearRect(0, 0, width, height);
// } else if (this.previousFrameInfo && this.previousFrameInfo.disposal === 2) {
} else if (this.previousFrameInfo) {
// disposal was "restore to background" which is essentially "restore to transparent"
context.clearRect(this.previousFrameInfo.left,
this.previousFrameInfo.top,
this.previousFrameInfo.width,
this.previousFrameInfo.height);
}
const imageData = context.getImageData(0, 0, width, height);
// reader.decodeAndBlitFrameRGBA(frameNum, imageData.data);
// context.putImageData(imageData, 0, 0);
context.drawImage(frameInfo.img,frameInfo.left,frameInfo.top,frameInfo.width,frameInfo.height);
this.needsUpdate = true;
this.previousFrameInfo = frameInfo;
this.timeoutId = setTimeout(this.draw.bind(this), frameInfo.delay);
最终的apng贴图效果如下图所示
总结
本文介绍了 theejs 贴图动画的多种实现思路。 包括 纹理流动,雪碧图,gif和apng动画。 通过这些动画能力,可以创建出丰富多彩的可视化效果。
如果对可视化感兴趣,可以和我交流,微信541002349(可入微信群)。另寻求有三维建模能力,UI设计能力的人员。
关注公号“ITMan彪叔” 可以及时收到更多有价值的文章。
threejs 贴图动画总结的更多相关文章
- 8款超绚丽的jQuery焦点图动画
随着前端技术和浏览器技术的不断发展,人们开始对网页视觉效果的要求越来越高.我们经常会在页面中看到很多炫酷的图片焦点图播放控件,有些甚至是大屏的焦点图占用大片的页面空间,从而吸引用户的眼球.本文要分享的 ...
- 用CAShapeLayer写股市K线图动画效果
用CAShapeLayer写股市K线图动画效果 说明 入市有风险,炒股需谨慎.(因项目需求,本人提供了写这种效果的源码) 效果 源码 // // ViewController.m // Path // ...
- 第166天:canvas绘制饼状图动画
canvas绘制饼状图动画 1.HTML <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- Laya的动画制作,整图动画,序列图动画,时间轴动画,龙骨动画
参考: Laya动画基础 Egret帧动画工具类 版本:2.1.1.1 序列图动画 白鹭的序列图动画,使用TexureMerger合图,然后使用MovieClip类播放. Laya的话,使用图集打包工 ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu
示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...
- HTML5 随音乐节奏变化的频谱图动画
这里将要介绍的HTML5 音频处理接口与Audio标签是不一样的.页面上的Audio标签只是HTML5更语义化的一个表现,而HTML5提供给JavaScript编程用的Audio API则让我们有能力 ...
- android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]
http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...
- js实现轮播图动画
在网页浏览中,可以看到轮播图是无处不在的,这是一个前端工程最基本的技巧.首先看看几个网页的呈现的效果. QQ音乐: 网易云音乐: 天猫: 接下来将从简到难总结几种实现轮播图的方法. 1.样式一:鼠标滑 ...
- Android 开发 VectorDrawable 矢量图 (三)矢量图动画
VectorDrawable 矢量图 三部曲: Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图 Android 开发 VectorDrawabl ...
随机推荐
- 分布式配置系统Apollo如何实时更新配置的?
引言 记得我们那时候刚开始学习Java的时候都只是一个单体项目,项目里面的配置基本都是写在项目里面的properties文件中,比如数据库配置啥的,各种逻辑开关,一旦这些配置修改了,还需要重启项目这修 ...
- 最难忘的一次bug:谢谢实习时候爱学习的自己
前言 时间的车轮一直向前不停,试图在时光洪流中碾碎一些久远的记忆.虽然记忆中的人离我越来越远,但是故事却越来越深刻. 当在博客园看到这次的正文题目是"最难忘的bug",脑海里瞬间浮 ...
- SPOJ 1557 GSS2 - Can you answer these queries II (线段树+维护历史最值)
都说这题是 GSS 系列中最难的,今天做了一下,名副其实 首先你可以想到各种各样的在线乱搞想法,线段树,主席树,平衡树,等等,但发现都不太可行. 注意到题目也没有说强制在线,因此可以想到离线地去解决这 ...
- 洛谷 P5502 - [JSOI2015]最大公约数(区间 gcd 的性质+分治)
洛谷题面传送门 学校模拟赛的某道题让我联想到了这道题-- 先讲一下我的野鸡做法. 首先考虑分治,对于左右端点都在 \([L,R]\) 中的区间我们将其分成三类:完全包含于 \([L,mid]\) 的区 ...
- Small but Funny Tricks [Remember them all!]
模数 1e9 的神奇求行列式: #include <bits/stdc++.h> using namespace std; const int maxn = 1e2, mod = 1e9; ...
- dotnet 将自动代码格式化机器人带入团队 GitLab 平台
给团队带入一个 代码格式化机器人 能提升团队的幸福度,让团队的成员安心写代码,不用关注代码格式化问题,将格式代码这个粗活交给机器人去做.同时也能减少在代码审查里撕格式化问题的时间,让更多的时间投入到更 ...
- R语言与医学统计图形【3】条形图、误差图
R语言基础绘图系统 基础图形--条形图.误差图 3.条形图 barplot接收的数据是矩阵而非数据框. data <- sample(c(50:80),5) barplot(data,col=h ...
- 宏GENERATED_BODY做了什么?
Version:4.26.2 UE4 C++工程名:MyProject \ 一般语境下,我们说c++源码的编译大体分为:预处理.编译.链接; cppreference-translation_phas ...
- 学习java 6.29
今天是学习Java的第一天. 学习内容:了解了JDK的下载和安装: 学会了如何配置Path环境变量及安装eclipse: 执行了HelloWorld案例: 在Java中关键字需要小写,Java中最基本 ...
- 16. Linux find查找文件及文件夹命令
find的主要用来查找文件,查找文件的用法我们比较熟悉,也可用它来查找文件夹,用法跟查找文件类似,只要在最后面指明查找的文件类型 -type d,如果不指定type类型,会将包含查找内容的文件和文件夹 ...