天天看點

【開源】微信小程式、小遊戲以及 Web 通用 Canvas 渲染引擎 - CaxCax

Cax

小程式、小遊戲以及 Web 通用 Canvas 渲染引擎

特性

  • Learn Once, Write Anywhere(小程式、小遊戲、PC Web、Mobile Web)
  • 支援小程式、小遊戲以及 Web 浏覽器渲染
  • 小程式、小遊戲和 Web 擁有相同簡潔輕巧的 API
  • 高性能的渲染架構
  • 超輕量級的代碼體積
  • 松耦合的渲染架構
  • 支援 Canvas 元素管理
  • 支援 Canvas 元素事件體系
  • 圖靈完畢的 group 嵌套體系
  • 内置 tween 運動能力
  • 内置文本、位圖、序列幀、繪圖對象和多種矢量繪制對象

到 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')
})
複制代碼           

const stage = new cax.Stage()
複制代碼           

和小程式以及 Web 不同的是,小遊戲建立 Stage 不需要傳任何參數。

通過 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 的 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 的上面。

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 複制代碼           

序列幀動畫元件,可以把任意圖檔的任意區域組合成一串動畫。

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 () {

 }
});
複制代碼           

文本對象

const text = new cax.Text('Hello World', {
 font: '20px Arial',
 color: '#ff7700',
 baseline: 'top'
})
複制代碼           

繪圖對象,用于使用基本的連綴方式的 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)
複制代碼           

與 Graphics 不同的是, Shape 一般擁有有限的寬高,是以可以使用離屏 Canvas 進行緩存。下面這些屬于 Shape。

const rect = new cax.Rect(200, 100, {
 fillStyle: 'black'
})
複制代碼           

const circel = new cax.Circel(10)
複制代碼           

const ellipse = new cax.Ellipse(10)
複制代碼           

注意:從技術上小遊戲和 Web 可以離屏 Canvas,小程式不行,因為小程式不支援動态建立離屏 Canvas。

Element 是多種元素的組合,如 Bitmap、Group、 Text、 Shape 等混合起來的圖像。

const button = new cax.Button({
 width: 100,
 height: 40,
 text: "Click Me!"
})
複制代碼           

屬性名 描述
x 水準偏移
y 豎直偏移
scaleX 水準縮放
scaleY 豎直縮放
rotation 旋轉
skewX 歪斜 X
skewY 歪斜 Y
originX 旋轉基點 X
originY 旋轉基點 Y

alpha 元素的透明度

注意這裡父子都設定了 alpha 會進行乘法疊加。

compositeOperation

源圖像繪制到目标圖像上的疊加模式

注意這裡如果自身沒有定義 compositeOperation 會進行向上查找,找到最近的定義了 compositeOperation 的父容器作為自己的 compositeOperation。

cursor 滑鼠移上去的形狀

事件名
tap 手指觸摸後馬上離開
touchstart 手指觸摸動作開始
touchmove 手指觸摸後移動
touchend 手指觸摸動作結束
drag 拖拽

click 元素上發生點選時觸發
mousedown 當元素上按下滑鼠按鈕時觸發
mousemove 當滑鼠指針移動到元素上時觸發
mouseup 當在元素上釋放滑鼠按鈕時觸發
mouseover
mouseout 當滑鼠指針移出元素時觸發

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 繼承自 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 繼承自 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。

原文釋出時間:06月21日

原文作者:當耐特

本文來源

掘金

如需轉載請緊急聯系作者