摘要:海報(bào)生成示例最近智酷君在做小程序生成海報(bào)的項(xiàng)目中遇到一些棘手的問(wèn)題,在網(wǎng)上查閱了各種資料,也踩扁了各種坑,智酷君希望把這些填坑經(jīng)驗(yàn)整理一下分享出來(lái),避免后來(lái)的兄弟重復(fù)掉坑。
海報(bào)生成示例
最近智酷君在做[小程序]canvas生成海報(bào)的項(xiàng)目中遇到一些棘手的問(wèn)題,在網(wǎng)上查閱了各種資料,也踩扁了各種坑,智酷君希望把這些“填坑”經(jīng)驗(yàn)整理一下分享出來(lái),避免后來(lái)的兄弟重復(fù)“掉坑”。
原型圖
這是一個(gè)大致的原型圖,下面來(lái)看下如何制作這個(gè)海報(bào),以及整體的思路。
海報(bào)生成流程
### [代碼片段]Canvas生成海報(bào)實(shí)戰(zhàn)demo
demo的微信路徑:https://developers.weixin.qq....
demo的ID:Q74OU3m57c9x
如果你裝了IDE工具,可以直接訪問(wèn)上面的demo路徑
通過(guò)代碼片段將demo的ID輸入進(jìn)去也可添加:
下面分享下主要的代碼內(nèi)容和“填坑現(xiàn)場(chǎng)”:一、添加字體
https://developers.weixin.qq.com/miniprogram/dev/api/canvas/font.html
canvasContext.font = value //示例 ctx.font = `normal bold 20px sans-serif`//設(shè)置字體大小,默認(rèn)10 ctx.setTextAlign("left"); ctx.setTextBaseline("top"); ctx.fillText("《智酷方程式》專(zhuān)注研究和分享前端技術(shù)", 50, 15, 250)//繪制文本
符合 CSS font 語(yǔ)法的 DOMString 字符串,至少需要提供字體大小和字體族名。默認(rèn)值為 10px sans-serif
文字過(guò)長(zhǎng)在canvas下?lián)Q行問(wèn)題處理(最多兩行,超過(guò)“...”代替)ctx.setTextAlign("left"); ctx.setFillStyle("#000");//文字顏色:默認(rèn)黑色 ctx.font = `normal bold 18px sans-serif`//設(shè)置字體大小,默認(rèn)10 let canvasTitleArray = canvasTitle.split(""); let firstTitle = ""; //第一行字 let secondTitle = ""; //第二行字 for (let i = 0; i < canvasTitleArray.length; i++) { let element = canvasTitleArray[i]; let firstWidth = ctx.measureText(firstTitle).width; //console.log(ctx.measureText(firstTitle).width); if (firstWidth > 260) { let secondWidth = ctx.measureText(secondTitle).width; //第二行字?jǐn)?shù)超過(guò),變?yōu)?.. if (secondWidth > 260) { secondTitle += "..."; break; } else { secondTitle += element; } } else { firstTitle += element; } } //第一行文字 ctx.fillText(firstTitle, 20, 278, 280)//繪制文本 //第二行問(wèn)題 if (secondTitle) { ctx.fillText(secondTitle, 20, 300, 280)//繪制文本 }
通過(guò) ctx.measureText 這個(gè)方法可以判斷文字的寬度,然后進(jìn)行切割。
(一行字允許寬度為280時(shí),判斷需要寫(xiě)小點(diǎn),比如260)
let mainImg = "https://demo.com/url.jpg"; wx.getImageInfo({ src: mainImg,//服務(wù)器返回的圖片地址 success: function (res) { //處理圖片縱橫比例過(guò)大或者過(guò)小的問(wèn)題?。?! let h = res.height; let w = res.width; let setHeight = 280, //默認(rèn)源圖截取的區(qū)域 setWidth = 220; //默認(rèn)源圖截取的區(qū)域 if (w / h > 1.5) { setHeight = h; setWidth = parseInt(280 / 220 * h); } else if (w / h < 1) { setWidth = w; setHeight = parseInt(220 / 280 * w); } else { setHeight = h; setWidth = w; }; console.log(setWidth, setHeight) ctx.drawImage(res.path, 0, 0, setWidth, setHeight, 20, 50, 280, 220); ctx.draw(true); }, fail: function (res) { //失敗回調(diào) } });
在開(kāi)發(fā)過(guò)程中如果封面圖無(wú)法按照約定的比例(280x220)給到:
那么我們就需要處理默認(rèn)封面圖過(guò)大或者過(guò)小的問(wèn)題,大致思路是:代碼中通過(guò)比較縱橫比(280/220=1.27)正比例放大或者縮小原圖,然后從左上切割,竟可能保證過(guò)高的圖是寬度100%,過(guò)寬的圖是高度100%。
在canvas中draw圖片,必須是一個(gè)(相對(duì))本地路徑,我們可以通過(guò)將圖片保存在本地后生成的臨時(shí)路徑。
微信官方提供兩個(gè)API:
wx.downloadFile(OBJECT)和wx.getImageInfo(OBJECT)。都需先配置download域名才能生效。
ctx.save(); //保存畫(huà)圖板 ctx.beginPath()//開(kāi)始創(chuàng)建一個(gè)路徑 ctx.arc(35, 25, 15, 0, 2 * Math.PI, false)//畫(huà)一個(gè)圓形裁剪區(qū)域 ctx.clip()//裁剪 ctx.closePath(); ctx.drawImage(headImageLocal, 20, 10, 30, 30); ctx.draw(true); ctx.restore()//恢復(fù)之前保存的繪圖上下文
使用圖形上下文的不帶參數(shù)的clip()方法來(lái)實(shí)現(xiàn)Canvas的圖像裁剪功能。該方法使用路徑來(lái)對(duì)Canvas話不設(shè)置一個(gè)裁剪區(qū)域。因此,必須先創(chuàng)建好路徑。創(chuàng)建完整后,調(diào)用clip()方法來(lái)設(shè)置裁剪區(qū)域。
需要注意的是裁剪是對(duì)畫(huà)布進(jìn)行的,裁切后的畫(huà)布不能恢復(fù)到原來(lái)的大小,也就是說(shuō)畫(huà)布是越切越小的,要想保證最后仍然能在canvas最初定義的大小下繪圖需要注意save()和restore()。畫(huà)布是先裁切完了再進(jìn)行繪圖。并不一定非要是圖片,路徑也可以放進(jìn)去~
ctx.setFillStyle("#fff"); ctx.fillRect(0, 0, 320, 500); //第一個(gè)填充矩形 wx.downloadFile({ url: headUri, success(res) { ctx.beginPath() ctx.arc(50, 50, 25, 0, 2 * Math.PI) ctx.clip() ctx.drawImage(res.tempFilePath, 25, 25); //第二個(gè)填充圖片 ctx.draw() ctx.restore() ctx.setFillStyle("#fff"); ctx.fillRect(0, 0, 320, 500); ctx.draw(true) ctx.restore() } })
clip裁切這個(gè)功能,如果有超過(guò)一張圖片/背景疊加,則裁切效果失效。
錯(cuò)誤參考:http://html51.com/info-38753-1/
wx.canvasToTempFilePath({ fileType: "jpg", canvasId: "customCanvas", success: (res) => { console.log(res.tempFilePath) //為canvas的虛擬地址 } }) res: { errMsg: "canvasToTempFilePath:ok", tempFilePath: "http://tmp/wx02935bb29080a7b4.o6zAJswFAuZuKQ5NZfPr….cGnD1a02PlVC0b3284be3a41d08986c2477579a5fd8e.jpg" }
這里需要把canvas里面的內(nèi)容,導(dǎo)出成一個(gè)臨時(shí)地址才能保存在相冊(cè),比如:
http://tmp/wx02935bb29080a7b4...
wx.getSetting({ success(res) { console.log(res) if (!res.authSetting["scope.writePhotosAlbum"]) { //判斷權(quán)限 wx.authorize({ //獲取權(quán)限 scope: "scope.writePhotosAlbum", success() { console.log("授權(quán)成功") //轉(zhuǎn)化路徑 self.saveImg(); } }) } else { self.saveImg(); } } })
判斷是否有訪問(wèn)相冊(cè)的權(quán)限,如果沒(méi)有,則請(qǐng)求權(quán)限。
六、保存到用戶(hù)手機(jī)本地相冊(cè)wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success: function (data) { wx.showToast({ title: "保存到系統(tǒng)相冊(cè)成功", icon: "success", duration: 2000 }) }, fail: function (err) { console.log(err); if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") { console.log("當(dāng)初用戶(hù)拒絕,再次發(fā)起授權(quán)") wx.openSetting({ success(settingdata) { console.log(settingdata) if (settingdata.authSetting["scope.writePhotosAlbum"]) { console.log("獲取權(quán)限成功,給出再次點(diǎn)擊圖片保存到相冊(cè)的提示。") } else { console.log("獲取權(quán)限失敗,給出不給權(quán)限就無(wú)法正常使用的提示") } } }) } else { wx.showToast({ title: "保存失敗", icon: "none" }); } }, complete(res) { console.log(res); } })
保存到本地需要一定的時(shí)間,需要加一個(gè)loading的狀態(tài)。
七、關(guān)于組件中引用canvaslet ctx = wx.createCanvasContext("posterCanvas",this); //需要加this
在components中canvas無(wú)法選中的問(wèn)題:
在components自定義組件下,當(dāng)前組件實(shí)例的this,表示在這個(gè)自定義組件下查找擁有 canvas-id 的
如果有什么疑問(wèn)或者糾錯(cuò)可以在下面給智酷君留言。
如果智酷君的分享能夠幫助到你,或者想持續(xù)獲得最新的全棧攻略
可以在segmentfault關(guān)注我,或在VX搜索“ Geek_Club ”或者“ 智酷方程式 ”
掃描關(guān)注公眾號(hào)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/109772.html
摘要:組件模板與組件數(shù)據(jù)結(jié)合后生成的節(jié)點(diǎn)樹(shù),將被插入到組件的引用位置上。事件用于子組件向父組件傳遞數(shù)據(jù),可以傳遞任意數(shù)據(jù)。官方文檔往期回顧填坑手冊(cè)小程序生成海報(bào)一拆彈時(shí)刻小程序生成海報(bào)二 showImg(https://user-gold-cdn.xitu.io/2019/6/19/16b6e94bcde767a1?w=1069&h=652&f=jpeg&s=120912); 小程序目錄結(jié)構(gòu)...
摘要:發(fā)帖的功能只要理清思路,其實(shí)并不復(fù)雜,利用機(jī)器做內(nèi)容審查是關(guān)鍵,直接關(guān)系到小程序的整體安全。內(nèi)容檢查重點(diǎn)由于內(nèi)容安全對(duì)于小程序運(yùn)營(yíng)至關(guān)重要,稍有不慎就容易導(dǎo)致小程序被封,所以在這塊的校驗(yàn)除了常規(guī)人工檢查外,我們還可以用到微信的內(nèi)容安全。 showImg(https://segmentfault.com/img/remote/1460000019955210?w=658&h=440); ...
摘要:往期回顧打怪升級(jí)小程序評(píng)論回復(fù)和發(fā)貼功能實(shí)戰(zhàn)二填坑手冊(cè)小程序生成海報(bào)一拆彈時(shí)刻小程序生成海報(bào)二填坑手冊(cè)小程序目錄結(jié)構(gòu)和組件使用心得 showImg(https://segmentfault.com/img/remote/1460000019733090?w=818&h=516); 在學(xué)習(xí)成長(zhǎng)的過(guò)程中,常常會(huì)遇到一些自己從未接觸的事物,這就好比是打怪升級(jí),每次打倒一只怪,都會(huì)獲得經(jīng)驗(yàn),讓...
摘要:注意如果用戶(hù)一開(kāi)始沒(méi)有微信授權(quán),生成海報(bào)時(shí)又必須要用戶(hù)頭像不能使用默認(rèn)的話,那就只能老老實(shí)實(shí)走之前的流程了。組件名稱(chēng)終端類(lèi)型微信版本觸發(fā)方法關(guān)于的調(diào)用方法相冊(cè)權(quán)限需要你提供保存相冊(cè)權(quán)限獲取相冊(cè)權(quán)限成功,給出再次點(diǎn)擊圖片保存到相冊(cè)的提示。 showImg(https://segmentfault.com/img/bVbs5V8?w=343&h=517);海報(bào)生成示例 海報(bào)生成速度緩慢...
摘要:全屏蒙版彈窗遮不住的層級(jí)還是很高的,當(dāng)出現(xiàn)全屏蒙版彈窗時(shí),是無(wú)法蓋住的,可以調(diào)用微信的,不過(guò)需要注意兼容低版本在類(lèi)設(shè)置的顏色并沒(méi)有變化。 從6月份開(kāi)始到現(xiàn)在,寫(xiě)小程序?qū)⒔?個(gè)月了開(kāi)發(fā)時(shí)給自己埋了不少坑~給大家分享下我的填坑經(jīng)驗(yàn)~~ 開(kāi)發(fā)部分 1.小程序的組件修改不能觸發(fā)頁(yè)面刷新?需要在父級(jí)文件上保存下才會(huì)觸發(fā)(使用wepy開(kāi)發(fā)) 2.接口請(qǐng)求出現(xiàn)的問(wèn)題?記得勾選調(diào)試開(kāi)發(fā)工具上 不校驗(yàn)...
閱讀 2792·2021-11-17 17:01
閱讀 2177·2021-09-28 09:35
閱讀 3689·2021-09-01 11:04
閱讀 996·2020-06-22 14:41
閱讀 3038·2019-08-30 15:55
閱讀 2683·2019-08-30 15:43
閱讀 2399·2019-08-26 13:54
閱讀 2568·2019-08-26 13:48