輕松生成小程序分享海報(bào)

小程序海報(bào)組件

https://github.com/jasondu/wx...

需求

小程序分享到朋友圈只能使用小程序碼海報(bào)來實(shí)現(xiàn)溜歪,生成小程序碼的方式有兩種若专,一種是使用后端方式,一種是使用小程序自帶的canvas生成蝴猪;后端的方式開發(fā)難度大富岳,由于生成圖片耗用內(nèi)存比較大對(duì)服務(wù)端也是不小的壓力;所以使用小程序的canvas是一個(gè)不錯(cuò)的選擇拯腮,但由于canvas水比較深,坑比較多蚁飒,還有不同海報(bào)需要重現(xiàn)寫渲染流程动壤,導(dǎo)致代碼冗余難以維護(hù),加上不同設(shè)備版本的情況不一樣淮逻,因此小程序海報(bào)生成組件的需求十分迫切琼懊。

在實(shí)際開發(fā)中阁簸,我發(fā)現(xiàn)海報(bào)中的元素?zé)o非一下幾種,只要實(shí)現(xiàn)這幾種哼丈,就可以通過一份配置文件生成各種各樣的海報(bào)了启妹。

海報(bào)中的元素分類

要解決的問題

  • 單位問題
  • canvas隱藏問題
  • 圓角矩形、圓角圖片
  • 多段文字
  • 超長(zhǎng)文字和多行文字縮略問題
  • 矩形包含文字
  • 多個(gè)元素間的層級(jí)問題
  • 圖片尺寸和渲染尺寸不一致問題
  • canvas轉(zhuǎn)圖片
  • IOS 6.6.7 clip問題
  • 關(guān)于獲取canvas實(shí)例

單位問題

canvas繪制使用的是px單位醉旦,但不同設(shè)備的px是需要換算的饶米,所以在組件中統(tǒng)一使用rpx單位,這里就涉及到單位怎么換算問題车胡。

通過wx.getSystemInfoSync獲取設(shè)備屏幕尺寸檬输,從而得到比例,進(jìn)而做轉(zhuǎn)換匈棘,代碼如下:

const sysInfo = wx.getSystemInfoSync();
const screenWidth = sysInfo.screenWidth;
this.factor = screenWidth / 750;    // 獲取比例
function toPx(rpx) {    // rpx轉(zhuǎn)px
    return rpx * this.factor;
}
function toRpx(px) {    // px轉(zhuǎn)rpx
    return px / this.factor;
},

canvas隱藏問題

在繪制海報(bào)過程時(shí)丧慈,我們不想讓用戶看到canvas,所以我們必須把canvas隱藏起來主卫,一開始想到的是使用display:none; 但這樣在轉(zhuǎn)化成圖片時(shí)會(huì)空白逃默,所以這個(gè)是行不通的,所以只能控制canvas的絕對(duì)定位簇搅,將其移出可視界面完域,代碼如下:

.canvas.pro {
    position: absolute;
    bottom: 0;
    left: -9999rpx;
}

圓角矩形、圓角圖片

由于canvas沒有提供現(xiàn)成的圓角api馍资,所以我們只能手工畫啦筒主,實(shí)際上圓角矩形就是由4條線(黃色)和4個(gè)圓弧(紅色)組成的鸟蟹,如下:

圓弧可以使用canvasContext.arcTo這個(gè)api實(shí)現(xiàn)乌妙,這個(gè)api的入?yún)⒂蓛蓚€(gè)控制點(diǎn)一個(gè)半徑組成,對(duì)應(yīng)上圖的示例

canvasContext.arcTo(x1, y1, x2, y2, r)

接下來我們就可以非常輕松的寫出生成圓角矩形的函數(shù)啦

/**
 * 畫圓角矩形
 */
_drawRadiusRect(x, y, w, h, r) {
    const br = r / 2;
    this.ctx.beginPath();
    this.ctx.moveTo(this.toPx(x + br), this.toPx(y));            // 移動(dòng)到左上角的點(diǎn)
    this.ctx.lineTo(this.toPx(x + w - br), this.toPx(y));        // 畫上邊的線
    this.ctx.arcTo(this.toPx(x + w), this.toPx(y), this.toPx(x + w), this.toPx(y + br), this.toPx(br));                                                    // 畫右上角的弧        
    this.ctx.lineTo(this.toPx(x + w), this.toPx(y + h - br));    // 畫右邊的線
    this.ctx.arcTo(this.toPx(x + w), this.toPx(y + h), this.toPx(x + w - br), this.toPx(y + h), this.toPx(br));                                              // 畫右下角的弧
    this.ctx.lineTo(this.toPx(x + br), this.toPx(y + h));        // 畫下邊的線
    this.ctx.arcTo(this.toPx(x), this.toPx(y + h), this.toPx(x), this.toPx(y + h - br), this.toPx(br));                                                    // 畫左下角的弧
    this.ctx.lineTo(this.toPx(x), this.toPx(y + br));            // 畫左邊的線
    this.ctx.arcTo(this.toPx(x), this.toPx(y), this.toPx(x + br), this.toPx(y), this.toPx(br));                                                    // 畫左上角的弧
}

如果是 畫線框 就使用 this.ctx.stroke();

如果是 畫色塊 就使用 this.ctx.fill();

如果是 圓角圖片 就使用

this.ctx.clip();
this.ctx.drawImage(***);

clip() 方法從原始畫布中剪切任意形狀和尺寸建钥。一旦剪切了某個(gè)區(qū)域藤韵,則所有之后的繪圖都會(huì)被限制在被剪切的區(qū)域內(nèi)(不能訪問畫布上的其他區(qū)域)⌒芫可以在使用 clip() 方法前通過使用 save() 方法對(duì)當(dāng)前畫布區(qū)域進(jìn)行保存泽艘,并在以后的任意時(shí)間對(duì)其進(jìn)行恢復(fù)(通過 restore() 方法)。

多段文字

如果是連續(xù)多段不同格式的文字镐依,如果讓用戶每段文字都指定坐標(biāo)是不現(xiàn)實(shí)的匹涮,因?yàn)樯弦欢挝淖值拈L(zhǎng)度是不固定的,這里的解決方案是使用 ctx.measureText (基礎(chǔ)庫(kù) 1.9.90 開始支持)Api來計(jì)算一段文字的寬度槐壳,記住這里返回寬度的單位是px( )然低,從而知道下一段文字的坐標(biāo)。

超長(zhǎng)文字和多行文字縮略問題

設(shè)置文字的寬度,通過 ctx.measureText 知道文字的寬度雳攘,如果超出設(shè)定的寬度带兜,超出部分使用“...”代替;對(duì)于多行文字吨灭,經(jīng)測(cè)試發(fā)現(xiàn)字體的高度大約等于字體大小刚照,并提供lineHeight參數(shù)讓用戶可以自定義行高,這樣我們就可以知道下一行的y軸坐標(biāo)了喧兄。

矩形包含文字

這個(gè)同樣使用 ctx.measureText 接口无畔,從而控制矩形的寬度,當(dāng)然這里用戶還可以設(shè)置paddingLeft和paddingRight字段繁莹;

文字的垂直居中問題可以設(shè)置文字的基線對(duì)齊方式為middle( this.ctx.setTextBaseline('middle'); )檩互,設(shè)置文字的坐標(biāo)為矩形的中線就可以了;水平居中 this.ctx.setTextAlign('center'); ;

多個(gè)元素間的層級(jí)問題

由于canvas沒有Api可以設(shè)置繪制元素的層級(jí)咨演,只能是根據(jù)后繪制層級(jí)高于前面繪制的方式闸昨,所以需要用戶傳入zIndex字段,利用數(shù)組排序(Array.prototype.sort)后再根據(jù)順序繪制薄风。

圖片尺寸和渲染尺寸不一致問題

繪制圖片我們使用 ctx.drawImage() API饵较;

如果使用 drawImage(dx, dy, dWidth, dHeight) ,圖片會(huì)壓縮尺寸以適應(yīng)繪制的尺寸遭赂,圖片會(huì)變形循诉,如下圖:

在基礎(chǔ)庫(kù)1.9.0起支持 drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight),sx和sy是源圖像的矩形選擇框左上角的坐標(biāo)撇他,sWidth和sHeight是源圖像的矩形選擇框的寬度和高度茄猫,如下圖:

如果繪制尺寸比源圖尺寸寬,那么繪制尺寸的寬度就等于源圖寬度困肩;反之稍浆,繪制尺寸比源圖尺寸高篙程,那么繪制尺寸的高度等于源圖高度黎做;

我們可以通過 wx.getImageInfo Api獲取源圖的尺寸随夸;

canvas轉(zhuǎn)圖片

在canvas繪制完成后調(diào)用 wx.canvasToTempFilePath Api將canvas轉(zhuǎn)為圖片輸出,這樣需要注意潭枣, wx.canvasToTempFilePath 需要寫在 this.ctx.draw 的回調(diào)中比默,并且在組件中使用這個(gè)接口需要在第二個(gè)入?yún)魅雝his( ),如下

this.ctx.draw(false, () => {
    wx.canvasToTempFilePath({
        canvasId: 'canvasid',
        success: (res) => {
            wx.hideLoading();
            this.triggerEvent('success', res.tempFilePath);
        },
        fail: (err) => {
            wx.hideLoading();
            this.triggerEvent('fail', err);
        }
    }, this);
});

IOS 6.6.7 clip問題

在IOS 6.6.7版本中clip方法連續(xù)裁剪圖片時(shí),只有第一張有效盆犁,這是微信的bug命咐,官方也證實(shí)了( https://developers.weixin.qq....

關(guān)于獲取canvas實(shí)例

我們可以使用 wx.createCanvasContext 獲取小程序?qū)嵗诮M件中使用切記第二個(gè)參數(shù)需要帶上this谐岁,如下

this.ctx = wx.createCanvasContext('canvasid', this);

如何使用組件

https://github.com/jasondu/wx...

專欄作家

weizaidu醋奠。小程序社區(qū)博主瓮下,堅(jiān)持原創(chuàng)分享技術(shù)博文。

本文原創(chuàng)發(fā)布于小程序社區(qū)钝域。未經(jīng)許可,禁止轉(zhuǎn)載

原文地址:輕松生成小程序分享海報(bào)-小程序社區(qū)/博主專區(qū)-微信小程序開發(fā)社區(qū)-微信小程序聯(lián)盟

相關(guān)文章:

小程序生成海報(bào)保存分享圖片完全指南

微信小程序朋友圈分享圖片生成方案實(shí)現(xiàn)

微信小程序中的分享事件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锭魔,一起剝皮案震驚了整個(gè)濱河市例证,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迷捧,老刑警劉巖织咧,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異漠秋,居然都是意外死亡笙蒙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門庆锦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來捅位,“玉大人,你說我怎么就攤上這事搂抒⊥Р螅” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵求晶,是天一觀的道長(zhǎng)焰雕。 經(jīng)常有香客問我,道長(zhǎng)芳杏,這世上最難降的妖魔是什么矩屁? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮爵赵,結(jié)果婚禮上吝秕,老公的妹妹穿的比我還像新娘。我一直安慰自己亚再,他們只是感情好郭膛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著氛悬,像睡著了一般则剃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上如捅,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天棍现,我揣著相機(jī)與錄音,去河邊找鬼镜遣。 笑死己肮,一個(gè)胖子當(dāng)著我的面吹牛士袄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谎僻,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼娄柳,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了艘绍?” 一聲冷哼從身側(cè)響起赤拒,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诱鞠,沒想到半個(gè)月后挎挖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡航夺,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年蕉朵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阳掐。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡始衅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锚烦,到底是詐尸還是另有隱情觅闽,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布涮俄,位于F島的核電站蛉拙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏彻亲。R本人自食惡果不足惜孕锄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望苞尝。 院中可真熱鬧畸肆,春花似錦、人聲如沸宙址。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抡砂。三九已至大咱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間注益,已是汗流浹背碴巾。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丑搔,地道東北人厦瓢。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓提揍,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親煮仇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子劳跃,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 第一章 HTML5 (2014年10月29日發(fā)布)新特性: 10個(gè) (1)新的語義標(biāo)簽 (2)增強(qiáng)型表單 (3)視...
    fastwe閱讀 959評(píng)論 0 1
  • 啥是canvas售碳? HTML5 標(biāo)簽用于繪制圖像(通過腳本,通常是 JavaScript)绞呈。不過, 元素本身...
    kiaizi閱讀 772評(píng)論 0 4
  • 線條樣式 繪制直線间景,第五章知識(shí)簡(jiǎn)單回顧 lineWidth 設(shè)置或返回當(dāng)前的線條寬度佃声,單位為像素 lineCap ...
    Zd_silent閱讀 476評(píng)論 0 0
  • 最怕一生碌碌無為封拧,還說平凡可貴 站酷網(wǎng)看到一篇這樣的文章志鹃,寫的是愛情,感觸頗深泽西! 今天又刷屏的“逃離北上廣” 引發(fā)...
    啡常識(shí)閱讀 258評(píng)論 2 1
  • 2015-09-08周二 晴 真正關(guān)注股市是去年12月份曹铃,某天看新聞?wù)f牛市要來了,于是持續(xù)關(guān)注了好一段時(shí)間捧杉。到今年...
    韓日記閱讀 611評(píng)論 0 3