当Pixi使用WebGL去调用GPU渲染图像时,需要先将图像转化为GPU可以处理的版本。而能够被GPU处理的图像就叫做纹理,在pixi中使用纹理缓存来存储和引用所有纹理。通过将纹理分配给精灵,再将精灵添加到舞台上,从而显示图像。

图像转化为纹理的方式

1. app的loader对象

Pixi强大的loader对象可以加载任何种类的图像资源,并保存在纹理缓存中。后续如果需要继续获取纹理,就不用再重复加载图像,直接从缓存中获取即可,减轻GPU内存占用。

  1. app.loader
  2. .add("imgs/1.jpg")
  3. .load(setup);
  4. function setup() {
  5. //This code will run when the loader has finished loading the image
  6. let sprite = new PIXI.Sprite(app.loader.resources["imgs/1.jpg"].texture);
  7. app.stage.add(spirte)
  8. }
2. Pixi的Texture类型

Pixi的Texture类型,实现了加载图像的静态方法。

static from(source: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | PIXI.BaseTexture, options?: any, strict?: boolean): PIXI.Texture;

从允许的参数类型可以看出,我们可以通过直接传入图像地址、img标签、canvas标签、video标签,将图像转化为纹理。

  • 通过图像链接加载
  1. var texture = PIXI.Texture.from("imgs/1.jpg");
  2. var sprite = new PIXI.Sprite(PIXI.utils.TextureCache["imgs/1.jpg"]);
  3. app.stage.addChild(sprite);

根据链接加载图像,更推荐这种方式,可以捕获到图像加载失败

ps:其实fromURL(),内部调用的还是from()

  1. PIXI.Texture.fromURL(data)
  2. .then((texture) => {
  3. const spirte = new PIXI.Sprite(texture);
  4. app.stage.addChild(spirte);
  5. })
  6. .catch((e) => {
  7. console.log("load error", e);
  8. });
  • 通过标签加载
  1. var img = document.getElementById("img");
  2. var texture = PIXI.Texture.from(img);
  3. var sprite = new PIXI.Sprite(texture)
  4. app.stage.addChild(sprite)

将SVG Dom节点转为纹理

如果只是单纯的把svg作为一个单独的外部文件,其实只要按照上面两种转换纹理的方式,传入svg图像链接就可以实现了。但是如果这个svg是在同一个html页上的dom节点呢?这时候还能将其转为纹理吗?答案是可以的。

注意观察Texture.from()的参数,可以传入图像的链接。那么base64编码后的图像地址,按理来说也可以。所以只要将页面上的svg节点,转化为base64编码即可。

  1. function getSvgBase64(id) {
  2. var svg = document.getElementById(id)
  3. return "data:image/svg+xml;base64," + window.btoa(svg.outerHTML);
  4. }

关键代码:window.btoa() 创建一个base64编码的字符串,解码方法 window.atob()

源码解析

首先,从Texture.from()开始入手,我们具体看看pixi是如何加载图像纹理的。

在from方法中有这么一句话texture = new Texture(new BaseTexture(source, options));。所有的Texture对应的还有一个BaseTexture,他们之间的关系可以这么解释

BaseTexture : The base texture source to create the texture from

接下来看一下 BaseTexture类的构造函数,其中调用了autoDetectResource()方法,在这个方法中真正的对资源进行了检测分类,并根据不同类型的资源调用不同的资源插件(ResourcePlugin)。

  1. function autoDetectResource(source: unknown, options?: IAutoDetectOptions): Resource
  2. {
  3. if (!source)
  4. {
  5. return null;
  6. }
  7. let extension = '';
  8. if (typeof source === 'string')
  9. {
  10. // search for file extension: period, 3-4 chars, then ?, # or EOL
  11. const result = (/\.(\w{3,4})(?:$|\?|#)/i).exec(source);
  12. if (result)
  13. {
  14. extension = result[1].toLowerCase();
  15. }
  16. }
  17. for (let i = INSTALLED.length - 1; i >= 0; --i)
  18. {
  19. const ResourcePlugin = INSTALLED[i];
  20. if (ResourcePlugin.test && ResourcePlugin.test(source, extension))
  21. {
  22. return new ResourcePlugin(source, options);
  23. }
  24. }
  25. throw new Error('Unrecognized source type to auto-detect Resource');
  26. }

INSTALLED在index.ts中已经初始化注入所有的ResourcePlugin

  1. INSTALLED.push(
  2. ImageResource,
  3. ImageBitmapResource,
  4. CanvasResource,
  5. VideoResource,
  6. SVGResource,
  7. BufferResource,
  8. CubeResource,
  9. ArrayResource
  10. );

在这里可以看到,pixi中有一个SVGResource,我们就以这个为例继续深入看下内部的处理机制。

简化版SVGResource类:

  1. export class SVGResource extends BaseImageResource
  2. {
  3. constructor(sourceBase64: string, options?: ISVGResourceOptions)
  4. {
  5. //...
  6. super(document.createElement('canvas'));
  7. if (options.autoLoad !== false)
  8. {
  9. this.load();
  10. }
  11. }
  12. load(): Promise<SVGResource>
  13. {
  14. // Convert SVG inline string to data-uri
  15. if ((/^\<svg/).test(this.svg.trim()))
  16. {
  17. if (!btoa)
  18. {
  19. throw new Error('Your browser doesn\'t support base64 conversions.');
  20. }
  21. (this as any).svg = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(this.svg)))}`;
  22. }
  23. this._loadSvg();
  24. return this._load;
  25. }
  26. /**
  27. * Loads an SVG image from `imageUrl` or `data URL`.
  28. *
  29. * @private
  30. */
  31. private _loadSvg(): void
  32. {
  33. const tempImage = new Image();
  34. BaseImageResource.crossOrigin(tempImage, this.svg, this._crossorigin);
  35. tempImage.src = this.svg;//将base64编码的Svg字符串,创建为Image对象
  36. tempImage.onload = (): void =>
  37. {
  38. // Draw the Svg to the canvas
  39. canvas
  40. .getContext('2d')
  41. .drawImage(tempImage, 0, 0, svgWidth, svgHeight, 0, 0, width, height);
  42. };
  43. }
  44. static test(source: unknown, extension?: string): boolean
  45. {
  46. // url file extension is SVG
  47. return extension === 'svg'
  48. // source is SVG data-uri
  49. || (typeof source === 'string' && (/^data:image\/svg\+xml(;(charset=utf8|utf8))?;base64/).test(source))
  50. // source is SVG inline
  51. || (typeof source === 'string' && source.indexOf('<svg') === 0);
  52. }
  53. }

看完这里就差不多明白了,对于传入的Source来说,当在autoDetectResource()中通过test()方法检测到资源为SVG格式后,将其转换为Base64字符串(也就是说直接传入拼接好的svg字符串也是可以被解析的~),然后再load为Image对象,加载到临时canvas中。最后再通过BaseImageResourceupload()调用GPU输出图像资源。

总结

一步步了解一个东西过程还是很有意思的,每走一步都会有新的发现。事实上还是有很多东西没有搞懂,就留着以后去发现了。

pixi.js 图像资源(svg)转纹理的更多相关文章

  1. HTML5游戏开发引擎Pixi.js完全入门手册(一)框架简介及框架结构分析,作者思路剖析

    前言: 最近无聊在淘宝弄了个小店,打算做一个兼职.遇到一个客户,要我帮忙拷贝一个html5游戏.. 我这人有一个习惯,拿到自己没见过的东西.都会去研究一番.去网上查了下发现,资料都是英文版.感觉极度不 ...

  2. pixi.js 总结

    我的博客简单简洁 可能表达不清. 如有想法, 敬请留言.谢谢! 群:881784250 https://github.com/ccaleb/endless-runner/tree/master/jav ...

  3. pixi.js教程中文版--基础篇

    前言 Pixi.js使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库.提供无缝 C ...

  4. CocosCraetor中图像资源Texture和SpriteFrame的区别

    Texture是保存在GPU缓冲中的一张纹理.是由一张图片创建获得的. SpriteFrame是Texture+Rect,根据一张纹理材质来剪切获得. SpriteFrame是Texture+Rect ...

  5. Hero Patterns - 聚合各种 SVG 背景纹理素材的网站

    Hero Patterns 是一个聚合了各种 SVG 背景纹理素材的网站,提供的多样的素材可以给你的网站带去特色. SVG 是一种分辨率无关的图形(矢量图形).这意味着它在任何类型的屏幕都不会遭受任何 ...

  6. 如何在PIXI.js里面使用json文件来管理瓦片集(tileset)?

    如何在PIXI.js里面使用json文件来管理瓦片集(tileset)? PIXI建议我们将素材图片汇总成一个瓦片集(tileset),然后用纹理地图集(texture atlas,通常是一个json ...

  7. pixi.js持续渲染页面

    Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而制作游戏或应用. 项目地址:https://github.com/pixijs/pixi.js A ...

  8. pixi.js 自定义光标样式

    pixi 介绍 Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而制作游戏或应用. 项目地址:https://github.com/pixijs/p ...

  9. (原)用pixi.js 实现 方块阵点击后原地自转效果

    源码 各位,请教一个问题,我这个还有BUG,我是想实现,点击一下可以 停止转动,然后再点一下重新转动.而不是一直加速,有没有什么好办法?  PS:问题已经解决,谢谢评论的大神@Antineutrino ...

随机推荐

  1. MySQL ERROR 1040: Too many connections

    如题,本章主要讲下当服务器出现 ERROR 1040: Too many connections错误时的一些处理心得. max_connections查看 ## 查看最大连接数 SHOW VARIAB ...

  2. john快速破解各种散列hash

    0x01 john工具安装: kali系统自带的有,也可以自己安装在其他linux和windows系统上,关于安装步骤网上都有可自行百度. 0x02 john常用选项 具体的其他选项可通过john - ...

  3. 你必须知道的MySQL知识点

    什么是索引 索引是帮助MySQL高效获取数据的排好序的数据结构 索引数据结构(掌握) 数据结构可视化 前置知识:树的高度越低查询效率越高 二叉树:不能自平衡,极端情况出现倾斜,查询效率和链表类似 红黑 ...

  4. JQuery获取父,子,兄弟节点

    jQuery.parent(expr) // 查找父节点,可以传入expr进行过滤,比如$("span").parent()或者$("span").parent ...

  5. JVM命令手册

    原文链接:https://blog.csdn.net/qq_41345773/article/details/93895532 aconst_null 将null对象引用压入栈iconst_m1 将i ...

  6. 深入理解Java虚拟机(九)——后端编译与优化

    即时编译器 Java程序最初都是通过解释器进行执行,当发现某个方法或者代码块被运行得非常频繁,这些代码就被认为是热点代码,为了提高这些代码得运行效率,虚拟机会把热点代码编译成本地机器码,并进行优化,运 ...

  7. Java8新增的这些集合骚操作,你掌握了嘛?

    目录 Iterable的forEach Iterator的forEachRemaining Collection的removeIf Stream操作 List的replaceAll List的sort ...

  8. 九、TestNG超时测试

    "超时"表示如果单元测试花费的时间超过指定的毫秒数,那么TestNG将会中止它并将其标记为失败. 使用属性 timeOut = 参数(1s*1000) package com.lc ...

  9. 跨站点脚本编制 - SpringBoot配置XSS过滤器(基于Jsoup)

    1. 跨站点脚本编制   风险:可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看或变更用户记录以及执行事务.   原因:未对用户输入正确执行危险字符清 ...

  10. Java后端使用socketio,实现小程序答题pk功能

    在使用socket.io跟前端通信过程中,出现了一系列问题,现做下记录. 一.功能需求是,在小程序端,用户可相互邀请,进入房间后进行答题PK.实现方法是,用户点击邀请好友,建立连接,查询当前是否有房间 ...