午夜91福利视频,午夜成人在线观看,午夜在线视频免费观看,午夜福利短视频,精品午夜成人免费视频APP

小程序模板網

輕松生成小程序分享海報

發布時間:2018-09-01 09:51 所屬欄目:小程序開發教程

小程序海報組件

 

需求

小程(cheng)序(xu)分(fen)享到朋友圈只能使(shi)用(yong)(yong)(yong)小程(cheng)序(xu)碼海(hai)報來實(shi)現,生成(cheng)小程(cheng)序(xu)碼的(de)(de)方式有(you)兩種,一種是使(shi)用(yong)(yong)(yong)后端方式,一種是使(shi)用(yong)(yong)(yong)小程(cheng)序(xu)自(zi)帶的(de)(de)canvas生成(cheng);后端的(de)(de)方式開(kai)發難(nan)度大,由于生成(cheng)圖(tu)片耗用(yong)(yong)(yong)內存比較大對(dui)服務端也是不(bu)小的(de)(de)壓(ya)力;所以使(shi)用(yong)(yong)(yong)小程(cheng)序(xu)的(de)(de)canvas是一個不(bu)錯的(de)(de)選擇,但由于canvas水(shui)比較深,坑比較多(duo),還有(you)不(bu)同海(hai)報需要重(zhong)現寫渲染流(liu)程(cheng),導致(zhi)代碼冗(rong)余難(nan)以維(wei)護,加上不(bu)同設備版本(ben)的(de)(de)情況不(bu)一樣,因此(ci)小程(cheng)序(xu)海(hai)報生成(cheng)組件(jian)的(de)(de)需求(qiu)十分(fen)迫切。

在實際開(kai)發中(zhong)(zhong),我發現(xian)海報中(zhong)(zhong)的元素無(wu)非一(yi)下幾(ji)種(zhong),只要實現(xian)這幾(ji)種(zhong),就可以通過一(yi)份配置文件生成各種(zhong)各樣的海報了。

海報中的元素分類

 

要解決的問題

  • 單位問題
  • canvas隱藏問題
  • 圓角矩形、圓角圖片
  • 多段文字
  • 超長文字和多行文字縮略問題
  • 矩形包含文字
  • 多個元素間的層級問題
  • 圖片尺寸和渲染尺寸不一致問題
  • canvas轉圖片
  • IOS 6.6.7 clip問題
  • 關于獲取canvas實例

單位問題

canvas繪制使用(yong)的是(shi)px單位(wei),但不(bu)同(tong)設備(bei)的px是(shi)需要換(huan)算的,所以在組件中統(tong)一(yi)使用(yong)rpx單位(wei),這(zhe)里就涉及到單位(wei)怎(zen)么(me)換(huan)算問題。

通過(guo)wx.getSystemInfoSync獲(huo)取設備屏(ping)幕尺寸,從而(er)得(de)到比例,進而(er)做(zuo)轉(zhuan)換,代碼如下:

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

canvas隱藏問題

在(zai)繪制(zhi)海報(bao)過程時(shi),我們(men)不(bu)想讓用戶看到(dao)canvas,所以(yi)(yi)我們(men)必須(xu)把canvas隱(yin)藏起來,一開(kai)始想到(dao)的(de)(de)是使用display:none; 但這(zhe)樣在(zai)轉化成圖片時(shi)會空白,所以(yi)(yi)這(zhe)個是行不(bu)通的(de)(de),所以(yi)(yi)只能控制(zhi)canvas的(de)(de)絕對(dui)定(ding)位,將其(qi)移出(chu)可(ke)視界(jie)面(mian),代碼(ma)如下:

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

圓角矩形、圓角圖片

由于canvas沒有提供現成的(de)圓(yuan)角api,所以我們只能(neng)手工畫啦,實(shi)際上(shang)圓(yuan)角矩形就是(shi)由4條線(黃色(se))和4個圓(yuan)弧(hu)(紅色(se))組成的(de),如下:

 

圓(yuan)弧可以使(shi)用canvasContext.arcTo這(zhe)個(ge)api實(shi)現,這(zhe)個(ge)api的(de)入參由兩(liang)個(ge)控制點一個(ge)半徑組成,對應上(shang)圖的(de)示例

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

接下來我們就可以(yi)非常輕松的(de)寫(xie)出生(sheng)成圓角矩形的(de)函數(shu)啦

/**
 * 畫圓角矩形
 */
_drawRadiusRect(x, y, w, h, r) {
    const br = r / 2;
    this.ctx.beginPath();
    this.ctx.moveTo(this.toPx(x + br), this.toPx(y));            // 移動到左上角的點
    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() 方(fang)法從原(yuan)始畫(hua)(hua)布中剪(jian)切(qie)任意形狀和(he)尺寸。一旦剪(jian)切(qie)了某個區(qu)域(yu),則所有之后(hou)的繪圖都會被限制在被剪(jian)切(qie)的區(qu)域(yu)內(不能訪(fang)問畫(hua)(hua)布上的其他區(qu)域(yu))。可以(yi)在使(shi)(shi)用(yong) clip() 方(fang)法前通過使(shi)(shi)用(yong) save() 方(fang)法對當前畫(hua)(hua)布區(qu)域(yu)進行(xing)保存(cun),并在以(yi)后(hou)的任意時(shi)間對其進行(xing)恢(hui)復(fu)(通過 restore() 方(fang)法)。

多段文字

如果(guo)是(shi)連續多(duo)段不同格式的(de)文字(zi),如果(guo)讓用戶每段文字(zi)都(dou)指定坐(zuo)標(biao)是(shi)不現(xian)實的(de),因為上一(yi)段文字(zi)的(de)長度(du)是(shi)不固定的(de),這里(li)的(de)解(jie)決方案是(shi)使用 ctx.measureText (基礎庫(ku) 1.9.90 開始支持)Api來計算(suan)一(yi)段文字(zi)的(de)寬度(du),記住這里(li)返(fan)回寬度(du)的(de)單位(wei)是(shi)px( 坑 ),從(cong)而知(zhi)道下一(yi)段文字(zi)的(de)坐(zuo)標(biao)。

超長文字和多行文字縮略問題

設(she)置(zhi)文字的(de)寬度,通過(guo) ctx.measureText 知道文字的(de)寬度,如果超出(chu)設(she)定的(de)寬度,超出(chu)部分使用“...”代替;對于多(duo)行文字,經測試發現(xian)字體的(de)高度大約等于字體大小,并提(ti)供lineHeight參數(shu)讓用戶(hu)可以(yi)自定義(yi)行高,這樣(yang)我們就可以(yi)知道下一行的(de)y軸坐標(biao)了。

矩形包含文字

這(zhe)(zhe)個同(tong)樣使用(yong) ctx.measureText 接口,從而控制矩形的寬度,當然這(zhe)(zhe)里(li)用(yong)戶(hu)還可以設(she)置(zhi)paddingLeft和paddingRight字段;

文字(zi)(zi)的(de)垂直居中(zhong)問題可以(yi)設置文字(zi)(zi)的(de)基線對齊(qi)方(fang)式為middle( this.ctx.setTextBaseline('middle'); ),設置文字(zi)(zi)的(de)坐標為矩形的(de)中(zhong)線就可以(yi)了;水(shui)平(ping)居中(zhong) this.ctx.setTextAlign('center'); ;

 

多個元素間的層級問題

由于canvas沒有Api可以設置繪制(zhi)元素(su)的(de)層級,只(zhi)能是根據后繪制(zhi)層級高于前面繪制(zhi)的(de)方式,所(suo)以需(xu)要(yao)用戶(hu)傳入zIndex字段(duan),利用數組排序(Array.prototype.sort)后再根據順序繪制(zhi)。

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

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

如果使用(yong) drawImage(dx, dy, dWidth, dHeight) ,圖片(pian)會(hui)壓縮尺寸以(yi)適應繪制的尺寸,圖片(pian)會(hui)變(bian)形,如下圖:

在(zai)基(ji)礎(chu)庫1.9.0起支持 drawImage(sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)  ,sx和sy是(shi)(shi)源圖(tu)像的矩(ju)形選(xuan)擇(ze)框左(zuo)上角的坐(zuo)標,sWidth和sHeight是(shi)(shi)源圖(tu)像的矩(ju)形選(xuan)擇(ze)框的寬度(du)(du)和高度(du)(du),如下(xia)圖(tu):

 

如果繪(hui)制(zhi)(zhi)尺(chi)寸(cun)(cun)比源(yuan)(yuan)圖(tu)尺(chi)寸(cun)(cun)寬,那么繪(hui)制(zhi)(zhi)尺(chi)寸(cun)(cun)的(de)寬度就等于(yu)(yu)源(yuan)(yuan)圖(tu)寬度;反之,繪(hui)制(zhi)(zhi)尺(chi)寸(cun)(cun)比源(yuan)(yuan)圖(tu)尺(chi)寸(cun)(cun)高,那么繪(hui)制(zhi)(zhi)尺(chi)寸(cun)(cun)的(de)高度等于(yu)(yu)源(yuan)(yuan)圖(tu)高度;

我們可以通過(guo) wx.getImageInfo Api獲(huo)取(qu)源圖的(de)尺寸;

canvas轉圖片

在(zai)(zai)canvas繪(hui)制完成后調用(yong)(yong) wx.canvasToTempFilePath Api將canvas轉為圖片輸出,這樣(yang)需要(yao)注意, wx.canvasToTempFilePath 需要(yao)寫在(zai)(zai) this.ctx.draw 的(de)回調中,并(bing)且(qie)在(zai)(zai)組件中使用(yong)(yong)這個(ge)接口需要(yao)在(zai)(zai)第二個(ge)入(ru)參傳入(ru)this( 坑 ),如(ru)下(xia)

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);
});


易(yi)優小程序(企業版)+靈活(huo)api+前后(hou)代碼(ma)開源 碼云(yun)倉庫:
本文地址://www.jinyoudianli.com/wxmini/doc/course/24758.html 復制鏈接 如需定制請聯系易優客服咨詢:

工作日 8:30-12:00 14:30-18:00
周六及(ji)部(bu)分節假日提供值班服務

易小優(you)
轉人工(gong) ×