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

Cax

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

特性

  • 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 裏渲染邏輯:bash

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 拖拽

自定義對象

自定義 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

相關文章
相關標籤/搜索