init cax svg
This commit is contained in:
parent
f84dee2673
commit
39ab9a340c
|
@ -0,0 +1,39 @@
|
|||
//app.js
|
||||
App({
|
||||
onLaunch: function () {
|
||||
// 展示本地存储能力
|
||||
var logs = wx.getStorageSync('logs') || []
|
||||
logs.unshift(Date.now())
|
||||
wx.setStorageSync('logs', logs)
|
||||
|
||||
// 登录
|
||||
wx.login({
|
||||
success: res => {
|
||||
// 发送 res.code 到后台换取 openId, sessionKey, unionId
|
||||
}
|
||||
})
|
||||
// 获取用户信息
|
||||
wx.getSetting({
|
||||
success: res => {
|
||||
if (res.authSetting['scope.userInfo']) {
|
||||
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
|
||||
wx.getUserInfo({
|
||||
success: res => {
|
||||
// 可以将 res 发送给后台解码出 unionId
|
||||
this.globalData.userInfo = res.userInfo
|
||||
|
||||
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
|
||||
// 所以此处加入 callback 以防止这种情况
|
||||
if (this.userInfoReadyCallback) {
|
||||
this.userInfoReadyCallback(res)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
globalData: {
|
||||
userInfo: null
|
||||
}
|
||||
})
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"pages":[
|
||||
"pages/index/index",
|
||||
"pages/logs/logs"
|
||||
],
|
||||
"window":{
|
||||
"backgroundTextStyle":"light",
|
||||
"navigationBarBackgroundColor": "#fff",
|
||||
"navigationBarTitleText": "WeChat",
|
||||
"navigationBarTextStyle":"black"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/**app.wxss**/
|
||||
.container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 200rpx 0;
|
||||
box-sizing: border-box;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
import cax from './index'
|
||||
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
|
||||
option: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
width: 0,
|
||||
height: 0,
|
||||
id: 'caxCanvas' + cax.caxCanvasId++,
|
||||
index: cax.caxCanvasId - 1
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
|
||||
getCaxCanvasId: function () {
|
||||
return this.data.id
|
||||
},
|
||||
|
||||
touchStart: function (evt) {
|
||||
this.stage.touchStartHandler(evt)
|
||||
this.stage.touchStart && this.stage.touchStart(evt)
|
||||
},
|
||||
|
||||
touchMove: function (evt) {
|
||||
this.stage.touchMoveHandler(evt)
|
||||
this.stage.touchMove && this.stage.touchMove(evt)
|
||||
},
|
||||
|
||||
touchEnd: function (evt) {
|
||||
this.stage.touchEndHandler(evt)
|
||||
this.stage.touchEnd && this.stage.touchEnd(evt)
|
||||
}
|
||||
|
||||
}
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<canvas
|
||||
class="cax-canvas"
|
||||
bindtouchstart="touchStart"
|
||||
bindtouchmove="touchMove"
|
||||
bindtouchend="touchEnd"
|
||||
canvas-id="{{ id }}"
|
||||
style="border-top: 1px solid;border-bottom: 1px solid;width: {{width}}px; height: {{height}}px;">
|
||||
<slot></slot>
|
||||
</canvas>
|
||||
|
||||
<canvas class="cax-canvas-hit" canvas-id="{{id}}Hit" style='width:1px;height:1px;display: none;'></canvas>
|
||||
<canvas class="cax-canvas-measure" canvas-id="measure{{index}}" style='width:1px;height:1px;display: none;'></canvas>
|
|
@ -0,0 +1,105 @@
|
|||
import To from './to'
|
||||
|
||||
To.extend('rubber', [['to', ['scaleX', {
|
||||
'0': 1.25,
|
||||
'1': 300
|
||||
}], ['scaleY', {
|
||||
'0': 0.75,
|
||||
'1': 300
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 0.75,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 1.25,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1.15,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 0.85,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 0.95,
|
||||
'1': 150
|
||||
}], ['scaleY', {
|
||||
'0': 1.05,
|
||||
'1': 150
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1.05,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 0.95,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1,
|
||||
'1': 250
|
||||
}], ['scaleY', {
|
||||
'0': 1,
|
||||
'1': 250
|
||||
}]]])
|
||||
|
||||
To.extend('bounceIn', [['to', ['scaleX', {
|
||||
'0': 0,
|
||||
'1': 0
|
||||
}], ['scaleY', {
|
||||
'0': 0,
|
||||
'1': 0
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1.35,
|
||||
'1': 200
|
||||
}], ['scaleY', {
|
||||
'0': 1.35,
|
||||
'1': 200
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 0.9,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 0.9,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1.1,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 1.1,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 0.95,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 0.95,
|
||||
'1': 100
|
||||
}]], ['to', ['scaleX', {
|
||||
'0': 1,
|
||||
'1': 100
|
||||
}], ['scaleY', {
|
||||
'0': 1,
|
||||
'1': 100
|
||||
}]]])
|
||||
|
||||
To.extend('flipInX', [['to', ['rotateX', {
|
||||
'0': -90,
|
||||
'1': 0
|
||||
}]], ['to', ['rotateX', {
|
||||
'0': 20,
|
||||
'1': 300
|
||||
}]], ['to', ['rotateX', {
|
||||
'0': -20,
|
||||
'1': 300
|
||||
}]], ['to', ['rotateX', {
|
||||
'0': 10,
|
||||
'1': 300
|
||||
}]], ['to', ['rotateX', {
|
||||
'0': -5,
|
||||
'1': 300
|
||||
}]], ['to', ['rotateX', {
|
||||
'0': 0,
|
||||
'1': 300
|
||||
}]]])
|
||||
|
||||
To.extend('zoomOut', [['to', ['scaleX', {
|
||||
'0': 0,
|
||||
'1': 400
|
||||
}], ['scaleY', {
|
||||
'0': 0,
|
||||
'1': 400
|
||||
}]]])
|
|
@ -0,0 +1,112 @@
|
|||
/*!
|
||||
* raf-interval v0.3.0 By dntzhang
|
||||
* Github: https://github.com/dntzhang/raf-interval
|
||||
* MIT Licensed.
|
||||
*/
|
||||
|
||||
if (!Date.now) {
|
||||
Date.now = function now () {
|
||||
return new Date().getTime()
|
||||
}
|
||||
}
|
||||
|
||||
let queue = [],
|
||||
id = -1,
|
||||
ticking = false,
|
||||
tickId = null,
|
||||
now = Date.now,
|
||||
lastTime = 0,
|
||||
vendors = ['ms', 'moz', 'webkit', 'o'],
|
||||
x = 0,
|
||||
isWeapp = typeof wx !== 'undefined' && !wx.createCanvas,
|
||||
isWegame = typeof wx !== 'undefined' && wx.createCanvas,
|
||||
isBrowser = typeof window !== 'undefined'
|
||||
|
||||
let raf = isBrowser ? window.requestAnimationFrame : null
|
||||
let caf = isBrowser ? window.cancelAnimationFrame : null
|
||||
|
||||
function mockRaf (callback, element) {
|
||||
let currTime = now()
|
||||
let timeToCall = Math.max(0, 16 - (currTime - lastTime))
|
||||
let id = setTimeout(function () {
|
||||
callback(currTime + timeToCall)
|
||||
}, timeToCall)
|
||||
lastTime = currTime + timeToCall
|
||||
return id
|
||||
}
|
||||
|
||||
function mockCaf (id) {
|
||||
clearTimeout(id)
|
||||
}
|
||||
|
||||
if (isBrowser) {
|
||||
window.setRafInterval = setRafInterval
|
||||
window.clearRafInterval = clearRafInterval
|
||||
|
||||
for (; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
|
||||
window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
|
||||
window[vendors[x] + 'CancelRequestAnimationFrame']
|
||||
}
|
||||
|
||||
if (!raf) {
|
||||
raf = mockRaf
|
||||
caf = mockCaf
|
||||
window.requestAnimationFrame = raf
|
||||
window.cancelAnimationFrame = caf
|
||||
}
|
||||
} else if (isWeapp) {
|
||||
raf = mockRaf
|
||||
caf = mockCaf
|
||||
} else if (isWegame) {
|
||||
raf = requestAnimationFrame
|
||||
caf = cancelAnimationFrame
|
||||
}
|
||||
|
||||
export function setRafInterval (fn, interval) {
|
||||
id++
|
||||
queue.push({ id: id, fn: fn, interval: interval, lastTime: now() })
|
||||
if (!ticking) {
|
||||
let tick = function () {
|
||||
tickId = raf(tick)
|
||||
each(queue, function (item) {
|
||||
if (item.interval < 17 || now() - item.lastTime >= item.interval) {
|
||||
item.fn()
|
||||
item.lastTime = now()
|
||||
}
|
||||
})
|
||||
}
|
||||
ticking = true
|
||||
tick()
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
export function clearRafInterval (id) {
|
||||
let i = 0,
|
||||
len = queue.length
|
||||
|
||||
for (; i < len; i++) {
|
||||
if (id === queue[i].id) {
|
||||
queue.splice(i, 1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (queue.length === 0) {
|
||||
caf(tickId)
|
||||
ticking = false
|
||||
}
|
||||
}
|
||||
|
||||
function each (arr, fn) {
|
||||
if (Array.prototype.forEach) {
|
||||
arr.forEach(fn)
|
||||
} else {
|
||||
let i = 0,
|
||||
len = arr.length
|
||||
for (; i < len; i++) {
|
||||
fn(arr[i], i)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,264 @@
|
|||
import TWEEN from './tween'
|
||||
import {setRafInterval, clearRafInterval} from './raf-interval'
|
||||
|
||||
class To {
|
||||
constructor (element) {
|
||||
this.element = element
|
||||
this.cmds = []
|
||||
this.index = 0
|
||||
this.tweens = []
|
||||
this._pause = false
|
||||
this.loop = setRafInterval(function () {
|
||||
TWEEN.update()
|
||||
}, 15)
|
||||
this.cycleCount = 0
|
||||
}
|
||||
|
||||
to (target, duration, easing) {
|
||||
this.cmds.push(['to'])
|
||||
if (arguments.length !== 0) {
|
||||
for (let key in target) {
|
||||
this.set(key, target[key], duration || 0, easing)
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
set (prop, value, duration, easing) {
|
||||
this.cmds[this.cmds.length - 1].push([prop, [value, duration, easing]])
|
||||
return this
|
||||
}
|
||||
|
||||
x () {
|
||||
this.cmds[this.cmds.length - 1].push(['x', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
y () {
|
||||
this.cmds[this.cmds.length - 1].push(['y', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
z () {
|
||||
this.cmds[this.cmds.length - 1].push(['z', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
rotation () {
|
||||
this.cmds[this.cmds.length - 1].push(['rotation', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
scaleX () {
|
||||
this.cmds[this.cmds.length - 1].push(['scaleX', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
scaleY () {
|
||||
this.cmds[this.cmds.length - 1].push(['scaleY', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
skewX () {
|
||||
this.cmds[this.cmds.length - 1].push(['skewX', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
skewY () {
|
||||
this.cmds[this.cmds.length - 1].push(['skewY', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
originX () {
|
||||
this.cmds[this.cmds.length - 1].push(['originX', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
originY () {
|
||||
this.cmds[this.cmds.length - 1].push(['originY', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
alpha () {
|
||||
this.cmds[this.cmds.length - 1].push(['alpha', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
begin (fn) {
|
||||
this.cmds[this.cmds.length - 1].begin = fn
|
||||
return this
|
||||
}
|
||||
|
||||
progress (fn) {
|
||||
this.cmds[this.cmds.length - 1].progress = fn
|
||||
return this
|
||||
}
|
||||
|
||||
end (fn) {
|
||||
this.cmds[this.cmds.length - 1].end = fn
|
||||
return this
|
||||
}
|
||||
|
||||
wait () {
|
||||
this.cmds.push(['wait', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
then () {
|
||||
this.cmds.push(['then', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
cycle () {
|
||||
this.cmds.push(['cycle', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
start () {
|
||||
if (this._pause) return
|
||||
var len = this.cmds.length
|
||||
if (this.index < len) {
|
||||
this.exec(this.cmds[this.index], this.index === len - 1)
|
||||
} else {
|
||||
clearRafInterval(this.loop)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
pause () {
|
||||
this._pause = true
|
||||
for (var i = 0, len = this.tweens.length; i < len; i++) {
|
||||
this.tweens[i].pause()
|
||||
}
|
||||
if (this.currentTask === 'wait') {
|
||||
this.timeout -= new Date() - this.currentTaskBegin
|
||||
this.currentTaskBegin = new Date()
|
||||
}
|
||||
}
|
||||
|
||||
toggle () {
|
||||
if (this._pause) {
|
||||
this.play()
|
||||
} else {
|
||||
this.pause()
|
||||
}
|
||||
}
|
||||
|
||||
play () {
|
||||
this._pause = false
|
||||
for (var i = 0, len = this.tweens.length; i < len; i++) {
|
||||
this.tweens[i].play()
|
||||
}
|
||||
var self = this
|
||||
if (this.currentTask === 'wait') {
|
||||
setTimeout(function () {
|
||||
if (self._pause) return
|
||||
self.index++
|
||||
self.start()
|
||||
if (self.index === self.cmds.length && self.complete) self.complete()
|
||||
}, this.timeout)
|
||||
}
|
||||
}
|
||||
|
||||
stop () {
|
||||
for (var i = 0, len = this.tweens.length; i < len; i++) {
|
||||
this.tweens[i].stop()
|
||||
}
|
||||
this.cmds.length = 0
|
||||
}
|
||||
|
||||
animate (name) {
|
||||
this.cmds = this.cmds.concat(To.animationMap[name] || [])
|
||||
return this
|
||||
}
|
||||
|
||||
exec (cmd, last) {
|
||||
var len = cmd.length,
|
||||
self = this
|
||||
this.currentTask = cmd[0]
|
||||
switch (this.currentTask) {
|
||||
case 'to':
|
||||
self.stepCompleteCount = 0
|
||||
for (var i = 1; i < len; i++) {
|
||||
var task = cmd[i]
|
||||
var ease = task[1][2]
|
||||
var target = {}
|
||||
var prop = task[0]
|
||||
target[prop] = task[1][0]
|
||||
|
||||
var t = new TWEEN.Tween(this.element)
|
||||
.to(target, task[1][1])
|
||||
.onStart(function () {
|
||||
if (cmd.begin) cmd.begin.call(self.element, self.element)
|
||||
})
|
||||
.onUpdate(function () {
|
||||
if (cmd.progress) cmd.progress.call(self.element, self.element)
|
||||
// self.element[prop] = this[prop];
|
||||
})
|
||||
.easing(ease || TWEEN.Easing.Linear.None)
|
||||
.onComplete(function () {
|
||||
self.stepCompleteCount++
|
||||
if (self.stepCompleteCount === len - 1) {
|
||||
if (cmd.end) cmd.end.call(self.element, self.element)
|
||||
if (last && self.complete) self.complete()
|
||||
self.index++
|
||||
self.start()
|
||||
}
|
||||
})
|
||||
.start()
|
||||
this.tweens.push(t)
|
||||
}
|
||||
break
|
||||
case 'wait':
|
||||
this.currentTaskBegin = new Date()
|
||||
this.timeout = cmd[1][0]
|
||||
setTimeout(function () {
|
||||
if (self._pause) return
|
||||
self.index++
|
||||
self.start()
|
||||
if (cmd.end) cmd.end.call(self.element, self.element)
|
||||
if (last && self.complete) self.complete()
|
||||
}, cmd[1][0])
|
||||
break
|
||||
case 'then':
|
||||
var arg = cmd[1][0]
|
||||
arg.index = 0
|
||||
arg.complete = function () {
|
||||
self.index++
|
||||
self.start()
|
||||
if (last && self.complete) self.complete()
|
||||
}
|
||||
arg.start()
|
||||
break
|
||||
case 'cycle':
|
||||
var count = cmd[1][1]
|
||||
if (count === undefined) {
|
||||
self.index = cmd[1][0] || 0
|
||||
self.start()
|
||||
} else {
|
||||
if (count && self.cycleCount === count) {
|
||||
self.index++
|
||||
self.start()
|
||||
if (last && self.complete) self.complete()
|
||||
} else {
|
||||
self.cycleCount++
|
||||
self.index = cmd[1][0]
|
||||
self.start()
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
To.get = function (element) {
|
||||
var to = new To(element)
|
||||
return to
|
||||
}
|
||||
|
||||
To.animationMap = {}
|
||||
To.extend = function (animationName, cmds) {
|
||||
To.animationMap[animationName] = cmds
|
||||
}
|
||||
|
||||
export default To
|
|
@ -0,0 +1,773 @@
|
|||
/**
|
||||
* Tween.js - Licensed under the MIT license
|
||||
* https://github.com/tweenjs/tween.js
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* See https://github.com/tweenjs/tween.js/graphs/contributors for the full list of contributors.
|
||||
* Thank you all, you're awesome!
|
||||
*/
|
||||
|
||||
var _Group = function () {
|
||||
this._tweens = {}
|
||||
this._tweensAddedDuringUpdate = {}
|
||||
}
|
||||
|
||||
_Group.prototype = {
|
||||
getAll: function () {
|
||||
return Object.keys(this._tweens).map(function (tweenId) {
|
||||
return this._tweens[tweenId]
|
||||
}.bind(this))
|
||||
},
|
||||
|
||||
removeAll: function () {
|
||||
this._tweens = {}
|
||||
},
|
||||
|
||||
add: function (tween) {
|
||||
this._tweens[tween.getId()] = tween
|
||||
this._tweensAddedDuringUpdate[tween.getId()] = tween
|
||||
},
|
||||
|
||||
remove: function (tween) {
|
||||
delete this._tweens[tween.getId()]
|
||||
delete this._tweensAddedDuringUpdate[tween.getId()]
|
||||
},
|
||||
|
||||
update: function (time, preserve) {
|
||||
var tweenIds = Object.keys(this._tweens)
|
||||
|
||||
if (tweenIds.length === 0) {
|
||||
return false
|
||||
}
|
||||
|
||||
time = time !== undefined ? time : TWEEN.now()
|
||||
|
||||
// Tweens are updated in "batches". If you add a new tween during an update, then the
|
||||
// new tween will be updated in the next batch.
|
||||
// If you remove a tween during an update, it may or may not be updated. However,
|
||||
// if the removed tween was added during the current batch, then it will not be updated.
|
||||
while (tweenIds.length > 0) {
|
||||
this._tweensAddedDuringUpdate = {}
|
||||
|
||||
for (var i = 0; i < tweenIds.length; i++) {
|
||||
var tween = this._tweens[tweenIds[i]]
|
||||
|
||||
if (tween && tween.update(time) === false) {
|
||||
tween._isPlaying = false
|
||||
|
||||
if (!preserve) {
|
||||
delete this._tweens[tweenIds[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tweenIds = Object.keys(this._tweensAddedDuringUpdate)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
var TWEEN = new _Group()
|
||||
|
||||
TWEEN.Group = _Group
|
||||
TWEEN._nextId = 0
|
||||
TWEEN.nextId = function () {
|
||||
return TWEEN._nextId++
|
||||
}
|
||||
|
||||
// Include a performance.now polyfill.
|
||||
// In node.js, use process.hrtime.
|
||||
if (typeof (window) === 'undefined' && typeof (process) !== 'undefined') {
|
||||
if (typeof wx !== 'undefined') {
|
||||
TWEEN.now = Date.now
|
||||
} else {
|
||||
TWEEN.now = function () {
|
||||
var time = process.hrtime()
|
||||
|
||||
// Convert [seconds, nanoseconds] to milliseconds.
|
||||
return time[0] * 1000 + time[1] / 1000000
|
||||
}
|
||||
}
|
||||
} else if (typeof (window) !== 'undefined' &&
|
||||
// In a browser, use window.performance.now if it is available.
|
||||
window.performance !== undefined && window.performance.now !== undefined) {
|
||||
// This must be bound, because directly assigning this function
|
||||
// leads to an invocation exception in Chrome.
|
||||
TWEEN.now = window.performance.now.bind(window.performance)
|
||||
} else if (Date.now !== undefined) { // Use Date.now if it is available.
|
||||
TWEEN.now = Date.now
|
||||
} else { // Otherwise, use 'new Date().getTime()'.
|
||||
TWEEN.now = function () {
|
||||
return new Date().getTime()
|
||||
}
|
||||
}
|
||||
|
||||
TWEEN.Tween = function (object, group) {
|
||||
this._object = object
|
||||
this._valuesStart = {}
|
||||
this._valuesEnd = {}
|
||||
this._valuesStartRepeat = {}
|
||||
this._duration = 1000
|
||||
this._repeat = 0
|
||||
this._repeatDelayTime = undefined
|
||||
this._yoyo = false
|
||||
this._isPlaying = false
|
||||
this._reversed = false
|
||||
this._delayTime = 0
|
||||
this._startTime = null
|
||||
this._easingFunction = TWEEN.Easing.Linear.None
|
||||
this._interpolationFunction = TWEEN.Interpolation.Linear
|
||||
this._chainedTweens = []
|
||||
this._onStartCallback = null
|
||||
this._onStartCallbackFired = false
|
||||
this._onUpdateCallback = null
|
||||
this._onCompleteCallback = null
|
||||
this._onStopCallback = null
|
||||
this._group = group || TWEEN
|
||||
this._id = TWEEN.nextId()
|
||||
|
||||
this._paused = false
|
||||
this._passTime = null
|
||||
}
|
||||
|
||||
TWEEN.Tween.prototype = {
|
||||
getId: function getId () {
|
||||
return this._id
|
||||
},
|
||||
|
||||
toggle () {
|
||||
if (this._paused) {
|
||||
this.play()
|
||||
} else {
|
||||
this.pause()
|
||||
}
|
||||
},
|
||||
|
||||
pause: function () {
|
||||
this._paused = true
|
||||
var pauseTime = TWEEN.now()
|
||||
this._passTime = pauseTime - this._startTime
|
||||
},
|
||||
|
||||
play: function () {
|
||||
this._paused = false
|
||||
var nowTime = TWEEN.now()
|
||||
this._startTime = nowTime - this._passTime
|
||||
},
|
||||
|
||||
isPlaying: function isPlaying () {
|
||||
return this._isPlaying
|
||||
},
|
||||
|
||||
to: function to (properties, duration) {
|
||||
this._valuesEnd = properties
|
||||
|
||||
if (duration !== undefined) {
|
||||
this._duration = duration
|
||||
}
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
start: function start (time) {
|
||||
this._group.add(this)
|
||||
|
||||
this._isPlaying = true
|
||||
|
||||
this._onStartCallbackFired = false
|
||||
|
||||
this._startTime = time !== undefined ? typeof time === 'string' ? TWEEN.now() + parseFloat(time) : time : TWEEN.now()
|
||||
this._startTime += this._delayTime
|
||||
|
||||
for (var property in this._valuesEnd) {
|
||||
// Check if an Array was provided as property value
|
||||
if (this._valuesEnd[property] instanceof Array) {
|
||||
if (this._valuesEnd[property].length === 0) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create a local copy of the Array with the start value at the front
|
||||
this._valuesEnd[property] = [this._object[property]].concat(this._valuesEnd[property])
|
||||
}
|
||||
|
||||
// If `to()` specifies a property that doesn't exist in the source object,
|
||||
// we should not set that property in the object
|
||||
if (this._object[property] === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Save the starting value.
|
||||
this._valuesStart[property] = this._object[property]
|
||||
|
||||
if ((this._valuesStart[property] instanceof Array) === false) {
|
||||
this._valuesStart[property] *= 1.0 // Ensures we're using numbers, not strings
|
||||
}
|
||||
|
||||
this._valuesStartRepeat[property] = this._valuesStart[property] || 0
|
||||
}
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
stop: function stop () {
|
||||
if (!this._isPlaying) {
|
||||
return this
|
||||
}
|
||||
|
||||
this._group.remove(this)
|
||||
this._isPlaying = false
|
||||
|
||||
if (this._onStopCallback !== null) {
|
||||
this._onStopCallback(this._object)
|
||||
}
|
||||
|
||||
this.stopChainedTweens()
|
||||
return this
|
||||
},
|
||||
|
||||
end: function end () {
|
||||
this.update(this._startTime + this._duration)
|
||||
return this
|
||||
},
|
||||
|
||||
stopChainedTweens: function stopChainedTweens () {
|
||||
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
|
||||
this._chainedTweens[i].stop()
|
||||
}
|
||||
},
|
||||
|
||||
group: function group (group) {
|
||||
this._group = group
|
||||
return this
|
||||
},
|
||||
|
||||
delay: function delay (amount) {
|
||||
this._delayTime = amount
|
||||
return this
|
||||
},
|
||||
|
||||
repeat: function repeat (times) {
|
||||
this._repeat = times
|
||||
return this
|
||||
},
|
||||
|
||||
repeatDelay: function repeatDelay (amount) {
|
||||
this._repeatDelayTime = amount
|
||||
return this
|
||||
},
|
||||
|
||||
yoyo: function yoyo (yy) {
|
||||
this._yoyo = yy
|
||||
return this
|
||||
},
|
||||
|
||||
easing: function easing (eas) {
|
||||
this._easingFunction = eas
|
||||
return this
|
||||
},
|
||||
|
||||
interpolation: function interpolation (inter) {
|
||||
this._interpolationFunction = inter
|
||||
return this
|
||||
},
|
||||
|
||||
chain: function chain () {
|
||||
this._chainedTweens = arguments
|
||||
return this
|
||||
},
|
||||
|
||||
onStart: function onStart (callback) {
|
||||
this._onStartCallback = callback
|
||||
return this
|
||||
},
|
||||
|
||||
onUpdate: function onUpdate (callback) {
|
||||
this._onUpdateCallback = callback
|
||||
return this
|
||||
},
|
||||
|
||||
onComplete: function onComplete (callback) {
|
||||
this._onCompleteCallback = callback
|
||||
return this
|
||||
},
|
||||
|
||||
onStop: function onStop (callback) {
|
||||
this._onStopCallback = callback
|
||||
return this
|
||||
},
|
||||
|
||||
update: function update (time) {
|
||||
if (this._paused) return true
|
||||
var property
|
||||
var elapsed
|
||||
var value
|
||||
|
||||
if (time < this._startTime) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (this._onStartCallbackFired === false) {
|
||||
if (this._onStartCallback !== null) {
|
||||
this._onStartCallback(this._object)
|
||||
}
|
||||
|
||||
this._onStartCallbackFired = true
|
||||
}
|
||||
|
||||
elapsed = (time - this._startTime) / this._duration
|
||||
elapsed = (this._duration === 0 || elapsed > 1) ? 1 : elapsed
|
||||
|
||||
value = this._easingFunction(elapsed)
|
||||
|
||||
for (property in this._valuesEnd) {
|
||||
// Don't update properties that do not exist in the source object
|
||||
if (this._valuesStart[property] === undefined) {
|
||||
continue
|
||||
}
|
||||
|
||||
var start = this._valuesStart[property] || 0
|
||||
var end = this._valuesEnd[property]
|
||||
|
||||
if (end instanceof Array) {
|
||||
this._object[property] = this._interpolationFunction(end, value)
|
||||
} else {
|
||||
// Parses relative end values with start as base (e.g.: +10, -3)
|
||||
if (typeof (end) === 'string') {
|
||||
if (end.charAt(0) === '+' || end.charAt(0) === '-') {
|
||||
end = start + parseFloat(end)
|
||||
} else {
|
||||
end = parseFloat(end)
|
||||
}
|
||||
}
|
||||
|
||||
// Protect against non numeric properties.
|
||||
if (typeof (end) === 'number') {
|
||||
this._object[property] = start + (end - start) * value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this._onUpdateCallback !== null) {
|
||||
this._onUpdateCallback(this._object)
|
||||
}
|
||||
|
||||
if (elapsed === 1) {
|
||||
if (this._repeat > 0) {
|
||||
if (isFinite(this._repeat)) {
|
||||
this._repeat--
|
||||
}
|
||||
|
||||
// Reassign starting values, restart by making startTime = now
|
||||
for (property in this._valuesStartRepeat) {
|
||||
if (typeof (this._valuesEnd[property]) === 'string') {
|
||||
this._valuesStartRepeat[property] = this._valuesStartRepeat[property] + parseFloat(this._valuesEnd[property])
|
||||
}
|
||||
|
||||
if (this._yoyo) {
|
||||
var tmp = this._valuesStartRepeat[property]
|
||||
|
||||
this._valuesStartRepeat[property] = this._valuesEnd[property]
|
||||
this._valuesEnd[property] = tmp
|
||||
}
|
||||
|
||||
this._valuesStart[property] = this._valuesStartRepeat[property]
|
||||
}
|
||||
|
||||
if (this._yoyo) {
|
||||
this._reversed = !this._reversed
|
||||
}
|
||||
|
||||
if (this._repeatDelayTime !== undefined) {
|
||||
this._startTime = time + this._repeatDelayTime
|
||||
} else {
|
||||
this._startTime = time + this._delayTime
|
||||
}
|
||||
|
||||
return true
|
||||
} else {
|
||||
if (this._onCompleteCallback !== null) {
|
||||
this._onCompleteCallback(this._object)
|
||||
}
|
||||
|
||||
for (var i = 0, numChainedTweens = this._chainedTweens.length; i < numChainedTweens; i++) {
|
||||
// Make the chained tweens start exactly at the time they should,
|
||||
// even if the `update()` method was called way past the duration of the tween
|
||||
this._chainedTweens[i].start(this._startTime + this._duration)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
TWEEN.Easing = {
|
||||
|
||||
Linear: {
|
||||
|
||||
None: function (k) {
|
||||
return k
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Quadratic: {
|
||||
|
||||
In: function (k) {
|
||||
return k * k
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return k * (2 - k)
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * k * k
|
||||
}
|
||||
|
||||
return -0.5 * (--k * (k - 2) - 1)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Cubic: {
|
||||
|
||||
In: function (k) {
|
||||
return k * k * k
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return --k * k * k + 1
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * k * k * k
|
||||
}
|
||||
|
||||
return 0.5 * ((k -= 2) * k * k + 2)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Quartic: {
|
||||
|
||||
In: function (k) {
|
||||
return k * k * k * k
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return 1 - (--k * k * k * k)
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * k * k * k * k
|
||||
}
|
||||
|
||||
return -0.5 * ((k -= 2) * k * k * k - 2)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Quintic: {
|
||||
|
||||
In: function (k) {
|
||||
return k * k * k * k * k
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return --k * k * k * k * k + 1
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * k * k * k * k * k
|
||||
}
|
||||
|
||||
return 0.5 * ((k -= 2) * k * k * k * k + 2)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Sinusoidal: {
|
||||
|
||||
In: function (k) {
|
||||
return 1 - Math.cos(k * Math.PI / 2)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return Math.sin(k * Math.PI / 2)
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
return 0.5 * (1 - Math.cos(Math.PI * k))
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Exponential: {
|
||||
|
||||
In: function (k) {
|
||||
return k === 0 ? 0 : Math.pow(1024, k - 1)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return k === 1 ? 1 : 1 - Math.pow(2, -10 * k)
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if (k === 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (k === 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * Math.pow(1024, k - 1)
|
||||
}
|
||||
|
||||
return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Circular: {
|
||||
|
||||
In: function (k) {
|
||||
return 1 - Math.sqrt(1 - k * k)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
return Math.sqrt(1 - (--k * k))
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if ((k *= 2) < 1) {
|
||||
return -0.5 * (Math.sqrt(1 - k * k) - 1)
|
||||
}
|
||||
|
||||
return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Elastic: {
|
||||
|
||||
In: function (k) {
|
||||
if (k === 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (k === 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
if (k === 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (k === 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if (k === 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
if (k === 1) {
|
||||
return 1
|
||||
}
|
||||
|
||||
k *= 2
|
||||
|
||||
if (k < 1) {
|
||||
return -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
|
||||
}
|
||||
|
||||
return 0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Back: {
|
||||
|
||||
In: function (k) {
|
||||
var s = 1.70158
|
||||
|
||||
return k * k * ((s + 1) * k - s)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
var s = 1.70158
|
||||
|
||||
return --k * k * ((s + 1) * k + s) + 1
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
var s = 1.70158 * 1.525
|
||||
|
||||
if ((k *= 2) < 1) {
|
||||
return 0.5 * (k * k * ((s + 1) * k - s))
|
||||
}
|
||||
|
||||
return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Bounce: {
|
||||
|
||||
In: function (k) {
|
||||
return 1 - TWEEN.Easing.Bounce.Out(1 - k)
|
||||
},
|
||||
|
||||
Out: function (k) {
|
||||
if (k < (1 / 2.75)) {
|
||||
return 7.5625 * k * k
|
||||
} else if (k < (2 / 2.75)) {
|
||||
return 7.5625 * (k -= (1.5 / 2.75)) * k + 0.75
|
||||
} else if (k < (2.5 / 2.75)) {
|
||||
return 7.5625 * (k -= (2.25 / 2.75)) * k + 0.9375
|
||||
} else {
|
||||
return 7.5625 * (k -= (2.625 / 2.75)) * k + 0.984375
|
||||
}
|
||||
},
|
||||
|
||||
InOut: function (k) {
|
||||
if (k < 0.5) {
|
||||
return TWEEN.Easing.Bounce.In(k * 2) * 0.5
|
||||
}
|
||||
|
||||
return TWEEN.Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TWEEN.Interpolation = {
|
||||
|
||||
Linear: function (v, k) {
|
||||
var m = v.length - 1
|
||||
var f = m * k
|
||||
var i = Math.floor(f)
|
||||
var fn = TWEEN.Interpolation.Utils.Linear
|
||||
|
||||
if (k < 0) {
|
||||
return fn(v[0], v[1], f)
|
||||
}
|
||||
|
||||
if (k > 1) {
|
||||
return fn(v[m], v[m - 1], m - f)
|
||||
}
|
||||
|
||||
return fn(v[i], v[i + 1 > m ? m : i + 1], f - i)
|
||||
},
|
||||
|
||||
Bezier: function (v, k) {
|
||||
var b = 0
|
||||
var n = v.length - 1
|
||||
var pw = Math.pow
|
||||
var bn = TWEEN.Interpolation.Utils.Bernstein
|
||||
|
||||
for (var i = 0; i <= n; i++) {
|
||||
b += pw(1 - k, n - i) * pw(k, i) * v[i] * bn(n, i)
|
||||
}
|
||||
|
||||
return b
|
||||
},
|
||||
|
||||
CatmullRom: function (v, k) {
|
||||
var m = v.length - 1
|
||||
var f = m * k
|
||||
var i = Math.floor(f)
|
||||
var fn = TWEEN.Interpolation.Utils.CatmullRom
|
||||
|
||||
if (v[0] === v[m]) {
|
||||
if (k < 0) {
|
||||
i = Math.floor(f = m * (1 + k))
|
||||
}
|
||||
|
||||
return fn(v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m], f - i)
|
||||
} else {
|
||||
if (k < 0) {
|
||||
return v[0] - (fn(v[0], v[0], v[1], v[1], -f) - v[0])
|
||||
}
|
||||
|
||||
if (k > 1) {
|
||||
return v[m] - (fn(v[m], v[m], v[m - 1], v[m - 1], f - m) - v[m])
|
||||
}
|
||||
|
||||
return fn(v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2], f - i)
|
||||
}
|
||||
},
|
||||
|
||||
Utils: {
|
||||
|
||||
Linear: function (p0, p1, t) {
|
||||
return (p1 - p0) * t + p0
|
||||
},
|
||||
|
||||
Bernstein: function (n, i) {
|
||||
var fc = TWEEN.Interpolation.Utils.Factorial
|
||||
|
||||
return fc(n) / fc(i) / fc(n - i)
|
||||
},
|
||||
|
||||
Factorial: (function () {
|
||||
var a = [1]
|
||||
|
||||
return function (n) {
|
||||
var s = 1
|
||||
|
||||
if (a[n]) {
|
||||
return a[n]
|
||||
}
|
||||
|
||||
for (var i = n; i > 1; i--) {
|
||||
s *= i
|
||||
}
|
||||
|
||||
a[n] = s
|
||||
return s
|
||||
}
|
||||
})(),
|
||||
|
||||
CatmullRom: function (p0, p1, p2, p3, t) {
|
||||
var v0 = (p2 - p0) * 0.5
|
||||
var v1 = (p3 - p1) * 0.5
|
||||
var t2 = t * t
|
||||
var t3 = t * t2
|
||||
|
||||
return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// UMD (Universal Module Definition)
|
||||
(function (root) {
|
||||
if (typeof module !== 'undefined' && typeof exports === 'object') {
|
||||
// Node.js
|
||||
module.exports = TWEEN
|
||||
} else if (root !== undefined) {
|
||||
// Global variable
|
||||
root.TWEEN = TWEEN
|
||||
}
|
||||
})(this)
|
|
@ -0,0 +1,57 @@
|
|||
export function getImageInWx (img, callback) {
|
||||
if ((img.indexOf('https://') === -1 && img.indexOf('http://') === -1) || img.indexOf('http://tmp/') === 0) {
|
||||
wx.getImageInfo({
|
||||
src: img,
|
||||
success: (info) => {
|
||||
callback({
|
||||
img: img,
|
||||
width: info.width,
|
||||
height: info.height
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
wx.downloadFile({
|
||||
url: img,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
wx.getImageInfo({
|
||||
src: res.tempFilePath,
|
||||
success: (info) => {
|
||||
callback({
|
||||
img: res.tempFilePath,
|
||||
width: info.width,
|
||||
height: info.height
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function getGlobal () {
|
||||
if (typeof global !== 'object' || !global || global.Math !== Math || global.Array !== Array) {
|
||||
if (typeof self !== 'undefined') {
|
||||
return self
|
||||
} else if (typeof window !== 'undefined') {
|
||||
return window
|
||||
} else if (typeof global !== 'undefined') {
|
||||
return global
|
||||
}
|
||||
return (function () {
|
||||
return this
|
||||
})()
|
||||
}
|
||||
return global
|
||||
}
|
||||
|
||||
const root = getGlobal()
|
||||
|
||||
export default{
|
||||
getImageInWx,
|
||||
root,
|
||||
isWeapp: typeof wx !== 'undefined' && !wx.createCanvas && wx.createCanvasContext,
|
||||
isWegame: typeof wx !== 'undefined' && wx.createCanvas
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
import TWEEN from './common/tween'
|
||||
import To from './common/to'
|
||||
import './common/animate'
|
||||
|
||||
import Stage from './render/display/stage'
|
||||
import WeStage from './render/display/we-stage'
|
||||
import Graphics from './render/display/graphics'
|
||||
import Bitmap from './render/display/bitmap'
|
||||
import Text from './render/display/text'
|
||||
import Group from './render/display/group'
|
||||
import Sprite from './render/display/sprite'
|
||||
import Shape from './render/display/shape/shape'
|
||||
|
||||
import RoundedRect from './render/display/shape/rounded-rect'
|
||||
import ArrowPath from './render/display/shape/arrow-path'
|
||||
import Ellipse from './render/display/shape/ellipse'
|
||||
import Path from './render/display/shape/path'
|
||||
|
||||
import Button from './render/display/element/button'
|
||||
|
||||
import Rect from './render/display/shape/rect'
|
||||
import Circle from './render/display/shape/circle'
|
||||
import Polygon from './render/display/shape/polygon'
|
||||
import EquilateralPolygon from './render/display/shape/equilateral-polygon'
|
||||
|
||||
import {setRafInterval, clearRafInterval} from './common/raf-interval'
|
||||
|
||||
To.easing = {
|
||||
linear: TWEEN.Easing.Linear.None
|
||||
}
|
||||
|
||||
const cax = {
|
||||
easing: {
|
||||
linear: TWEEN.Easing.Linear.None
|
||||
},
|
||||
util: {
|
||||
randomInt: (min, max) => {
|
||||
return min + Math.floor(Math.random() * (max - min + 1))
|
||||
}
|
||||
},
|
||||
|
||||
Stage,
|
||||
WeStage,
|
||||
Graphics,
|
||||
Bitmap,
|
||||
Text,
|
||||
Group,
|
||||
Sprite,
|
||||
Shape,
|
||||
|
||||
ArrowPath,
|
||||
Ellipse,
|
||||
Path,
|
||||
|
||||
Button,
|
||||
|
||||
RoundedRect,
|
||||
Rect,
|
||||
Circle,
|
||||
Polygon,
|
||||
EquilateralPolygon,
|
||||
|
||||
setInterval: setRafInterval,
|
||||
clearInterval: clearRafInterval,
|
||||
tick: function (fn) {
|
||||
return setRafInterval(fn, 16)
|
||||
},
|
||||
untick: function (tickId) {
|
||||
clearRafInterval(tickId)
|
||||
},
|
||||
|
||||
caxCanvasId: 0,
|
||||
TWEEN,
|
||||
To
|
||||
};
|
||||
|
||||
['Quadratic',
|
||||
'Cubic',
|
||||
'Quartic',
|
||||
'Quintic',
|
||||
'Sinusoidal',
|
||||
'Exponential',
|
||||
'Circular',
|
||||
'Elastic',
|
||||
'Back',
|
||||
'Bounce'].forEach(item => {
|
||||
const itemLower = item.toLowerCase()
|
||||
cax.easing[itemLower + 'In'] = TWEEN.Easing[item].In
|
||||
cax.easing[itemLower + 'Out'] = TWEEN.Easing[item].Out
|
||||
cax.easing[itemLower + 'InOut'] = TWEEN.Easing[item].InOut
|
||||
|
||||
To.easing[itemLower + 'In'] = TWEEN.Easing[item].In
|
||||
To.easing[itemLower + 'Out'] = TWEEN.Easing[item].Out
|
||||
To.easing[itemLower + 'InOut'] = TWEEN.Easing[item].InOut
|
||||
})
|
||||
|
||||
const isWegame = typeof wx !== 'undefined' && wx.createCanvas
|
||||
|
||||
cax.loadImg = function (option) {
|
||||
const img = isWegame ? wx.createImage() : new Image()
|
||||
img.onload = function () {
|
||||
option.complete(this)
|
||||
}
|
||||
img.src = option.img
|
||||
}
|
||||
|
||||
cax.loadImgs = function (option) {
|
||||
const result = []
|
||||
let loaded = 0
|
||||
const len = option.imgs.length
|
||||
option.imgs.forEach((src, index) => {
|
||||
const img = isWegame ? wx.createImage() : new Image()
|
||||
img.onload = (function (i, img) {
|
||||
return function(){
|
||||
result[i] = img
|
||||
loaded++
|
||||
option.progress && option.progress(loaded / len, loaded, i, img, result)
|
||||
if (loaded === len) {
|
||||
option.complete && option.complete(result)
|
||||
}
|
||||
}
|
||||
})(index,img)
|
||||
img.src = src
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = cax
|
|
@ -0,0 +1,186 @@
|
|||
// https://github.com/colinmeinke/svg-arc-to-cubic-bezier
|
||||
|
||||
const TAU = Math.PI * 2
|
||||
|
||||
const mapToEllipse = ({ x, y }, rx, ry, cosphi, sinphi, centerx, centery) => {
|
||||
x *= rx
|
||||
y *= ry
|
||||
|
||||
const xp = cosphi * x - sinphi * y
|
||||
const yp = sinphi * x + cosphi * y
|
||||
|
||||
return {
|
||||
x: xp + centerx,
|
||||
y: yp + centery
|
||||
}
|
||||
}
|
||||
|
||||
const approxUnitArc = (ang1, ang2) => {
|
||||
const a = 4 / 3 * Math.tan(ang2 / 4)
|
||||
|
||||
const x1 = Math.cos(ang1)
|
||||
const y1 = Math.sin(ang1)
|
||||
const x2 = Math.cos(ang1 + ang2)
|
||||
const y2 = Math.sin(ang1 + ang2)
|
||||
|
||||
return [
|
||||
{
|
||||
x: x1 - y1 * a,
|
||||
y: y1 + x1 * a
|
||||
},
|
||||
{
|
||||
x: x2 + y2 * a,
|
||||
y: y2 - x2 * a
|
||||
},
|
||||
{
|
||||
x: x2,
|
||||
y: y2
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const vectorAngle = (ux, uy, vx, vy) => {
|
||||
const sign = (ux * vy - uy * vx < 0) ? -1 : 1
|
||||
const umag = Math.sqrt(ux * ux + uy * uy)
|
||||
const vmag = Math.sqrt(ux * ux + uy * uy)
|
||||
const dot = ux * vx + uy * vy
|
||||
|
||||
let div = dot / (umag * vmag)
|
||||
|
||||
if (div > 1) {
|
||||
div = 1
|
||||
}
|
||||
|
||||
if (div < -1) {
|
||||
div = -1
|
||||
}
|
||||
|
||||
return sign * Math.acos(div)
|
||||
}
|
||||
|
||||
const getArcCenter = (
|
||||
px,
|
||||
py,
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
ry,
|
||||
largeArcFlag,
|
||||
sweepFlag,
|
||||
sinphi,
|
||||
cosphi,
|
||||
pxp,
|
||||
pyp
|
||||
) => {
|
||||
const rxsq = Math.pow(rx, 2)
|
||||
const rysq = Math.pow(ry, 2)
|
||||
const pxpsq = Math.pow(pxp, 2)
|
||||
const pypsq = Math.pow(pyp, 2)
|
||||
|
||||
let radicant = (rxsq * rysq) - (rxsq * pypsq) - (rysq * pxpsq)
|
||||
|
||||
if (radicant < 0) {
|
||||
radicant = 0
|
||||
}
|
||||
|
||||
radicant /= (rxsq * pypsq) + (rysq * pxpsq)
|
||||
radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1)
|
||||
|
||||
const centerxp = radicant * rx / ry * pyp
|
||||
const centeryp = radicant * -ry / rx * pxp
|
||||
|
||||
const centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2
|
||||
const centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2
|
||||
|
||||
const vx1 = (pxp - centerxp) / rx
|
||||
const vy1 = (pyp - centeryp) / ry
|
||||
const vx2 = (-pxp - centerxp) / rx
|
||||
const vy2 = (-pyp - centeryp) / ry
|
||||
|
||||
let ang1 = vectorAngle(1, 0, vx1, vy1)
|
||||
let ang2 = vectorAngle(vx1, vy1, vx2, vy2)
|
||||
|
||||
if (sweepFlag === 0 && ang2 > 0) {
|
||||
ang2 -= TAU
|
||||
}
|
||||
|
||||
if (sweepFlag === 1 && ang2 < 0) {
|
||||
ang2 += TAU
|
||||
}
|
||||
|
||||
return [ centerx, centery, ang1, ang2 ]
|
||||
}
|
||||
|
||||
const arcToBezier = ({
|
||||
px,
|
||||
py,
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
ry,
|
||||
xAxisRotation = 0,
|
||||
largeArcFlag = 0,
|
||||
sweepFlag = 0
|
||||
}) => {
|
||||
const curves = []
|
||||
|
||||
if (rx === 0 || ry === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
const sinphi = Math.sin(xAxisRotation * TAU / 360)
|
||||
const cosphi = Math.cos(xAxisRotation * TAU / 360)
|
||||
|
||||
const pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2
|
||||
const pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2
|
||||
|
||||
if (pxp === 0 && pyp === 0) {
|
||||
return []
|
||||
}
|
||||
|
||||
rx = Math.abs(rx)
|
||||
ry = Math.abs(ry)
|
||||
|
||||
const lambda =
|
||||
Math.pow(pxp, 2) / Math.pow(rx, 2) +
|
||||
Math.pow(pyp, 2) / Math.pow(ry, 2)
|
||||
|
||||
if (lambda > 1) {
|
||||
rx *= Math.sqrt(lambda)
|
||||
ry *= Math.sqrt(lambda)
|
||||
}
|
||||
|
||||
let [ centerx, centery, ang1, ang2 ] = getArcCenter(
|
||||
px,
|
||||
py,
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
ry,
|
||||
largeArcFlag,
|
||||
sweepFlag,
|
||||
sinphi,
|
||||
cosphi,
|
||||
pxp,
|
||||
pyp
|
||||
)
|
||||
|
||||
const segments = Math.max(Math.ceil(Math.abs(ang2) / (TAU / 4)), 1)
|
||||
|
||||
ang2 /= segments
|
||||
|
||||
for (let i = 0; i < segments; i++) {
|
||||
curves.push(approxUnitArc(ang1, ang2))
|
||||
ang1 += ang2
|
||||
}
|
||||
|
||||
return curves.map(curve => {
|
||||
const { x: x1, y: y1 } = mapToEllipse(curve[ 0 ], rx, ry, cosphi, sinphi, centerx, centery)
|
||||
const { x: x2, y: y2 } = mapToEllipse(curve[ 1 ], rx, ry, cosphi, sinphi, centerx, centery)
|
||||
const { x, y } = mapToEllipse(curve[ 2 ], rx, ry, cosphi, sinphi, centerx, centery)
|
||||
|
||||
return { x1, y1, x2, y2, x, y }
|
||||
})
|
||||
}
|
||||
|
||||
export default arcToBezier
|
|
@ -0,0 +1,82 @@
|
|||
import option from "./stage-propagation-tag"
|
||||
|
||||
class EventDispatcher {
|
||||
constructor () {
|
||||
this._listeners = null
|
||||
this._captureListeners = null
|
||||
}
|
||||
|
||||
addEventListener (type, listener, useCapture) {
|
||||
var listeners
|
||||
if (useCapture) {
|
||||
listeners = this._captureListeners = this._captureListeners || {}
|
||||
} else {
|
||||
listeners = this._listeners = this._listeners || {}
|
||||
}
|
||||
var arr = listeners[type]
|
||||
if (arr) { this.removeEventListener(type, listener, useCapture) }
|
||||
arr = listeners[type] // remove may have deleted the array
|
||||
if (!arr) { listeners[type] = [listener] } else { arr.push(listener) }
|
||||
return listener
|
||||
}
|
||||
|
||||
removeEventListener (type, listener, useCapture) {
|
||||
var listeners = useCapture ? this._captureListeners : this._listeners
|
||||
if (!listeners) { return }
|
||||
var arr = listeners[type]
|
||||
if (!arr) { return }
|
||||
|
||||
arr.every((item, index) => {
|
||||
if (item === listener) {
|
||||
arr.splice(index, 1)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
on (type, listener, useCapture) {
|
||||
this.addEventListener(type, listener, useCapture)
|
||||
}
|
||||
|
||||
off (type, listener, useCapture) {
|
||||
this.removeEventListener(type, listener, useCapture)
|
||||
}
|
||||
|
||||
dispatchEvent (evt) {
|
||||
option.stagePropagationStopped[evt.type] = false
|
||||
|
||||
var top = this, list = [top]
|
||||
while (top.parent) { list.push(top = top.parent) }
|
||||
var i, l = list.length
|
||||
|
||||
// capture & atTarget
|
||||
for (i = l - 1; i >= 0 && !evt.propagationStopped; i--) {
|
||||
list[i]._dispatchEvent(evt, 0)
|
||||
}
|
||||
// bubbling
|
||||
for (i = 0; i < l && !evt.propagationStopped; i++) {
|
||||
list[i]._dispatchEvent(evt, 1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_dispatchEvent (evt, type) {
|
||||
evt.target = this
|
||||
if (this._captureListeners && type === 0) {
|
||||
let cls = this._captureListeners[evt.type]
|
||||
cls && cls.forEach(fn => {
|
||||
fn.call(this, evt)
|
||||
})
|
||||
}
|
||||
|
||||
if (this._listeners && type === 1) {
|
||||
let ls = this._listeners[evt.type]
|
||||
ls && ls.forEach(fn => {
|
||||
fn.call(this, evt)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EventDispatcher
|
|
@ -0,0 +1,21 @@
|
|||
import option from "./stage-propagation-tag"
|
||||
|
||||
class Event {
|
||||
constructor () {
|
||||
this.propagationStopped = false
|
||||
this.stageX = null
|
||||
this.stageY = null
|
||||
this.pureEvent = null
|
||||
}
|
||||
|
||||
stopPropagation () {
|
||||
option.stagePropagationStopped[this.type] = true
|
||||
this.propagationStopped = true
|
||||
}
|
||||
|
||||
preventDefault () {
|
||||
this.pureEvent.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
export default Event
|
|
@ -0,0 +1,136 @@
|
|||
|
||||
const DEG_TO_RAD = 0.017453292519943295
|
||||
const PI_2 = Math.PI * 2
|
||||
|
||||
class Matrix2D {
|
||||
constructor (a, b, c, d, tx, ty) {
|
||||
this.a = a == null ? 1 : a
|
||||
this.b = b || 0
|
||||
this.c = c || 0
|
||||
this.d = d == null ? 1 : d
|
||||
this.tx = tx || 0
|
||||
this.ty = ty || 0
|
||||
return this
|
||||
}
|
||||
|
||||
identity () {
|
||||
this.a = this.d = 1
|
||||
this.b = this.c = this.tx = this.ty = 0
|
||||
return this
|
||||
}
|
||||
|
||||
appendTransform (x, y, scaleX, scaleY, rotation, skewX, skewY, originX, originY) {
|
||||
if (rotation % 360) {
|
||||
var r = rotation * DEG_TO_RAD
|
||||
var cos = Math.cos(r)
|
||||
var sin = Math.sin(r)
|
||||
} else {
|
||||
cos = 1
|
||||
sin = 0
|
||||
}
|
||||
if (skewX || skewY) {
|
||||
skewX *= DEG_TO_RAD
|
||||
skewY *= DEG_TO_RAD
|
||||
this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y)
|
||||
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0)
|
||||
} else {
|
||||
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y)
|
||||
}
|
||||
if (originX || originY) {
|
||||
this.tx -= originX * this.a + originY * this.c
|
||||
this.ty -= originX * this.b + originY * this.d
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
append (a, b, c, d, tx, ty) {
|
||||
var a1 = this.a
|
||||
var b1 = this.b
|
||||
var c1 = this.c
|
||||
var d1 = this.d
|
||||
this.a = a * a1 + b * c1
|
||||
this.b = a * b1 + b * d1
|
||||
this.c = c * a1 + d * c1
|
||||
this.d = c * b1 + d * d1
|
||||
this.tx = tx * a1 + ty * c1 + this.tx
|
||||
this.ty = tx * b1 + ty * d1 + this.ty
|
||||
return this
|
||||
}
|
||||
|
||||
initialize (a, b, c, d, tx, ty) {
|
||||
this.a = a
|
||||
this.b = b
|
||||
this.c = c
|
||||
this.d = d
|
||||
this.tx = tx
|
||||
this.ty = ty
|
||||
return this
|
||||
}
|
||||
|
||||
setValues (a, b, c, d, tx, ty) {
|
||||
this.a = a == null ? 1 : a
|
||||
this.b = b || 0
|
||||
this.c = c || 0
|
||||
this.d = d == null ? 1 : d
|
||||
this.tx = tx || 0
|
||||
this.ty = ty || 0
|
||||
return this
|
||||
}
|
||||
|
||||
invert () {
|
||||
let a1 = this.a
|
||||
let b1 = this.b
|
||||
let c1 = this.c
|
||||
let d1 = this.d
|
||||
let tx1 = this.tx
|
||||
let n = a1 * d1 - b1 * c1
|
||||
|
||||
this.a = d1 / n
|
||||
this.b = -b1 / n
|
||||
this.c = -c1 / n
|
||||
this.d = a1 / n
|
||||
this.tx = (c1 * this.ty - d1 * tx1) / n
|
||||
this.ty = -(a1 * this.ty - b1 * tx1) / n
|
||||
return this
|
||||
};
|
||||
|
||||
copy (matrix) {
|
||||
return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty)
|
||||
}
|
||||
}
|
||||
|
||||
Matrix2D.decompose = function(a, b, c, d, tx, ty, transform){
|
||||
const skewX = -Math.atan2(-c, d);
|
||||
const skewY = Math.atan2(b, a);
|
||||
|
||||
const delta = Math.abs(skewX + skewY);
|
||||
|
||||
if (delta < 0.00001 || Math.abs(PI_2 - delta) < 0.00001)
|
||||
{
|
||||
transform.rotation = skewY;
|
||||
|
||||
if (a < 0 && d >= 0)
|
||||
{
|
||||
transform.rotation += (transform.rotation <= 0) ? Math.PI : -Math.PI;
|
||||
}
|
||||
|
||||
transform.skewX = transform.skewY = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.rotation = 0;
|
||||
transform.skewX = skewX;
|
||||
transform.skewY = skewY;
|
||||
}
|
||||
|
||||
// next set scale
|
||||
transform.scaleX = Math.sqrt((a * a) + (b * b));
|
||||
transform.scaleY = Math.sqrt((c * c) + (d * d));
|
||||
|
||||
// next set position
|
||||
transform.x = tx;
|
||||
transform.y = ty;
|
||||
|
||||
}
|
||||
|
||||
export default Matrix2D
|
|
@ -0,0 +1,57 @@
|
|||
// https://github.com/jkroso/parse-svg-path/blob/master/index.js
|
||||
/**
|
||||
* expected argument lengths
|
||||
* @type {Object}
|
||||
*/
|
||||
|
||||
var length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}
|
||||
|
||||
/**
|
||||
* segment pattern
|
||||
* @type {RegExp}
|
||||
*/
|
||||
|
||||
var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig
|
||||
|
||||
/**
|
||||
* parse an svg path data string. Generates an Array
|
||||
* of commands where each command is an Array of the
|
||||
* form `[command, arg1, arg2, ...]`
|
||||
*
|
||||
* @param {String} path
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
function parse (path) {
|
||||
var data = []
|
||||
path.replace(segment, function (_, command, args) {
|
||||
var type = command.toLowerCase()
|
||||
args = parseValues(args)
|
||||
|
||||
// overloaded moveTo
|
||||
if (type === 'm' && args.length > 2) {
|
||||
data.push([command].concat(args.splice(0, 2)))
|
||||
type = 'l'
|
||||
command = command === 'm' ? 'l' : 'L'
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (args.length === length[type]) {
|
||||
args.unshift(command)
|
||||
return data.push(args)
|
||||
}
|
||||
if (args.length < length[type]) throw new Error('malformed path data')
|
||||
data.push([command].concat(args.splice(0, length[type])))
|
||||
}
|
||||
})
|
||||
return data
|
||||
}
|
||||
|
||||
var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig
|
||||
|
||||
function parseValues (args) {
|
||||
var numbers = args.match(number)
|
||||
return numbers ? numbers.map(Number) : []
|
||||
}
|
||||
|
||||
export default parse
|
|
@ -0,0 +1,3 @@
|
|||
export default {
|
||||
stagePropagationStopped:{}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
var UID = {}
|
||||
|
||||
UID._nextID = 0
|
||||
|
||||
UID.get = function () {
|
||||
return UID._nextID++
|
||||
}
|
||||
|
||||
export default UID
|
|
@ -0,0 +1,80 @@
|
|||
import DisplayObject from './display-object.js'
|
||||
import util from '../../common/util'
|
||||
|
||||
class Bitmap extends DisplayObject {
|
||||
constructor (img, onLoad) {
|
||||
super()
|
||||
if (typeof img === 'string') {
|
||||
if (Bitmap.cache[img]) {
|
||||
if (util.isWeapp) {
|
||||
this.img = Bitmap.cache[img].img
|
||||
this.rect = [0, 0, Bitmap.cache[img].width, Bitmap.cache[img].height]
|
||||
this.width = this.rect[2]
|
||||
this.height = this.rect[3]
|
||||
} else {
|
||||
this.img = Bitmap.cache[img]
|
||||
this.rect = [0, 0, this.img.width, this.img.height]
|
||||
this.width = this.img.width
|
||||
this.height = this.img.height
|
||||
}
|
||||
onLoad && onLoad.call(this)
|
||||
} else if (util.isWeapp) {
|
||||
util.getImageInWx(img, (result) => {
|
||||
this.img = result.img
|
||||
if (!this.rect) {
|
||||
this.rect = [0, 0, result.width, result.height]
|
||||
}
|
||||
this.width = result.width
|
||||
this.height = result.height
|
||||
onLoad && onLoad.call(this)
|
||||
Bitmap.cache[img] = result
|
||||
})
|
||||
} else {
|
||||
this.img = util.isWegame ? wx.createImage() : new window.Image()
|
||||
|
||||
this.img.onload = () => {
|
||||
|
||||
if (!this.rect) {
|
||||
this.rect = [0, 0, this.img.width, this.img.height]
|
||||
}
|
||||
this.width = this.img.width
|
||||
this.height = this.img.height
|
||||
onLoad && onLoad.call(this)
|
||||
Bitmap.cache[img] = this.img
|
||||
}
|
||||
this.img.src = img
|
||||
}
|
||||
} else {
|
||||
this.img = img
|
||||
this.rect = [0, 0, img.width, img.height]
|
||||
this.width = img.width
|
||||
this.height = img.height
|
||||
Bitmap.cache[img.src] = img
|
||||
}
|
||||
}
|
||||
|
||||
clone () {
|
||||
// 复制完img宽度0??所以直接传字符串
|
||||
const bitmap = new Bitmap(typeof this.img === 'string' ? this.img : this.img.src)
|
||||
bitmap.x = this.x
|
||||
bitmap.y = this.y
|
||||
bitmap.scaleX = this.scaleX
|
||||
bitmap.scaleY = this.scaleY
|
||||
bitmap.rotation = this.rotation
|
||||
bitmap.skewX = this.skewX
|
||||
bitmap.skewY = this.skewY
|
||||
bitmap.originX = this.originX
|
||||
bitmap.originY = this.originY
|
||||
bitmap.width = this.width
|
||||
bitmap.height = this.height
|
||||
bitmap.cursor = this.cursor
|
||||
|
||||
return bitmap
|
||||
}
|
||||
}
|
||||
|
||||
Bitmap.cache = {
|
||||
|
||||
}
|
||||
|
||||
export default Bitmap
|
|
@ -0,0 +1,215 @@
|
|||
import Matrix2D from '../base/matrix2d.js'
|
||||
import EventDispatcher from '../base/event-dispatcher'
|
||||
import UID from '../base/uid.js'
|
||||
|
||||
class DisplayObject extends EventDispatcher {
|
||||
constructor () {
|
||||
super()
|
||||
this.alpha = this.complexAlpha = this.scaleX = this.scaleY = 1
|
||||
this.x = this.y = this.rotation = this.skewX = this.skewY = this.originX = this.originY = 0
|
||||
this.cursor = null
|
||||
this.visible = true
|
||||
this._matrix = new Matrix2D()
|
||||
this._hitMatrix = new Matrix2D()
|
||||
this.id = UID.get()
|
||||
this.clipGraphics = null
|
||||
this.clipRuleNonzero = true
|
||||
this.fixed = false
|
||||
this.shadow = null
|
||||
this.compositeOperation = null
|
||||
this.absClipGraphics = null
|
||||
this.absClipRuleNonzero = true
|
||||
this.cacheUpdating = false
|
||||
|
||||
try {
|
||||
Object.defineProperties(this, {
|
||||
stage: { get: this._getStage },
|
||||
scale: {
|
||||
get: function() { return this.scaleX; },
|
||||
set: function(scale) { this.scaleX = this.scaleY = scale; }
|
||||
}
|
||||
});
|
||||
} catch (e) {}
|
||||
|
||||
this.hitBox = null
|
||||
}
|
||||
|
||||
isVisible () {
|
||||
return this.visible && this.alpha > 0 && this.scaleX !== 0 && this.scaleY !== 0
|
||||
}
|
||||
|
||||
initAABB () {
|
||||
|
||||
if ((this.width === undefined || this.height === undefined) && !this.hitBox) {
|
||||
return
|
||||
}
|
||||
|
||||
let x,
|
||||
y,
|
||||
width = this.width,
|
||||
height = this.height,
|
||||
mtx = this._matrix,
|
||||
tx = mtx.tx,
|
||||
ty = mtx.ty
|
||||
|
||||
if(this.hitBox){
|
||||
width = this.hitBox[2]
|
||||
height = this.hitBox[3]
|
||||
tx = this.hitBox[0] * mtx.a + this.hitBox[1] * mtx.c + tx
|
||||
ty = this.hitBox[0] * mtx.b + this.hitBox[1] * mtx.d + ty
|
||||
}
|
||||
|
||||
let xA = width * mtx.a,
|
||||
xB = width * mtx.b,
|
||||
yC = height * mtx.c,
|
||||
yD = height * mtx.d,
|
||||
minX = tx,
|
||||
maxX = tx,
|
||||
minY = ty,
|
||||
maxY = ty
|
||||
|
||||
if ((x = xA + tx) < minX) {
|
||||
minX = x
|
||||
} else if (x > maxX) {
|
||||
maxX = x
|
||||
}
|
||||
if ((x = xA + yC + tx) < minX) {
|
||||
minX = x
|
||||
} else if (x > maxX) {
|
||||
maxX = x
|
||||
}
|
||||
if ((x = yC + tx) < minX) {
|
||||
minX = x
|
||||
} else if (x > maxX) {
|
||||
maxX = x
|
||||
}
|
||||
if ((y = xB + ty) < minY) {
|
||||
minY = y
|
||||
} else if (y > maxY) {
|
||||
maxY = y
|
||||
}
|
||||
if ((y = xB + yD + ty) < minY) {
|
||||
minY = y
|
||||
} else if (y > maxY) {
|
||||
maxY = y
|
||||
}
|
||||
if ((y = yD + ty) < minY) {
|
||||
minY = y
|
||||
} else if (y > maxY) {
|
||||
maxY = y
|
||||
}
|
||||
this.AABB = [minX, minY, maxX - minX, maxY - minY]
|
||||
this.rectPoints = [{
|
||||
x: tx,
|
||||
y: ty
|
||||
}, {
|
||||
x: xA + tx,
|
||||
y: xB + ty
|
||||
}, {
|
||||
x: xA + yC + tx,
|
||||
y: xB + yD + ty
|
||||
}, {
|
||||
x: yC + tx,
|
||||
y: yD + ty
|
||||
}]
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.parent.remove(this)
|
||||
}
|
||||
|
||||
hover (over, out, move) {
|
||||
this.on('mouseover', over)
|
||||
this.on('mouseout', out)
|
||||
move && this.on('mousemove', move)
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/clip
|
||||
clip (graphics, notClipRuleNonzero) {
|
||||
this.clipGraphics = graphics
|
||||
this.clipRuleNonzero = !notClipRuleNonzero
|
||||
}
|
||||
|
||||
unclip () {
|
||||
this.clipGraphics = null
|
||||
}
|
||||
|
||||
absClip (graphics, notClipRuleNonzero) {
|
||||
this.absClipGraphics = graphics
|
||||
this.absClipRuleNonzero = !notClipRuleNonzero
|
||||
}
|
||||
|
||||
unAbsClip () {
|
||||
this.absClipGraphics = null
|
||||
}
|
||||
|
||||
cache (x, y, width, height, scale, cacheUpdating) {
|
||||
this._cacheData = {
|
||||
x: x || 0,
|
||||
y: y || 0,
|
||||
width: width || this.width,
|
||||
height: height || this.height,
|
||||
scale: scale || 1
|
||||
}
|
||||
this.cacheUpdating = cacheUpdating
|
||||
if (!this.cacheCanvas) {
|
||||
if (typeof wx !== 'undefined' && wx.createCanvas) {
|
||||
this.cacheCanvas = wx.createCanvas()
|
||||
} else {
|
||||
this.cacheCanvas = document.createElement('canvas')
|
||||
}
|
||||
this.cacheCtx = this.cacheCanvas.getContext('2d')
|
||||
}
|
||||
this.cacheCanvas.width = this._cacheData.width * this._cacheData.scale
|
||||
this.cacheCanvas.height = this._cacheData.height * this._cacheData.scale
|
||||
|
||||
// debug cache canvas
|
||||
// this.cacheCtx.fillRect(0,0,1000,1000)
|
||||
this._readyToCache = true
|
||||
}
|
||||
|
||||
uncache () {
|
||||
this.cacheCanvas = null
|
||||
}
|
||||
|
||||
filter(filterName, filterBox) {
|
||||
filterBox = Object.assign({}, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: this.width,
|
||||
height: this.height
|
||||
}, filterBox)
|
||||
this.cache(filterBox.x, filterBox.y, filterBox.width, filterBox.height)
|
||||
this._readyToFilter = true
|
||||
this._filterName = filterName
|
||||
}
|
||||
|
||||
setTransform (x, y, scaleX, scaleY, rotation, skewX, skewY, originX, originY) {
|
||||
this.x = x || 0;
|
||||
this.y = y || 0;
|
||||
this.scaleX = scaleX == null ? 1 : scaleX;
|
||||
this.scaleY = scaleY == null ? 1 : scaleY;
|
||||
this.rotation = rotation || 0;
|
||||
this.skewX = skewX || 0;
|
||||
this.skewY = skewY || 0;
|
||||
this.originX = originX || 0;
|
||||
this.originY = originY || 0;
|
||||
}
|
||||
|
||||
setMatrix(a, b, c, d, tx, ty){
|
||||
Matrix2D.decompose(a, b, c, d, tx, ty, this)
|
||||
}
|
||||
|
||||
unfilter () {
|
||||
this.uncache()
|
||||
}
|
||||
|
||||
_getStage () {
|
||||
var o = this
|
||||
while (o.parent) { o = o.parent }
|
||||
if (o.___instanceof === 'Stage') { return o; }
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default DisplayObject
|
|
@ -0,0 +1,114 @@
|
|||
import Group from '../group'
|
||||
import Text from '../text'
|
||||
import RoundedRect from '../shape/rounded-rect'
|
||||
import Bitmap from '../bitmap'
|
||||
|
||||
/*
|
||||
Options
|
||||
font:
|
||||
text:
|
||||
textColor:
|
||||
image: [path, width, height]
|
||||
bgColor:
|
||||
bgImage: [path, width, height]
|
||||
borderRadius:
|
||||
borderColor:
|
||||
*/
|
||||
|
||||
class Button extends Group {
|
||||
constructor (option) {
|
||||
super()
|
||||
this.width = option.width
|
||||
this.height = option.height
|
||||
this.x = option.x
|
||||
this.y = option.y
|
||||
|
||||
let textHeight = 0
|
||||
var textGroup
|
||||
|
||||
if (option.text) {
|
||||
textGroup = new Group()
|
||||
this.text = new Text(option.text, {
|
||||
font: option.font,
|
||||
color: option.color
|
||||
})
|
||||
const textWidth = this.text.getWidth()
|
||||
|
||||
if (textWidth > option.width) {
|
||||
const step = Math.round(option.text.length * (option.width) / textWidth / 2)
|
||||
|
||||
const textList = this.stringSplit(option.text, step)
|
||||
const lineHeight = option.lineHeight || 12
|
||||
textHeight = textList.length * lineHeight + 6
|
||||
|
||||
textList.forEach((text, index) => {
|
||||
this.text = new Text(text, {
|
||||
font: option.font,
|
||||
color: option.color
|
||||
})
|
||||
|
||||
this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX + (option.textX || 0)
|
||||
this.text.y = Math.max(textHeight, option.height) / 2 - 10 + 5 * this.text.scaleY + (option.textY || 0) + index * 12 - textHeight / 2 + lineHeight / 2
|
||||
textGroup.add(this.text)
|
||||
})
|
||||
} else {
|
||||
this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX + (option.textX || 0)
|
||||
this.text.y = option.height / 2 - 10 + 5 * this.text.scaleY + (option.textY || 0)
|
||||
textGroup.add(this.text)
|
||||
}
|
||||
}
|
||||
|
||||
if (option.bgImage) {
|
||||
var ratio = SCALE_RATIO
|
||||
let bitmap = new Bitmap(option.bgImage[0])
|
||||
bitmap.scaleX = ratio
|
||||
bitmap.scaleY = ratio
|
||||
bitmap.width = option.bgImage[1]
|
||||
bitmap.height = option.bgImage[2]
|
||||
bitmap.x = (this.width - bitmap.width) / 2
|
||||
bitmap.y = (this.height - bitmap.height) / 2
|
||||
this.add(bitmap)
|
||||
} else if (option.bgColor || option.borderColor) {
|
||||
this.roundedRect = new RoundedRect(option.width, option.autoHeight ? Math.max(textHeight, option.height) : option.height, option.borderRadius, {
|
||||
strokeStyle: option.borderColor || 'black',
|
||||
fillStyle: option.bgColor || '#F5F5F5'
|
||||
})
|
||||
this.add(this.roundedRect)
|
||||
}
|
||||
|
||||
if (option.image) {
|
||||
var ratio = SCALE_RATIO
|
||||
let bitmap = new Bitmap(option.image[0])
|
||||
bitmap.scaleX = ratio
|
||||
bitmap.scaleY = ratio
|
||||
bitmap.width = option.image[1]
|
||||
bitmap.height = option.image[2]
|
||||
bitmap.x = (this.width - bitmap.width) / 2
|
||||
bitmap.y = (this.height - bitmap.height) / 2
|
||||
this.add(bitmap)
|
||||
}
|
||||
|
||||
if (textGroup) {
|
||||
this.add(textGroup)
|
||||
}
|
||||
}
|
||||
|
||||
stringSplit (str, len) {
|
||||
let arr = [],
|
||||
offset = 0,
|
||||
char_length = 0
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
let son_str = str.charAt(i)
|
||||
encodeURI(son_str).length > 2 ? char_length += 1 : char_length += 0.5
|
||||
if (char_length >= len || (char_length < len && i === str.length - 1)) {
|
||||
let sub_len = char_length == len ? i + 1 : i
|
||||
arr.push(str.substr(offset, sub_len - offset + ((char_length < len && i === str.length - 1) ? 1 : 0)))
|
||||
offset = i + 1
|
||||
char_length = 0
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
}
|
||||
|
||||
export default Button
|
|
@ -0,0 +1,174 @@
|
|||
import DisplayObject from './display-object.js'
|
||||
|
||||
const assMap = {
|
||||
fillStyle: true,
|
||||
strokeStyle: true,
|
||||
lineWidth: true,
|
||||
lineCap: true,
|
||||
lineDashOffset: true,
|
||||
lineJoin: true,
|
||||
miterLimit: true
|
||||
}
|
||||
|
||||
class Graphics extends DisplayObject {
|
||||
constructor () {
|
||||
super()
|
||||
this.cmds = []
|
||||
this.currentGradient = null
|
||||
}
|
||||
|
||||
clearRect () {
|
||||
this.cmds.push(['clearRect', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
rect () {
|
||||
this.cmds.push(['rect', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
clear () {
|
||||
this.cmds.length = 0
|
||||
return this
|
||||
}
|
||||
|
||||
setLineDash () {
|
||||
this.cmds.push(['setLineDash', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
strokeRect () {
|
||||
this.cmds.push(['strokeRect', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
fillRect () {
|
||||
this.cmds.push(['fillRect', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
beginPath () {
|
||||
this.cmds.push(['beginPath', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
arc () {
|
||||
this.cmds.push(['arc', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
closePath () {
|
||||
this.cmds.push(['closePath', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
fillStyle () {
|
||||
this.cmds.push(['fillStyle', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
fill () {
|
||||
this.cmds.push(['fill', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
strokeStyle () {
|
||||
this.cmds.push(['strokeStyle', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
lineWidth () {
|
||||
this.cmds.push(['lineWidth', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
lineCap () {
|
||||
this.cmds.push(['lineCap', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
lineDashOffset () {
|
||||
this.cmds.push(['lineDashOffset', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
lineJoin () {
|
||||
this.cmds.push(['lineJoin', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
miterLimit () {
|
||||
this.cmds.push(['miterLimit', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
stroke () {
|
||||
this.cmds.push(['stroke', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
moveTo () {
|
||||
this.cmds.push(['moveTo', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
lineTo () {
|
||||
this.cmds.push(['lineTo', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
bezierCurveTo () {
|
||||
this.cmds.push(['bezierCurveTo', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
quadraticCurveTo () {
|
||||
this.cmds.push(['quadraticCurveTo', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
createRadialGradient () {
|
||||
this.cmds.push(['createRadialGradient', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
createLinearGradient () {
|
||||
this.cmds.push(['createLinearGradient', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
addColorStop () {
|
||||
this.cmds.push(['addColorStop', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
fillGradient () {
|
||||
this.cmds.push(['fillGradient'])
|
||||
return this
|
||||
}
|
||||
|
||||
arcTo () {
|
||||
this.cmds.push(['arcTo', arguments])
|
||||
return this
|
||||
}
|
||||
|
||||
render (ctx) {
|
||||
this.cmds.forEach(cmd => {
|
||||
const methodName = cmd[0]
|
||||
if (assMap[methodName]) {
|
||||
ctx[methodName] = cmd[1][0]
|
||||
} else if (methodName === 'addColorStop') {
|
||||
this.currentGradient && this.currentGradient.addColorStop(cmd[1][0], cmd[1][1])
|
||||
} else if (methodName === 'fillGradient') {
|
||||
ctx.fillStyle = this.currentGradient
|
||||
} else {
|
||||
let result = ctx[methodName].apply(ctx, Array.prototype.slice.call(cmd[1]))
|
||||
if (methodName === 'createRadialGradient' || methodName === 'createLinearGradient') {
|
||||
this.currentGradient = result
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Graphics
|
|
@ -0,0 +1,72 @@
|
|||
import DisplayObject from './display-object.js'
|
||||
|
||||
class Group extends DisplayObject {
|
||||
constructor (data) {
|
||||
super(data)
|
||||
this.children = []
|
||||
}
|
||||
|
||||
add (child) {
|
||||
const len = arguments.length
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const c = arguments[i]
|
||||
const parent = c.parent
|
||||
if(parent){
|
||||
parent.removeChildAt(parent.children.indexOf(c))
|
||||
}
|
||||
this.children.push(c)
|
||||
c.parent = this
|
||||
}
|
||||
}
|
||||
|
||||
addChildAt (child, index) {
|
||||
var par = child.parent
|
||||
par && par.removeChildAt(par.children.indexOf(child))
|
||||
child.parent = this
|
||||
this.children.splice(index, 0, child)
|
||||
}
|
||||
|
||||
removeChildAt (index) {
|
||||
var child = this.children[index]
|
||||
if (child) { child.parent = null }
|
||||
this.children.splice(index, 1)
|
||||
}
|
||||
|
||||
replace (current, pre) {
|
||||
const index = pre.parent.children.indexOf(pre)
|
||||
this.removeChildAt(index)
|
||||
this.addChildAt(current, index)
|
||||
}
|
||||
|
||||
remove (child) {
|
||||
const len = arguments.length
|
||||
let cLen = this.children.length
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
for (let j = 0; j < cLen; j++) {
|
||||
if (child.id === this.children[j].id) {
|
||||
child.parent = null
|
||||
this.children.splice(j, 1)
|
||||
j--
|
||||
cLen--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
empty () {
|
||||
this.children.forEach(child => {
|
||||
child.parent = null
|
||||
})
|
||||
this.children.length = 0
|
||||
}
|
||||
|
||||
destroy () {
|
||||
this.empty()
|
||||
// Stage does not have a parent
|
||||
this.parent && super.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
export default Group
|
|
@ -0,0 +1,60 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class ArrowPath extends Shape {
|
||||
constructor (path, option) {
|
||||
super()
|
||||
|
||||
this.path = path
|
||||
this.option = Object.assign({
|
||||
strokeStyle: 'black',
|
||||
lineWidth: 1,
|
||||
headSize: 10
|
||||
}, option)
|
||||
}
|
||||
|
||||
draw () {
|
||||
const path = this.path
|
||||
this.beginPath()
|
||||
const len = path.length
|
||||
if (len === 2) {
|
||||
this.drawArrow(path[0].x, path[0].y, path[1].x, path[1].y, 30)
|
||||
} else {
|
||||
this.moveTo(path[0].x, path[0].y)
|
||||
for (let i = 1; i < len - 1; i++) {
|
||||
this.lineTo(path[i].x, path[i].y)
|
||||
}
|
||||
this.drawArrow(path[len - 2].x, path[len - 2].y, path[len - 1].x, path[len - 1].y, 30)
|
||||
}
|
||||
|
||||
this.stroke()
|
||||
}
|
||||
|
||||
drawArrow (fromX, fromY, toX, toY, theta) {
|
||||
let angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
|
||||
angle1 = (angle + theta) * Math.PI / 180,
|
||||
angle2 = (angle - theta) * Math.PI / 180,
|
||||
hs = this.option.headSize,
|
||||
topX = hs * Math.cos(angle1),
|
||||
topY = hs * Math.sin(angle1),
|
||||
botX = hs * Math.cos(angle2),
|
||||
botY = hs * Math.sin(angle2)
|
||||
|
||||
let arrowX = fromX - topX,
|
||||
arrowY = fromY - topY
|
||||
|
||||
this.moveTo(arrowX, arrowY)
|
||||
this.moveTo(fromX, fromY)
|
||||
this.lineTo(toX, toY)
|
||||
arrowX = toX + topX
|
||||
arrowY = toY + topY
|
||||
this.moveTo(arrowX, arrowY)
|
||||
this.lineTo(toX, toY)
|
||||
arrowX = toX + botX
|
||||
arrowY = toY + botY
|
||||
this.lineTo(arrowX, arrowY)
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
}
|
||||
}
|
||||
|
||||
export default ArrowPath
|
|
@ -0,0 +1,31 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class Circle extends Shape {
|
||||
constructor (r, option) {
|
||||
super()
|
||||
this.option = option || {}
|
||||
this.r = r
|
||||
|
||||
this._dp = Math.PI * 2
|
||||
}
|
||||
|
||||
draw () {
|
||||
this.beginPath()
|
||||
this.arc(0, 0, this.r, 0, this._dp, false)
|
||||
|
||||
if (this.option.strokeStyle) {
|
||||
if (this.option.lineWidth !== undefined) {
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
}
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
this.stroke()
|
||||
}
|
||||
|
||||
if (this.option.fillStyle) {
|
||||
this.fillStyle(this.option.fillStyle)
|
||||
this.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Circle
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
import Shape from './shape'
|
||||
|
||||
class Ellipse extends Shape {
|
||||
constructor (width, height, option) {
|
||||
super()
|
||||
this.option = option || {}
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
|
||||
draw () {
|
||||
const w = this.width
|
||||
const h = this.height
|
||||
const k = 0.5522848
|
||||
const ox = (w / 2) * k
|
||||
const oy = (h / 2) * k
|
||||
const xe = w
|
||||
const ye = h
|
||||
const xm = w / 2
|
||||
const ym = h / 2
|
||||
|
||||
this.beginPath()
|
||||
this.moveTo(0, ym)
|
||||
this.bezierCurveTo(0, ym - oy, xm - ox, 0, xm, 0)
|
||||
this.bezierCurveTo(xm + ox, 0, xe, ym - oy, xe, ym)
|
||||
this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye)
|
||||
this.bezierCurveTo(xm - ox, ye, 0, ym + oy, 0, ym)
|
||||
|
||||
if (this.option.strokeStyle) {
|
||||
if (this.option.lineWidth !== undefined) {
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
}
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
this.stroke()
|
||||
}
|
||||
|
||||
if (this.option.fillStyle) {
|
||||
this.fillStyle(this.option.fillStyle)
|
||||
this.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Ellipse
|
|
@ -0,0 +1,72 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class EquilateralPolygon extends Shape {
|
||||
constructor (num, r, options) {
|
||||
super()
|
||||
|
||||
this.num = num
|
||||
this.r = r
|
||||
this.options = options || {}
|
||||
|
||||
this.vertex = []
|
||||
this.initVertex()
|
||||
}
|
||||
|
||||
initVertex () {
|
||||
this.vertex.length = []
|
||||
const num = this.num
|
||||
const r = this.r
|
||||
let i, startX, startY, newX, newY
|
||||
|
||||
if (num % 2 === 0) {
|
||||
startX = r * Math.cos(2 * Math.PI * 0 / num)
|
||||
startY = r * Math.sin(2 * Math.PI * 0 / num)
|
||||
|
||||
this.vertex.push([startX, startY])
|
||||
for (i = 1; i < num; i++) {
|
||||
newX = r * Math.cos(2 * Math.PI * i / num)
|
||||
newY = r * Math.sin(2 * Math.PI * i / num)
|
||||
|
||||
this.vertex.push([newX, newY])
|
||||
}
|
||||
} else {
|
||||
startX = r * Math.cos(2 * Math.PI * 0 / num - Math.PI / 2)
|
||||
startY = r * Math.sin(2 * Math.PI * 0 / num - Math.PI / 2)
|
||||
|
||||
this.vertex.push([startX, startY])
|
||||
for (i = 1; i < num; i++) {
|
||||
newX = r * Math.cos(2 * Math.PI * i / num - Math.PI / 2)
|
||||
newY = r * Math.sin(2 * Math.PI * i / num - Math.PI / 2)
|
||||
|
||||
this.vertex.push([newX, newY])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
draw () {
|
||||
this.beginPath()
|
||||
|
||||
this.moveTo(this.vertex[0][0], this.vertex[0][1])
|
||||
|
||||
for (let i = 1, len = this.vertex.length; i < len; i++) {
|
||||
this.lineTo(this.vertex[i][0], this.vertex[i][1])
|
||||
}
|
||||
this.closePath()
|
||||
|
||||
if (this.options.fillStyle) {
|
||||
this.fillStyle(this.options.fillStyle)
|
||||
this.fill()
|
||||
}
|
||||
|
||||
|
||||
if (this.options.strokeStyle) {
|
||||
this.strokeStyle(this.options.strokeStyle)
|
||||
if(typeof this.options.lineWidth === 'number'){
|
||||
this.lineWidth(this.options.lineWidth)
|
||||
}
|
||||
this.stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EquilateralPolygon
|
|
@ -0,0 +1,242 @@
|
|||
import parse from '../../base/path-parser.js'
|
||||
import Shape from './shape'
|
||||
import arcToBezier from '../../base/arc-to-bezier'
|
||||
|
||||
class Path extends Shape {
|
||||
constructor (d, option) {
|
||||
super()
|
||||
this.d = d
|
||||
|
||||
option = Object.assign({
|
||||
lineWidth: 1
|
||||
}, option)
|
||||
this.option = option
|
||||
}
|
||||
|
||||
draw () {
|
||||
const cmds = parse(this.d)
|
||||
|
||||
this.beginPath()
|
||||
// https://developer.mozilla.org/zh-CN/docs/Web/SVG/Tutorial/Paths
|
||||
// M = moveto
|
||||
// L = lineto
|
||||
// H = horizontal lineto
|
||||
// V = vertical lineto
|
||||
// C = curveto
|
||||
// S = smooth curveto
|
||||
// Q = quadratic Belzier curve
|
||||
// T = smooth quadratic Belzier curveto
|
||||
// A = elliptical Arc 暂时未实现,用贝塞尔拟合椭圆
|
||||
// Z = closepath
|
||||
// 以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位(从上一个点开始)。
|
||||
let preX,
|
||||
preY,
|
||||
curves,
|
||||
lastCurve
|
||||
|
||||
// 参考我的 pasition https://github.com/AlloyTeam/pasition/blob/master/src/index.js
|
||||
for (let j = 0, cmdLen = cmds.length; j < cmdLen; j++) {
|
||||
let item = cmds[j]
|
||||
let action = item[0]
|
||||
let preItem = cmds[j - 1]
|
||||
|
||||
switch (action) {
|
||||
case 'M':
|
||||
preX = item[1]
|
||||
preY = item[2]
|
||||
this.moveTo(preX, preY)
|
||||
break
|
||||
case 'L':
|
||||
preX = item[1]
|
||||
preY = item[2]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'H':
|
||||
preX = item[1]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'V':
|
||||
preY = item[1]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'C':
|
||||
preX = item[5]
|
||||
preY = item[6]
|
||||
this.bezierCurveTo(item[1], item[2], item[3], item[4], preX, preY)
|
||||
break
|
||||
case 'S':
|
||||
|
||||
if (preItem[0] === 'C' || preItem[0] === 'c') {
|
||||
this.bezierCurveTo( preX + preItem[5] - preItem[3], preY + preItem[6] - preItem[4], item[1], item[2], item[3], item[4])
|
||||
} else if (preItem[0] === 'S' || preItem[0] === 's') {
|
||||
this.bezierCurveTo( preX + preItem[3] - preItem[1], preY + preItem[4] - preItem[2], item[1], item[2], item[3], item[4])
|
||||
}
|
||||
preX = item[3]
|
||||
preY = item[4]
|
||||
break
|
||||
|
||||
case 'Q':
|
||||
preX = item[3]
|
||||
preY = item[4]
|
||||
this.quadraticCurveTo(item[1], item[2], preX, preY)
|
||||
break
|
||||
|
||||
case 'm':
|
||||
preX += item[1]
|
||||
preY += item[2]
|
||||
this.moveTo(preX, preY)
|
||||
break
|
||||
case 'l':
|
||||
preX += item[1]
|
||||
preY += item[2]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'h':
|
||||
preX += item[1]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'v':
|
||||
preY += item[1]
|
||||
this.lineTo(preX, preY)
|
||||
break
|
||||
case 'c':
|
||||
this.bezierCurveTo(preX + item[1], preY + item[2], preX + item[3], preY + item[4], preX + item[5], preY + item[6])
|
||||
preX = preX + item[5]
|
||||
preY = preY + item[6]
|
||||
break
|
||||
case 's':
|
||||
if (preItem[0] === 'C' || preItem[0] === 'c') {
|
||||
this.bezierCurveTo( preX + preItem[5] - preItem[3], preY + preItem[6] - preItem[4], preX + item[1], preY + item[2], preX + item[3], preY + item[4])
|
||||
} else if (preItem[0] === 'S' || preItem[0] === 's') {
|
||||
this.bezierCurveTo( preX + preItem[3] - preItem[1], preY + preItem[4] - preItem[2], preX + item[1], preY + item[2], preX + item[3], preY + item[4])
|
||||
}
|
||||
|
||||
preX += item[3]
|
||||
preY += item[4]
|
||||
break
|
||||
case 'q':
|
||||
|
||||
this.quadraticCurveTo(preX + item[1], preY + item[2], item[3] + preX, item[4] + preY)
|
||||
preX += item[3]
|
||||
preY += item[4]
|
||||
break
|
||||
case 'Z':
|
||||
this.closePath()
|
||||
break
|
||||
case 'z':
|
||||
this.closePath()
|
||||
break
|
||||
|
||||
case 'a':
|
||||
curves = arcToBezier({
|
||||
rx: item[1],
|
||||
ry: item[2],
|
||||
px: preX,
|
||||
py: preY,
|
||||
xAxisRotation: item[3],
|
||||
largeArcFlag: item[4],
|
||||
sweepFlag: item[5],
|
||||
cx: preX + item[6],
|
||||
cy: preX + item[7]
|
||||
})
|
||||
lastCurve = curves[curves.length - 1]
|
||||
|
||||
curves.forEach((curve, index) => {
|
||||
if (index === 0) {
|
||||
this.moveTo(preX, preY)
|
||||
this.bezierCurveTo( curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y)
|
||||
} else {
|
||||
//curves[index - 1].x, curves[index - 1].y,
|
||||
this.bezierCurveTo(curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y)
|
||||
}
|
||||
})
|
||||
|
||||
preX = lastCurve.x
|
||||
preY = lastCurve.y
|
||||
|
||||
break
|
||||
|
||||
case 'A':
|
||||
|
||||
curves = arcToBezier({
|
||||
rx: item[1],
|
||||
ry: item[2],
|
||||
px: preX,
|
||||
py: preY,
|
||||
xAxisRotation: item[3],
|
||||
largeArcFlag: item[4],
|
||||
sweepFlag: item[5],
|
||||
cx: item[6],
|
||||
cy: item[7]
|
||||
})
|
||||
lastCurve = curves[curves.length - 1]
|
||||
|
||||
curves.forEach((curve, index) => {
|
||||
if (index === 0) {
|
||||
this.moveTo(preX, preY)
|
||||
this.bezierCurveTo( curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y)
|
||||
} else {
|
||||
//curves[index - 1].x, curves[index - 1].y
|
||||
this.bezierCurveTo( curve.x1, curve.y1, curve.x2, curve.y2, curve.x, curve.y)
|
||||
}
|
||||
})
|
||||
|
||||
preX = lastCurve.x
|
||||
preY = lastCurve.y
|
||||
|
||||
break
|
||||
|
||||
case 'T':
|
||||
|
||||
if (preItem[0] === 'Q' || preItem[0] === 'q') {
|
||||
preCX = preX + preItem[3] - preItem[1]
|
||||
preCY = preY + preItem[4] - preItem[2]
|
||||
this.quadraticCurveTo(preX, preY, preCX, preCY, item[1], item[2])
|
||||
} else if (preItem[0] === 'T' || preItem[0] === 't') {
|
||||
this.quadraticCurveTo(preX, preY, preX + preX - preCX, preY + preY - preCY, item[1], item[2])
|
||||
preCX = preX + preX - preCX
|
||||
preCY = preY + preY - preCY
|
||||
}
|
||||
|
||||
preX = item[1]
|
||||
preY = item[2]
|
||||
break
|
||||
|
||||
case 't':
|
||||
if (preItem[0] === 'Q' || preItem[0] === 'q') {
|
||||
preCX = preX + preItem[3] - preItem[1]
|
||||
preCY = preY + preItem[4] - preItem[2]
|
||||
this.quadraticCurveTo(preX, preY, preCX, preCY, preX + item[1], preY + item[2])
|
||||
} else if (preItem[0] === 'T' || preItem[0] === 't') {
|
||||
this.quadraticCurveTo(preX, preY, preX + preX - preCX, preY + preY - preCY, preX + item[1], preY + item[2])
|
||||
preCX = preX + preX - preCX
|
||||
preCY = preY + preY - preCY
|
||||
}
|
||||
|
||||
preX += item[1]
|
||||
preY += item[2]
|
||||
break
|
||||
}
|
||||
}
|
||||
if (this.option.fillStyle) {
|
||||
this.fillStyle(this.option.fillStyle)
|
||||
this.fill()
|
||||
}
|
||||
|
||||
if (this.option.strokeStyle) {
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
this.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
clone(){
|
||||
return new Path(this.d,{
|
||||
lineWidth:this.option.lineWidth,
|
||||
strokeStyle:this.option.strokeStyle,
|
||||
fillStyle:this.option.fillStyle
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Path
|
|
@ -0,0 +1,40 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class Polygon extends Shape {
|
||||
constructor (vertex, options) {
|
||||
super()
|
||||
|
||||
this.vertex = vertex || []
|
||||
this.options = options || {}
|
||||
this.strokeColor = this.options.strokeColor
|
||||
this.fillColor = this.options.fillColor
|
||||
}
|
||||
|
||||
draw () {
|
||||
this.clear().beginPath()
|
||||
this.strokeStyle(this.strokeColor)
|
||||
this.moveTo(this.vertex[0][0], this.vertex[0][1])
|
||||
|
||||
for (let i = 1, len = this.vertex.length; i < len; i++) {
|
||||
this.lineTo(this.vertex[i][0], this.vertex[i][1])
|
||||
}
|
||||
this.closePath()
|
||||
// 路径闭合
|
||||
// if (this.options.strokeStyle) {
|
||||
// this.strokeStyle = strokeStyle;
|
||||
// this.lineWidth(this.options.width);
|
||||
// this.lineJoin('round');
|
||||
// this.stroke();
|
||||
// }
|
||||
if (this.strokeColor) {
|
||||
this.strokeStyle(this.strokeColor)
|
||||
this.stroke()
|
||||
}
|
||||
if (this.fillColor) {
|
||||
this.fillStyle(this.fillColor)
|
||||
this.fill()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Polygon
|
|
@ -0,0 +1,28 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class Rect extends Shape {
|
||||
constructor (width, height, option) {
|
||||
super()
|
||||
|
||||
this.width = width
|
||||
this.height = height
|
||||
this.option = option || {}
|
||||
}
|
||||
|
||||
draw () {
|
||||
if (this.option.fillStyle) {
|
||||
this.fillStyle(this.option.fillStyle)
|
||||
this.fillRect(0, 0, this.width, this.height)
|
||||
}
|
||||
|
||||
if (this.option.strokeStyle) {
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
if(typeof this.option.lineWidth === 'number'){
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
}
|
||||
this.strokeRect(0, 0, this.width, this.height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Rect
|
|
@ -0,0 +1,75 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class RoundedRect extends Shape {
|
||||
constructor (width, height, r, option) {
|
||||
super()
|
||||
this.option = Object.assign({
|
||||
lineWidth: 1,
|
||||
lt: true,
|
||||
rt: true,
|
||||
lb: true,
|
||||
rb: true
|
||||
}, option)
|
||||
this.r = r || 0
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
|
||||
draw () {
|
||||
const width = this.width,
|
||||
height = this.height,
|
||||
r = this.r
|
||||
|
||||
const ax = r,
|
||||
ay = 0,
|
||||
bx = width,
|
||||
by = 0,
|
||||
cx = width,
|
||||
cy = height,
|
||||
dx = 0,
|
||||
dy = height,
|
||||
ex = 0,
|
||||
ey = 0
|
||||
|
||||
this.beginPath()
|
||||
|
||||
this.moveTo(ax, ay)
|
||||
if (this.option.rt) {
|
||||
this.arcTo(bx, by, cx, cy, r)
|
||||
} else {
|
||||
this.lineTo(bx, by)
|
||||
}
|
||||
|
||||
if (this.option.rb) {
|
||||
this.arcTo(cx, cy, dx, dy, r)
|
||||
} else {
|
||||
this.lineTo(cx, cy)
|
||||
}
|
||||
|
||||
if (this.option.lb) {
|
||||
this.arcTo(dx, dy, ex, ey, r)
|
||||
} else {
|
||||
this.lineTo(dx, dy)
|
||||
}
|
||||
|
||||
if (this.option.lt) {
|
||||
this.arcTo(ex, ey, ax, ay, r)
|
||||
} else {
|
||||
this.lineTo(ex, ey)
|
||||
}
|
||||
|
||||
if (this.option.fillStyle) {
|
||||
this.closePath()
|
||||
this.fillStyle(this.option.fillStyle)
|
||||
this.fill()
|
||||
}
|
||||
|
||||
if (this.option.strokeStyle) {
|
||||
this.lineWidth(this.option.lineWidth)
|
||||
this.strokeStyle(this.option.strokeStyle)
|
||||
this.stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default RoundedRect
|
|
@ -0,0 +1,26 @@
|
|||
import Shape from './shape'
|
||||
|
||||
class Sector extends Shape {
|
||||
constructor (r, from, to, option) {
|
||||
super()
|
||||
|
||||
this.option = option || {}
|
||||
this.r = r
|
||||
this.from = from
|
||||
this.to = to
|
||||
}
|
||||
|
||||
draw () {
|
||||
this.beginPath()
|
||||
.moveTo(0, 0)
|
||||
.arc(0, 0, this.r, this.from, this.to)
|
||||
.closePath()
|
||||
.fillStyle(this.option.fillStyle)
|
||||
.fill()
|
||||
.strokeStyle(this.option.strokeStyle)
|
||||
.lineWidth(this.option.lineWidth)
|
||||
.stroke()
|
||||
}
|
||||
}
|
||||
|
||||
export default Sector
|
|
@ -0,0 +1,19 @@
|
|||
import Graphics from '../graphics'
|
||||
|
||||
class Shape extends Graphics {
|
||||
// constructor() {
|
||||
// super()
|
||||
// }
|
||||
|
||||
draw () {
|
||||
|
||||
}
|
||||
|
||||
render (ctx) {
|
||||
this.clear()
|
||||
this.draw()
|
||||
super.render(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
export default Shape
|
|
@ -0,0 +1,152 @@
|
|||
import DisplayObject from './display-object'
|
||||
import util from '../../common/util'
|
||||
import Bitmap from './bitmap'
|
||||
|
||||
class Sprite extends DisplayObject {
|
||||
constructor (option) {
|
||||
super()
|
||||
this.option = option
|
||||
const len = this.option.imgs.length
|
||||
let count = 0
|
||||
const firstImg = this.option.imgs[0]
|
||||
this.imgMap = {}
|
||||
|
||||
if (util.isWeapp) {
|
||||
this.option.imgs.forEach(img => {
|
||||
util.getImageInWx(img, (result) => {
|
||||
this.imgMap[img] = result.img
|
||||
count++
|
||||
if (count === len) {
|
||||
this.img = this.imgMap[firstImg]
|
||||
this.rect = [0, 0, 0, 0]
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
} else {
|
||||
if (typeof firstImg === 'string') {
|
||||
const len = this.option.imgs.length
|
||||
let loadedCount = 0
|
||||
this.option.imgs.forEach(src => {
|
||||
if (Bitmap.cache[src]) {
|
||||
this.imgMap[src] = Bitmap.cache[src]
|
||||
loadedCount++
|
||||
if (loadedCount === len) {
|
||||
this.img = this.imgMap[firstImg]
|
||||
this.rect = [0, 0, 0, 0]
|
||||
}
|
||||
} else {
|
||||
const img = util.isWegame ? wx.createImage() : new window.Image()
|
||||
img.onload = () => {
|
||||
this.imgMap[src] = img
|
||||
loadedCount++
|
||||
if (loadedCount === len) {
|
||||
this.img = this.imgMap[firstImg]
|
||||
this.rect = [0, 0, 0, 0]
|
||||
}
|
||||
Bitmap.cache[src] = img
|
||||
}
|
||||
img.src = src
|
||||
}
|
||||
})
|
||||
} else if (firstImg instanceof Bitmap) {
|
||||
this.rect = [0, 0, 0, 0]
|
||||
this.img = firstImg.img
|
||||
} else {
|
||||
this.rect = [0, 0, 0, 0]
|
||||
this.img = firstImg
|
||||
}
|
||||
}
|
||||
|
||||
this.x = option.x || 0
|
||||
this.y = option.y || 0
|
||||
this.currentFrameIndex = 0
|
||||
this.animationFrameIndex = 0
|
||||
this.currentAnimation = option.currentAnimation || null
|
||||
|
||||
this.interval = 1e3 / option.framerate
|
||||
|
||||
this.paused = false
|
||||
this.animationEnd = option.animationEnd || function () {}
|
||||
if (this.currentAnimation) {
|
||||
if (option.playOnce) {
|
||||
this.gotoAndPlayOnce(this.currentAnimation)
|
||||
} else {
|
||||
this.gotoAndPlay(this.currentAnimation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
play () {
|
||||
this.paused = false
|
||||
}
|
||||
|
||||
pause () {
|
||||
this.paused = true
|
||||
}
|
||||
|
||||
reset () {
|
||||
this.currentFrameIndex = 0
|
||||
this.animationFrameIndex = 0
|
||||
}
|
||||
|
||||
updateFrame () {
|
||||
if (!this.paused) {
|
||||
let opt = this.option
|
||||
this.dt = Date.now() - this.startTime
|
||||
let frames = opt.animations[this.currentAnimation].frames
|
||||
const len = frames.length
|
||||
const index = Math.floor(this.dt / this.interval % len)
|
||||
this.rect = opt.frames[ frames[ index ] ]
|
||||
const rectLen = this.rect.length
|
||||
|
||||
rectLen > 4 && (this.originX = this.rect[2] * this.rect[4])
|
||||
rectLen > 5 && (this.originY = this.rect[3] * this.rect[5])
|
||||
if (rectLen > 6) {
|
||||
const img = this.option.imgs[this.rect[6]]
|
||||
this.img = typeof img === 'string' ? this.imgMap[img] : img
|
||||
}
|
||||
|
||||
if (index === len - 1 && (!this.endTime || Date.now() - this.endTime > this.interval)) {
|
||||
this.endTime = Date.now()
|
||||
this.animationEnd()
|
||||
if (this._willDestroy) {
|
||||
this.destroy()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gotoAndPlay (animation) {
|
||||
this.paused = false
|
||||
this.reset()
|
||||
this.currentAnimation = animation
|
||||
this.startTime = Date.now()
|
||||
}
|
||||
|
||||
gotoAndStop (animation) {
|
||||
this.reset()
|
||||
this.paused = true
|
||||
this.currentAnimation = animation
|
||||
var opt = this.option
|
||||
var frames = opt.animations[this.currentAnimation].frames
|
||||
this.rect = opt.frames[frames[this.animationFrameIndex]]
|
||||
const rect = this.rect
|
||||
this.width = rect[2]
|
||||
this.height = rect[3]
|
||||
const rectLen = rect.length
|
||||
rectLen > 4 && (this.originX = rect[2] * rect[4])
|
||||
rectLen > 5 && (this.originY = rect[3] * rect[5])
|
||||
if (rectLen > 6) {
|
||||
const img = this.option.imgs[rect[6]]
|
||||
this.img = typeof img === 'string' ? this.imgMap[img] : img
|
||||
}
|
||||
}
|
||||
|
||||
gotoAndPlayOnce (animation) {
|
||||
this.gotoAndPlay(animation)
|
||||
this._willDestroy = true
|
||||
}
|
||||
}
|
||||
|
||||
export default Sprite
|
|
@ -0,0 +1,294 @@
|
|||
import wegameCanvas from './wegame-canvas'
|
||||
import Group from './group.js'
|
||||
import Renderer from '../render/renderer.js'
|
||||
import HitRender from '../render/hit-render.js'
|
||||
import Event from '../base/event.js'
|
||||
import WeStage from './we-stage'
|
||||
import option from '../base/stage-propagation-tag'
|
||||
|
||||
class Stage extends Group {
|
||||
constructor (width, height, renderTo) {
|
||||
super()
|
||||
const len = arguments.length
|
||||
this.isWegame = typeof wx !== 'undefined' && wx.createCanvas
|
||||
this.moveDetectionInterval = 0
|
||||
if (len === 0) { // wegame
|
||||
this.canvas = wegameCanvas
|
||||
this.disableMoveDetection = true
|
||||
this.moveDetectionInterval = 500
|
||||
} else if (len === 4) { // weapp
|
||||
return new WeStage(arguments[0], arguments[1], arguments[2], arguments[3])
|
||||
} else {
|
||||
if (len === 1) {
|
||||
this.canvas = typeof width === 'string' ? document.querySelector(width) : width
|
||||
} else {
|
||||
this.renderTo = typeof renderTo === 'string' ? document.querySelector(renderTo) : renderTo
|
||||
if (this.renderTo.tagName === 'CANVAS') {
|
||||
this.canvas = this.renderTo
|
||||
this.canvas.width = width
|
||||
this.canvas.height = height
|
||||
} else {
|
||||
this.canvas = document.createElement('canvas')
|
||||
this.canvas.width = width
|
||||
this.canvas.height = height
|
||||
this.renderTo.appendChild(this.canvas)
|
||||
}
|
||||
}
|
||||
// get rect again when trigger onscroll onresize event!?
|
||||
this._boundingClientRect = this.canvas.getBoundingClientRect()
|
||||
|
||||
this.offset = this._getOffset(this.canvas)
|
||||
}
|
||||
this.renderer = new Renderer(this.canvas)
|
||||
if (this.isWegame) {
|
||||
wx.onTouchStart(evt => this._handleMouseDown(evt))
|
||||
|
||||
wx.onTouchMove(evt => this._handleMouseMove(evt))
|
||||
|
||||
wx.onTouchEnd(evt => this._handleMouseUp(evt))
|
||||
} else {
|
||||
this.canvas.addEventListener('click', evt => this._handleClick(evt))
|
||||
this.canvas.addEventListener('mousedown', evt => this._handleMouseDown(evt))
|
||||
this.canvas.addEventListener('mousemove', evt => this._handleMouseMove(evt))
|
||||
this.canvas.addEventListener('mouseup', evt => this._handleMouseUp(evt))
|
||||
this.canvas.addEventListener('mouseout', evt => this._handleMouseOut(evt))
|
||||
this.canvas.addEventListener('touchstart', evt => this._handleMouseDown(evt))
|
||||
this.canvas.addEventListener('touchmove', evt => this._handleMouseMove(evt))
|
||||
this.canvas.addEventListener('touchend', evt => this._handleMouseUp(evt))
|
||||
|
||||
this.canvas.addEventListener('dblclick', evt => this._handleDblClick(evt))
|
||||
// this.addEvent(this.canvas, "mousewheel", this._handleMouseWheel.bind(this));
|
||||
|
||||
document.addEventListener('contextmenu', evt => this._handleContextmenu(evt))
|
||||
}
|
||||
|
||||
this.borderTopWidth = 0
|
||||
this.borderLeftWidth = 0
|
||||
|
||||
this.hitAABB = false
|
||||
this._hitRender = new HitRender()
|
||||
|
||||
this._overObject = null
|
||||
|
||||
this._scaleX = 1
|
||||
this._scaleY = 1
|
||||
|
||||
this._mouseDownX = 0
|
||||
this._mouseDownY = 0
|
||||
|
||||
this._mouseUpX = 0
|
||||
this._mouseUpY = 0
|
||||
|
||||
this.willDragObject = null
|
||||
this.preStageX = null
|
||||
this.preStageY = null
|
||||
|
||||
this.width = this.canvas.width
|
||||
this.height = this.canvas.height
|
||||
|
||||
this.___instanceof = 'Stage'
|
||||
|
||||
this._moveDetectionTime = Date.now()
|
||||
}
|
||||
|
||||
_handleContextmenu (evt) {
|
||||
this._getObjectUnderPoint(evt)
|
||||
}
|
||||
|
||||
_handleDblClick (evt) {
|
||||
this._getObjectUnderPoint(evt)
|
||||
}
|
||||
|
||||
_handleClick (evt) {
|
||||
if (Math.abs(this._mouseDownX - this._mouseUpX) < 20 && Math.abs(this._mouseDownY - this._mouseUpY) < 20) {
|
||||
this._getObjectUnderPoint(evt)
|
||||
}
|
||||
}
|
||||
|
||||
_handleMouseDown (evt) {
|
||||
if (this.isWegame) {
|
||||
evt.type = 'touchstart'
|
||||
}
|
||||
this.offset = this._getOffset(this.canvas)
|
||||
let obj = this._getObjectUnderPoint(evt)
|
||||
this.willDragObject = obj
|
||||
this._mouseDownX = evt.stageX
|
||||
this._mouseDownY = evt.stageY
|
||||
this.preStageX = evt.stageX
|
||||
this.preStageY = evt.stageY
|
||||
}
|
||||
|
||||
scaleEventPoint (x, y) {
|
||||
this._scaleX = x
|
||||
this._scaleY = y
|
||||
}
|
||||
|
||||
_handleMouseUp (evt) {
|
||||
if (this.isWegame) {
|
||||
evt.type = 'touchend'
|
||||
}
|
||||
const obj = this._getObjectUnderPoint(evt)
|
||||
this._mouseUpX = evt.stageX
|
||||
this._mouseUpY = evt.stageY
|
||||
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
mockEvt.pureEvent = evt
|
||||
|
||||
this.willDragObject = null
|
||||
this.preStageX = null
|
||||
this.preStageY = null
|
||||
|
||||
if (obj && evt.type === 'touchend' && Math.abs(this._mouseDownX - this._mouseUpX) < 30 && Math.abs(this._mouseDownY - this._mouseUpY) < 30) {
|
||||
mockEvt.type = 'tap'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
}
|
||||
|
||||
_handleMouseOut (evt) {
|
||||
this._computeStageXY(evt)
|
||||
this.dispatchEvent({
|
||||
pureEvent: evt,
|
||||
type: 'mouseout',
|
||||
stageX: evt.stageX,
|
||||
stageY: evt.stageY
|
||||
})
|
||||
}
|
||||
|
||||
_handleMouseMove (evt) {
|
||||
if(Date.now() - this._moveDetectionTime < this.moveDetectionInterval){
|
||||
return
|
||||
}
|
||||
this._moveDetectionTime = Date.now()
|
||||
|
||||
if (this.isWegame) {
|
||||
evt.type = 'touchmove'
|
||||
}
|
||||
if (this.disableMoveDetection) return
|
||||
let obj = this._getObjectUnderPoint(evt)
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
mockEvt.pureEvent = evt
|
||||
|
||||
if (this.willDragObject) {
|
||||
mockEvt.type = 'drag'
|
||||
mockEvt.dx = mockEvt.stageX - this.preStageX
|
||||
mockEvt.dy = mockEvt.stageY - this.preStageY
|
||||
this.preStageX = mockEvt.stageX
|
||||
this.preStageY = mockEvt.stageY
|
||||
this.willDragObject.dispatchEvent(mockEvt)
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
if (this._overObject === null) {
|
||||
mockEvt.type = 'mouseover'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
this._overObject = obj
|
||||
this._setCursor(obj)
|
||||
} else {
|
||||
if (obj.id !== this._overObject.id) {
|
||||
this._overObject.dispatchEvent({
|
||||
pureEvent: evt,
|
||||
type: 'mouseout',
|
||||
stageX: evt.stageX,
|
||||
stageY: evt.stageY
|
||||
})
|
||||
mockEvt.type = 'mouseover'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
this._setCursor(obj)
|
||||
this._overObject = obj
|
||||
} else {
|
||||
mockEvt.type = 'mousemove'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
mockEvt.type = 'touchmove'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
}
|
||||
} else if (this._overObject) {
|
||||
mockEvt.type = 'mouseout'
|
||||
this._overObject.dispatchEvent(mockEvt)
|
||||
this._overObject = null
|
||||
this._setCursor({ cursor: 'default' })
|
||||
}
|
||||
}
|
||||
|
||||
_setCursor (obj) {
|
||||
if(!this.canvas.style){
|
||||
return
|
||||
}
|
||||
if (obj.cursor) {
|
||||
this.canvas.style.cursor = obj.cursor
|
||||
} else if (obj.parent) {
|
||||
this._setCursor(obj.parent)
|
||||
} else {
|
||||
this._setCursor({ cursor: 'default' })
|
||||
}
|
||||
}
|
||||
|
||||
_getObjectUnderPoint (evt) {
|
||||
this._computeStageXY(evt)
|
||||
if (this.hitAABB) {
|
||||
return this._hitRender.hitAABB(this, evt)
|
||||
} else {
|
||||
return this._hitRender.hitPixel(this, evt)
|
||||
}
|
||||
}
|
||||
|
||||
_computeStageXY (evt) {
|
||||
this._boundingClientRect = this.isWegame ? {left: 0, top: 0} : this.canvas.getBoundingClientRect()
|
||||
if (evt.touches || evt.changedTouches) {
|
||||
const firstTouch = evt.touches[0] || evt.changedTouches[0]
|
||||
if (firstTouch) {
|
||||
evt.stageX = (firstTouch.pageX - this.offset[0]) / this._scaleX
|
||||
evt.stageY = (firstTouch.pageY - this.offset[1]) / this._scaleY
|
||||
}
|
||||
} else {
|
||||
evt.stageX = (evt.clientX - this._boundingClientRect.left - this.borderLeftWidth) / this._scaleX
|
||||
evt.stageY = (evt.clientY - this._boundingClientRect.top - this.borderTopWidth) / this._scaleY
|
||||
}
|
||||
}
|
||||
|
||||
_getOffset (el) {
|
||||
if (this.isWegame) {
|
||||
return [0, 0]
|
||||
}
|
||||
let _t = 0,
|
||||
_l = 0
|
||||
if (document.documentElement.getBoundingClientRect && el.getBoundingClientRect) {
|
||||
let box = el.getBoundingClientRect()
|
||||
_l = box.left
|
||||
_t = box.top
|
||||
} else {
|
||||
while (el.offsetParent) {
|
||||
_t += el.offsetTop
|
||||
_l += el.offsetLeft
|
||||
el = el.offsetParent
|
||||
}
|
||||
return [_l, _t]
|
||||
}
|
||||
return [_l + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft), _t + Math.max(document.documentElement.scrollTop, document.body.scrollTop)]
|
||||
}
|
||||
|
||||
update () {
|
||||
this.renderer.update(this)
|
||||
}
|
||||
|
||||
on (type, fn) {
|
||||
this.canvas.addEventListener(type, (evt) => {
|
||||
if(!option.stagePropagationStopped[type]){
|
||||
this._computeStageXY(evt)
|
||||
fn(evt)
|
||||
}
|
||||
option.stagePropagationStopped[type] = false
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
off (type, fn) {
|
||||
this.canvas.removeEventListener(type, fn)
|
||||
}
|
||||
}
|
||||
|
||||
export default Stage
|
|
@ -0,0 +1,38 @@
|
|||
import DisplayObject from './display-object'
|
||||
import util from '../../common/util'
|
||||
|
||||
let measureCtx
|
||||
|
||||
if (util.isWeapp) {
|
||||
measureCtx = wx.createCanvasContext('measure0')
|
||||
} else if (typeof document !== 'undefined') {
|
||||
measureCtx = document.createElement('canvas').getContext('2d')
|
||||
}
|
||||
|
||||
class Text extends DisplayObject {
|
||||
constructor (text, option) {
|
||||
super()
|
||||
|
||||
this.text = text
|
||||
option = option || {}
|
||||
this.font = option.font || '10px sans-serif'
|
||||
this.color = option.color || 'black'
|
||||
this.textAlign = option.textAlign || 'left'
|
||||
this.baseline = option.baseline || 'top'
|
||||
}
|
||||
|
||||
getWidth () {
|
||||
if (!measureCtx) {
|
||||
if (util.isWegame) {
|
||||
measureCtx = wx.createCanvas().getContext('2d')
|
||||
}
|
||||
}
|
||||
|
||||
if (this.font) {
|
||||
measureCtx.font = this.font
|
||||
}
|
||||
return measureCtx.measureText(this.text).width
|
||||
}
|
||||
}
|
||||
|
||||
export default Text
|
|
@ -0,0 +1,147 @@
|
|||
import Group from './group.js'
|
||||
import Renderer from '../render/renderer.js'
|
||||
import WxHitRender from '../render/wx-hit-render.js'
|
||||
import Event from '../base/event.js'
|
||||
|
||||
class WeStage extends Group {
|
||||
constructor (width, height, id, page) {
|
||||
super()
|
||||
|
||||
const component = page.selectComponent('#' + id)
|
||||
component.setData({
|
||||
width,
|
||||
height
|
||||
})
|
||||
component.stage = this
|
||||
const canvasId = component.getCaxCanvasId()
|
||||
|
||||
const ctx = wx.createCanvasContext(canvasId, component)
|
||||
const hitCtx = wx.createCanvasContext(canvasId + 'Hit', component)
|
||||
this.renderer = new Renderer(ctx, width, height)
|
||||
this._hitRender = new WxHitRender(hitCtx, component, canvasId)
|
||||
this._overObject = null
|
||||
this.ctx = ctx
|
||||
this.hitAABB = true
|
||||
this.width = width
|
||||
this.height = height
|
||||
}
|
||||
|
||||
touchStartHandler (evt) {
|
||||
const p1 = evt.changedTouches[0]
|
||||
|
||||
evt.stageX = Math.round(p1.x * this.scaleX);
|
||||
evt.stageY = Math.round(p1.y * this.scaleY);
|
||||
|
||||
this._getObjectUnderPoint(evt, (obj) => {
|
||||
this.willDragObject = obj
|
||||
this._mouseDownX = evt.stageX
|
||||
this._mouseDownY = evt.stageY
|
||||
this.preStageX = evt.stageX
|
||||
this.preStageY = evt.stageY
|
||||
})
|
||||
}
|
||||
|
||||
touchMoveHandler (evt) {
|
||||
const p1 = evt.changedTouches[0]
|
||||
|
||||
evt.stageX = Math.round(p1.x * this.scaleX);
|
||||
evt.stageY = Math.round(p1.y * this.scaleY);
|
||||
|
||||
this._getObjectUnderPoint(evt, (obj) => {
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
mockEvt.pureEvent = evt
|
||||
|
||||
if (this.willDragObject) {
|
||||
mockEvt.type = 'drag'
|
||||
mockEvt.dx = mockEvt.stageX - this.preStageX
|
||||
mockEvt.dy = mockEvt.stageY - this.preStageY
|
||||
this.preStageX = mockEvt.stageX
|
||||
this.preStageY = mockEvt.stageY
|
||||
this.willDragObject.dispatchEvent(mockEvt)
|
||||
}
|
||||
|
||||
if (obj) {
|
||||
if (this._overObject === null) {
|
||||
this._overObject = obj
|
||||
} else {
|
||||
if (obj.id !== this._overObject.id) {
|
||||
this._overObject = obj
|
||||
} else {
|
||||
mockEvt.type = 'touchmove'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
}
|
||||
} else if (this._overObject) {
|
||||
this._overObject = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
touchEndHandler (evt) {
|
||||
const p1 = evt.changedTouches[0]
|
||||
|
||||
evt.stageX = Math.round(p1.x * this.scaleX);
|
||||
evt.stageY = Math.round(p1.y * this.scaleY);
|
||||
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
|
||||
mockEvt.pureEvent = evt
|
||||
|
||||
this._getObjectUnderPoint(evt, (obj) => {
|
||||
this._mouseUpX = evt.stageX
|
||||
this._mouseUpY = evt.stageY
|
||||
|
||||
this.willDragObject = null
|
||||
this.preStageX = null
|
||||
this.preStageY = null
|
||||
|
||||
if (obj && Math.abs(this._mouseDownX - this._mouseUpX) < 30 && Math.abs(this._mouseDownY - this._mouseUpY) < 30) {
|
||||
mockEvt.type = 'tap'
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
_handleMouseOut (evt) {
|
||||
this.dispatchEvent({
|
||||
pureEvent: evt,
|
||||
type: 'mouseout',
|
||||
stageX: evt.stageX,
|
||||
stageY: evt.stageY
|
||||
})
|
||||
}
|
||||
|
||||
_getObjectUnderPoint (evt, cb) {
|
||||
const list = this.renderer.getHitRenderList(this)
|
||||
if (this.hitAABB) {
|
||||
return this._hitRender.hitAABB(list, evt, cb)
|
||||
} else {
|
||||
this._hitRender.clear()
|
||||
this._hitRender.hit(list, evt, cb, list.length - 1)
|
||||
}
|
||||
}
|
||||
|
||||
on(type, cb) {
|
||||
switch (type) {
|
||||
case 'touchstart':
|
||||
this.touchStart = cb
|
||||
break
|
||||
case 'touchmove':
|
||||
this.touchMove = cb
|
||||
break
|
||||
case 'touchend':
|
||||
this.touchEnd = cb
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
update () {
|
||||
this.renderer.update(this)
|
||||
}
|
||||
}
|
||||
|
||||
export default WeStage
|
|
@ -0,0 +1,11 @@
|
|||
let wegameCanvas = null
|
||||
if (typeof wx !== 'undefined') {
|
||||
// 在开放数据域的环境下,用`wx.getSharedCanvas`创建canvas
|
||||
if (wx.getSharedCanvas) {
|
||||
wegameCanvas = wx.getSharedCanvas()
|
||||
} else if (wx.createCanvas) {
|
||||
wegameCanvas = wx.createCanvas()
|
||||
}
|
||||
}
|
||||
|
||||
export default wegameCanvas
|
|
@ -0,0 +1,29 @@
|
|||
## Interface design reference
|
||||
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
|
||||
* http://www.runoob.com/cssref/css3-pr-filter.html
|
||||
* https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function
|
||||
|
||||
## Usage
|
||||
|
||||
``` js
|
||||
const bitmap = new cax.Bitmap(img)
|
||||
bitmap.filter('brightness(0.5)')
|
||||
|
||||
//or filter rect of bitmap
|
||||
//bitmap.filter('brightness(0.5)'), { x: 0, y: 0, width: 80, height: 80 }
|
||||
```
|
||||
|
||||
## Todo
|
||||
|
||||
horizontalFlip 和 verticalFlip 来制作镜像 spritesheet
|
||||
|
||||
``` js
|
||||
new cax.Sprite({
|
||||
imgs:[bitmap.flipX()]
|
||||
})
|
||||
|
||||
//bitmap.flipX()
|
||||
//flipX return的就是 this.cacheCanvas
|
||||
//bitmap.filpY()
|
||||
```
|
|
@ -0,0 +1,112 @@
|
|||
import { createImageData } from './create-image-data'
|
||||
|
||||
export function blur (pixels, diameter) {
|
||||
diameter = Math.abs(diameter)
|
||||
if (diameter <= 1) return pixels
|
||||
var radius = diameter / 2
|
||||
var len = Math.ceil(diameter) + (1 - (Math.ceil(diameter) % 2))
|
||||
var weights = new Float32Array(len)
|
||||
var rho = (radius + 0.5) / 3
|
||||
var rhoSq = rho * rho
|
||||
var gaussianFactor = 1 / Math.sqrt(2 * Math.PI * rhoSq)
|
||||
var rhoFactor = -1 / (2 * rho * rho)
|
||||
var wsum = 0
|
||||
var middle = Math.floor(len / 2)
|
||||
for (var i = 0; i < len; i++) {
|
||||
var x = i - middle
|
||||
var gx = gaussianFactor * Math.exp(x * x * rhoFactor)
|
||||
weights[i] = gx
|
||||
wsum += gx
|
||||
}
|
||||
for (var i = 0; i < weights.length; i++) {
|
||||
weights[i] /= wsum
|
||||
}
|
||||
return separableConvolve(pixels, weights, weights, false)
|
||||
}
|
||||
|
||||
function separableConvolve (pixels, horizWeights, vertWeights, opaque) {
|
||||
return horizontalConvolve(
|
||||
verticalConvolve(pixels, vertWeights, opaque),
|
||||
horizWeights, opaque
|
||||
)
|
||||
}
|
||||
|
||||
function horizontalConvolve (pixels, weightsVector, opaque) {
|
||||
var side = weightsVector.length
|
||||
var halfSide = Math.floor(side / 2)
|
||||
|
||||
var src = pixels.data
|
||||
var sw = pixels.width
|
||||
var sh = pixels.height
|
||||
|
||||
var w = sw
|
||||
var h = sh
|
||||
var output = createImageData(w, h)
|
||||
var dst = output.data
|
||||
|
||||
var alphaFac = opaque ? 1 : 0
|
||||
|
||||
for (var y = 0; y < h; y++) {
|
||||
for (var x = 0; x < w; x++) {
|
||||
var sy = y
|
||||
var sx = x
|
||||
var dstOff = (y * w + x) * 4
|
||||
var r = 0, g = 0, b = 0, a = 0
|
||||
for (var cx = 0; cx < side; cx++) {
|
||||
var scy = sy
|
||||
var scx = Math.min(sw - 1, Math.max(0, sx + cx - halfSide))
|
||||
var srcOff = (scy * sw + scx) * 4
|
||||
var wt = weightsVector[cx]
|
||||
r += src[srcOff] * wt
|
||||
g += src[srcOff + 1] * wt
|
||||
b += src[srcOff + 2] * wt
|
||||
a += src[srcOff + 3] * wt
|
||||
}
|
||||
dst[dstOff] = r
|
||||
dst[dstOff + 1] = g
|
||||
dst[dstOff + 2] = b
|
||||
dst[dstOff + 3] = a + alphaFac * (255 - a)
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
function verticalConvolve (pixels, weightsVector, opaque) {
|
||||
var side = weightsVector.length
|
||||
var halfSide = Math.floor(side / 2)
|
||||
|
||||
var src = pixels.data
|
||||
var sw = pixels.width
|
||||
var sh = pixels.height
|
||||
|
||||
var w = sw
|
||||
var h = sh
|
||||
var output = createImageData(w, h)
|
||||
var dst = output.data
|
||||
|
||||
var alphaFac = opaque ? 1 : 0
|
||||
|
||||
for (var y = 0; y < h; y++) {
|
||||
for (var x = 0; x < w; x++) {
|
||||
var sy = y
|
||||
var sx = x
|
||||
var dstOff = (y * w + x) * 4
|
||||
var r = 0, g = 0, b = 0, a = 0
|
||||
for (var cy = 0; cy < side; cy++) {
|
||||
var scy = Math.min(sh - 1, Math.max(0, sy + cy - halfSide))
|
||||
var scx = sx
|
||||
var srcOff = (scy * sw + scx) * 4
|
||||
var wt = weightsVector[cy]
|
||||
r += src[srcOff] * wt
|
||||
g += src[srcOff + 1] * wt
|
||||
b += src[srcOff + 2] * wt
|
||||
a += src[srcOff + 3] * wt
|
||||
}
|
||||
dst[dstOff] = r
|
||||
dst[dstOff + 1] = g
|
||||
dst[dstOff + 2] = b
|
||||
dst[dstOff + 3] = a + alphaFac * (255 - a)
|
||||
}
|
||||
}
|
||||
return output
|
||||
};
|
|
@ -0,0 +1,10 @@
|
|||
export function brightness (pixels, adjustment) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
data[i] += adjustment
|
||||
data[i + 1] += adjustment
|
||||
data[i + 2] += adjustment
|
||||
}
|
||||
return pixels
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
export function colorize (pixels, option) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
const hex = (option.color.charAt(0) === '#') ? option.color.substr(1) : option.color
|
||||
const colorRGB = {
|
||||
r: parseInt(hex.substr(0, 2), 16),
|
||||
g: parseInt(hex.substr(2, 2), 16),
|
||||
b: parseInt(hex.substr(4, 2), 16)
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
data[i] -= (data[i] - colorRGB.r) * (option.amount)
|
||||
data[i + 1] -= (data[i + 1] - colorRGB.g) * (option.amount)
|
||||
data[i + 2] -= (data[i + 2] - colorRGB.b) * (option.amount)
|
||||
}
|
||||
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
export function contrast (pixels, contrast) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
const factor = (259 * (contrast + 255)) / (255 * (259 - contrast))
|
||||
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
data[i] = factor * (data[i] - 128) + 128
|
||||
data[i + 1] = factor * (data[i + 1] - 128) + 128
|
||||
data[i + 2] = factor * (data[i + 2] - 128) + 128
|
||||
}
|
||||
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
let tmpCtx = null
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
tmpCtx = document.createElement('canvas').getContext('2d')
|
||||
} else if (typeof wx !== 'undefined' && wx.createCanvas) {
|
||||
tmpCtx = wx.createCanvas().getContext('2d')
|
||||
}
|
||||
|
||||
export function createImageData (w, h) {
|
||||
return tmpCtx.createImageData(w, h)
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
export function gamma (pixels, adjustment) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
data[i] = Math.pow(data[i] / 255, adjustment) * 255
|
||||
data[i + 1] = Math.pow(data[i + 1] / 255, adjustment) * 255
|
||||
data[i + 2] = Math.pow(data[i + 2] / 255, adjustment) * 255
|
||||
}
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
export function grayscale (pixels, adjustment) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
let r = data[i]
|
||||
let g = data[i + 1]
|
||||
let b = data[i + 2]
|
||||
|
||||
// CIE luminance for the RGB
|
||||
// The human eye is bad at seeing red and blue, so we de-emphasize them.
|
||||
let v = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
||||
data[i] = r + (v - r) * adjustment
|
||||
data[i + 1] = g + (v - g) * adjustment
|
||||
data[i + 2] = b + (v - b) * adjustment
|
||||
}
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
import { invert } from './invert'
|
||||
import { blur } from './blur'
|
||||
import { brightness } from './brightness'
|
||||
import { contrast } from './contrast'
|
||||
import { grayscale } from './grayscale'
|
||||
import { sepia } from './sepia'
|
||||
import { threshold } from './threshold'
|
||||
import { gamma } from './gamma'
|
||||
import { colorize } from './colorize'
|
||||
|
||||
export function filter (pixels, name) {
|
||||
if (typeof name === 'string') {
|
||||
let type = name.split('(')[0]
|
||||
let num = getNumber(name)
|
||||
switch (type) {
|
||||
case 'invert':
|
||||
return invert(pixels, num)
|
||||
case 'brightness':
|
||||
return brightness(pixels, -255 + num * 255)
|
||||
case 'blur':
|
||||
return blur(pixels, num)
|
||||
case 'contrast':
|
||||
return contrast(pixels, -255 + num * 255)
|
||||
case 'grayscale':
|
||||
return grayscale(pixels, num)
|
||||
case 'sepia':
|
||||
return sepia(pixels, num)
|
||||
case 'threshold':
|
||||
return threshold(pixels, num)
|
||||
case 'gamma':
|
||||
return gamma(pixels, num)
|
||||
}
|
||||
} else {
|
||||
switch (name.type) {
|
||||
case 'colorize':
|
||||
return colorize(pixels, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNumber (str) {
|
||||
str = str.replace(/(invert)|(brightness)|(blur)|(contrast)|(grayscale)|(sepia)|(threshold)|(gamma)?\(/g, '').replace(')', '')
|
||||
if (str.indexOf('%') !== -1) {
|
||||
return Number(str.replace('%', '')) / 100
|
||||
} else if (str.indexOf('px') !== -1) {
|
||||
return Number(str.replace('px', ''))
|
||||
} else {
|
||||
return Number(str)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
export function invert (pixels, ratio) {
|
||||
const d = pixels.data
|
||||
ratio = ratio === undefined ? 1 : ratio
|
||||
for (var i = 0; i < d.length; i += 4) {
|
||||
d[i] = d[i] + ratio * (255 - 2 * d[i])
|
||||
d[i + 1] = d[i + 1] + ratio * (255 - 2 * d[i + 1])
|
||||
d[i + 2] = d[i + 2] + ratio * (255 - 2 * d[i + 2])
|
||||
}
|
||||
return pixels
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
export function sepia (pixels, adjustment) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
const r = data[i]
|
||||
const g = data[i + 1]
|
||||
const b = data[i + 2]
|
||||
|
||||
const sr = (r * 0.393) + (g * 0.769) + (b * 0.189)
|
||||
const sg = (r * 0.349) + (g * 0.686) + (b * 0.168)
|
||||
const sb = (r * 0.272) + (g * 0.534) + (b * 0.131)
|
||||
|
||||
data[i] = r + (sr - r) * adjustment
|
||||
data[i + 1] = g + (sg - g) * adjustment
|
||||
data[i + 2] = b + (sb - b) * adjustment
|
||||
}
|
||||
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,12 @@
|
|||
export function threshold (pixels, threshold) {
|
||||
const data = pixels.data
|
||||
const length = data.length
|
||||
for (let i = 0; i < length; i += 4) {
|
||||
const r = data[i]
|
||||
const g = data[i + 1]
|
||||
const b = data[i + 2]
|
||||
const v = (0.2126 * r + 0.7152 * g + 0.0722 * b >= threshold) ? 255 : 0
|
||||
data[i] = data[i + 1] = data[i + 2] = v
|
||||
}
|
||||
return pixels
|
||||
};
|
|
@ -0,0 +1,165 @@
|
|||
import Group from '../display/group.js'
|
||||
import Graphics from '../display/graphics.js'
|
||||
import Render from './render.js'
|
||||
import Sprite from '../display/sprite.js'
|
||||
import Bitmap from '../display/bitmap.js'
|
||||
import Text from '../display/text.js'
|
||||
import { filter } from '../filter/index.js'
|
||||
|
||||
class CanvasRender extends Render {
|
||||
constructor (canvasOrContext, width, height) {
|
||||
super()
|
||||
if (arguments.length === 3) {
|
||||
this.ctx = canvasOrContext
|
||||
this.width = width
|
||||
this.height = height
|
||||
} else {
|
||||
this.ctx = canvasOrContext.getContext('2d')
|
||||
this.width = canvasOrContext.width
|
||||
this.height = canvasOrContext.height
|
||||
}
|
||||
}
|
||||
|
||||
clear (ctx, width, height) {
|
||||
ctx.clearRect(0, 0, width, height)
|
||||
}
|
||||
|
||||
render (ctx, o, cacheData) {
|
||||
let mtx = o._matrix
|
||||
if (o.children) {
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = 0; i < l; i++) {
|
||||
let child = list[i]
|
||||
mtx.initialize(1, 0, 0, 1, 0, 0)
|
||||
mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
|
||||
// if (!this.checkBoundEvent(child)) continue
|
||||
ctx.save()
|
||||
this._render(ctx, child, cacheData ? null : mtx, cacheData, true)
|
||||
ctx.restore()
|
||||
}
|
||||
} else {
|
||||
this._render(ctx, o, cacheData ? null : mtx, cacheData)
|
||||
}
|
||||
}
|
||||
|
||||
_render (ctx, o, mtx, cacheData, inGroup) {
|
||||
if (!o.isVisible()) return
|
||||
if (mtx && !o.fixed) {
|
||||
o._matrix.initialize(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
} else if (cacheData && !o.fixed) {
|
||||
o._matrix.initialize(cacheData.scale, 0, 0, cacheData.scale, cacheData.x * -1, cacheData.y * -1)
|
||||
} else {
|
||||
o._matrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
}
|
||||
mtx = o._matrix
|
||||
|
||||
// group 进行 cache canvas 内部的子元素需要进行appendTransform
|
||||
// cache canvas 渲染不叠加自身的 transform,因为进入主渲染会进行appendTransform
|
||||
if (inGroup || !cacheData) {
|
||||
mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
|
||||
}
|
||||
const ocg = o.clipGraphics
|
||||
if (ocg) {
|
||||
ctx.beginPath()
|
||||
ocg._matrix.copy(mtx)
|
||||
ocg._matrix.appendTransform(ocg.x, ocg.y, ocg.scaleX, ocg.scaleY, ocg.rotation, ocg.skewX, ocg.skewY, ocg.originX, ocg.originY)
|
||||
ctx.setTransform(ocg._matrix.a, ocg._matrix.b, ocg._matrix.c, ocg._matrix.d, ocg._matrix.tx, ocg._matrix.ty)
|
||||
ocg.render(ctx)
|
||||
ctx.clip(o.clipRuleNonzero ? 'nonzero' : 'evenodd')
|
||||
}
|
||||
|
||||
const oacg = o.absClipGraphics
|
||||
if (oacg) {
|
||||
ctx.beginPath()
|
||||
oacg._matrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
oacg._matrix.appendTransform(oacg.x, oacg.y, oacg.scaleX, oacg.scaleY, oacg.rotation, oacg.skewX, oacg.skewY, oacg.originX, oacg.originY)
|
||||
ctx.setTransform(oacg._matrix.a, oacg._matrix.b, oacg._matrix.c, oacg._matrix.d, oacg._matrix.tx, oacg._matrix.ty)
|
||||
oacg.render(ctx)
|
||||
ctx.clip(o.absClipRuleNonzero ? 'nonzero' : 'evenodd')
|
||||
}
|
||||
|
||||
// if(!cacheData){
|
||||
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
// }
|
||||
if (o._readyToCache || o.cacheUpdating) {
|
||||
this.setComplexProps(ctx, o)
|
||||
o._readyToCache = false
|
||||
o.cacheCtx.clearRect(0, 0, o.cacheCanvas.width, o.cacheCanvas.height)
|
||||
o.cacheCtx.save()
|
||||
this.render(o.cacheCtx, o, o._cacheData)
|
||||
o.cacheCtx.restore()
|
||||
// debug cacheCanvas
|
||||
// document.body.appendChild(o.cacheCanvas)
|
||||
if (o._readyToFilter) {
|
||||
o.cacheCtx.putImageData(filter(o.cacheCtx.getImageData(0, 0, o.cacheCanvas.width, o.cacheCanvas.height), o._filterName), 0, 0)
|
||||
this._readyToFilter = false
|
||||
}
|
||||
|
||||
ctx.drawImage(o.cacheCanvas, o._cacheData.x, o._cacheData.y)
|
||||
} else if (o.cacheCanvas && !cacheData) {
|
||||
this.setComplexProps(ctx, o)
|
||||
ctx.drawImage(o.cacheCanvas, o._cacheData.x, o._cacheData.y)
|
||||
} else if (o instanceof Group) {
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = 0; i < l; i++) {
|
||||
ctx.save()
|
||||
this._render(ctx, list[i], mtx)
|
||||
ctx.restore()
|
||||
}
|
||||
} else if (o instanceof Graphics) {
|
||||
this.setComplexProps(ctx, o)
|
||||
o.render(ctx)
|
||||
} else if (o instanceof Sprite && o.rect) {
|
||||
this.setComplexProps(ctx, o)
|
||||
o.updateFrame()
|
||||
let rect = o.rect
|
||||
ctx.drawImage(o.img, rect[0], rect[1], rect[2], rect[3], 0, 0, rect[2], rect[3])
|
||||
} else if (o instanceof Bitmap && o.rect) {
|
||||
this.setComplexProps(ctx, o)
|
||||
let bRect = o.rect
|
||||
ctx.drawImage(o.img, bRect[0], bRect[1], bRect[2], bRect[3], 0, 0, bRect[2], bRect[3])
|
||||
} else if (o instanceof Text) {
|
||||
this.setComplexProps(ctx, o)
|
||||
ctx.font = o.font
|
||||
ctx.fillStyle = o.color
|
||||
ctx.textAlign= o.textAlign
|
||||
ctx.textBaseline = o.baseline
|
||||
ctx.fillText(o.text, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
setComplexProps (ctx, o) {
|
||||
o.complexCompositeOperation = ctx.globalCompositeOperation = this.getCompositeOperation(o)
|
||||
o.complexAlpha = ctx.globalAlpha = this.getAlpha(o, 1)
|
||||
|
||||
o.complexShadow = this.getShadow(o)
|
||||
if (o.complexShadow) {
|
||||
ctx.shadowColor = o.complexShadow.color
|
||||
ctx.shadowOffsetX = o.complexShadow.offsetX
|
||||
ctx.shadowOffsetY = o.complexShadow.offsetY
|
||||
ctx.shadowBlur = o.complexShadow.blur
|
||||
}
|
||||
}
|
||||
|
||||
getCompositeOperation (o) {
|
||||
if (o.compositeOperation) return o.compositeOperation
|
||||
if (o.parent) return this.getCompositeOperation(o.parent)
|
||||
}
|
||||
|
||||
getAlpha (o, alpha) {
|
||||
var result = o.alpha * alpha
|
||||
if (o.parent) {
|
||||
return this.getAlpha(o.parent, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
getShadow (o) {
|
||||
if (o.shadow) return o.shadow
|
||||
if (o.parent) return this.getShadow(o.parent)
|
||||
}
|
||||
}
|
||||
|
||||
export default CanvasRender
|
|
@ -0,0 +1,222 @@
|
|||
import Group from '../display/group.js'
|
||||
import Graphics from '../display/graphics.js'
|
||||
import Render from './render.js'
|
||||
import Event from '../base/event.js'
|
||||
import Sprite from '../display/sprite.js'
|
||||
import Bitmap from '../display/bitmap.js'
|
||||
import Text from '../display/text.js'
|
||||
|
||||
class HitRender extends Render {
|
||||
constructor () {
|
||||
super()
|
||||
if (typeof wx !== 'undefined' && wx.createCanvas) {
|
||||
this.canvas = wx.createCanvas()
|
||||
} else {
|
||||
this.canvas = document.createElement('canvas')
|
||||
}
|
||||
|
||||
this.canvas.width = 1
|
||||
this.canvas.height = 1
|
||||
this.ctx = this.canvas.getContext('2d')
|
||||
|
||||
// debug event
|
||||
// this.canvas.width = 441
|
||||
// this.canvas.height = 441
|
||||
// this.ctx = this.canvas.getContext('2d')
|
||||
// document.body.appendChild(this.canvas)
|
||||
|
||||
this.disableEvents = ['mouseover', 'mouseout', 'mousemove', 'touchmove']
|
||||
}
|
||||
|
||||
clear () {
|
||||
this.ctx.clearRect(0, 0, this.width, this.height)
|
||||
}
|
||||
|
||||
hitAABB (o, evt) {
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = l - 1; i >= 0; i--) {
|
||||
let child = list[i]
|
||||
// if (!this.isbindingEvent(child)) continue;
|
||||
let path = this._hitAABB(child, evt, [], true)
|
||||
|
||||
if (path.length > 0) {
|
||||
let target = path[path.length - 1]
|
||||
this._dispatchEvent(target, evt)
|
||||
return target
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_hitAABB (o, evt, path, rootCall) {
|
||||
if (o.ignoreHit || !o.isVisible()) {
|
||||
return
|
||||
}
|
||||
|
||||
o.initAABB()
|
||||
if (o.AABB && this.checkPointInAABB(evt.stageX, evt.stageY, o.AABB)) {
|
||||
// this._bubbleEvent(o, type, evt);
|
||||
o.___$push = true
|
||||
path.push(o)
|
||||
//return o
|
||||
}
|
||||
|
||||
if (o instanceof Group) {
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = l - 1; i >= 0; i--) {
|
||||
let child = list[i]
|
||||
this._hitAABB(child, evt, path)
|
||||
if(child.___$push){
|
||||
delete child.___$push
|
||||
//同级只找一个就好了,所有 break
|
||||
break
|
||||
}
|
||||
//if (target) return target
|
||||
}
|
||||
}
|
||||
|
||||
if(rootCall){
|
||||
return path
|
||||
}
|
||||
}
|
||||
|
||||
checkPointInAABB (x, y, AABB) {
|
||||
let minX = AABB[0]
|
||||
if (x < minX) return false
|
||||
let minY = AABB[1]
|
||||
if (y < minY) return false
|
||||
let maxX = minX + AABB[2]
|
||||
if (x > maxX) return false
|
||||
let maxY = minY + AABB[3]
|
||||
if (y > maxY) return false
|
||||
return true
|
||||
}
|
||||
|
||||
hitPixel (o, evt) {
|
||||
const ctx = this.ctx
|
||||
ctx.clearRect(0, 0, 2, 2)
|
||||
let mtx = o._hitMatrix
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = l - 1; i >= 0; i--) {
|
||||
let child = list[i]
|
||||
mtx.initialize(1, 0, 0, 1, 0, 0)
|
||||
mtx.appendTransform(o.x - evt.stageX, o.y - evt.stageY, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
|
||||
// if (!this.checkBoundEvent(child)) continue
|
||||
ctx.save()
|
||||
let target = this._hitPixel(child, evt, mtx)
|
||||
ctx.restore()
|
||||
if (target) return target
|
||||
}
|
||||
}
|
||||
|
||||
_hitPixel (o, evt, mtx) {
|
||||
if (o.ignoreHit || !o.isVisible()) return
|
||||
let ctx = this.ctx
|
||||
if(o.fixed){
|
||||
o._hitMatrix.initialize(1, 0, 0, 1, -evt.stageX, -evt.stageY)
|
||||
}else if (mtx) {
|
||||
o._hitMatrix.initialize(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
} else {
|
||||
o._hitMatrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
}
|
||||
mtx = o._hitMatrix
|
||||
mtx.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
|
||||
|
||||
const ocg = o.clipGraphics
|
||||
if (ocg) {
|
||||
ctx.beginPath()
|
||||
ocg._matrix.copy(mtx)
|
||||
ocg._matrix.appendTransform(ocg.x, ocg.y, ocg.scaleX, ocg.scaleY, ocg.rotation, ocg.skewX, ocg.skewY, ocg.originX, ocg.originY)
|
||||
ctx.setTransform(ocg._matrix.a, ocg._matrix.b, ocg._matrix.c, ocg._matrix.d, ocg._matrix.tx, ocg._matrix.ty)
|
||||
ocg.render(ctx)
|
||||
ctx.clip(o.clipRuleNonzero ? 'nonzero' : 'evenodd')
|
||||
}
|
||||
|
||||
const oacg = o.absClipGraphics
|
||||
if (oacg) {
|
||||
ctx.beginPath()
|
||||
oacg._matrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
oacg._matrix.appendTransform(oacg.x, oacg.y, oacg.scaleX, oacg.scaleY, oacg.rotation, oacg.skewX, oacg.skewY, oacg.originX, oacg.originY)
|
||||
ctx.setTransform(oacg._matrix.a, oacg._matrix.b, oacg._matrix.c, oacg._matrix.d, oacg._matrix.tx, oacg._matrix.ty)
|
||||
oacg.render(ctx)
|
||||
ctx.clip(o.absClipRuleNonzero ? 'nonzero' : 'evenodd')
|
||||
}
|
||||
|
||||
if (o.cacheCanvas) {
|
||||
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
ctx.drawImage(o.cacheCanvas, o._cacheData.x, o._cacheData.y)
|
||||
} else if (o instanceof Group) {
|
||||
let list = o.children.slice(0),
|
||||
l = list.length
|
||||
for (let i = l - 1; i >= 0; i--) {
|
||||
ctx.save()
|
||||
let target = this._hitPixel(list[i], evt, mtx)
|
||||
ctx.restore()
|
||||
if (target) return target
|
||||
}
|
||||
} else {
|
||||
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
if (o instanceof Graphics) {
|
||||
this.setComplexProps(ctx, o)
|
||||
|
||||
o.render(ctx)
|
||||
} else if (o instanceof Sprite && o.rect) {
|
||||
this.setComplexProps(ctx, o)
|
||||
|
||||
o.updateFrame()
|
||||
let rect = o.rect
|
||||
ctx.drawImage(o.img, rect[0], rect[1], rect[2], rect[3], 0, 0, rect[2], rect[3])
|
||||
} else if (o instanceof Bitmap && o.rect) {
|
||||
this.setComplexProps(ctx, o)
|
||||
|
||||
let bRect = o.rect
|
||||
ctx.drawImage(o.img, bRect[0], bRect[1], bRect[2], bRect[3], 0, 0, bRect[2], bRect[3])
|
||||
} else if (o instanceof Text) {
|
||||
this.setComplexProps(ctx, o)
|
||||
|
||||
ctx.font = o.font
|
||||
ctx.fillStyle = o.color
|
||||
ctx.textAlign= o.textAlign
|
||||
ctx.textBaseline = o.baseline
|
||||
ctx.fillText(o.text, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if(o.hitBox){
|
||||
o.initAABB()
|
||||
if (this.checkPointInAABB(evt.stageX, evt.stageY, o.AABB)) {
|
||||
this._dispatchEvent(o, evt)
|
||||
return o
|
||||
}
|
||||
}else if (ctx.getImageData(0, 0, 1, 1).data[3] > 0) {
|
||||
this._dispatchEvent(o, evt)
|
||||
return o
|
||||
}
|
||||
}
|
||||
|
||||
setComplexProps (ctx, o) {
|
||||
ctx.globalCompositeOperation = o.complexCompositeOperation
|
||||
ctx.globalAlpha = o.complexAlpha
|
||||
// The shadow does not trigger the event, so remove it
|
||||
// if(o.complexShadow){
|
||||
// ctx.shadowColor = o.complexShadow.color
|
||||
// ctx.shadowOffsetX = o.complexShadow.offsetX
|
||||
// ctx.shadowOffsetY = o.complexShadow.offsetY
|
||||
// ctx.shadowBlur = o.complexShadow.blur
|
||||
// }
|
||||
}
|
||||
|
||||
_dispatchEvent (obj, evt) {
|
||||
if (this.disableEvents.indexOf(evt.type) !== -1) return
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
mockEvt.pureEvent = evt
|
||||
mockEvt.type = evt.type
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
}
|
||||
|
||||
export default HitRender
|
|
@ -0,0 +1,15 @@
|
|||
class Render {
|
||||
render () {
|
||||
|
||||
}
|
||||
|
||||
renderGraphics () {
|
||||
|
||||
}
|
||||
|
||||
clear () {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default Render
|
|
@ -0,0 +1,106 @@
|
|||
import CanvasRender from '../render/canvas-render'
|
||||
import Group from '../display/group.js'
|
||||
|
||||
class Renderer {
|
||||
constructor (canvasOrContext, width, height) {
|
||||
this.renderList = []
|
||||
if (arguments.length === 3) {
|
||||
this.renderer = new CanvasRender(canvasOrContext, width, height)
|
||||
this.width = width
|
||||
this.height = height
|
||||
} else {
|
||||
this.renderer = new CanvasRender(canvasOrContext)
|
||||
this.width = canvasOrContext.width
|
||||
this.height = canvasOrContext.height
|
||||
}
|
||||
this.ctx = this.renderer.ctx
|
||||
}
|
||||
|
||||
update (stage) {
|
||||
this.renderer.clear(this.ctx, this.width, this.height)
|
||||
this.renderer.render(this.ctx, stage)
|
||||
this.ctx.draw && this.ctx.draw()
|
||||
}
|
||||
|
||||
getHitRenderList (stage) {
|
||||
const objs = this.renderList
|
||||
objs.length = 0
|
||||
this.computeMatrix(stage)
|
||||
return objs
|
||||
}
|
||||
|
||||
computeMatrix (stage) {
|
||||
for (var i = 0, len = stage.children.length; i < len; i++) {
|
||||
this._computeMatrix(stage.children[i])
|
||||
}
|
||||
}
|
||||
|
||||
initComplex (o) {
|
||||
o.complexCompositeOperation = this._getCompositeOperation(o)
|
||||
o.complexAlpha = this._getAlpha(o, 1)
|
||||
}
|
||||
|
||||
_computeMatrix (o, mtx) {
|
||||
if (!o.isVisible()) {
|
||||
return
|
||||
}
|
||||
if (mtx && !o.fixed) {
|
||||
o._matrix.initialize(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
} else {
|
||||
o._matrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
}
|
||||
|
||||
o._matrix.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
|
||||
|
||||
if (o instanceof Group) {
|
||||
var list = o.children,
|
||||
len = list.length,
|
||||
i = 0
|
||||
for (; i < len; i++) {
|
||||
this._computeMatrix(list[i], o._matrix)
|
||||
}
|
||||
} else {
|
||||
// if (o instanceof Graphics) {
|
||||
// this.renderList.push(o)
|
||||
// this.initComplex(o)
|
||||
// } else {
|
||||
o.initAABB()
|
||||
// if (this.isInStage(o)) {
|
||||
this.renderList.push(o)
|
||||
this.initComplex(o)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
_getCompositeOperation (o) {
|
||||
if (o.compositeOperation) return o.compositeOperation
|
||||
if (o.parent) return this._getCompositeOperation(o.parent)
|
||||
}
|
||||
|
||||
_getAlpha (o, alpha) {
|
||||
var result = o.alpha * alpha
|
||||
if (o.parent) {
|
||||
return this._getAlpha(o.parent, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
isInStage (o) {
|
||||
return this.collisionBetweenAABB(o.AABB, this.stage.AABB)
|
||||
}
|
||||
|
||||
collisionBetweenAABB (AABB1, AABB2) {
|
||||
var maxX = AABB1[0] + AABB1[2]
|
||||
if (maxX < AABB2[0]) return false
|
||||
var minX = AABB1[0]
|
||||
if (minX > AABB2[0] + AABB2[2]) return false
|
||||
var maxY = AABB1[1] + AABB1[3]
|
||||
if (maxY < AABB2[1]) return false
|
||||
var minY = AABB1[1]
|
||||
if (minY > AABB2[1] + AABB2[3]) return false
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
export default Renderer
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
import Graphics from '../display/graphics.js'
|
||||
import Render from './render.js'
|
||||
import Event from '../base/event.js'
|
||||
import Sprite from '../display/sprite.js'
|
||||
import Bitmap from '../display/bitmap.js'
|
||||
import Text from '../display/text.js'
|
||||
|
||||
class WxHitRender extends Render {
|
||||
constructor (ctx, component, canvasId) {
|
||||
super()
|
||||
|
||||
this.ctx = ctx
|
||||
this._isWeapp = true
|
||||
this._component = component
|
||||
this._hitCanvasId = canvasId + 'Hit'
|
||||
|
||||
this.disableEvents = ['mouseover', 'mouseout', 'mousemove', 'touchmove']
|
||||
}
|
||||
|
||||
clear () {
|
||||
this.ctx.clearRect(0, 0, 2, 2)
|
||||
}
|
||||
|
||||
hitAABB (list, evt, cb) {
|
||||
const len = list.length
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
let o = list[i]
|
||||
|
||||
if (o.AABB && this.checkPointInAABB(evt.stageX, evt.stageY, o.AABB)) {
|
||||
this._dispatchEvent(o, evt)
|
||||
cb(o)
|
||||
return o
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkPointInAABB (x, y, AABB) {
|
||||
let minX = AABB[0]
|
||||
if (x < minX) return false
|
||||
let minY = AABB[1]
|
||||
if (y < minY) return false
|
||||
let maxX = minX + AABB[2]
|
||||
if (x > maxX) return false
|
||||
let maxY = minY + AABB[3]
|
||||
if (y > maxY) return false
|
||||
return true
|
||||
}
|
||||
|
||||
hit (list, evt, cb, current) {
|
||||
const ctx = this.ctx
|
||||
const obj = list[current]
|
||||
const mtx = obj._hitMatrix.initialize(1, 0, 0, 1, 0, 0)
|
||||
ctx.save()
|
||||
mtx.appendTransform(obj.x - evt.stageX, obj.y - evt.stageY, obj.scaleX, obj.scaleY, obj.rotation, obj.skewX, obj.skewY, obj.originX, obj.originY)
|
||||
ctx.globalCompositeOperation = obj.complexCompositeOperation
|
||||
ctx.globalAlpha = obj.complexAlpha
|
||||
ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
|
||||
if (obj instanceof Graphics) {
|
||||
obj.render(ctx)
|
||||
} else if (obj instanceof Sprite && obj.rect) {
|
||||
obj.updateFrame()
|
||||
const rect = obj.rect
|
||||
ctx.drawImage(obj.img, rect[0], rect[1], rect[2], rect[3], 0, 0, rect[2], rect[3])
|
||||
} else if (obj instanceof Bitmap && obj.rect) {
|
||||
const bRect = obj.rect
|
||||
ctx.drawImage(obj.img, bRect[0], bRect[1], bRect[2], bRect[3], 0, 0, bRect[2], bRect[3])
|
||||
} else if (obj instanceof Text) {
|
||||
ctx.font = obj.font
|
||||
ctx.fillStyle = obj.color
|
||||
ctx.textAlign= obj.textAlign
|
||||
ctx.fillText(obj.text, 0, 0)
|
||||
}
|
||||
ctx.restore()
|
||||
current--
|
||||
ctx.draw(false, () => {
|
||||
wx.canvasGetImageData({
|
||||
canvasId: this._hitCanvasId,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 1,
|
||||
height: 1,
|
||||
success: (res) => {
|
||||
if (res.data[3] > 1) {
|
||||
this._dispatchEvent(obj, evt)
|
||||
cb(obj)
|
||||
} else {
|
||||
if (current > -1) { this.hit(list, evt, cb, current) }
|
||||
}
|
||||
}
|
||||
}, this._component)
|
||||
})
|
||||
}
|
||||
|
||||
_dispatchEvent (obj, evt) {
|
||||
if (this.disableEvents.indexOf(evt.type) !== -1) return
|
||||
let mockEvt = new Event()
|
||||
mockEvt.stageX = evt.stageX
|
||||
mockEvt.stageY = evt.stageY
|
||||
mockEvt.pureEvent = evt
|
||||
mockEvt.type = evt.type
|
||||
obj.dispatchEvent(mockEvt)
|
||||
}
|
||||
}
|
||||
|
||||
export default WxHitRender
|
|
@ -0,0 +1,49 @@
|
|||
import cax from '../../cax/index'
|
||||
|
||||
Page({
|
||||
onLoad: function (options) {
|
||||
const info = wx.getSystemInfoSync()
|
||||
const stage = new cax.Stage(info.windowWidth, info.windowHeight / 2, 'myCanvas', this)
|
||||
|
||||
const rect = new cax.Rect(100, 100, {
|
||||
fillStyle: 'black'
|
||||
})
|
||||
|
||||
rect.originX = 50
|
||||
rect.originY = 50
|
||||
rect.x = 100
|
||||
rect.y = 100
|
||||
rect.rotation = 30
|
||||
|
||||
rect.on('touchstart', () => {
|
||||
console.log('rect touchstart')
|
||||
})
|
||||
|
||||
rect.on('touchmove', () => {
|
||||
console.log('rect touchmove')
|
||||
})
|
||||
|
||||
rect.on('touchend', () => {
|
||||
console.log('rect touchend')
|
||||
})
|
||||
|
||||
rect.on('tap', () => {
|
||||
console.log('rect tap')
|
||||
})
|
||||
|
||||
|
||||
stage.add(rect)
|
||||
|
||||
|
||||
cax.To.get(rect).to().x(200, 2000, cax.easing.elasticInOut).start()
|
||||
|
||||
|
||||
|
||||
|
||||
setInterval(function () {
|
||||
rect.rotation++
|
||||
stage.update()
|
||||
}, 16)
|
||||
|
||||
}
|
||||
})
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"usingComponents": {
|
||||
"cax":"../../cax/cax"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
<!--index.wxml-->
|
||||
<view class="container">
|
||||
<cax id="myCanvas"></cax>
|
||||
</view>
|
|
@ -0,0 +1,21 @@
|
|||
/**index.wxss**/
|
||||
.userinfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.userinfo-avatar {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
margin: 20rpx;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.userinfo-nickname {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.usermotto {
|
||||
margin-top: 200px;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//logs.js
|
||||
const util = require('../../utils/util.js')
|
||||
|
||||
Page({
|
||||
data: {
|
||||
logs: []
|
||||
},
|
||||
onLoad: function () {
|
||||
this.setData({
|
||||
logs: (wx.getStorageSync('logs') || []).map(log => {
|
||||
return util.formatTime(new Date(log))
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"navigationBarTitleText": "查看启动日志",
|
||||
"usingComponents": {}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<!--logs.wxml-->
|
||||
<view class="container log-list">
|
||||
<block wx:for="{{logs}}" wx:for-item="log">
|
||||
<text class="log-item">{{index + 1}}. {{log}}</text>
|
||||
</block>
|
||||
</view>
|
|
@ -0,0 +1,8 @@
|
|||
.log-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 40rpx;
|
||||
}
|
||||
.log-item {
|
||||
margin: 10rpx;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"description": "项目配置文件",
|
||||
"packOptions": {
|
||||
"ignore": []
|
||||
},
|
||||
"setting": {
|
||||
"urlCheck": true,
|
||||
"es6": true,
|
||||
"postcss": true,
|
||||
"minified": true,
|
||||
"newFeature": true,
|
||||
"autoAudits": false
|
||||
},
|
||||
"compileType": "miniprogram",
|
||||
"libVersion": "2.6.4",
|
||||
"appid": "wxfaf6dad43f57c6bd",
|
||||
"projectname": "cax-svg",
|
||||
"debugOptions": {
|
||||
"hidedInDevtools": []
|
||||
},
|
||||
"isGameTourist": false,
|
||||
"condition": {
|
||||
"search": {
|
||||
"current": -1,
|
||||
"list": []
|
||||
},
|
||||
"conversation": {
|
||||
"current": -1,
|
||||
"list": []
|
||||
},
|
||||
"game": {
|
||||
"currentL": -1,
|
||||
"list": []
|
||||
},
|
||||
"miniprogram": {
|
||||
"current": -1,
|
||||
"list": []
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
const formatTime = date => {
|
||||
const year = date.getFullYear()
|
||||
const month = date.getMonth() + 1
|
||||
const day = date.getDate()
|
||||
const hour = date.getHours()
|
||||
const minute = date.getMinutes()
|
||||
const second = date.getSeconds()
|
||||
|
||||
return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')
|
||||
}
|
||||
|
||||
const formatNumber = n => {
|
||||
n = n.toString()
|
||||
return n[1] ? n : '0' + n
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
formatTime: formatTime
|
||||
}
|
Loading…
Reference in New Issue