Canvas 繪製 3d 圓柱體

當耐特發表於2018-07-12

Canvas 繪製 3d 圓柱體

Pie

眾所周知 Cax 是基於 2d Canvas 的跨平臺(小遊戲、小程式和Web)渲染引擎。但是能夠繪製 3d 圖表嗎? 答案是可以!有兩種方式:

  • 自己計算透視投影最終各個點的座標,然後連線填充起來
  • 自己按照眼睛成像經驗直接繪製 3d 的 2d 影象

本文將使用第二種方式。

快速開始

const cy = new Cylinder(60, 200, 0.5, 'red')
stage.add(cy)
stage.update()
複製程式碼

因為 Cylinder 也是繼承自 cax.Group 的自定義 element,所以可以直接新增到stage渲染展示。顯示效果如下:

Pie

會發現使用的時候只需要傳一個顏色遍可以,怎麼做到的?圓柱體裡包含了三種顏色是怎麼來的?且看原理。

實現原理

Canvas 繪製 3d 圓柱體

一圖勝千言,就這麼簡單!

  • 左邊第一張是半透的灰色
  • 第二張是紅色
  • 第三張頂部橢圓是灰色,中間橢圓是半透的灰色橢圓蓋住紅色橢圓,底部是紅色橢圓
  • 第四張是最終合成的影象!

且看部分實現程式碼:

const btRect = new Graphics()
btRect.beginPath().fillStyle(color).fillRect(0, 0, width, height - th)
btRect.y = th

const topEllipse = new Ellipse(width, width / 2.5, {
    fillStyle: bottleColor
})
topEllipse.y = shortSize * -1

const middleEllipse = new Ellipse(width, width / 2.5, {
    fillStyle: color
})
middleEllipse.y = th - shortSize

const middleEllipseMask = new Ellipse(width, width / 2.5, {
    fillStyle: bottleColor
})
middleEllipseMask.alpha = 0.618
middleEllipseMask.y = th - shortSize

const bottomEllipse = new Ellipse(width, width / 2.5, {
    fillStyle: color
})
bottomEllipse.y = height - shortSize

this.add(topRect, topEllipse, btRect, bottomEllipse, middleEllipse, middleEllipseMask)
複製程式碼

cax 內建的物件可以通過調整 alpha 來設定透明度,非常靈活方便,完整程式碼請到這裡檢視 → Cylinder Source

那麼問題來了?橢圓怎麼擬合?

橢圓

CanvasRenderingContext2D.ellipse() 是 Canvas 2D API 新增橢圓路徑的方法。橢圓的圓心在(x,y)位置,半徑分別是radiusX 和 radiusY ,按照anticlockwise(預設順時針)指定的方向,從 startAngle 開始繪製,到 endAngle 結束。

但是!這是一個實驗中的功能,不能在相容所有瀏覽器。

且看 → cax 怎麼實現的


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
複製程式碼

Canvas 繪製 3d 圓柱體

通過 4 條貝賽爾曲線去擬合一個橢圓。

更多圖表教程請關注 Wechart by Cax ,我們將持續更新!

Cax 和 Wechart 微信交流群2

Canvas 繪製 3d 圓柱體

相關文章