引言

在三维可视化中,会波及到很多动画,其中贴图动画是其中很重要的一种,本文介绍几种贴图动画的思路,供大家一起探讨。

流动动画

流动动画通过设置贴图的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/T... 成果如下图所示:

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彪叔” 能够及时收到更多有价值的文章。