mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 21:25:24 +00:00
[adapters] 增加小游戏适配部分源码
This commit is contained in:
205
adapters/platforms/taobao/wrapper/builtin/Audio.js
Normal file
205
adapters/platforms/taobao/wrapper/builtin/Audio.js
Normal file
@@ -0,0 +1,205 @@
|
||||
import HTMLAudioElement from './HTMLAudioElement'
|
||||
|
||||
const HAVE_NOTHING = 0
|
||||
const HAVE_METADATA = 1
|
||||
const HAVE_CURRENT_DATA = 2
|
||||
const HAVE_FUTURE_DATA = 3
|
||||
const HAVE_ENOUGH_DATA = 4
|
||||
|
||||
let SN_SEED = 1
|
||||
|
||||
const _innerAudioContextMap = {}
|
||||
|
||||
export default class Audio extends HTMLAudioElement {
|
||||
|
||||
constructor(url) {
|
||||
super()
|
||||
|
||||
this._$sn = SN_SEED++;
|
||||
|
||||
this.HAVE_NOTHING = HAVE_NOTHING
|
||||
this.HAVE_METADATA = HAVE_METADATA
|
||||
this.HAVE_CURRENT_DATA = HAVE_CURRENT_DATA
|
||||
this.HAVE_FUTURE_DATA = HAVE_FUTURE_DATA
|
||||
this.HAVE_ENOUGH_DATA = HAVE_ENOUGH_DATA
|
||||
|
||||
this.readyState = HAVE_NOTHING
|
||||
|
||||
const innerAudioContext = my.createInnerAudioContext()
|
||||
|
||||
_innerAudioContextMap[this._$sn] = innerAudioContext
|
||||
|
||||
this._canplayEvents = [
|
||||
'load',
|
||||
'loadend',
|
||||
'canplay',
|
||||
'canplaythrough',
|
||||
'loadedmetadata'
|
||||
]
|
||||
|
||||
innerAudioContext.onCanplay(() => {
|
||||
this._loaded = true
|
||||
this.readyState = this.HAVE_CURRENT_DATA
|
||||
this._canplayEvents.forEach((type) => {
|
||||
this.dispatchEvent({ type: type })
|
||||
})
|
||||
})
|
||||
innerAudioContext.onPlay(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'play' })
|
||||
})
|
||||
innerAudioContext.onPause(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'pause' })
|
||||
})
|
||||
innerAudioContext.onEnded(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
if (_innerAudioContextMap[this._$sn].loop === false) {
|
||||
this.dispatchEvent({ type: 'ended' })
|
||||
}
|
||||
this.readyState = HAVE_ENOUGH_DATA
|
||||
})
|
||||
innerAudioContext.onError(() => {
|
||||
this._paused = _innerAudioContextMap[this._$sn].paused
|
||||
this.dispatchEvent({ type: 'error' })
|
||||
})
|
||||
|
||||
if (url) {
|
||||
this.src = url
|
||||
} else {
|
||||
this._src = ''
|
||||
}
|
||||
|
||||
this._loop = innerAudioContext.loop
|
||||
this._autoplay = innerAudioContext.autoplay
|
||||
this._paused = innerAudioContext.paused
|
||||
this._volume = innerAudioContext.volume
|
||||
this._muted = false;
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options = {}) {
|
||||
super.addEventListener(type, listener, options)
|
||||
|
||||
type = String(type).toLowerCase()
|
||||
|
||||
if (this._loaded && this._canplayEvents.indexOf(type) !== -1) {
|
||||
this.dispatchEvent({ type: type })
|
||||
}
|
||||
}
|
||||
|
||||
load() {
|
||||
// console.warn('HTMLAudioElement.load() is not implemented.')
|
||||
// weixin doesn't need call load() manually
|
||||
}
|
||||
|
||||
play() {
|
||||
_innerAudioContextMap[this._$sn].play()
|
||||
}
|
||||
|
||||
resume() {
|
||||
_innerAudioContextMap[this._$sn].resume()
|
||||
}
|
||||
|
||||
pause() {
|
||||
_innerAudioContextMap[this._$sn].pause()
|
||||
}
|
||||
|
||||
stop() {
|
||||
_innerAudioContextMap[this._$sn].stop()
|
||||
}
|
||||
|
||||
destroy() {
|
||||
_innerAudioContextMap[this._$sn].destroy()
|
||||
}
|
||||
|
||||
canPlayType(mediaType = '') {
|
||||
if (typeof mediaType !== 'string') {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (mediaType.indexOf('audio/mpeg') > -1 || mediaType.indexOf('audio/mp4')) {
|
||||
return 'probably'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
get currentTime() {
|
||||
return _innerAudioContextMap[this._$sn].currentTime
|
||||
}
|
||||
|
||||
set currentTime(value) {
|
||||
_innerAudioContextMap[this._$sn].seek(value)
|
||||
}
|
||||
|
||||
get duration () {
|
||||
return _innerAudioContextMap[this._$sn].duration
|
||||
}
|
||||
|
||||
get src() {
|
||||
return this._src
|
||||
}
|
||||
|
||||
set src(value) {
|
||||
this._src = value
|
||||
this._loaded = false
|
||||
this.readyState = this.HAVE_NOTHING
|
||||
|
||||
const innerAudioContext = _innerAudioContextMap[this._$sn]
|
||||
|
||||
innerAudioContext.src = value
|
||||
}
|
||||
|
||||
get loop() {
|
||||
return this._loop
|
||||
}
|
||||
|
||||
set loop(value) {
|
||||
this._loop = value
|
||||
_innerAudioContextMap[this._$sn].loop = value
|
||||
}
|
||||
|
||||
get autoplay() {
|
||||
return this.autoplay
|
||||
}
|
||||
|
||||
set autoplay(value) {
|
||||
this._autoplay = value
|
||||
_innerAudioContextMap[this._$sn].autoplay = value
|
||||
}
|
||||
|
||||
get paused() {
|
||||
return this._paused;
|
||||
}
|
||||
|
||||
get volume() {
|
||||
return this._volume;
|
||||
}
|
||||
|
||||
set volume(value) {
|
||||
this._volume = value;
|
||||
if (!this._muted) {
|
||||
_innerAudioContextMap[this._$sn].volume = value;
|
||||
}
|
||||
}
|
||||
|
||||
get muted() {
|
||||
return this._muted;
|
||||
}
|
||||
|
||||
set muted(value) {
|
||||
this._muted = value;
|
||||
if (value) {
|
||||
_innerAudioContextMap[this._$sn].volume = 0;
|
||||
} else {
|
||||
_innerAudioContextMap[this._$sn].volume = this._volume;
|
||||
}
|
||||
}
|
||||
|
||||
cloneNode() {
|
||||
const newAudio = new Audio()
|
||||
newAudio.loop = this.loop
|
||||
newAudio.autoplay = this.autoplay
|
||||
newAudio.src = this.src
|
||||
return newAudio
|
||||
}
|
||||
}
|
69
adapters/platforms/taobao/wrapper/builtin/Canvas.js
Normal file
69
adapters/platforms/taobao/wrapper/builtin/Canvas.js
Normal file
@@ -0,0 +1,69 @@
|
||||
import { innerWidth, innerHeight } from './WindowProperties'
|
||||
|
||||
function Canvas () {}
|
||||
|
||||
let CanvasProxy = new Proxy(Canvas, {
|
||||
construct () {
|
||||
|
||||
const canvas = my.createOffscreenCanvas()
|
||||
|
||||
canvas.type = 'canvas'
|
||||
|
||||
// canvas.__proto__.__proto__.__proto__ = new HTMLCanvasElement()
|
||||
|
||||
const _getContext = canvas.getContext
|
||||
|
||||
canvas.getBoundingClientRect = () => {
|
||||
const ret = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
canvas.style = {
|
||||
top: '0px',
|
||||
left: '0px',
|
||||
width: innerWidth + 'px',
|
||||
height: innerHeight + 'px',
|
||||
}
|
||||
|
||||
canvas.addEventListener = function (type, listener, options = {}) {
|
||||
// console.log('canvas.addEventListener', type);
|
||||
document.addEventListener(type, listener, options);
|
||||
}
|
||||
|
||||
canvas.removeEventListener = function (type, listener) {
|
||||
// console.log('canvas.removeEventListener', type);
|
||||
document.removeEventListener(type, listener);
|
||||
}
|
||||
|
||||
canvas.dispatchEvent = function (event = {}) {
|
||||
console.log('canvas.dispatchEvent' , event.type, event);
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
Object.defineProperty(canvas, 'clientWidth', {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return innerWidth
|
||||
}
|
||||
})
|
||||
|
||||
Object.defineProperty(canvas, 'clientHeight', {
|
||||
enumerable: true,
|
||||
get: function get() {
|
||||
return innerHeight
|
||||
}
|
||||
})
|
||||
|
||||
return canvas
|
||||
},
|
||||
});
|
||||
|
||||
// NOTE: this is a hack operation
|
||||
// let canvas = new window.Canvas()
|
||||
// console.error(canvas instanceof window.Canvas) => false
|
||||
export default CanvasProxy;
|
10
adapters/platforms/taobao/wrapper/builtin/Element.js
Normal file
10
adapters/platforms/taobao/wrapper/builtin/Element.js
Normal file
@@ -0,0 +1,10 @@
|
||||
import Node from './Node'
|
||||
|
||||
export default class Element extends Node {
|
||||
className = ''
|
||||
children = []
|
||||
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
}
|
14
adapters/platforms/taobao/wrapper/builtin/Event.js
Normal file
14
adapters/platforms/taobao/wrapper/builtin/Event.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import {noop} from './util'
|
||||
|
||||
export default class Event {
|
||||
cancelBubble = false
|
||||
cancelable = false
|
||||
target = null
|
||||
timestampe = Date.now()
|
||||
preventDefault = noop
|
||||
stopPropagation = noop
|
||||
|
||||
constructor(type) {
|
||||
this.type = type
|
||||
}
|
||||
}
|
57
adapters/platforms/taobao/wrapper/builtin/EventTarget.js
Normal file
57
adapters/platforms/taobao/wrapper/builtin/EventTarget.js
Normal file
@@ -0,0 +1,57 @@
|
||||
const _events = new WeakMap()
|
||||
|
||||
export default class EventTarget {
|
||||
constructor() {
|
||||
_events.set(this, {})
|
||||
}
|
||||
|
||||
addEventListener(type, listener, options = {}) {
|
||||
let events = _events.get(this)
|
||||
|
||||
if (!events) {
|
||||
events = {}
|
||||
_events.set(this, events)
|
||||
}
|
||||
if (!events[type]) {
|
||||
events[type] = []
|
||||
}
|
||||
events[type].push(listener)
|
||||
|
||||
if (options.capture) {
|
||||
// console.warn('EventTarget.addEventListener: options.capture is not implemented.')
|
||||
}
|
||||
if (options.once) {
|
||||
// console.warn('EventTarget.addEventListener: options.once is not implemented.')
|
||||
}
|
||||
if (options.passive) {
|
||||
// console.warn('EventTarget.addEventListener: options.passive is not implemented.')
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener(type, listener) {
|
||||
const events = _events.get(this)
|
||||
|
||||
if (events) {
|
||||
const listeners = events[type]
|
||||
|
||||
if (listeners && listeners.length > 0) {
|
||||
for (let i = listeners.length; i--; i > 0) {
|
||||
if (listeners[i] === listener) {
|
||||
listeners.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dispatchEvent(event = {}) {
|
||||
const listeners = _events.get(this)[event.type]
|
||||
|
||||
if (listeners) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,7 @@
|
||||
import HTMLElement from './HTMLElement'
|
||||
|
||||
export default class HTMLAudioElement extends HTMLElement {
|
||||
constructor() {
|
||||
super('audio')
|
||||
}
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
let HTMLCanvasElement = my.createOffscreenCanvas().constructor;
|
||||
|
||||
export default HTMLCanvasElement;
|
54
adapters/platforms/taobao/wrapper/builtin/HTMLElement.js
Normal file
54
adapters/platforms/taobao/wrapper/builtin/HTMLElement.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import Element from './Element'
|
||||
import { noop } from './util/index.js'
|
||||
import { innerWidth, innerHeight } from './WindowProperties'
|
||||
|
||||
export default class HTMLElement extends Element {
|
||||
className = ''
|
||||
childern = []
|
||||
style = {
|
||||
width: `${innerWidth}px`,
|
||||
height: `${innerHeight}px`
|
||||
}
|
||||
|
||||
insertBefore = noop
|
||||
|
||||
innerHTML = ''
|
||||
|
||||
constructor(tagName = '') {
|
||||
super()
|
||||
this.tagName = tagName.toUpperCase()
|
||||
}
|
||||
|
||||
setAttribute(name, value) {
|
||||
this[name] = value
|
||||
}
|
||||
|
||||
getAttribute(name) {
|
||||
return this[name]
|
||||
}
|
||||
|
||||
get clientWidth() {
|
||||
const ret = parseInt(this.style.fontSize, 10) * this.innerHTML.length
|
||||
|
||||
return Number.isNaN(ret) ? 0 : ret
|
||||
}
|
||||
|
||||
get clientHeight() {
|
||||
const ret = parseInt(this.style.fontSize, 10)
|
||||
|
||||
return Number.isNaN(ret) ? 0 : ret
|
||||
}
|
||||
|
||||
getBoundingClientRect() {
|
||||
return {
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: innerWidth,
|
||||
height: innerHeight
|
||||
}
|
||||
}
|
||||
|
||||
focus() {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
var screencanvas = $global.screencanvas;
|
||||
let HTMLImageElement = screencanvas.createImage().constructor;
|
||||
|
||||
export default HTMLImageElement;
|
40
adapters/platforms/taobao/wrapper/builtin/Image.js
Normal file
40
adapters/platforms/taobao/wrapper/builtin/Image.js
Normal file
@@ -0,0 +1,40 @@
|
||||
// var screencanvas = $global.screencanvas;
|
||||
|
||||
function Image () {
|
||||
// empty constructor
|
||||
}
|
||||
|
||||
// NOTE: Proxy not supported on iOS 8 and 9.
|
||||
// let ImageProxy = new Proxy(Image, {
|
||||
// construct (target, args) {
|
||||
// let img = screencanvas.createImage();
|
||||
// if (!img.addEventListener) {
|
||||
// img.addEventListener = function (eventName, eventCB) {
|
||||
// if (eventName === 'load') {
|
||||
// img.onload = eventCB;
|
||||
// } else if (eventName === 'error') {
|
||||
// // img.onerror = eventCB;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
// if (!img.removeEventListener) {
|
||||
// img.removeEventListener = function (eventName) {
|
||||
// if (eventName === 'load') {
|
||||
// img.onload = null;
|
||||
// } else if (eventName === 'error') {
|
||||
// // img.onerror = null;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// return img;
|
||||
// },
|
||||
// });
|
||||
|
||||
// NOTE: this is a hack operation
|
||||
// let img = new window.Image()
|
||||
// console.error(img instanceof window.Image) => false
|
||||
// export default ImageProxy;
|
||||
|
||||
|
||||
export default Image;
|
5
adapters/platforms/taobao/wrapper/builtin/ImageBitmap.js
Normal file
5
adapters/platforms/taobao/wrapper/builtin/ImageBitmap.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export default class ImageBitmap {
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
}
|
34
adapters/platforms/taobao/wrapper/builtin/Node.js
Normal file
34
adapters/platforms/taobao/wrapper/builtin/Node.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import EventTarget from './EventTarget.js'
|
||||
|
||||
export default class Node extends EventTarget {
|
||||
constructor() {
|
||||
super()
|
||||
}
|
||||
|
||||
childNodes = []
|
||||
|
||||
appendChild(node) {
|
||||
this.childNodes.push(node)
|
||||
// if (node instanceof Node) {
|
||||
// this.childNodes.push(node)
|
||||
// } else {
|
||||
// throw new TypeError('Failed to executed \'appendChild\' on \'Node\': parameter 1 is not of type \'Node\'.')
|
||||
// }
|
||||
}
|
||||
|
||||
cloneNode() {
|
||||
const copyNode = Object.create(this)
|
||||
|
||||
Object.assign(copyNode, this)
|
||||
return copyNode
|
||||
}
|
||||
|
||||
removeChild(node) {
|
||||
const index = this.childNodes.findIndex((child) => child === node)
|
||||
|
||||
if (index > -1) {
|
||||
return this.childNodes.splice(index, 1)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
export default class WebGLRenderingContext {
|
||||
constructor() {
|
||||
// TODO
|
||||
}
|
||||
}
|
139
adapters/platforms/taobao/wrapper/builtin/WebSocket.js
Normal file
139
adapters/platforms/taobao/wrapper/builtin/WebSocket.js
Normal file
@@ -0,0 +1,139 @@
|
||||
const _utils = require('../../../../common/utils');
|
||||
|
||||
const MAX_AMOUNT_WEBSOCKET = 1 // The maximum number of WEBSOCKET
|
||||
let CURR_AMOUNT_WEBSOCKET = 0 // The current number of WEBSOCKET
|
||||
|
||||
export default class WebSocket {
|
||||
static CONNECTING = 0 // The connection is not yet open.
|
||||
static OPEN = 1 // The connection is open and ready to communicate.
|
||||
static CLOSING = 2 // The connection is in the process of closing.
|
||||
static CLOSED = 3 // The connection is closed or couldn't be opened.
|
||||
|
||||
binaryType = '' // TODO 更新 binaryType
|
||||
bufferedAmount = 0 // TODO 更新 bufferedAmount
|
||||
extensions = ''
|
||||
|
||||
onopen = null
|
||||
onmessage = null
|
||||
onerror = null
|
||||
onclose = null
|
||||
|
||||
_onMessage = null
|
||||
_onOpen = null
|
||||
_onError = null
|
||||
_onClose = null
|
||||
_isReduced = false
|
||||
|
||||
protocol = '' // TODO 小程序内目前获取不到,实际上需要根据服务器选择的 sub-protocol 返回
|
||||
readyState = 3
|
||||
|
||||
constructor(url, protocols = []) {
|
||||
if(this._isMaxCount()){
|
||||
console.warn(`Failed to construct 'WebSocket': Only ${CURR_AMOUNT_WEBSOCKET} WebSocket can be created at the same time on TaoBao.`);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (typeof url !== 'string' || !(/(^ws:\/\/)|(^wss:\/\/)/).test(url)) {
|
||||
throw new TypeError(`Failed to construct 'WebSocket': The URL '${url}' is invalid`)
|
||||
}
|
||||
|
||||
this.url = url
|
||||
this.readyState = WebSocket.CONNECTING
|
||||
this._increaseCount();
|
||||
|
||||
my.connectSocket({
|
||||
url,
|
||||
fail: function fail(res) {
|
||||
this._triggerEvent('error', res)
|
||||
}
|
||||
})
|
||||
|
||||
this._onOpen = (res) => {
|
||||
this.readyState = WebSocket.OPEN
|
||||
this._triggerEvent('open')
|
||||
}
|
||||
my.onSocketOpen(this._onOpen)
|
||||
|
||||
this._onMessage = (res) => {
|
||||
if (res && res.data && res.isBuffer) {
|
||||
res.data = _utils.base64ToArrayBuffer(res.data)
|
||||
}
|
||||
this._triggerEvent('message', res)
|
||||
}
|
||||
my.onSocketMessage(this._onMessage)
|
||||
|
||||
this._onError = (res) => {
|
||||
this._triggerEvent('error', res)
|
||||
this._decreaseCount();
|
||||
}
|
||||
my.onSocketError(this._onError)
|
||||
|
||||
this._onClose = (res) => {
|
||||
this.readyState = WebSocket.CLOSED
|
||||
this._triggerEvent('close')
|
||||
this._removeAllSocketListenr()
|
||||
this._decreaseCount();
|
||||
}
|
||||
my.onSocketClose(this._onClose)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
close() {
|
||||
this.readyState = WebSocket.CLOSING
|
||||
my.closeSocket()
|
||||
}
|
||||
|
||||
send(data) {
|
||||
if (typeof data !== 'string' && !(data instanceof ArrayBuffer) && !ArrayBuffer.isView(data)) {
|
||||
throw new TypeError(`Failed to send message: The data ${data} is invalid`)
|
||||
}else{
|
||||
var isBuffer = false;
|
||||
if (data instanceof ArrayBuffer) {
|
||||
data = _utils.arrayBufferToBase64(data)
|
||||
isBuffer = true
|
||||
}
|
||||
|
||||
my.sendSocketMessage({
|
||||
data,
|
||||
isBuffer,
|
||||
fail: function (res) {
|
||||
this._triggerEvent('error', res)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_triggerEvent(type, ...args) {
|
||||
if (typeof this[`on${type}`] === 'function') {
|
||||
this[`on${type}`].apply(this, args)
|
||||
}
|
||||
}
|
||||
|
||||
_removeAllSocketListenr(){
|
||||
my.offSocketOpen(this._onOpen)
|
||||
my.offSocketMessage(this._onMessage)
|
||||
my.offSocketError(this._onError)
|
||||
my.offSocketClose(this._onClose)
|
||||
|
||||
this._onOpen = null
|
||||
this._onMessage = null
|
||||
this._onError = null
|
||||
this._onClose = null
|
||||
}
|
||||
|
||||
_increaseCount(){
|
||||
CURR_AMOUNT_WEBSOCKET += 1
|
||||
}
|
||||
|
||||
_decreaseCount(){
|
||||
if(!this._isReduced){
|
||||
CURR_AMOUNT_WEBSOCKET -= 1
|
||||
this._isReduced = true
|
||||
}
|
||||
}
|
||||
|
||||
_isMaxCount(){
|
||||
return CURR_AMOUNT_WEBSOCKET >= MAX_AMOUNT_WEBSOCKET
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
const { pixelRatio, windowWidth, windowHeight } = my.getSystemInfoSync()
|
||||
const devicePixelRatio = pixelRatio;
|
||||
|
||||
let width, height;
|
||||
if ($global.screencanvas.getBoundingClientRect) {
|
||||
let rect = $global.screencanvas.getBoundingClientRect();
|
||||
width = rect.width;
|
||||
height = rect.height;
|
||||
} else {
|
||||
width = windowWidth;
|
||||
height = windowHeight;
|
||||
}
|
||||
export const innerWidth = width;
|
||||
export const innerHeight = height;
|
||||
export { devicePixelRatio }
|
||||
export const screen = {
|
||||
width,
|
||||
height,
|
||||
availWidth: innerWidth,
|
||||
availHeight: innerHeight,
|
||||
availLeft: 0,
|
||||
availTop: 0,
|
||||
}
|
||||
|
||||
export const performance = {
|
||||
now: Date.now
|
||||
};
|
||||
|
||||
export const ontouchstart = null;
|
||||
export const ontouchmove = null;
|
||||
export const ontouchend = null;
|
172
adapters/platforms/taobao/wrapper/builtin/XMLHttpRequest.js
Normal file
172
adapters/platforms/taobao/wrapper/builtin/XMLHttpRequest.js
Normal file
@@ -0,0 +1,172 @@
|
||||
import EventTarget from './EventTarget.js'
|
||||
|
||||
const _url = new WeakMap()
|
||||
const _method = new WeakMap()
|
||||
const _requestHeader = new WeakMap()
|
||||
const _responseHeader = new WeakMap()
|
||||
const _requestTask = new WeakMap()
|
||||
|
||||
function _triggerEvent(type, ...args) {
|
||||
if (typeof this[`on${type}`] === 'function') {
|
||||
this[`on${type}`].apply(this, args)
|
||||
}
|
||||
}
|
||||
|
||||
function _changeReadyState(readyState) {
|
||||
this.readyState = readyState
|
||||
_triggerEvent.call(this, 'readystatechange')
|
||||
}
|
||||
|
||||
export default class XMLHttpRequest extends EventTarget {
|
||||
// TODO 没法模拟 HEADERS_RECEIVED 和 LOADING 两个状态
|
||||
static UNSEND = 0
|
||||
static OPENED = 1
|
||||
static HEADERS_RECEIVED = 2
|
||||
static LOADING = 3
|
||||
static DONE = 4
|
||||
|
||||
timeout = 0;
|
||||
/*
|
||||
* TODO 这一批事件应该是在 XMLHttpRequestEventTarget.prototype 上面的
|
||||
*/
|
||||
onabort = null
|
||||
onerror = null
|
||||
onload = null
|
||||
onloadstart = null
|
||||
onprogress = null
|
||||
ontimeout = null
|
||||
onloadend = null
|
||||
|
||||
onreadystatechange = null
|
||||
readyState = 0
|
||||
response = null
|
||||
responseText = null
|
||||
responseType = ''
|
||||
responseXML = null
|
||||
status = 0
|
||||
statusText = ''
|
||||
upload = {}
|
||||
withCredentials = false
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
_requestHeader.set(this, {
|
||||
'content-type': 'application/json'
|
||||
})
|
||||
_responseHeader.set(this, {})
|
||||
}
|
||||
|
||||
abort() {
|
||||
const myRequestTask = _requestTask.get(this)
|
||||
|
||||
if (myRequestTask) {
|
||||
myRequestTask.abort()
|
||||
}
|
||||
}
|
||||
|
||||
getAllResponseHeaders() {
|
||||
const responseHeader = _responseHeader.get(this)
|
||||
|
||||
return Object.keys(responseHeader).map((header) => {
|
||||
return `${header}: ${responseHeader[header]}`
|
||||
}).join('\n')
|
||||
}
|
||||
|
||||
getResponseHeader(header) {
|
||||
return _responseHeader.get(this)[header]
|
||||
}
|
||||
|
||||
open(method, url/* async, user, password 这几个参数在小程序内不支持*/) {
|
||||
_method.set(this, method)
|
||||
_url.set(this, url)
|
||||
_changeReadyState.call(this, XMLHttpRequest.OPENED)
|
||||
}
|
||||
|
||||
overrideMimeType() {
|
||||
}
|
||||
|
||||
send(data = '') {
|
||||
if (this.readyState !== XMLHttpRequest.OPENED) {
|
||||
throw new Error("Failed to execute 'send' on 'XMLHttpRequest': The object's state must be OPENED.")
|
||||
} else {
|
||||
let myRequestTask = my.request({
|
||||
data,
|
||||
url: _url.get(this),
|
||||
method: _method.get(this),
|
||||
headers: _requestHeader.get(this),
|
||||
dataType: 'other',
|
||||
responseType: this.responseType === 'arraybuffer' ? 'arraybuffer' : 'text',
|
||||
timeout: this.timeout || undefined,
|
||||
success: ({ data, status, headers }) => {
|
||||
this.status = status
|
||||
_responseHeader.set(this, headers)
|
||||
_triggerEvent.call(this, 'loadstart')
|
||||
_changeReadyState.call(this, XMLHttpRequest.HEADERS_RECEIVED)
|
||||
_changeReadyState.call(this, XMLHttpRequest.LOADING)
|
||||
|
||||
switch (this.responseType) {
|
||||
case 'json':
|
||||
this.responseText = data;
|
||||
try {
|
||||
this.response = JSON.parse(data);
|
||||
}
|
||||
catch (e) {
|
||||
this.response = null;
|
||||
}
|
||||
break;
|
||||
case '':
|
||||
case 'text':
|
||||
this.responseText = this.response = data;
|
||||
break;
|
||||
case 'arraybuffer':
|
||||
this.response = data;
|
||||
this.responseText = '';
|
||||
var bytes = new Uint8Array(data);
|
||||
var len = bytes.byteLength;
|
||||
|
||||
for (var i = 0; i < len; i++) {
|
||||
this.responseText += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.response = null;
|
||||
}
|
||||
_changeReadyState.call(this, XMLHttpRequest.DONE)
|
||||
_triggerEvent.call(this, 'load')
|
||||
_triggerEvent.call(this, 'loadend')
|
||||
},
|
||||
fail: ({ error, errorMessage }) => {
|
||||
// TODO 规范错误
|
||||
if (9 === error || errorMessage.indexOf('abort') !== -1) {
|
||||
_triggerEvent.call(this, 'abort')
|
||||
} else if (13 === error || errorMessage.indexOf('超时') !== -1) {
|
||||
_triggerEvent.call(this, 'timeout')
|
||||
} else {
|
||||
_triggerEvent.call(this, 'error', errorMessage)
|
||||
}
|
||||
_triggerEvent.call(this, 'loadend')
|
||||
}
|
||||
})
|
||||
|
||||
_requestTask.set(this, myRequestTask);
|
||||
}
|
||||
}
|
||||
|
||||
setRequestHeader(header, value) {
|
||||
const myHeader = _requestHeader.get(this)
|
||||
|
||||
myHeader[header] = value
|
||||
_requestHeader.set(this, myHeader)
|
||||
}
|
||||
|
||||
addEventListener(type, listener) {
|
||||
if (typeof listener === 'function') {
|
||||
let _this = this
|
||||
let event = { target: _this }
|
||||
this['on' + type] = function (event) {
|
||||
listener.call(_this, event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
let screencanvas = $global.screencanvas;
|
||||
let cancelAnimationFrame = screencanvas.cancelAnimationFrame.bind(screencanvas);
|
||||
|
||||
export default cancelAnimationFrame;
|
124
adapters/platforms/taobao/wrapper/builtin/document.js
Normal file
124
adapters/platforms/taobao/wrapper/builtin/document.js
Normal file
@@ -0,0 +1,124 @@
|
||||
import * as _window from './window'
|
||||
import HTMLElement from './HTMLElement'
|
||||
import Image from './Image'
|
||||
import Canvas from './Canvas'
|
||||
import Audio from './Audio'
|
||||
|
||||
const events = {}
|
||||
|
||||
var document = {
|
||||
readyState: 'complete',
|
||||
visibilityState: 'visible',
|
||||
documentElement: _window,
|
||||
hidden: false,
|
||||
style: {},
|
||||
location: _window.location,
|
||||
ontouchstart: null,
|
||||
ontouchmove: null,
|
||||
ontouchend: null,
|
||||
|
||||
head: new HTMLElement('head'),
|
||||
body: new HTMLElement('body'),
|
||||
|
||||
createElement(tagName) {
|
||||
tagName = tagName.toLowerCase();
|
||||
if (tagName === 'canvas') {
|
||||
return new Canvas()
|
||||
} else if (tagName === 'audio') {
|
||||
return new Audio()
|
||||
} else if (tagName === 'img') {
|
||||
return new Image()
|
||||
}
|
||||
|
||||
return new HTMLElement(tagName)
|
||||
},
|
||||
|
||||
createElementNS(nameSpace, tagName) {
|
||||
return this.createElement(tagName);
|
||||
},
|
||||
|
||||
getElementById(id) {
|
||||
if (id === _window.canvas.id) {
|
||||
return _window.canvas
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
getElementsByTagName(tagName) {
|
||||
if (tagName === 'head') {
|
||||
return [document.head]
|
||||
} else if (tagName === 'body') {
|
||||
return [document.body]
|
||||
} else if (tagName === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
getElementsByName(tagName) {
|
||||
if (tagName === 'head') {
|
||||
return [document.head]
|
||||
} else if (tagName === 'body') {
|
||||
return [document.body]
|
||||
} else if (tagName === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
querySelector(query) {
|
||||
if (query === 'head') {
|
||||
return document.head
|
||||
} else if (query === 'body') {
|
||||
return document.body
|
||||
} else if (query === 'canvas') {
|
||||
return _window.canvas
|
||||
} else if (query === `#${_window.canvas.id}`) {
|
||||
return _window.canvas
|
||||
}
|
||||
return null
|
||||
},
|
||||
|
||||
querySelectorAll(query) {
|
||||
if (query === 'head') {
|
||||
return [document.head]
|
||||
} else if (query === 'body') {
|
||||
return [document.body]
|
||||
} else if (query === 'canvas') {
|
||||
return [_window.canvas]
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
||||
addEventListener(type, listener) {
|
||||
if (!events[type]) {
|
||||
events[type] = []
|
||||
}
|
||||
events[type].push(listener)
|
||||
},
|
||||
|
||||
removeEventListener(type, listener) {
|
||||
const listeners = events[type]
|
||||
|
||||
if (listeners && listeners.length > 0) {
|
||||
for (let i = listeners.length; i--; i > 0) {
|
||||
if (listeners[i] === listener) {
|
||||
listeners.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dispatchEvent(event) {
|
||||
const listeners = events[event.type]
|
||||
|
||||
if (listeners) {
|
||||
for (let i = 0; i < listeners.length; i++) {
|
||||
listeners[i](event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default document
|
61
adapters/platforms/taobao/wrapper/builtin/index.js
Normal file
61
adapters/platforms/taobao/wrapper/builtin/index.js
Normal file
@@ -0,0 +1,61 @@
|
||||
import * as _window from './window'
|
||||
import * as _document from './document'
|
||||
|
||||
var global = $global;
|
||||
|
||||
function inject () {
|
||||
// 暴露全局的 canvas
|
||||
_window.canvas = $global.screencanvas;
|
||||
_window.document = _document;
|
||||
|
||||
_window.addEventListener = (type, listener) => {
|
||||
_window.document.addEventListener(type, listener)
|
||||
}
|
||||
_window.removeEventListener = (type, listener) => {
|
||||
_window.document.removeEventListener(type, listener)
|
||||
}
|
||||
_window.dispatchEvent = _window.document.dispatchEvent;
|
||||
|
||||
const { platform } = my.getSystemInfoSync()
|
||||
|
||||
// 开发者工具无法重定义 window
|
||||
if (typeof __devtoolssubcontext === 'undefined' && platform === 'devtools') {
|
||||
for (const key in _window) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(global, key)
|
||||
|
||||
if (!descriptor || descriptor.configurable === true) {
|
||||
Object.defineProperty(window, key, {
|
||||
value: _window[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for (const key in _window.document) {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(global.document, key)
|
||||
|
||||
if (!descriptor || descriptor.configurable === true) {
|
||||
Object.defineProperty(global.document, key, {
|
||||
value: _window.document[key]
|
||||
})
|
||||
}
|
||||
}
|
||||
window.parent = window
|
||||
} else {
|
||||
for (const key in _window) {
|
||||
global[key] = _window[key]
|
||||
}
|
||||
// global.window = _window
|
||||
// window = global
|
||||
// window.top = window.parent = window
|
||||
}
|
||||
|
||||
global.setTimeout = setTimeout;
|
||||
global.clearTimeout = clearTimeout;
|
||||
global.setInterval = setInterval;
|
||||
global.clearInterval = clearInterval;
|
||||
}
|
||||
|
||||
if (!global.__isAdapterInjected) {
|
||||
global.__isAdapterInjected = true
|
||||
inject()
|
||||
}
|
37
adapters/platforms/taobao/wrapper/builtin/localStorage.js
Normal file
37
adapters/platforms/taobao/wrapper/builtin/localStorage.js
Normal file
@@ -0,0 +1,37 @@
|
||||
const localStorage = {
|
||||
get length() {
|
||||
const { keys } = my.getStorageInfoSync()
|
||||
|
||||
return keys.length
|
||||
},
|
||||
|
||||
key(n) {
|
||||
const { keys } = my.getStorageInfoSync()
|
||||
|
||||
return keys[n]
|
||||
},
|
||||
|
||||
getItem(key) {
|
||||
let ret = my.getStorageSync({
|
||||
key,
|
||||
});
|
||||
return ret && ret.data;
|
||||
},
|
||||
|
||||
setItem(key, data) {
|
||||
return my.setStorageSync({
|
||||
key,
|
||||
data,
|
||||
});
|
||||
},
|
||||
|
||||
removeItem(key) {
|
||||
my.removeStorageSync(key)
|
||||
},
|
||||
|
||||
clear() {
|
||||
my.clearStorageSync()
|
||||
}
|
||||
}
|
||||
|
||||
export default localStorage
|
7
adapters/platforms/taobao/wrapper/builtin/location.js
Normal file
7
adapters/platforms/taobao/wrapper/builtin/location.js
Normal file
@@ -0,0 +1,7 @@
|
||||
var location = {
|
||||
href: 'game.js',
|
||||
reload() {
|
||||
}
|
||||
}
|
||||
|
||||
export default location
|
38
adapters/platforms/taobao/wrapper/builtin/navigator.js
Normal file
38
adapters/platforms/taobao/wrapper/builtin/navigator.js
Normal file
@@ -0,0 +1,38 @@
|
||||
import { noop } from './util/index.js'
|
||||
|
||||
// TODO 需要 my.getSystemInfo 获取更详细信息
|
||||
const systemInfo = my.getSystemInfoSync()
|
||||
console.log(systemInfo)
|
||||
|
||||
const system = systemInfo.system;
|
||||
const platform = systemInfo.platform;
|
||||
const language = systemInfo.language;
|
||||
const version = systemInfo.version;
|
||||
|
||||
const android = system ? system.toLowerCase().indexOf('android') !== -1 : false;
|
||||
|
||||
const uaDesc = android ? `Android; CPU ${system}` : `iPhone; CPU iPhone OS ${system} like Mac OS X`;
|
||||
const ua = `Mozilla/5.0 (${uaDesc}) AppleWebKit/603.1.30 (KHTML, like Gecko) Mobile/14E8301 MicroMessenger/${version} MiniGame NetType/WIFI Language/${language}`;
|
||||
|
||||
const navigator = {
|
||||
platform,
|
||||
language: language,
|
||||
appVersion: `5.0 (${uaDesc}) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1`,
|
||||
userAgent: ua,
|
||||
onLine: true, // TODO 用 my.getNetworkStateChange 和 my.onNetworkStateChange 来返回真实的状态
|
||||
|
||||
// TODO 用 my.getLocation 来封装 geolocation
|
||||
geolocation: {
|
||||
getCurrentPosition: noop,
|
||||
watchPosition: noop,
|
||||
clearWatch: noop
|
||||
}
|
||||
}
|
||||
|
||||
if (my.onNetworkStatusChange) {
|
||||
my.onNetworkStatusChange(function(event){
|
||||
navigator.onLine = event.isConnected;
|
||||
});
|
||||
}
|
||||
|
||||
export default navigator
|
@@ -0,0 +1,4 @@
|
||||
let screencanvas = $global.screencanvas;
|
||||
let requestAnimationFrame = screencanvas.requestAnimationFrame.bind(screencanvas);
|
||||
|
||||
export default requestAnimationFrame;
|
1
adapters/platforms/taobao/wrapper/builtin/util/index.js
Normal file
1
adapters/platforms/taobao/wrapper/builtin/util/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export function noop() {}
|
15
adapters/platforms/taobao/wrapper/builtin/window.js
Normal file
15
adapters/platforms/taobao/wrapper/builtin/window.js
Normal file
@@ -0,0 +1,15 @@
|
||||
export navigator from './navigator'
|
||||
export XMLHttpRequest from './XMLHttpRequest'
|
||||
export WebSocket from './WebSocket'
|
||||
export Image from './Image'
|
||||
export ImageBitmap from './ImageBitmap'
|
||||
export HTMLElement from './HTMLElement'
|
||||
export HTMLImageElement from './HTMLImageElement'
|
||||
export HTMLCanvasElement from './HTMLCanvasElement'
|
||||
export WebGLRenderingContext from './WebGLRenderingContext'
|
||||
export localStorage from './localStorage'
|
||||
export location from './location'
|
||||
export requestAnimationFrame from './requestAnimationFrame'
|
||||
export cancelAnimationFrame from './cancelAnimationFrame'
|
||||
export * from './WindowProperties'
|
||||
|
Reference in New Issue
Block a user