最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2019年06月25日 17:25:23   作者:極樂叔  
這篇文章主要介紹了微信小程序利用Canvas繪制圖片和豎排文字詳解,合成圖片應(yīng)該按照 Canvas 的文檔來做都沒什么問題,主要是有個(gè)豎排文字的需求,這里和大家分享一下,需要的朋友可以參考下

前言

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

正文

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

自我感覺良好,至少達(dá)到了我自己的預(yù)期吧~~~

下面讓我們一步一步來看看如何實(shí)現(xiàn)的吧。

整個(gè)圖片分為三個(gè)部分:

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

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

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

武將圖片

drawHeroImage: function (path) {
var that = this;
// 拿到canvas context
let ctx = wx.createCanvasContext('share_canvas');
// 為了保證圖片比例以及繪制的位置,先要拿到圖片的大小
wx.getImageInfo({
src: path,
success: function (res) {
// 計(jì)算圖片占比信息 
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是本地路徑,不可以傳網(wǎng)絡(luò)url,如果是網(wǎng)絡(luò)圖片需要先下載
ctx.drawImage(path, 10, offsetY, res.width * radio, res.height * radio)
// 繪制小程序碼
that.drawQrCodeImage(ctx);
// 繪制勢(shì)力漢字:吳
that.drawInfluence(ctx, that.data.hero.HERO.INFLUENCE);
// 繪制武將姓名:陸遜
that.drawName(ctx, that.data.hero.HERO.NAME);
// 繪制武將稱號(hào):江陵侯
that.drawHorner(ctx, that.data.hero.HERO.HORNER);
// 最終調(diào)用draw函數(shù),生成預(yù)覽圖
// 一個(gè)坑點(diǎn):只能調(diào)用一次,否則后面的會(huì)覆蓋前面的
ctx.draw();
}
});
}

小程序碼

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

武將文字信息

從剛剛的代碼可以看出,我分了3個(gè)部分來繪制,其實(shí) 吳 和 陸遜 應(yīng)該是可以放到一起的,但是我在繪制的時(shí)候發(fā)現(xiàn),空格在繪制的時(shí)候會(huì)引起異常,導(dǎo)致空格后面的文字無法繪制出來,所以我這里 吳 和 陸遜 中間的空白是靠位置偏移來做的。

這里就展示一下如何繪制武將稱號(hào)的。

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

繪制豎排文字從網(wǎng)上找了個(gè)開源的代碼,需要看原理的請(qǐng)看這里

當(dāng)然我這里為了適用小程序做了些改動(dòng),函數(shù)原型是這樣子的:

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

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

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

改造后的函數(shù)像下面的樣子:

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;
// 這里為了找到那個(gè)空格的 bug 做了許多努力,不過似乎是白費(fèi)力了
// 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) {
// 確定下一個(gè)字符的縱坐標(biāo)位置
var letterWidth = arrWidth[index];
// 是否需要旋轉(zhuǎn)判斷
var code = letter.charCodeAt(0);
if (code <= 256) {
context.translate(x, y);
// 英文字符,旋轉(zhuǎn)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);
// 旋轉(zhuǎn)坐標(biāo)系還原成初始態(tài)
context.setTransform(1, 0, 0, 1, 0, 0);
// 確定下一個(gè)字符的縱坐標(biāo)位置
var letterWidth = arrWidth[index];
y = y + letterWidth;
});
// 水平垂直對(duì)齊方式還原
context.textAlign = align;
context.textBaseline = baseline;
}
module.exports = {
drawTextVertical: drawTextVertical
}

繪制網(wǎng)絡(luò)圖片

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

downloadHeroImage: function () {
// 微信不支持非https的圖片下載,這里了個(gè)替換
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 的圖片保存到手機(jī)相冊(cè),這里需要用戶授權(quán),你需要自己處理。
用的是微信給我們提供的接口 wx.canvasToTempFilePath 。需要我們傳入起點(diǎn)坐標(biāo) (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: '保存到相冊(cè)成功',
duration: 1500,
})
},
fail(res) {
console.log(res)
wx.showToast({
title: '保存到相冊(cè)失敗',
icon: 'fail'
})
},
complete(res) {
console.log(res)
}
})
}
})
}

開源

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • bootstrap-table formatter 使用vue組件的方法

    bootstrap-table formatter 使用vue組件的方法

    Bootstrap table是國人開發(fā)的一款基于 Bootstrap 的 jQuery 表格插件,通過簡(jiǎn)單的設(shè)置,就可以擁有強(qiáng)大的單選、多選、排序、分頁,以及編輯、導(dǎo)出、過濾(擴(kuò)展)等等的功能。這篇文章重點(diǎn)給大家介紹bootstrap-table formatter 使用vue組件的方法,感興趣的朋友一起看看
    2019-05-05
  • 微信小程序頁面與組件之間信息傳遞與函數(shù)調(diào)用

    微信小程序頁面與組件之間信息傳遞與函數(shù)調(diào)用

    不管是vue還是react中,都在強(qiáng)調(diào)組件思想,所以下面這篇文章主要給大家介紹了關(guān)于微信小程序頁面與組件之間信息傳遞與函數(shù)調(diào)用的相關(guān)資料,需要的朋友可以參考下
    2021-05-05
  • JS簡(jiǎn)單獲取客戶端IP地址的方法【調(diào)用搜狐接口】

    JS簡(jiǎn)單獲取客戶端IP地址的方法【調(diào)用搜狐接口】

    這篇文章主要介紹了JS簡(jiǎn)單獲取客戶端IP地址的方法,通過調(diào)用搜狐接口來簡(jiǎn)單實(shí)現(xiàn)獲取訪客IP地址的功能,非常簡(jiǎn)便實(shí)用,需要的朋友可以參考下
    2016-09-09
  • javascript 延遲加載技術(shù)(lazyload)簡(jiǎn)單實(shí)現(xiàn)

    javascript 延遲加載技術(shù)(lazyload)簡(jiǎn)單實(shí)現(xiàn)

    延遲加載技術(shù)(簡(jiǎn)稱lazyload)并不是新技術(shù), 它是js程序員對(duì)網(wǎng)頁性能優(yōu)化的一種方案.
    2011-01-01
  • JavaScript中this的綁定你知道幾種?

    JavaScript中this的綁定你知道幾種?

    this對(duì)于一些有經(jīng)驗(yàn)的JavaScript開發(fā)者來說是一種非常復(fù)雜的機(jī)制。并且很多開發(fā)者對(duì)于this的理解并不是很清晰,導(dǎo)致在面試的時(shí)候經(jīng)常受挫。今天我們就來看一看這個(gè)this真的有那么難嗎
    2023-02-02
  • JS實(shí)現(xiàn)手寫parseInt的方法示例

    JS實(shí)現(xiàn)手寫parseInt的方法示例

    這篇文章主要給大家介紹了JS實(shí)現(xiàn)手寫parseInt的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • JS基于Location實(shí)現(xiàn)訪問Url、重定向及刷新頁面的方法分析

    JS基于Location實(shí)現(xiàn)訪問Url、重定向及刷新頁面的方法分析

    這篇文章主要介紹了JS基于Location實(shí)現(xiàn)訪問Url、重定向及刷新頁面的方法,結(jié)合實(shí)例形式分析了javascript使用Location進(jìn)行URL訪問、重定向、頁面刷新等操作相關(guān)原理、操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-12-12
  • JavaScript中變量的相互引用

    JavaScript中變量的相互引用

    變量相互引用的原因是:由于某些類型的變量是按地址存儲(chǔ)的而導(dǎo)致的兩個(gè)或多的參數(shù)的值互相影響.
    2010-05-05
  • js實(shí)現(xiàn)addClass,removeClass,hasClass的函數(shù)代碼

    js實(shí)現(xiàn)addClass,removeClass,hasClass的函數(shù)代碼

    js實(shí)現(xiàn)addClass,removeClass,hasClass的函數(shù)代碼,需要的朋友可以參考下。
    2011-07-07
  • layer彈出子iframe層父子頁面?zhèn)髦档膶?shí)現(xiàn)方法

    layer彈出子iframe層父子頁面?zhèn)髦档膶?shí)現(xiàn)方法

    這篇文章主要介紹了layer彈出子iframe層父子頁面?zhèn)髦档膶?shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11

最新評(píng)論

三原县| 平阳县| 吉林市| 多伦县| 新兴县| 娄底市| 德阳市| 嘉兴市| 灵武市| 涡阳县| 磐安县| 水城县| 乌拉特后旗| 奇台县| 美姑县| 兴隆县| 永定县| 常宁市| 河西区| 新巴尔虎左旗| 香港| 昆山市| 登封市| 紫阳县| 赞皇县| 玛曲县| 陈巴尔虎旗| 建宁县| 宾阳县| 嵊州市| 永宁县| 台南市| 龙里县| 博罗县| 潍坊市| 密云县| 枣庄市| 安康市| 滁州市| 报价| 莒南县|