小程序繪圖篇:如何正確地給一個漸變背景按鈕繪製陰影

最近在開發一個小程序項目中遇到了一個小的問題。那就是須要給一個背景是漸變色的按鈕添加一層陰影,下圖中紅色線標記的地方。javascript

file

目的是爲了讓這個按鈕更有立體感。剛開始作的時候以爲沒有什麼難度,在開發工具上也可以很好的展現;可是到了真機測試的時候,才發現原來給按鈕繪製陰影的方法在真機上顯示不出來。因而就有了下面我尋找解決方案的過程,最終我順利的解決了這個問題。我把我解決這個問題的思路記錄下來,方便我往後回顧,也但願可以跟你們一塊兒交流,咱們一塊兒進步。java

當我在手機上發現繪製的按鈕沒有陰影的時候,我就知道接下來我將可能要付出幾個小時的時間去解決這個問題。我也作好了心理準備,因而就踏上了尋找解決方案的道路。canvas

第一步:搜索問題

當我遇到這個問題的時候,個人第一反應就是先上網搜索一下看看有沒有同窗也遇到過這種問題。因而我就搜索小程序canvas繪圖與按鈕陰影相關的一些問題和資料。個人確找到了一些相關的文章和問題,可是我發現這些資料要麼跟本身遇到的問題不太符合,要麼搜到的問題尚未回覆。小程序

我提取了這些文章和問題中有用的點,得出了下面的結論:編輯器

  • 小程序canvas能夠繪製圓角陰影
  • 小程序繪製陰影的API有新舊兩個版本
  • 沒有說明漸變色背景的按鈕是否能夠直接添加陰影

第二步:分析對比

先來看一下我如今的代碼是這樣的:工具

// ... 此處省去部分代碼
// 繪製漸變色
_ctxc.beginPath()
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2, btn_h + r, r, 0.5 * Math.PI, 1.5 * Math.PI)
// 繪製右邊圓弧
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2, btn_h + r, r, -0.5 * Math.PI, 0.5 * Math.PI)
// 閉合路徑
_ctxc.closePath()
// 添加漸變色
const grd = _ctxc.createLinearGradient((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2 - r, btn_h, (SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2 + r, btn_h)
grd.addColorStop(0, first_color)
grd.addColorStop(1, second_color)
_ctxc.setFillStyle(grd)
// 設置陰影
_ctxc.shadowOffsetX = 2
_ctxc.shadowOffsetY = 2
_ctxc.shadowColor = '#43454c'
_ctxc.shadowBlur = 5
// 填充漸變色
_ctxc.fill()

// 取消陰影
_ctxc.shadowOffsetX = 0
_ctxc.shadowOffsetY = 0
_ctxc.shadowColor = '#ffffff'
_ctxc.shadowBlur = 0
// 繪製中間的文案
_ctxc.font = `normal normal bold 36px sans-serif`
_ctxc.fillStyle = '#ffffff'
_ctxc.setTextBaseline('middle')
_ctxc.setTextAlign('center')
_ctxc.fillText(`當即打卡`, SHARE_TO_CHAT_CANVAS_WIDTH / 2, btn_h + r)
// 繪製
_ctxc.draw()
複製代碼

如今的代碼在模擬器上能夠完美的繪製出我想要的結果,以下圖學習

file

可是在真機上不行。咱們能夠看到在開發工具上是有陰影效果的,可是在真機上的效果倒是沒有陰影的。以下圖開發工具

file

因此我要作的就是逐步排查,要依次肯定下面幾個問題的答案:測試

問題一:看一下官方文檔給出的代碼在真機上能不可以顯示出來陰影。

官方文檔給出的代碼以下:字體

const ctx = wx.createCanvasContext('myCanvas')
ctx.setFillStyle('red')
ctx.setShadow(10, 50, 50, 'blue')
ctx.fillRect(10, 10, 150, 75)
ctx.draw()
複製代碼

咱們直接測試一下在編輯器和手機上的效果,編輯器上的效果以下:

file

模擬器上是能夠顯示效果的,真機上的效果以下:

file

也是能夠顯示的,這說明在真機上的確是能夠繪製出來陰影的。

可是我同時也注意到,這個實例的代碼使用的是老的API。

file

因此我再次嘗試把老的API替換成新的API進行測試

代碼修改以下:

// ...省略部分代碼
const ctx = wx.createCanvasContext('share-to-chat')
ctx.setFillStyle('red')
// ctx.setShadow(10, 50, 50, 'blue')
// 使用新的API
ctx.shadowOffsetX = 10
ctx.shadowOffsetY = 50
ctx.shadowColor = 'blue'
ctx.shadowBlur = 50

ctx.fillRect(10, 10, 150, 75)
ctx.draw()
複製代碼

此次修改以後,在編輯器上繪圖沒有發生什麼變化。可是,在真機上卻顯示不出來了,只有一個紅色的矩形,以下圖所示:

file

因此到這裏咱們能夠知道,使用新的繪製陰影的API在我這臺真機上是繪製不出來陰影的。那咱們就先使用老的API進行陰影的繪製,到這裏這個問題已經有了一點進展了,咱們繼續進行排查。

問題二:是否可以繪製出來圓角的陰影

咱們上面的測試繪製的陰影是矩形的陰影,若是咱們繪製的是一個圓弧呢?還能繪製出來陰影嗎?咱們接着向下走。此次咱們先繪製一個圓形,而後再給這個圓添加一個陰影。那麼代碼以下:

// ...省略部分代碼
const ctx = wx.createCanvasContext('share-to-chat')
ctx.arc(100, 75, 50, 0, 2 * Math.PI)
ctx.setFillStyle('red')
ctx.setShadow(10, 50, 50, 'blue')
// ctx.shadowOffsetX = 10
// ctx.shadowOffsetY = 50
// ctx.shadowColor = 'blue'
// ctx.shadowBlur = 50
ctx.fill()
ctx.draw()
複製代碼

此次在編輯器上的效果以下:

file

在手機上的效果以下:

file

也是能夠的,那麼按道理來講,若是咱們使用老版本繪製陰影的API的話,咱們繪製的這個圓形按鈕也應該可以顯示出來陰影。來咱們來試一試吧。

修改最初的代碼以下:

// ...省略部分代碼 
_ctxc.setFillStyle(grd)
// 設置陰影
// _ctxc.shadowOffsetX = 2
// _ctxc.shadowOffsetY = 2
// _ctxc.shadowColor = '#43454c'
// _ctxc.shadowBlur = 5
// 使用老的API
_ctxc.setShadow(2, 2, 5, '#43454c')
// 填充漸變色
_ctxc.fill()
// ...省略部分代碼
複製代碼

在編輯器上仍是能夠正常繪製陰影的,可是在手機上仍是不可以顯示陰影。

那麼問題出如今哪裏呢?這時候就要找可以繪製出來陰影和不可以繪製出來陰影這兩種狀況咱們改變了什麼。

問題3:在繪製漸變色背景按鈕的同時是否能夠繪製陰影

想到這裏,我就猜測會不會是由於我繪製的圓形按鈕使用的是漸變色背景的緣由,致使咱們沒有辦法繪製出來陰影呢?仍是要實踐一下,繼續修改代碼。此次我不使用漸變色背景,而改成使用純色背景來測試一下。修改代碼以下:

// ...省略部分代碼
// 添加漸變色
// const grd = _ctxc.createLinearGradient((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2 - r, btn_h, (SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2 + r, btn_h)
// grd.addColorStop(0, first_color)
// grd.addColorStop(1, second_color)
// _ctxc.setFillStyle(grd)

// 使用純色背景
_ctxc.setFillStyle('#4DAEFE')

// 設置陰影
// _ctxc.shadowOffsetX = 2
// _ctxc.shadowOffsetY = 2
// _ctxc.shadowColor = '#43454c'
// _ctxc.shadowBlur = 5
// 使用老的API
_ctxc.setShadow(2, 2, 5, '#43454c')
// 填充漸變色
_ctxc.fill()
// ...省略部分代碼
複製代碼

此次在編輯器的顯示以下圖:

file

是有陰影的,那麼在手機上效果如何呢?咱們看一下:

file

很棒,此次終於在真機上也繪製出來的陰影了;距離咱們成功也不遠啦。

那麼咱們接下來要解決的問題就是,如何可以把陰影和漸變色背景都添加上去,這一次咱們魚和熊掌都想獲得。

那怎麼辦呢,辦法總比問題多,咱們只須要在繪製好陰影的基礎上再繪製一次漸變的背景就能夠了。

就是先繪製一個純色的帶有陰影的按鈕,而後在一樣的位置咱們再次繪製一個有漸變背景色的按鈕,最後繪製文字就好啦。真是機智如我呀。最終的代碼以下:

// ...省略部分代碼
// 開始繪製
_ctxc.beginPath()
// 繪製左邊圓弧
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2, btn_h + r, r, 0.5 * Math.PI, 1.5 * Math.PI)
// 繪製右邊圓弧
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2, btn_h + r, r, -0.5 * Math.PI, 0.5 * Math.PI)
// 繪製中間的漸變矩形
_ctxc.closePath()
_ctxc.setFillStyle('#000')

// 設置陰影
// 新版本添加陰影
_ctxc.shadowOffsetX = 5
_ctxc.shadowOffsetY = 5
_ctxc.shadowColor = '#a5a6a7'
_ctxc.shadowBlur = 5
// 舊版本添加陰影
_ctxc.setShadow(5, 5, 5, '#a5a6a7')

_ctxc.fill()

// 重置取消陰影
// 新版本重置陰影
_ctxc.shadowOffsetX = 0
_ctxc.shadowOffsetY = 0
_ctxc.shadowColor = '#ffffff'
_ctxc.shadowBlur = 0
// 舊版本重置陰影
_ctxc.setShadow(0, 0, 0, '#ffffff')

// 繪製漸變色
_ctxc.beginPath()
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2, btn_h + r, r, 0.5 * Math.PI, 1.5 * Math.PI)
// 繪製右邊圓弧
_ctxc.arc((SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2, btn_h + r, r, -0.5 * Math.PI, 0.5 * Math.PI)
// 關閉路徑
_ctxc.closePath()
const grd = _ctxc.createLinearGradient((SHARE_TO_CHAT_CANVAS_WIDTH - w) / 2 - r, btn_h, (SHARE_TO_CHAT_CANVAS_WIDTH + w) / 2 + r, btn_h)
grd.addColorStop(0, first_color)
grd.addColorStop(1, second_color)
_ctxc.setFillStyle(grd)
_ctxc.fill()

// 當即打卡的文案字體大小
_ctxc.font = `normal normal bold 40px sans-serif`
_ctxc.fillStyle = '#ffffff'
_ctxc.setTextBaseline('middle')
_ctxc.setTextAlign('center')
_ctxc.fillText(`當即打卡`, SHARE_TO_CHAT_CANVAS_WIDTH / 2, btn_h + r)

// 繪製
_ctxc.draw()

// ...省略部分代碼
複製代碼

讓咱們來看一下在手機上的效果吧:

file

這一次終於完美地解決了這個問題,開心。

還有,一些同窗可能注意到,我上面的代碼在添加陰影的時候新版本和老版本的API我都使用了,主要是由於我可以測試的手機比較少,不知道在別的品牌的手機上表現如何。因此爲了保險起見,我兩種方法都使用了。

還有一點須要注意的是,我本次實踐的環境是:基礎調試庫 2.3.0手機型號 iPhone 8

最終這個帶陰影的有漸變背景色的按鈕就完成啦。

第三步:總結與思考

關於小程序繪圖此次遇到的問題咱們能夠總結一下:遇到在編輯器和真機表現不同的狀況,咱們首先應該先上網查一下看看小夥伴們有沒有遇到相似的問題,若是人家已經有比較好的解決方案,咱們就能夠參考別人的解決方案去解決咱們本身遇到的問題,這樣會比較省時省力。若是沒有的話,咱們就須要本身去逐步排查問題,不斷地縮小出現問題的範圍,最終定位出出現問題的地方;而後再去想辦法解決。

其實,若是想達到這樣的效果,咱們不必定非得經過代碼繪製去實現這麼一個功能;也能夠直接讓設計師把按鈕這一部分導出一張小的圖片來,咱們直接把這個包含陰影的按鈕圖片繪製在圖上就行了。若是咱們這個按鈕是不常常發生變化的話,那麼直接把包含陰影按鈕的圖片繪製在畫布上也許是挺好的一個解決方法。因此,咱們首先要考慮的是咱們的代碼想要達到什麼樣的效果,那麼達到這樣的效果有哪些途徑,各有什麼優缺點。而後咱們選擇一個最佳的方案去開發就能夠啦。

這篇文章到這裏就結束啦,但願個人分享可以幫助到一些遇到一樣繪圖問題的小夥伴。最後一點私心,推薦一下咱們開發的這一款小程序主線程

file

一個能夠幫助你們規劃時間和任務,而且能夠組隊學習找夥伴一塊兒打卡的小程序,若是你以爲的不錯的話,記得幫咱們分享一下喲。

相關文章
相關標籤/搜索