国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

微信小程序使用canvas生成分享海報功能復(fù)盤

這篇具有很好參考價值的文章主要介紹了微信小程序使用canvas生成分享海報功能復(fù)盤。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

近期需要開發(fā)一個微信小程序生成海報分享的功能。在h5一般都會直接采用 html2canvas 或者 dom2image 之類的庫直接處理。但是由于小程序不具備傳統(tǒng)意義的dom元素,所以也沒有辦法采用此類工具。
所以就只能一筆一筆的用 canvas 畫出來了,下面對實現(xiàn)這個功能中遇到的問題做一個簡單的復(fù)盤。

制作要求:

  • 主題切換。
  • 圖片彈框展示,適應(yīng)不同的手機(jī)尺寸。
  • 圖片上層有彈出框展示保存圖片按鈕。
  • 海報內(nèi)容,
    • 標(biāo)題部分根據(jù)實際內(nèi)容展示,可能為一行也可能為兩行
    • 描述部分,最多展示四行,超出的顯示成…
    • 圓角圖片展示
    • 圓角虛線框

基本方案流程

  1. 預(yù)先加載好所有需要的圖片。
  2. 在偏離視窗顯示區(qū)域使用 canvas 繪制海報,并生成臨時文件。
  3. 彈窗的圖片使用 生成的臨時圖片。
  4. 設(shè)置圖片的寬度為適應(yīng)屏幕的,可通過定位或者flex來實現(xiàn),圖片高度根據(jù)寬度自動縮放。超出的內(nèi)容滾動顯示。

效果圖如下:
微信小程序canvas繪制海報,js基礎(chǔ),微信小程序,小程序
微信小程序canvas繪制海報,js基礎(chǔ),微信小程序,小程序

微信canvas組件的相關(guān)問題

canvas 屬于微信客戶端創(chuàng)建的原生組件,所以需要注意一些原生組件的限制

  • 原生組件的層級是最高的,所以頁面中的其他組件無論設(shè)置 z-index 為多少,都無法蓋在原生組件上。
    • 后插入的原生組件可以覆蓋之前的原生組件。
  • 原生組件還無法在 picker-view 中使用
  • 部分 CSS 樣式無法應(yīng)用于原生組件
    • 無法對原生組件設(shè)置 CSS 動畫
    • 無法定義原生組件為 position: fixed
    • 不能在父級節(jié)點使用 overflow: hidden 來裁剪原生組件的顯示區(qū)域

所以無法使用 canvas 繪制的圖片直接用于顯示。會遇到層級以及尺寸的問題。

預(yù)加載圖片資源

在繪制之前我們需要先加載好圖片資源并保存。

function create(){
    const img1 = preLoadImg("https:xxxx.img1", 'img1')
    const img2 = preLoadImg("https:xxxx.img2", 'img2')
    const img3 = preLoadImg("https:xxxx.img3", 'img3')

    Promise.all([img1, img2, img3]).then(res=>{
        // 開始繪制canvas
    })
}


function preLoadImg(url, taskId) {

    if(this.imageTempPath[taskId]) return Promise.resolve();
    
    if (!url) return Promise.resolve();

    url = /^https/.test(url) ? url : `https:${url}`;

    return wx.getImageInfo({src: url}).then((res)=>{
        this.imageTempPath[taskId] = res.path;
    })
}

文本處理

計算不同長度的文本繪制高度

對于不同的文本長度,可能存在占一行或者多行的情況,這個時候?qū)τ谖谋疽韵碌膬?nèi)容繪制的 y 軸坐標(biāo)會造成影響。

解決方案:先定義好每一個元素在標(biāo)準(zhǔn)情況下的坐標(biāo)位置,然后對于存在可能有占據(jù)空間改變的文本,通過測量其文本寬度,計算出實際占據(jù)行數(shù),然后出多出的 y 軸位置(diff),并在后續(xù)的元素繪制上加上這個差值。

基本思路:

  1. 測量出文本的實際繪制需要的總長度
  2. 計算出實際繪制多少行
  3. 計算實際繪制行數(shù)與默認(rèn)行數(shù)的高度差

計算方法如下:

function getWordDiffDistance(
    ctx,        // canvas 上下文
    text,       // 要計算的文本
    baseline,   // 默認(rèn)顯示行數(shù)
    lineHeight, // 行高
    fontSize,   // 字號
    textIndent, // 首行縮進(jìn)字符
    maxWidth,   // 每一行繪制的最大寬度
    maxLine     // 最大允許顯示行數(shù)
) {
    // 設(shè)置上下文的字號
    ctx.setFontSize(fontSize);

    // 首行縮進(jìn)的寬度
    const textIndentWidth = fontSize * textIndent;
     //實際總共能分多少行
    let allRow = Math.ceil((ctx.measureText(text).width + textIndentWidth) / maxWidth);

    allRow = Math.min(allRow, maxLine);

    return (allRow - baseline) * lineHeight;
}

ctx.measureText() 要先設(shè)置好文本屬性。

文本超出指定行數(shù)后顯示 …

基本思路:

  1. 設(shè)置好 canvas 上下文的文字樣式
  2. 通過 measureText 計算出當(dāng)前文本需要繪制多少行
  3. 如果是首行且設(shè)置了首行縮進(jìn),繪制的 x 要加上縮進(jìn)的寬度
  4. 然后計算出每一行要繪制的文字并進(jìn)行繪制,并記錄最后的截取位置
  5. 如果最后一行的實際繪制寬度大于設(shè)置的最大寬度,添加… 否則正常繪制
dealWords(options) {
    const {
        ctx,
        fontSize,
        word,
        maxWidth,
        x,
        y,
        maxLine,
        lineHeight,
        style,
        textIndent = 0,
    } = options;
    ctx.font = style || "normal 12px PingFangSC-Regular";

     //設(shè)置字體大小
    ctx.setFontSize(fontSize);

     // 首行縮進(jìn)的寬度
    const textIndentWidth = fontSize * textIndent;

     //實際總共能分多少行
    let allRow = Math.ceil((ctx.measureText(word).width + textIndentWidth) / maxWidth);

     //實際能分多少行與設(shè)置的最大顯示行數(shù)比,誰小就用誰做循環(huán)次數(shù)
    let count = allRow >= maxLine ? maxLine : allRow;

     //當(dāng)前字符串的截斷點
    let endPos = 0;
    for (let j = 0; j < count; j++) {
        let startWidth = 0;
        if (j == 0 && textIndent) startWidth = textIndentWidth;
        let rowRealMaxWidth = maxWidth - startWidth;

         //當(dāng)前剩余的字符串
        let nowStr = word.slice(endPos);

         //每一行當(dāng)前寬度
        let rowWid = 0;
        if (ctx.measureText(nowStr).width > rowRealMaxWidth) {
            //如果當(dāng)前的字符串寬度大于最大寬度,然后開始截取
            for (let m = 0; m < nowStr.length; m++) {
                 //當(dāng)前字符串總寬度
                rowWid += ctx.measureText(nowStr[m]).width;
                if (rowWid > rowRealMaxWidth) {
                    if (j === maxLine - 1) {
                    //如果是最后一行
                    ctx.fillText(
                        nowStr.slice(0, m - 1) + "...",
                        x + startWidth,
                        y + (j + 1) * lineHeight
                    ); //(j+1)*18這是每一行的高度
                    } else {
                    ctx.fillText(
                        nowStr.slice(0, m),
                        x + startWidth,
                        y + (j + 1) * lineHeight
                    );
                    }
                    endPos += m; //下次截斷點
                    break;
                }
            }
        } else {
            //如果當(dāng)前的字符串寬度小于最大寬度就直接輸出
            ctx.fillText(nowStr.slice(0), x, y + (j + 1) * lineHeight);
        }
    }
}

繪制多行文本計算行寬的時候,空白字符可能會對最終的計算結(jié)果造成一定影響,所以可以先對其空白字符進(jìn)行過濾。

圖文對齊

微信小程序中通過 setTextBaseline 設(shè)置文本豎直對齊方式??蛇x值有 top,bottom,middle,normal;

微信小程序canvas繪制海報,js基礎(chǔ),微信小程序,小程序

圖片的坐標(biāo)基點為左上角坐標(biāo),所以在繪制的時候要注意 y 的起始坐標(biāo)。如果有修改 文本的對齊方式,在結(jié)束的時候最好將文本豎直對齊方式設(shè)置為 normal,避免影響后續(xù)的繪制。

形狀處理

繪制圓角矩形路徑

使用arc()方式繪制弧線
微信小程序canvas繪制海報,js基礎(chǔ),微信小程序,小程序

// 按照canvas的弧度從 0 - 2PI 開始順時針繪制
function drawRoundRectPathWithArc(ctx, x, y, width, height, radius) {
    ctx.beginPath();
    // 從右下角順時針繪制,弧度從0到1/2PI
    ctx.arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2);

    // 矩形下邊線
    ctx.lineTo(x + radius, y + height);

    // 左下角圓弧,弧度從1/2PI到PI
    ctx.arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);

    // 矩形左邊線
    ctx.lineTo(x, y + radius);

    // 左上角圓弧,弧度從PI到3/2PI
    ctx.arc(x + radius, y + radius, radius, Math.PI, (Math.PI * 3) / 2);

    // 上邊線
    ctx.lineTo(x + width - radius, y);

    //右上角圓弧
    ctx.arc(x + width - radius,y + radius, radius, (Math.PI * 3) / 2, Math.PI * 2);

    //右邊線
    ctx.lineTo(x + width, y + height - radius);
    ctx.closePath();
}

使用arcTo()方式繪制弧線

function drawRoundRectPathWithArcTo(ctx, x, y, width, height, radius) {
    ctx.beginPath();

    // 上邊線
    ctx.lineTo(x + width - radius, y);

    // 右上弧線
    ctx.arcTo(x + width, y, x + width, y + radius, radius)

    //右邊線
    ctx.lineTo(x + width, y + height - radius);


    // 從右下角順時針繪制,弧度從0到1/2PI
    ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius)

    // 矩形下邊線
    ctx.lineTo(x + radius, y + height);

    // 左下角圓弧,弧度從1/2PI到PI
    ctx.arcTo(x, y + height, x, y +height -radius, radius)

    // 矩形左邊線
    ctx.lineTo(x, y + radius);

    // 左上角圓弧,弧度從PI到3/2PI
    ctx.arcTo(x,y, x+ radius, y, radius)

    
    ctx.closePath();
}

背景色填充

function fillRoundRectPath(ctx, x, y, width, height, radius, color){
    ctx.save();
    this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
    ctx.setFillStyle(color);
    ctx.fill();
    ctx.restore();
}

圖片填充

function drawRoundRectImg(ctx, x, y, width, height, radius, img) {
    if(!img) return
    ctx.save();
    this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
    // 剪切  原始畫布中剪切任意形狀和尺寸。一旦剪切了某個區(qū)域,則所有之后的繪圖都會被限制在被剪切的區(qū)域內(nèi)
    ctx.clip();
    ctx.drawImage(img, x, y, width, height);
    ctx.restore();
}

虛線框

function strokeRoundRectPath(ctx, x, y, width, height, radius) {
    this.drawRoundRectPathWithArc(ctx, x, y, width, height, radius);
    ctx.strokeStyle = "#DDDDDD";
    ctx.lineWidth = 0.5;
    ctx.setLineDash([6, 5]);
    ctx.stroke();
}

生成臨時圖片

wx.canvasToTempFilePath(Object object, Object this)

把當(dāng)前畫布指定區(qū)域的內(nèi)容導(dǎo)出生成指定大小的圖片。在 draw() 回調(diào)里調(diào)用該方法才能保證圖片導(dǎo)出成功。

ctx.draw(false, async () => {
    // canvas畫布轉(zhuǎn)成圖片并返回圖片地址
    const { tempFilePath } = await wx.canvasToTempFilePath(
        {
            x: 0,       // 指定的畫布區(qū)域的左上角橫坐標(biāo)	
            y: 0,       // 指定的畫布區(qū)域的左上角縱坐標(biāo)
            width: posterImg_width,     // 指定的畫布區(qū)域的寬度	
            height: posterImg_height,   // 指定的畫布區(qū)域的高度
            destWidth: posterImg_width * pixelRatio, // 輸出的圖片的寬度 導(dǎo)出大小為 canvas 的 pixelRatio 倍
            destHeight: posterImg_height * pixelRatio, // 輸出的圖片的高度 
            canvasId: "posterCanvas",
        },
        this
    );
    this.posterTempFilePath = tempFilePath;
});

不同像素手機(jī)的顯示適配問題

由于只是一張圖片的展示,所以顯示適配的問題久很好解決。

  • 設(shè)置圖片父層容器的側(cè)邊距,使容器自動撐開。
  • 圖片寬度設(shè)置為 width:100%, 設(shè)置 mode="widthFix"讓圖片自動縮放。

微信本地保存臨時圖片

function savePoster(tempFilePath) {
    wx.saveImageToPhotosAlbum({
        filePath: tempFilePath,
    }).then(()=> {
        wx.showToast({
            title: "保存成功", // 提示的內(nèi)容,
            icon: "success", // 圖標(biāo),
            duration: 2000, // 延遲時間,
            mask: true, // 顯示透明蒙層,防止觸摸穿透,
        });
    },
    (err) => {
        wx.showToast({
            title: "保存失敗", // 提示的內(nèi)容,
            icon: "none", // 圖標(biāo),
            duration: 2000, // 延遲時間,
            mask: true, // 顯示透明蒙層,防止觸摸穿透,
        });
    },);
}

主題切換

通過替換不同的背景圖片來切換不同的主題。

參考文章

說說如何使用 Canvas 繪制弧線與曲線

canvas生成分享海報文章來源地址http://www.zghlxwxcb.cn/news/detail-598159.html

到了這里,關(guān)于微信小程序使用canvas生成分享海報功能復(fù)盤的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 微信小程序?qū)崿F(xiàn)生成分享海報案例

    微信小程序?qū)崿F(xiàn)生成分享海報案例

    一、引入插件painter (1)克隆地址:https://gitcode.net/mirrors/Kujiale-Mobile/Painter (2)下載的 painter 放到小程序的 components 目錄下 二、頁面中引入插件 (1)頁面的 json 文件 (2)頁面的 wxml 文件 其中 painter 插件可以獲取繪制出來的圖片路徑, image 標(biāo)簽展示出來 三、繪制海報 1、

    2024年02月08日
    瀏覽(22)
  • 使用taro+canvas實現(xiàn)微信小程序的圖片分享功能

    使用taro+canvas實現(xiàn)微信小程序的圖片分享功能

    二輪充電業(yè)務(wù)中,用戶充電完成后在訂單詳情頁展示訂單相關(guān)信息,用戶點擊分享按鈕喚起微信小程序分享菜單,將生成的圖片海報分享給微信好友或者下載到本地,好友可通過掃描海報中的二維碼加群領(lǐng)取優(yōu)惠。 使用場景及功能:微信小程序 生成海報圖片 分享好友 下載圖

    2024年02月05日
    瀏覽(704)
  • uniapp 使用canvas畫海報(微信小程序)

    uniapp 使用canvas畫海報(微信小程序)

    效果展示: ?項目要求:點擊分享繪制海報,并實現(xiàn)分享到好友,朋友圈,并保存 先實現(xiàn)繪制海報 ? 下面是海報下面的分享彈窗 因為分享到朋友圈實在沒找到有使用自定義按鈕的可能,所以還是需要點擊右上角膠囊 ? ?以上就是畫海報以及分享的全部過程了,另有一個點:

    2024年02月13日
    瀏覽(100)
  • 微信小程序生成二維碼海報并分享

    背景:點擊圖標(biāo),生成海報后,點擊保存相冊,可以保存 生成海報:插件wxa-plugin-canvas,此處使用頁面異步生成組件方式,官網(wǎng)地址:wxa-plugin-canvas - npm 二維碼:調(diào)用后端接口生成二維碼 需要調(diào)用獲取圖片信息接口wx.getImageInfo(),獲取到圖片的寬高以做整體寬高配置 closePos

    2024年03月21日
    瀏覽(96)
  • 微信小程序 api+前端實現(xiàn)生成分享海報

    微信小程序 api+前端實現(xiàn)生成分享海報

    1.先看效果圖,點擊分享海報按鈕,然后彈出分享海報 ?2.前端代碼 這里用的組件有vant組件庫還有canvas_drawer(一個畫布組件) canvas_drawer下載地址 https://github.com/kuckboy1994/mp_canvas_drawer 把 components 中的 canvasdrawer 拷貝到自己項目下,然后再app.json中引用就行了,如下 \\\"usingCompon

    2024年02月09日
    瀏覽(24)
  • uniapp微信小程序生成分享海報(模板自取)

    uniapp微信小程序生成分享海報(模板自取)

    uniapp微信小程序生成分享海報模板 1、模板自取 2、可自行按需求更改調(diào)整 3、效果圖如下: 生成前? ----- 生成后的圖 需知: 博主的實現(xiàn)效果是先把需要生成的圖片排版成靜態(tài)頁面,再點擊生成海報-----通過canvas生成海報?。?! ? ? ? ? ? ?不需要這樣效果話可以省略第一步

    2024年02月14日
    瀏覽(24)
  • 微信小程序?qū)崿F(xiàn)畫布生成海報功能

    微信小程序可以通過使用 標(biāo)簽來實現(xiàn)生成海報的功能。以下是基本實現(xiàn)步驟: 1.在 WXML 文件中創(chuàng)建一個 標(biāo)簽,并設(shè)置其寬度和高度屬性。 ’ 2.在 JS 文件中,獲取到 標(biāo)簽的上下文對象。 3.在 ctx 上下文對象中,使用各種繪圖 API 繪制出海報的內(nèi)容 4.最后調(diào)用 ctx.draw() 方法將海

    2024年02月16日
    瀏覽(24)
  • 微信小程序使用canvas繪制海報并保存本地相冊

    微信小程序使用canvas繪制海報并保存本地相冊

    在做微信小程序的時候,很多都會用到生成海報分享功能,剛好最近項目有這個需求,今天就發(fā)出來記錄下 首先是使用canvas繪制一張海報,微信小程序的canvas有老版本和新版本我是用的是新版本 代碼如下 js部分 我的做法是給canvas隱藏了不看到 ,等canvas繪制完畢后導(dǎo)出的url直接賦給

    2023年04月08日
    瀏覽(33)
  • 【微信小程序】用painter插件生成海報分享朋友圈簡單教程

    【微信小程序】用painter插件生成海報分享朋友圈簡單教程

    第一步:去Git下載插件 1.這是核心插件 需要下載全部內(nèi)容 2.官方文檔 3.新建painter文件夾放到下面 4.在引用文件的json文件引用一下 5.在使用文件里創(chuàng)建個canvas.js文件 獲取canvas.js內(nèi)容去這個網(wǎng)站 先點擊導(dǎo)出,在點擊復(fù)制,復(fù)制到canvas.js文件里(替換) 6.然后在對應(yīng)page頁面的

    2024年02月10日
    瀏覽(104)
  • uniapp 微信小程序 動態(tài)生成海報分享朋友圈,需先保存圖片

    uniapp 微信小程序 動態(tài)生成海報分享朋友圈,需先保存圖片

    直接拷貝代碼,不使用插件,自己純代碼實現(xiàn)。 從相冊 或拍照 選擇一個圖片做海報背景。 大吉大利 今晚吃雞。

    2024年02月11日
    瀏覽(92)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包