亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 課堂 > 小程序 > 正文

微信小程序利用Canvas繪制圖片和豎排文字詳解

2020-03-21 15:53:22
字體:
來源:轉載
供稿:網友

前言

閑暇時間抽個空寫了個三國殺武將手冊的小程序,中間有個需求設計的是合成武將皮膚圖、豎排的武將姓名、以及小程序碼,然后提供保存圖片到相冊,最終讓用戶可以分享到朋友圈或其他平臺。合成圖片應該按照 Canvas 的文檔來做都沒什么問題,主要是有個豎排文字的需求,這里和大家分享一下。

正文

首先放一張最終保存到相冊的圖片吧~

微信小程序,Canvas,繪制圖片,豎排文字

自我感覺良好,至少達到了我自己的預期吧~~~

下面讓我們一步一步來看看如何實現的吧。

整個圖片分為三個部分:

  • 武將圖片
  • 小程序碼
  • 武將文字信息

先來看一下 wxml 里面的代碼,主要是放了一個 canvas 標簽,控制了一下高度和寬度屬性。

<view><canvas class='share-canvas' style="width:100%;height:{{canvasHeight}}px" canvas-id="share_canvas"></canvas></view>

武將圖片

drawHeroImage: function (path) {var that = this;// 拿到canvas contextlet ctx = wx.createCanvasContext('share_canvas');// 為了保證圖片比例以及繪制的位置,先要拿到圖片的大小wx.getImageInfo({src: path,success: function (res) {// 計算圖片占比信息 let maxWidth = Math.min(res.width, that.data.canvasWidth * 0.65);let radio = maxWidth / res.width;let offsetY = (that.data.canvasHeight - res.height * radio) / 2;console.log('offsetY=' + offsetY);that.setData({imageWidth: res.width * radio,imageHeight: res.height * radio,offsetY: offsetY,});// 繪制canvas背景,不屬于繪制圖片部分ctx.setFillStyle('white')ctx.fillRect(0, 0, that.data.canvasWidth, that.data.canvasHeight);// 繪制武將圖片,path是本地路徑,不可以傳網絡url,如果是網絡圖片需要先下載ctx.drawImage(path, 10, offsetY, res.width * radio, res.height * radio)// 繪制小程序碼that.drawQrCodeImage(ctx);// 繪制勢力漢字:吳that.drawInfluence(ctx, that.data.hero.HERO.INFLUENCE);// 繪制武將姓名:陸遜that.drawName(ctx, that.data.hero.HERO.NAME);// 繪制武將稱號:江陵侯that.drawHorner(ctx, that.data.hero.HERO.HORNER);// 最終調用draw函數,生成預覽圖// 一個坑點:只能調用一次,否則后面的會覆蓋前面的ctx.draw();}});}

小程序碼

小程序碼和武將圖片是一個類型,無非就是需要計算繪制的位置,這里就不再展示相關代碼了。

武將文字信息

從剛剛的代碼可以看出,我分了3個部分來繪制,其實 吳 和 陸遜 應該是可以放到一起的,但是我在繪制的時候發現,空格在繪制的時候會引起異常,導致空格后面的文字無法繪制出來,所以我這里 吳 和 陸遜 中間的空白是靠位置偏移來做的。

這里就展示一下如何繪制武將稱號的。

// 繪制武將稱號:江陵侯drawHorner: function (ctx, text) {// 設置字號ctx.setFontSize(26);// 設置字體顏色ctx.setFillStyle("#000000");// 計算繪制起點let x = this.data.offsetX + 35;let y = this.data.offsetY + 10;console.log('drawHorner' + text);console.log(x);console.log(y);// 繪制豎排文字,這里是個Util函數,具體實現請繼續看Canvas.drawTextVertical(ctx, text, x, y);}

繪制豎排文字從網上找了個開源的代碼,需要看原理的請看 這里

當然我這里為了適用小程序做了些改動,函數原型是這樣子的:

CanvasRenderingContext2D.prototype.letterSpacingText = function (text, x, y, letterSpacing)

原諒我不是很會 js ,完全不懂這是個什么語法,看了一會沒弄懂,感覺像是給類添加新的屬性,不管他。

不管白貓黑貓,能抓到耗子就是好貓

改造后的函數像下面的樣子:

canvas.js /*** @author zhangxinxu(.com)* @licence MIT* @description http://www.zhangxinxu.com/wordpress/?p=7362*/function drawTextVertical(context, text, x, y) {var arrText = text.split('');var arrWidth = arrText.map(function (letter) {return 26;// 這里為了找到那個空格的 bug 做了許多努力,不過似乎是白費力了// const metrics = context.measureText(letter);// console.log(metrics);// const width = metrics.width;// return width;});var align = context.textAlign;var baseline = context.textBaseline;if (align == 'left') {x = x + Math.max.apply(null, arrWidth) / 2;} else if (align == 'right') {x = x - Math.max.apply(null, arrWidth) / 2;}if (baseline == 'bottom' || baseline == 'alphabetic' || baseline == 'ideographic') {y = y - arrWidth[0] / 2;} else if (baseline == 'top' || baseline == 'hanging') {y = y + arrWidth[0] / 2;}context.textAlign = 'center';context.textBaseline = 'middle';// 開始逐字繪制arrText.forEach(function (letter, index) {// 確定下一個字符的縱坐標位置var letterWidth = arrWidth[index];// 是否需要旋轉判斷var code = letter.charCodeAt(0);if (code <= 256) {context.translate(x, y);// 英文字符,旋轉90°context.rotate(90 * Math.PI / 180);context.translate(-x, -y);} else if (index > 0 && text.charCodeAt(index - 1) < 256) {// y修正y = y + arrWidth[index - 1] / 2;}context.fillText(letter, x, y);// 旋轉坐標系還原成初始態context.setTransform(1, 0, 0, 1, 0, 0);// 確定下一個字符的縱坐標位置var letterWidth = arrWidth[index];y = y + letterWidth;});// 水平垂直對齊方式還原context.textAlign = align;context.textBaseline = baseline;}module.exports = {drawTextVertical: drawTextVertical}

繪制網絡圖片

由于網絡圖片無法直接繪制,所以需要先下載到本地,然后再按住本地圖片繪制的流程走一遍。

downloadHeroImage: function () {// 微信不支持非https的圖片下載,這里了個替換let url = this.data.hero.HERO.ICON.replace(/http/, "https");var that = this;wx.downloadFile({url: url,success: function (res) {// 下載成功后拿到圖片的路徑,然后開始繪制var path = res.tempFilePath;that.drawHeroImage(path);}, fail: function (res) {console.log(res)}});}

保存圖片

說了這么多,自然少不了最終的一步,將繪制到 canvas 的圖片保存到手機相冊,這里需要用戶授權,你需要自己處理。
用的是微信給我們提供的接口 wx.canvasToTempFilePath 。需要我們傳入起點坐標 (x, y)和畫布大小 (width, height) 以及 canvasId 。

saveShareImage: function () {wx.showLoading({title: '正在保存圖片..',});let that = this;wx.canvasToTempFilePath({x: 0,y: 0,width: that.data.canvasWidth,height: that.data.canvasHeight,canvasId: 'share_canvas',success: function (res) {wx.saveImageToPhotosAlbum({filePath: res.tempFilePath,success(res) {console.log(res);wx.showToast({title: '保存到相冊成功',duration: 1500,})},fail(res) {console.log(res)wx.showToast({title: '保存到相冊失敗',icon: 'fail'})},complete(res) {console.log(res)}})}})}

開源

本著開源的精神,源碼已經放在 Github 上,大家可以去上面查看具體代碼。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一福利网站| 影音先锋日韩有码| 韩曰欧美视频免费观看| 精品国产成人在线| 国产精品成人av性教育| 亚洲午夜激情免费视频| 九九热精品视频在线播放| 久久综合九色九九| 国产精品成人v| 日韩一区二区久久久| 国产精品都在这里| 国产欧美最新羞羞视频在线观看| 亚洲成人三级在线| 欧美成人精品在线| 国产精品电影久久久久电影网| 久久人人爽亚洲精品天堂| 91av在线播放视频| 国产精品2018| 欧美色图在线视频| 欧美日韩另类字幕中文| 97视频免费在线观看| 亚洲精品国产成人| 亚洲最大的免费| 久99九色视频在线观看| 精品久久久久久| 久久影视三级福利片| 亚洲国产精品视频在线观看| 国产午夜精品一区二区三区| 91产国在线观看动作片喷水| 精品国产电影一区| 青草青草久热精品视频在线网站| 亚洲精品福利免费在线观看| 久久精彩免费视频| 久久精品国产69国产精品亚洲| 亚洲电影在线观看| 亚洲专区在线视频| 成人黄色短视频在线观看| 久色乳综合思思在线视频| 国产日韩在线观看av| 成人a级免费视频| 一本色道久久88亚洲综合88| 亚洲老板91色精品久久| 另类天堂视频在线观看| 成人激情视频在线观看| 欧亚精品中文字幕| 国产精品观看在线亚洲人成网| 亚洲一区二区三区777| 高清亚洲成在人网站天堂| 91久久国产综合久久91精品网站| 国产精品久久久久久久久久99| 欧美日韩国产综合新一区| 亚洲午夜精品久久久久久性色| 国产精品第二页| 一本一本久久a久久精品牛牛影视| 欧美性高跟鞋xxxxhd| 一本大道亚洲视频| 亚洲一区亚洲二区亚洲三区| 欧美激情一区二区三区在线视频观看| 中文字幕在线精品| 国产一区二区三区丝袜| 亚洲情综合五月天| 国产亚洲视频在线观看| 久久久亚洲网站| 在线国产精品播放| 欧美精品精品精品精品免费| 日韩精品中文在线观看| 97视频在线观看免费高清完整版在线观看| 正在播放欧美一区| 97久久伊人激情网| 黄色一区二区在线观看| 亚洲成人精品视频在线观看| 亚洲国产精品人人爽夜夜爽| 最新中文字幕亚洲| 久久五月天色综合| 欧美多人爱爱视频网站| 国产中文日韩欧美| 欧美日韩国产中文精品字幕自在自线| 精品久久久在线观看| 久久久免费电影| 北条麻妃久久精品| 久久精品国产成人| 欧美成人小视频| 性色av香蕉一区二区| 欧美成人免费全部观看天天性色| 国产视频观看一区| 激情懂色av一区av二区av| 亚洲欧美综合另类中字| 欧美激情在线一区| 日韩一区二区av| 精品中文字幕乱| 亚洲第一视频网| 久久久久久成人精品| 最近免费中文字幕视频2019| 日韩最新中文字幕电影免费看| 亚洲aⅴ日韩av电影在线观看| 91国内精品久久| 97国产成人精品视频| 欧美色欧美亚洲高清在线视频| 富二代精品短视频| 亚洲精品乱码久久久久久金桔影视| 亚洲天天在线日亚洲洲精| 国产专区精品视频| 国产视频精品在线| 成人福利网站在线观看11| 久久久久久久97| 日韩视频―中文字幕| 国产在线视频2019最新视频| 欧美激情综合色综合啪啪五月| 日韩欧美在线视频| 亚洲视频欧美视频| 日韩免费在线看| 国产有码在线一区二区视频| 国产精品成久久久久三级| 97超级碰碰碰久久久| 久久夜精品va视频免费观看| 国产日韩在线看片| 91久久久久久久久久久| 久久国产精品久久久久久久久久| 亚洲欧美制服综合另类| 亚洲精品少妇网址| 国产精品偷伦视频免费观看国产| 热re91久久精品国99热蜜臀| 精品视频—区二区三区免费| 国产伦精品一区二区三区精品视频| 97精品欧美一区二区三区| 欧美精品在线视频观看| 中国日韩欧美久久久久久久久| 日韩一区视频在线| 亚洲精品国产精品国自产在线| 久久成人国产精品| 亚洲欧美国产一本综合首页| 精品高清美女精品国产区| 97免费视频在线播放| 欧美一区二粉嫩精品国产一线天| 揄拍成人国产精品视频| 亚洲人成绝费网站色www| 精品国产一区二区三区久久| 国产精品久久久久久搜索| 欧美极品xxxx| 欧美电影免费观看高清| 日韩精品视频观看| 国产精品久久久久影院日本| 欧美贵妇videos办公室| 久久久亚洲精选| 色婷婷综合成人| 97香蕉超级碰碰久久免费的优势| 亚洲天堂色网站| 成人激情视频在线播放| 欧美人与性动交| 国产精品视频内| 中文字幕亚洲字幕| 欧美精品少妇videofree| 亚洲成**性毛茸茸| 久久人人爽国产| 亚洲欧美福利视频| 91午夜在线播放| 日韩免费在线观看视频| 日韩欧美在线视频观看| 国产99视频在线观看| 亚洲女人天堂色在线7777| 久久久99久久精品女同性| 国产免费一区二区三区在线观看| 久久久亚洲福利精品午夜| 亚洲美女在线观看|