pixi.js 图像资源(svg)转纹理
当Pixi使用WebGL去调用GPU渲染图像时,需要先将图像转化为GPU可以处理的版本。而能够被GPU处理的图像就叫做纹理,在pixi中使用纹理缓存来存储和引用所有纹理。通过将纹理分配给精灵,再将精灵添加到舞台上,从而显示图像。
图像转化为纹理的方式
1. app的loader对象
Pixi强大的loader
对象可以加载任何种类的图像资源,并保存在纹理缓存中。后续如果需要继续获取纹理,就不用再重复加载图像,直接从缓存中获取即可,减轻GPU内存占用。
app.loader
.add("imgs/1.jpg")
.load(setup);
function setup() {
//This code will run when the loader has finished loading the image
let sprite = new PIXI.Sprite(app.loader.resources["imgs/1.jpg"].texture);
app.stage.add(spirte)
}
2. Pixi的Texture类型
Pixi的Texture
类型,实现了加载图像的静态方法。
static from(source: string | HTMLImageElement | HTMLCanvasElement | HTMLVideoElement | PIXI.BaseTexture, options?: any, strict?: boolean): PIXI.Texture;
从允许的参数类型可以看出,我们可以通过直接传入图像地址、img标签、canvas标签、video标签,将图像转化为纹理。
- 通过图像链接加载
var texture = PIXI.Texture.from("imgs/1.jpg");
var sprite = new PIXI.Sprite(PIXI.utils.TextureCache["imgs/1.jpg"]);
app.stage.addChild(sprite);
根据链接加载图像,更推荐这种方式,可以捕获到图像加载失败
ps:其实fromURL()
,内部调用的还是from()
PIXI.Texture.fromURL(data)
.then((texture) => {
const spirte = new PIXI.Sprite(texture);
app.stage.addChild(spirte);
})
.catch((e) => {
console.log("load error", e);
});
- 通过标签加载
var img = document.getElementById("img");
var texture = PIXI.Texture.from(img);
var sprite = new PIXI.Sprite(texture)
app.stage.addChild(sprite)
将SVG Dom节点转为纹理
如果只是单纯的把svg作为一个单独的外部文件,其实只要按照上面两种转换纹理的方式,传入svg图像链接就可以实现了。但是如果这个svg是在同一个html页上的dom节点呢?这时候还能将其转为纹理吗?答案是可以的。
注意观察Texture.from()
的参数,可以传入图像的链接。那么base64
编码后的图像地址,按理来说也可以。所以只要将页面上的svg节点,转化为base64
编码即可。
function getSvgBase64(id) {
var svg = document.getElementById(id)
return "data:image/svg+xml;base64," + window.btoa(svg.outerHTML);
}
关键代码: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)。
function autoDetectResource(source: unknown, options?: IAutoDetectOptions): Resource
{
if (!source)
{
return null;
}
let extension = '';
if (typeof source === 'string')
{
// search for file extension: period, 3-4 chars, then ?, # or EOL
const result = (/\.(\w{3,4})(?:$|\?|#)/i).exec(source);
if (result)
{
extension = result[1].toLowerCase();
}
}
for (let i = INSTALLED.length - 1; i >= 0; --i)
{
const ResourcePlugin = INSTALLED[i];
if (ResourcePlugin.test && ResourcePlugin.test(source, extension))
{
return new ResourcePlugin(source, options);
}
}
throw new Error('Unrecognized source type to auto-detect Resource');
}
INSTALLED
在index.ts中已经初始化注入所有的ResourcePlugin
INSTALLED.push(
ImageResource,
ImageBitmapResource,
CanvasResource,
VideoResource,
SVGResource,
BufferResource,
CubeResource,
ArrayResource
);
在这里可以看到,pixi中有一个SVGResource
,我们就以这个为例继续深入看下内部的处理机制。
简化版SVGResource
类:
export class SVGResource extends BaseImageResource
{
constructor(sourceBase64: string, options?: ISVGResourceOptions)
{
//...
super(document.createElement('canvas'));
if (options.autoLoad !== false)
{
this.load();
}
}
load(): Promise<SVGResource>
{
// Convert SVG inline string to data-uri
if ((/^\<svg/).test(this.svg.trim()))
{
if (!btoa)
{
throw new Error('Your browser doesn\'t support base64 conversions.');
}
(this as any).svg = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(this.svg)))}`;
}
this._loadSvg();
return this._load;
}
/**
* Loads an SVG image from `imageUrl` or `data URL`.
*
* @private
*/
private _loadSvg(): void
{
const tempImage = new Image();
BaseImageResource.crossOrigin(tempImage, this.svg, this._crossorigin);
tempImage.src = this.svg;//将base64编码的Svg字符串,创建为Image对象
tempImage.onload = (): void =>
{
// Draw the Svg to the canvas
canvas
.getContext('2d')
.drawImage(tempImage, 0, 0, svgWidth, svgHeight, 0, 0, width, height);
};
}
static test(source: unknown, extension?: string): boolean
{
// url file extension is SVG
return extension === 'svg'
// source is SVG data-uri
|| (typeof source === 'string' && (/^data:image\/svg\+xml(;(charset=utf8|utf8))?;base64/).test(source))
// source is SVG inline
|| (typeof source === 'string' && source.indexOf('<svg') === 0);
}
}
看完这里就差不多明白了,对于传入的Source
来说,当在autoDetectResource()
中通过test()
方法检测到资源为SVG格式后,将其转换为Base64字符串(也就是说直接传入拼接好的svg字符串也是可以被解析的~),然后再load为Image
对象,加载到临时canvas
中。最后再通过BaseImageResource
的upload()
调用GPU输出图像资源。
总结
一步步了解一个东西过程还是很有意思的,每走一步都会有新的发现。事实上还是有很多东西没有搞懂,就留着以后去发现了。
pixi.js 图像资源(svg)转纹理的更多相关文章
- HTML5游戏开发引擎Pixi.js完全入门手册(一)框架简介及框架结构分析,作者思路剖析
前言: 最近无聊在淘宝弄了个小店,打算做一个兼职.遇到一个客户,要我帮忙拷贝一个html5游戏.. 我这人有一个习惯,拿到自己没见过的东西.都会去研究一番.去网上查了下发现,资料都是英文版.感觉极度不 ...
- pixi.js 总结
我的博客简单简洁 可能表达不清. 如有想法, 敬请留言.谢谢! 群:881784250 https://github.com/ccaleb/endless-runner/tree/master/jav ...
- pixi.js教程中文版--基础篇
前言 Pixi.js使用WebGL,是一个超快的HTML5 2D渲染引擎.作为一个Javascript的2D渲染器,Pixi.js的目标是提供一个快速的.轻量级而且是兼任所有设备的2D库.提供无缝 C ...
- CocosCraetor中图像资源Texture和SpriteFrame的区别
Texture是保存在GPU缓冲中的一张纹理.是由一张图片创建获得的. SpriteFrame是Texture+Rect,根据一张纹理材质来剪切获得. SpriteFrame是Texture+Rect ...
- Hero Patterns - 聚合各种 SVG 背景纹理素材的网站
Hero Patterns 是一个聚合了各种 SVG 背景纹理素材的网站,提供的多样的素材可以给你的网站带去特色. SVG 是一种分辨率无关的图形(矢量图形).这意味着它在任何类型的屏幕都不会遭受任何 ...
- 如何在PIXI.js里面使用json文件来管理瓦片集(tileset)?
如何在PIXI.js里面使用json文件来管理瓦片集(tileset)? PIXI建议我们将素材图片汇总成一个瓦片集(tileset),然后用纹理地图集(texture atlas,通常是一个json ...
- pixi.js持续渲染页面
Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而制作游戏或应用. 项目地址:https://github.com/pixijs/pixi.js A ...
- pixi.js 自定义光标样式
pixi 介绍 Pixi是一个超快的2D渲染引擎,通过Javascript和Html技术创建动画或管理交互式图像,从而制作游戏或应用. 项目地址:https://github.com/pixijs/p ...
- (原)用pixi.js 实现 方块阵点击后原地自转效果
源码 各位,请教一个问题,我这个还有BUG,我是想实现,点击一下可以 停止转动,然后再点一下重新转动.而不是一直加速,有没有什么好办法? PS:问题已经解决,谢谢评论的大神@Antineutrino ...
随机推荐
- 后端程序员必备的 Linux 基础知识
1. 从认识操作系统开始 正式开始 Linux 之前,简单花一点点篇幅科普一下操作系统相关的内容. 1.1. 操作系统简介 我通过以下四点介绍什么是操作系统: 操作系统(Operating Syste ...
- Scrapy简明教程
本文通过示例简要介绍一下使用Scrapy抓取网站内容的基本方法和流程. 继续阅读之前请确保已安装了scrapy. 基本安装方法为:pip install scrapy 我们已经在之前的文章中初步介绍了 ...
- 分别使用python和java练习冒泡排序
冒泡排序算法的运作如下:(从小到大) 比较相邻的元素.如果第一个比第二个大,就交换他们两个. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 针 ...
- 20192313 实验一《Linux基础与Java开发环境》实验报告
20192313 2020-10-8 <数据结构与面向对象程序设计>实验1报告 课程:<程序设计与数据结构> 班级: 1923 姓名: 陈宇帆 学号:20192313 实验教师 ...
- 两种方式简单免杀ew
1.资源操作法 使用工具: Restorator 2018 BeCyIconGrabber 首先我们从github下载ew使用360进行查杀 打开Restorator 将ew拖入,右键添加资源 选择图 ...
- centos7网卡bond配置--自己另一篇文章的补充
这篇文章是自己另一篇文章的第二种方法的一个完善的补充 https://www.cnblogs.com/zzf0305/p/9588585.html 1 备份网卡配置文件2 使用nmcli命令配置bon ...
- webstorm实现手机预览页面
效果:在webstorm中开发页面,复制该页面在电脑中的浏览网址,发给手机,在手机上点击链接,可以直接访问本地开发的页面.并且,电脑上修改后保存,手机上刷新即可看到效果. 步骤: 1.webstorm ...
- 数据结构与算法——循环链表的算法实现(Joseph 问题)
Joseph 问题: 如果有10 个人,按编号顺序1,2,...,10 顺时针方向围成一圈.从1 号开始顺时针方向1,2,...,9 报数,凡报数9 者出列(显然,第一个出圈为编号9 者). 最后一个 ...
- STL——容器(Set & multiset)的迭代器
1.set.insert(elem); //在容器中插入元素. 2.set.begin(); //返回容器中第一个数据的迭代器. 3.set.end(); / ...
- 我叫Mongo,干了「索引探索篇」提升我的效率,值得您拥有
这是mongo第四篇"索引探索",后续会连续更新4篇 mongodb的文章总结上会有一系列的文章,顺序是先学会怎么用,在学会怎么用好,戒急戒躁,循序渐进,跟着我一起来探索交流.通过 ...