微信小程序 canvas圓角矩形的繪製

微信小程序容許對普通元素經過 border-radius的設置來進行圓角的繪製,但有時候在使用 canvas繪圖的時候,也須要圓角,例如須要將頁面上某塊區域導出爲圖片下載到本地的時候,經常使用的解決方法就是使用 canvas將這塊區域繪製出來,最後導出 canvas便可,可是 canvas沒有直接提供圓角的繪製 api,因此須要 曲線救國git


圓角矩形與通常矩形的區別在於,前者的四個角都是圓弧,因此只須要將通常矩形的四個角切掉,換成圓弧便可,以下圖就是一個通常矩形被切掉了四個角的樣子:github

很明顯,切掉了四個角的矩形,剩下其實就是四條 line,既然如此,徹底能夠跳過繪製矩形而後切角這一步,由於切角的結果就是四條邊(line),直接繪製四條邊便可。 而後在每兩條邊的缺角處繪製弧度爲 0.5 * Math.PI 的圓弧,最後這四條邊與四個圓弧所封閉的圖形就是圓角矩形:canvas

原理知道了,代碼就很好寫了,這裏只說幾個注意點:小程序

  • 封閉圖形的 fillStyle顏色設置爲 transparent

想將封閉路徑的圖形繪製下來,須要調用 strokefill方法,默認 strokefill的顏色是 black,可是這裏有個問題, 圓弧的繪製可能會出現鋸齒或者糊邊,若是 strokefill的顏色,與你所須要繪製的圓角矩形的邊緣色調不一致,這種糊邊的感受會比兩者色調一致的更明顯, 下圖第一個爲色調一致,第二個爲色調不一致的狀況:微信小程序

不過據我觀測,只要不是特地放大仔細看,不管是色調是否一致,其實通常人很難注意到糊邊的事情api

  • clip

繪製好了圓角選區以後,還須要調用 ctx.clip方法來裁剪選區微信

  • saverestore

若是這個矩形選區只是 canvas畫布的一部分,爲了不對後續的影響,最好在 beginPath以前,將以前的動做 save,而後畫完後再 restoreui

一個關於 canvas上繪製圓角圖片,並下載到本地 的可運行示例代碼已經放到 github上了,註釋也比較詳細,須要的可自取spa

其中關鍵代碼以下:3d

/** * * @param {CanvasContext} ctx canvas上下文 * @param {number} x 圓角矩形選區的左上角 x座標 * @param {number} y 圓角矩形選區的左上角 y座標 * @param {number} w 圓角矩形選區的寬度 * @param {number} h 圓角矩形選區的高度 * @param {number} r 圓角的半徑 */
function roundRect(ctx, x, y, w, h, r) {
  // 開始繪製
  ctx.beginPath()
  // 由於邊緣描邊存在鋸齒,最好指定使用 transparent 填充
  // 這裏是使用 fill 仍是 stroke均可以,二選一便可
  ctx.setFillStyle('transparent')
  // ctx.setStrokeStyle('transparent')
  // 左上角
  ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)

  // border-top
  ctx.moveTo(x + r, y)
  ctx.lineTo(x + w - r, y)
  ctx.lineTo(x + w, y + r)
  // 右上角
  ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)

  // border-right
  ctx.lineTo(x + w, y + h - r)
  ctx.lineTo(x + w - r, y + h)
  // 右下角
  ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)

  // border-bottom
  ctx.lineTo(x + r, y + h)
  ctx.lineTo(x, y + h - r)
  // 左下角
  ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)

  // border-left
  ctx.lineTo(x, y + r)
  ctx.lineTo(x + r, y)

  // 這裏是使用 fill 仍是 stroke均可以,二選一便可,可是須要與上面對應
  ctx.fill()
  // ctx.stroke()
  ctx.closePath()
  // 剪切
  ctx.clip()
}
複製代碼
相關文章
相關標籤/搜索