PIXI兼容微信小游戏
首先导入官方的weapp-adapter,然后导入pixi.min.js,微信小程序使用ES6的module引用模块,具体参见ES6的Module。
import './libs/weapp-adapter';
import * as PIXI from './libs/pixi.min';
const { pixelRatio, windowWidth, windowHeight } = wx.getSystemInfoSync()
let game = new PIXI.Application({
width:windowWidth*pixelRatio,
height:windowHeight*pixelRatio,
view:canvas
}); let graphics = new PIXI.Graphics();
graphics.beginFill(0xfff000);
graphics.lineStyle(0, 0xffffff, 1);
graphics.drawRect(80,80,100,100);
graphics.endFill();
game.stage.addChild(graphics);
let clktext = new PIXI.Text("Click Me!",{fill:"#ffffff",fontSize:32});
clktext.interactive = true;
let times = 0;
clktext.on("pointerdown",()=>{
clktext.text = `times${++times}`;
});
clktext.x = 200;
clktext.y = 300;
game.stage.addChild(clktext);
目录结构如下
保存运行如下:
完美运行,但是当点击屏幕的任何位置时,报错了,内容如下:
TouchEvent未定义,为什么呢?看pixi源码:
InteractionManager.prototype.normalizeToPointerData = function normalizeToPointerData(event) {
var normalizedEvents = []; if (this.supportsTouchEvents && event instanceof TouchEvent) {
for (var i = 0, li = event.changedTouches.length; i < li; i++) {
var touch = event.changedTouches[i]; if (typeof touch.button === 'undefined') touch.button = event.touches.length ? 1 : 0;
if (typeof touch.buttons === 'undefined') touch.buttons = event.touches.length ? 1 : 0;
if (typeof touch.isPrimary === 'undefined') {
touch.isPrimary = event.touches.length === 1 && event.type === 'touchstart';
}
if (typeof touch.width === 'undefined') touch.width = touch.radiusX || 1;
if (typeof touch.height === 'undefined') touch.height = touch.radiusY || 1;
if (typeof touch.tiltX === 'undefined') touch.tiltX = 0;
if (typeof touch.tiltY === 'undefined') touch.tiltY = 0;
if (typeof touch.pointerType === 'undefined') touch.pointerType = 'touch';
if (typeof touch.pointerId === 'undefined') touch.pointerId = touch.identifier || 0;
if (typeof touch.pressure === 'undefined') touch.pressure = touch.force || 0.5;
touch.twist = 0;
touch.tangentialPressure = 0;
// TODO: Remove these, as layerX/Y is not a standard, is deprecated, has uneven
// support, and the fill ins are not quite the same
// offsetX/Y might be okay, but is not the same as clientX/Y when the canvas's top
// left is not 0,0 on the page
if (typeof touch.layerX === 'undefined') touch.layerX = touch.offsetX = touch.clientX;
if (typeof touch.layerY === 'undefined') touch.layerY = touch.offsetY = touch.clientY; // mark the touch as normalized, just so that we know we did it
touch.isNormalized = true; normalizedEvents.push(touch);
}
}
// apparently PointerEvent subclasses MouseEvent, so yay
else if (event instanceof MouseEvent && (!this.supportsPointerEvents || !(event instanceof window.PointerEvent))) {
if (typeof event.isPrimary === 'undefined') event.isPrimary = true;
if (typeof event.width === 'undefined') event.width = 1;
if (typeof event.height === 'undefined') event.height = 1;
if (typeof event.tiltX === 'undefined') event.tiltX = 0;
if (typeof event.tiltY === 'undefined') event.tiltY = 0;
if (typeof event.pointerType === 'undefined') event.pointerType = 'mouse';
if (typeof event.pointerId === 'undefined') event.pointerId = MOUSE_POINTER_ID;
if (typeof event.pressure === 'undefined') event.pressure = 0.5;
event.twist = 0;
event.tangentialPressure = 0; // mark the mouse event as normalized, just so that we know we did it
event.isNormalized = true; normalizedEvents.push(event);
} else {
normalizedEvents.push(event);
} return normalizedEvents;
};
第四行判断event是否是TouchEvent类型,报错显示就是TouchEvent未定义,TouchEvent是window的事件类型,打印一下window,发现window里没有TouchEvent属性,所以报错
其实只要把window.TouchEvent暴露出来即可,把weapp-adapter.js源码下载下来,查看源码发现有TouchEvent,但是没有对外导出,导出一下,然后在window.js文件再导出一下,打包一下。
webpack打包一下,替换原来的weapp-adapter.js文件,发现没问题了。但是点击事件出了问题,监听不到了,怎么回事呢?
问题出在事件的点击位置的转换上,pixi源码
InteractionManager.prototype.mapPositionToPoint = function mapPositionToPoint(point, x, y) {
var rect = void 0; // IE 11 fix
if (!this.interactionDOMElement.parentElement) {
rect = { x: 0, y: 0, width: 0, height: 0 };
} else {
rect = this.interactionDOMElement.getBoundingClientRect();
} var resolutionMultiplier = navigator.isCocoonJS ? this.resolution : 1.0 / this.resolution; point.x = (x - rect.left) * (this.interactionDOMElement.width / rect.width) * resolutionMultiplier;
point.y = (y - rect.top) * (this.interactionDOMElement.height / rect.height) * resolutionMultiplier;
};
向上追溯源码发现this.interactionDOMElement就是new Application()时传进来的canvas,打印发现就是一个canvas,没有parent。
这个重新映射的原理很简单。简单说就是canvas
的尺寸与渲染尺寸。
以iphone5
为例,全屏canvas
(landscape)大小是568x320
而渲染尺寸(devicePixelRatio=2)是1136x640
。事件监听捕获到的位置是基于canvas
(设备)的,比如有个sprite
在屏幕右下角,此时pixi.js
获取到的点击坐标是568, 320
,而sprite
在渲染尺寸的位置是1136, 640
,如果不进行正确的映射就无法触发pixi.js
内部实现的监听函数。
因为在微信小游戏里canvas肯定是全屏的,所以直接计算position即可
PIXI.interaction.InteractionManager.prototype.mapPositionToPoint = (point, x, y) => {
point.x = x * pixelRatio
point.y = y * pixelRatio
}
或者
app.renderer.plugins.interaction.mapPositionToPoint = (point, x, y) => {
point.x = x * pixelRatio
point.y = y * pixelRatio
}
再次运行完美!
还有一个PIXI.loader
和 ajax
相关的问题,
// weapp-adapter 源码
// src/XMLHttpRequest.js
// 添加 addEventListener 方法
addEventListener(ev, cb) {
this[`on${ev}`] = cb
}
基本完成了。大部分内容来自简书
https://www.jianshu.com/p/38fcbcaf2930,之所以一步步去实现,主要是因为对一些东西还不了解。
最新文章
- KALI Linux problems &; Study Red Hat | Ubuntu
- eclipse color theme 选择一款适合你的代码样式
- [maven] maven变量
- 想要完全导入swc中的所有类
- Codeforces 380 简要题解
- ASP常用函数
- @PostConstruct与@PreDestroy
- Python内置函数(60)——compile
- (六)SpringBoot2.0基础篇- Redis整合(JedisCluster集群连接)
- Charles使用心得总结
- Git使用教程,最详细,最傻瓜,最浅显,真正手把手教
- jQuery中异步问题:数据传递
- 《mysql必知必会》学习_第17章_20180807_欢
- css盒子模型和定位
- ARM的栈指令(转)
- 转 /etc/ld.so.conf.d/目录下文件的作用
- ES6 对象的扩展 Object.assign()
- java第一课总结
- Graphviz 环境变量设置
- 锋利的Jquery之插件Cookie记住密码