溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

小程序怎么用canvas繪制海報(bào)

發(fā)布時(shí)間:2021-03-11 11:31:22 來(lái)源:億速云 閱讀:387 作者:小新 欄目:移動(dòng)開(kāi)發(fā)

這篇文章主要介紹小程序怎么用canvas繪制海報(bào),文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

踩坑

問(wèn)題1:為什么在canvas上畫(huà)圖片模糊?

在canvas上繪制圖片/文字的時(shí)候,我們?cè)O(shè)定canvas:375*667的寬高,會(huì)發(fā)現(xiàn)繪制出來(lái)的圖片很模糊,感覺(jué)像是一張分辨率很差的圖片,文字看起來(lái)也會(huì)有疊影。

小程序怎么用canvas繪制海報(bào)

注意:物理像素是指手機(jī)屏幕上顯示的最小單元,而設(shè)備獨(dú)立像素(邏輯像素)計(jì)算機(jī)設(shè)備中的一個(gè)點(diǎn),css 中設(shè)置的像素指的就是該像素。

原因:在前端開(kāi)發(fā)中我們知道一個(gè)屬性叫devicePixelRatio(設(shè)備像素比),該屬性決定了在渲染界面時(shí)會(huì)用幾個(gè)(通常是2個(gè))物理像素來(lái)渲染一個(gè)設(shè)備獨(dú)立像素。

舉個(gè)例,一張100*100像素大小的圖片,在retina屏幕下,會(huì)用2個(gè)像素點(diǎn)去渲染圖片的一個(gè)像素點(diǎn),相當(dāng)于圖片放大了一倍,因此圖片會(huì)變得模糊,這也是1px在retina 屏上變粗的原因。

小程序怎么用canvas繪制海報(bào)

解決: 將canvas-width和canvas-height都放大2倍,在通過(guò)style將canvas的顯示width,height縮小2 倍.

例如:

<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>

問(wèn)題2:如何處理px和rpx的轉(zhuǎn)換?

rpx是小程序里特有的尺寸單位,可以根據(jù)屏幕的寬度進(jìn)行自適應(yīng),而在iphone6/iphonex上,1rpx等于不同的px。所以很可能會(huì)導(dǎo)致在不同手機(jī)下,你的canvas展示不一致。

在繪制海報(bào)的之前,我們拿到的設(shè)計(jì)稿一般都是基于iphone6的2倍圖。而且從上一個(gè)問(wèn)題的解決,我們知道canvas的大小也是2倍的,所以我們可以直接量取2倍圖的設(shè)計(jì)稿直接繪制canvas,而尺寸需要注意一下rpxtoPx.

/**
   * 
   * @param {*} rpx 
   * @param {*} int  //是否變成整數(shù)
   factor => 0.5 //iphone6
   pixelRatio => 2 像素比
   */
toPx(rpx, int) {
    if (int) {
      return parseInt(rpx * this.factor * this.pixelRatio)
    }
    return rpx * this.factor * this.pixelRatio
  }

問(wèn)題3:關(guān)于canvasContext.measureText計(jì)算純數(shù)字的時(shí)候手機(jī)上為0

在小程序中提供this.ctx.measureText(text).width去計(jì)算文本的長(zhǎng)度,但是如果你全數(shù)字 的話(huà),你會(huì)發(fā)現(xiàn)該API永遠(yuǎn)都計(jì)算成0.所以,最后采用模擬measureText方法去計(jì)算文本長(zhǎng)度。

measureText(text, fontSize = 10) {
    text = String(text)
    text = text.split('')
    let width = 0
    text.forEach(function(item) {
      if (/[a-zA-Z]/.test(item)) {
        width += 7
      } else if (/[0-9]/.test(item)) {
        width += 5.5
      } else if (/\./.test(item)) {
        width += 2.7
      } else if (/-/.test(item)) {
        width += 3.25
      } else if (/[\u4e00-\u9fa5]/.test(item)) { // 中文匹配
        width += 10
      } else if (/\(|\)/.test(item)) {
        width += 3.73
      } else if (/\s/.test(item)) {
        width += 2.5
      } else if (/%/.test(item)) {
        width += 8
      } else {
        width += 10
      }
    })
    return width * fontSize / 10
  }

問(wèn)題4:如何保證一行字體的居中展示?多行呢?

字體的如果過(guò)長(zhǎng),會(huì)超出canvas畫(huà)布,造成繪制難看,這個(gè)時(shí)候我們就應(yīng)該讓超出的部分變成...你可以設(shè)置一個(gè)width并且循環(huán)計(jì)算計(jì)算出文本的寬度,如果超出則利用substring截取后補(bǔ)充...即可。

let fillText=''
let width = 350
for (let i = 0; i <= text.length - 1; i++) { // 將文字轉(zhuǎn)為數(shù)組,一行文字一個(gè)元素
        fillText = fillText + text[i]
        // 判斷截?cái)嗟奈恢?
        if (this.measureText(fillText, this.toPx(fontSize, true)) >= width) {
          if (line === lineNum) {
            if (i !== text.length - 1) {
              fillText = fillText.substring(0, fillText.length - 1) + '...'
            }
          }
          if (line <= lineNum) {
            textArr.push(fillText)
          }
          fillText = ''
          line++
        } else {
          if (line <= lineNum) {
            if (i === text.length - 1) {
              textArr.push(fillText)
            }
          }
        }
      }

文字劇中展示計(jì)算公式:

居中在canvas中可以用(canvas的寬度-文字寬度)/2 + x (x為字體的x軸的推移)

let w = this.measureText(text, this.toPx(fontSize, true))
this.ctx.fillText(text, this.toPx((this.canvas.width - w) / 2 + x), this.toPx(y + (lineHeight || fontSize) * index))

問(wèn)題5:在小程序中如何處理網(wǎng)絡(luò)圖?

關(guān)于在小程序里使用網(wǎng)絡(luò)圖片,比如cdn上的圖片,是需要down到微信本地進(jìn)行 LRU 管理,讓后續(xù)繪制同樣圖片時(shí),節(jié)省下載時(shí)間。所以首先需要你在微信小程序的后臺(tái)配置downloadFile合法域名,其次你可以在canvas繪制之前,最好提前去down圖片,等待圖片下載好了,再開(kāi)始繪制,以避免一些繪制失敗的問(wèn)題。

問(wèn)題6:在 IDE 中可設(shè)置 base64 的圖片數(shù)據(jù)進(jìn)行繪制,但真機(jī)上無(wú)用?

先把 base64 轉(zhuǎn)成 Uint8ClampedArray 格式。然后再通過(guò) wx.canvasPutImageData(OBJECT, this) 繪制到畫(huà)布上,然后把畫(huà)布導(dǎo)出為圖片。

問(wèn)題6:如何畫(huà)一個(gè)圓角圖片?

問(wèn)題7:關(guān)于wx.canvasToTempFilePath

使用 Canvas 繪圖成功后,直接調(diào)用該方法生成圖片,在IDE上沒(méi)有問(wèn)題,但在真機(jī)上會(huì)出現(xiàn)生成的圖片不完整的情況,可以使用一個(gè)setTimeout來(lái)解決這個(gè)問(wèn)題。

this.ctx.draw(false, () => {
        setTimeout(() => {
            Taro.canvasToTempFilePath({
              canvasId: 'canvasid',
              success: async(res) => {
                this.props.onSavePoster(res.tempFilePath)//回調(diào)事件
                // 清空畫(huà)布
                this.ctx.clearRect(0, 0, canvas_width, canvas_height)
              },
              fail: (err) => {
                console.log(err)
              }
            }, this.$scope)
          }, time)
    })

問(wèn)題8:關(guān)于canvasContext.font

fontsize 不能使用小數(shù) 如果設(shè)置 font 中字體大小部分包含小數(shù),則會(huì)導(dǎo)致整個(gè) font 設(shè)置無(wú)效。

問(wèn)題9:安卓下字體渲染錯(cuò)位?

小程序怎么用canvas繪制海報(bào)

這個(gè)問(wèn)題出現(xiàn)在安卓手機(jī)上,ios表現(xiàn)正常。一開(kāi)始看到這個(gè)問(wèn)題,摸不著頭腦,為什么有的正常居中有的卻往前了很多。后面發(fā)現(xiàn)是安卓下this.ctx.setTextAlign(textAlign) 默認(rèn)是為center,所以導(dǎo)致了錯(cuò)亂,改成left后就正常了。

問(wèn)題10:繪制一個(gè)折線(xiàn)圖

小程序怎么用canvas繪制海報(bào)

利用canvas繪制一個(gè)簡(jiǎn)單的折線(xiàn)圖,只需要利用lineTomoveTo倆個(gè)API將點(diǎn)連接即可。利用createLinearGradient繪制陰影。

思考

思考1:用json配置表生成海報(bào)的局限

現(xiàn)在的海報(bào)生成只需要按照設(shè)計(jì)稿去量取尺寸就可以,但是量取的過(guò)程還是很繁瑣的,在設(shè)計(jì)稿量不到的地方還需要手動(dòng)微調(diào)一下。 后續(xù)還可以做一個(gè)web端使用拖拽的方式去完成設(shè)計(jì)稿的事情,自動(dòng)生成json應(yīng)用到小程序的海報(bào)上。

思考2:后端生成海報(bào)的局限

海報(bào)一開(kāi)始是后端同學(xué)生成的,優(yōu)點(diǎn)是不需要前端繪制時(shí)間,也不需要去踩微信API的坑,接口返回拿到url即可展示,但是在后端生成出來(lái)的效果不佳,畢竟這種工作更加前端一些。

思考3:前端生成海報(bào)的局限

前端生成海報(bào)的時(shí)候我發(fā)現(xiàn)耗時(shí)更長(zhǎng),包括圖片的下載本地而且還需要給安卓一個(gè)特意寫(xiě)一個(gè)setTimeout去確保繪制正常。各種兼容性問(wèn)題、手機(jī)的dpr、安卓和ios等不間斷彩蛋踩到你頭禿~ 哈哈哈哈~

彩蛋

采用了最新的canvas-2d背景圖確無(wú)法繪制全部?

在canvas開(kāi)發(fā)的過(guò)程中,小程序里一直有一束微光提醒我。

小程序怎么用canvas繪制海報(bào)

我也試了試最新的canvas2d的api,的確同步了web端,寫(xiě)法也更流暢,在開(kāi)發(fā)者工具中看是一切正常,跑在手機(jī)上則,只顯示寬度的一半在各種機(jī)型下測(cè)試也是一樣。

小程序怎么用canvas繪制海報(bào)

以上是“小程序怎么用canvas繪制海報(bào)”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI