微信小程序容許對普通元素經過 border-radius
的設置來進行圓角的繪製,但有時候在使用 canvas
繪圖的時候,也須要圓角,例如須要將頁面上某塊區域導出爲圖片下載到本地的時候,經常使用的解決方法就是使用 canvas
將這塊區域繪製出來,最後導出 canvas
便可,可是 canvas
沒有直接提供圓角的繪製 api
,因此須要 曲線救國
git
圓角矩形與通常矩形的區別在於,前者的四個角都是圓弧,因此只須要將通常矩形的四個角切掉,換成圓弧便可,以下圖就是一個通常矩形被切掉了四個角的樣子:github
很明顯,切掉了四個角的矩形,剩下其實就是四條 line
,既然如此,徹底能夠跳過繪製矩形而後切角這一步,由於切角的結果就是四條邊(line
),直接繪製四條邊便可。 而後在每兩條邊的缺角處繪製弧度爲 0.5 * Math.PI
的圓弧,最後這四條邊與四個圓弧所封閉的圖形就是圓角矩形:canvas
原理知道了,代碼就很好寫了,這裏只說幾個注意點:小程序
fillStyle
顏色設置爲 transparent
想將封閉路徑的圖形繪製下來,須要調用 stroke
或 fill
方法,默認 stroke
或 fill
的顏色是 black
,可是這裏有個問題, 圓弧的繪製可能會出現鋸齒或者糊邊,若是 stroke
或 fill
的顏色,與你所須要繪製的圓角矩形的邊緣色調不一致,這種糊邊的感受會比兩者色調一致的更明顯, 下圖第一個爲色調一致,第二個爲色調不一致的狀況:微信小程序
不過據我觀測,只要不是特地放大仔細看,不管是色調是否一致,其實通常人很難注意到糊邊的事情api
clip
繪製好了圓角選區以後,還須要調用 ctx.clip
方法來裁剪選區微信
save
與 restore
若是這個矩形選區只是 canvas
畫布的一部分,爲了不對後續的影響,最好在 beginPath
以前,將以前的動做 save
,而後畫完後再 restore
ui
一個關於 在 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()
}
複製代碼