Cax
小程式、小遊戲以及 Web 通用 Canvas 渲染引擎
- Github → github.com/dntzhang/ca…
- 綜合 DEMO | 運動 DEMO
- 小程式 DEMO 正在稽核中敬請期待
- 小遊戲 DEMO 正在稽核中敬請期待
特性
- Learn Once, Write Anywhere(小程式、小遊戲、PC Web、Mobile Web)
- 支援小程式、小遊戲以及 Web 瀏覽器渲染
- 小程式、小遊戲和 Web 擁有相同簡潔輕巧的 API
- 高效能的渲染架構
- 超輕量級的程式碼體積
- 鬆耦合的渲染架構
- 支援 Canvas 元素管理
- 支援 Canvas 元素事件體系
- 圖靈完畢的 group 巢狀體系
- 內建 tween 運動能力
- 內建文字、點陣圖、序列幀、繪圖物件和多種向量繪製物件
一分鐘入門小程式 cax 使用
到 GitHub 下載 cax 自定義元件,然後小程式引入 cax 自定義元件:
└── cax
├── cax.js
├── cax.json
├── cax.wxml
├── cax.wxss
└── index.js
複製程式碼
在 page 或者 component 裡宣告依賴:
{
"usingComponents": {
"cax":"../cax/cax"
}
}
複製程式碼
在的 wxml 裡引入 cax 標籤:
<cax id="myCanvas"></cax>
複製程式碼
在 js 裡渲染邏輯:
import cax from '../cax/index'
Page({
onLoad: function () {
//比 web 裡使用 cax 多傳遞 this,this 代表 Page 或 Component 的例項
const stage = new cax.Stage(200, 200, '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('tap', () => {
console.log('tap')
})
stage.add(rect)
stage.update()
}
})
複製程式碼
效果如下所示:
除了 tap 事件,也可以幫 rect 繫結其他觸控事件:
rect.on('touchstart', () => {
console.log('touchstart')
})
rect.on('touchmove', () => {
console.log('touchmove')
})
rect.on('touchend', () => {
console.log('touchend')
})
複製程式碼
一分鐘入門小遊戲 cax 使用
到 GitHub 下載 cax 小遊戲示例,目錄結構如下:
const stage = new cax.Stage()
複製程式碼
和小程式以及 Web 不同的是,小遊戲建立 Stage 不需要傳任何引數。
一分鐘入門 Web cax 使用
通過 npm 或者 CDN 獲取:
npm i cax
複製程式碼
import cax from 'cax'
const stage = new cax.Stage(200, 200, '#renderTo')
const rect = new cax.Rect(100, 100, {
fillStyle: 'black'
})
stage.add(rect)
stage.update()
複製程式碼
除了 Stage 建構函式比小程式第四個引數 this
,其他使用方式都一樣。
內建物件
Group
用於分組, group 也可以巢狀 group,父容器的屬性會疊加在子屬性上, 比如:
- group 的 x 是 100, group 裡的 bitmap 的 x 是 200, 最後 bitmap 渲染到 stage 上的 x 是 300
- group 的 alpha 是 0.7, group 裡的 bitmap 的 alpha 是 0.6, 最後 bitmap 渲染到 stage 上的 alpha 是 0.42
const group = new cax.Group()
const rect = new cax.Rect(100, 100 {
fillStyle: 'black'
})
group.add(rect)
stage.add(group)
stage.update()
複製程式碼
group 擁有常用的 add 和 remove 方法進行元素的增加和刪除。先 add 的會先繪製,所有後 add 的會蓋在先 add 的上面。
Bitmap
const bitmap = new cax.Bitmap(img)
stage.add(bitmap)
stage.update()
複製程式碼
如果只傳 url 而不是 Image 物件的例項,需要這樣:
const bitmap = new cax.Bitmap('./wepay.png', ()=>{
stage.update()
})
stage.add(bitmap)
複製程式碼
這裡需要注意小程式需要配置 downloadFile 需要配置合法域名才能正常載入到圖片。
可以設定圖片裁剪顯示區域,和其他 transform 屬性:
bitmap.rect = [0, 0, 170, 140]
bitmap.x = 200
複製程式碼
Sprite
序列幀動畫元件,可以把任意圖片的任意區域組合成一串動畫。
const sprite = new cax.Sprite({
framerate: 7,
imgs: ['./mario-sheet.png'],
frames: [
// x, y, width, height, originX, originY ,imageIndex
[0, 0, 32, 32],
[32 * 1, 0, 32, 32],
[32 * 2, 0, 32, 32],
[32 * 3, 0, 32, 32],
[32 * 4, 0, 32, 32],
[32 * 5, 0, 32, 32],
[32 * 6, 0, 32, 32],
[32 * 7, 0, 32, 32],
[32 * 8, 0, 32, 32],
[32 * 9, 0, 32, 32],
[32 * 10, 0, 32, 32],
[32 * 11, 0, 32, 32],
[32 * 12, 0, 32, 32],
[32 * 13, 0, 32, 32],
[32 * 14, 0, 32, 32]
],
animations: {
walk: {
frames: [0, 1]
},
happy: {
frames: [5, 6, 7, 8, 9]
},
win: {
frames: [12]
}
},
playOnce: false,
currentAnimation: "walk",
animationEnd: function () {
}
});
複製程式碼
Text
文字物件
const text = new cax.Text('Hello World', {
font: '20px Arial',
color: '#ff7700',
baseline: 'top'
})
複製程式碼
Graphics
繪圖物件,用於使用基本的連綴方式的 Canvas 指令繪製圖形。
const graphics = new cax.Graphics()
graphics
.beginPath()
.arc(0, 0, 10, 0, Math.PI * 2)
.closePath()
.fillStyle('#f4862c')
.fill()
.strokeStyle('black')
.stroke()
graphics.x = 100
graphics.y = 200
stage.add(graphics)
複製程式碼
Shape
與 Graphics 不同的是, Shape 一般擁有有限的寬高,所以可以使用離屏 Canvas 進行快取。下面這些屬於 Shape。
Rect
const rect = new cax.Rect(200, 100, {
fillStyle: 'black'
})
複製程式碼
Circel
const circel = new cax.Circel(10)
複製程式碼
Ellipse
const ellipse = new cax.Ellipse(10)
複製程式碼
注意:從技術上小遊戲和 Web 可以離屏 Canvas,小程式不行,因為小程式不支援動態建立離屏 Canvas。
Element
Element 是多種元素的組合,如 Bitmap、Group、 Text、 Shape 等混合起來的影象。
Button
const button = new cax.Button({
width: 100,
height: 40,
text: "Click Me!"
})
複製程式碼
屬性
Transform
屬性名 | 描述 |
---|---|
x | 水平偏移 |
y | 豎直偏移 |
scaleX | 水平縮放 |
scaleY | 豎直縮放 |
rotation | 旋轉 |
skewX | 歪斜 X |
skewY | 歪斜 Y |
originX | 旋轉基點 X |
originY | 旋轉基點 Y |
Alpha
屬性名 | 描述 |
---|---|
alpha | 元素的透明度 |
注意這裡父子都設定了 alpha 會進行乘法疊加。
compositeOperation
屬性名 | 描述 |
---|---|
compositeOperation | 源影象繪製到目標影象上的疊加模式 |
注意這裡如果自身沒有定義 compositeOperation 會進行向上查詢,找到最近的定義了 compositeOperation 的父容器作為自己的 compositeOperation。
Cursor
屬性名 | 描述 |
---|---|
cursor | 滑鼠移上去的形狀 |
事件
小程式事件
事件名 | 描述 |
---|---|
tap | 手指觸控後馬上離開 |
touchstart | 手指觸控動作開始 |
touchmove | 手指觸控後移動 |
touchend | 手指觸控動作結束 |
drag | 拖拽 |
Web 事件
事件名 | 描述 |
---|---|
click | 元素上發生點選時觸發 |
mousedown | 當元素上按下滑鼠按鈕時觸發 |
mousemove | 當滑鼠指標移動到元素上時觸發 |
mouseup | 當在元素上釋放滑鼠按鈕時觸發 |
mouseover | 當滑鼠指標移動到元素上時觸發 |
mouseout | 當滑鼠指標移出元素時觸發 |
tap | 手指觸控後馬上離開 |
touchstart | 手指觸控動作開始 |
touchmove | 手指觸控後移動 |
touchend | 手指觸控動作結束 |
drag | 拖拽 |
運動
cax 內建了 to 的能力以連綴的方式寫運動效果:
cax.To.get(bitmap)
.to()
.y(240, 2000, cax.easing.elasticInOut)
.rotation(240, 2000, cax.easing.elasticInOut)
.end(function () {
console.log(" task one has completed!")
})
.wait(500)
.to()
.rotation(0, 1400, cax.easing.elasticInOut)
.end(function () {
console.log(" task two has completed!")
})
.wait(500)
.to()
.scaleX(1, 1400, cax.easing.elasticInOut)
.scaleY(1, 1400, cax.easing.elasticInOut)
.end(function () {
console.log(" task three has completed!")
})
.start()
複製程式碼
當然,也可以通過 set 方法支援任意屬性的運動,如:
.set('y', 240, 2000, cax.easing.elasticInOut)
複製程式碼
等同於
.y(240, 2000, cax.easing.elasticInOut)
複製程式碼
自定義物件
自定義 Shape
自定義 Shape 繼承自 cax.Shape:
class Sector extends cax.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()
}
}
複製程式碼
使用 Shape:
const sector = new Sector(10, 0, Math.PI/6, {
fillStyle: 'red'
lineWidth: 2
})
stage.add(sector)
stage.update()
複製程式碼
自定義 Element
自定義 Element 繼承自 cax.Group:
class Button extends cax.Group {
constructor (option) {
super()
this.width = option.width
this.roundedRect = new cax.RoundedRect(option.width, option.height, option.r)
this.text = new cax.Text(option.text, {
font: option.font,
color: option.color
})
this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX
this.text.y = option.height / 2 - 10 + 5 * this.text.scaleY
this.add(this.roundedRect, this.text)
}
}
export default Button
複製程式碼
使用:
const button = new cax.Button({
width: 100,
height: 40,
text: "Click Me!"
})
複製程式碼
一般情況下,稍微複雜組合體都建議使用繼承自 Group,這樣利於擴充套件也方便管理自身內部的元件。 可以看到小遊戲的 DEMO 裡的 Player、Bullet、Enemy、Background 全都是繼承自 Group。
License
MIT