欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

微信小程序分享海報(bào)開發(fā)總結(jié) - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識(shí)

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們在追求其視覺表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

微信小程序分享海報(bào)開發(fā)總結(jié)

發(fā)表時(shí)間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):72

效果展示

1111.png

繪制流程簡述
  • 請求海報(bào)數(shù)據(jù)
  • 加載圖片
  • 初始化canvas
  • 繪制文字
  • 繪制區(qū)塊
  • 微信小程序碼獲取
  • 繪制圖片
  • 導(dǎo)出圖片內(nèi)容
  • 小程序碼解析
繪制關(guān)鍵點(diǎn)

Canvas 初始化

正常情況下,1px在屏幕上就顯示1px,但是在高清屏幕上,這個(gè)情況就不一樣了,以iPhone4S為例,它的devicePixelRatio為2,將看到100px的邏輯值等于200px的設(shè)備值。在元素的邏輯像素寬度上創(chuàng)建圖像,當(dāng)它們被繪制出來時(shí),它們會(huì)被設(shè)備像素按比例放大,并且會(huì)變得模糊。解決這個(gè)問題的方法是創(chuàng)建按devicePixelRatio縮放的圖像,然后使用CSS按相同的比例縮小.

canvas 的width 和 height控制元素位圖的屬性,如不設(shè)置默認(rèn)為width=300,height=150

// 獲取canvas
function getCanvas() {
    return new Promise((resolve, reject) => {
        Taro.createSelectorQuery()
            .select('#myCanvas')
            .fields({
                node: true,
                size: true
            })
            .exec(res => {
                res ? resolve(res[0]) : reject(null);
            });
    });
}
/**
 * 初始化canvas并返回 ctx
 *
 * @param {Object} res
 * @returns {*}
 */
function setContext(res: Object): any {
    let {canvas, width, height} = res;
    const ctx = canvas.getContext('2d');
   
    const dpr = Taro.getSystemInfoSync().pixelRatio;
    // 防止重復(fù)放大處理
    if (canvas.width !== width * dpr) {
       // 設(shè)置畫布繪畫尺寸 = CSS尺寸 * 設(shè)備像素比率。
        canvas.width = width * dpr;
        canvas.height = height * dpr;
       // 通過dpr縮放所有繪圖操作
        ctx.scale(dpr, dpr);
    }

    return ctx;
}

let {node: canvas, width, height} = await getCanvas();
let ctx = setContext({canvas, width, height});
// 繪制前先清除,以防被原有圖案影響
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = '#ffffff';
復(fù)制代碼

canvas標(biāo)簽,微信對Canvas做了同層渲染的優(yōu)化,特別注意不要將canvas標(biāo)簽放到子組件,必須放到page頁,否則無法獲取的canvas對象

<Canvas type='2d' id='myCanvas' style='width: 414px; height: 736px;' />
復(fù)制代碼

微信小程序碼獲取
  • 接口 A: 適用于需要的碼數(shù)量較少的業(yè)務(wù)場景
    • 生成小程序碼,可接受 path 參數(shù)較長,生成個(gè)數(shù)受限,請謹(jǐn)慎使用。
  • 接口 B:適用于需要的碼數(shù)量極多的業(yè)務(wù)場景
    • 生成小程序碼,可接受頁面參數(shù)較短,生成個(gè)數(shù)不受限。
  • 接口 C:適用于需要的碼數(shù)量較少的業(yè)務(wù)場景
    • 生成二維碼,可接受 path 參數(shù)較長,生成個(gè)數(shù)受限。

我們使用的是接口B,需要注意的點(diǎn),

  • scene參數(shù)只接收32的長度
  • 小程序未發(fā)布時(shí),page參數(shù)必須為空,scene=xxxx,才可以獲取到二維碼
  • 接口返回的數(shù)據(jù)需要為base64格式方便canvas繪制時(shí)使用

圖片繪制前獲取
Taro.getImageInfo({
    src: imgUrl
}).than(res => {
    let { path } = res;
    let imgtag = canvas.createImage();
    imgtag.src = http://www.wxapp-union.com/path;
    imgtag.onload = res => {
        ctx.save();
        ctx.drawImage(imgtag, 26, 615, 2 * 27, 2 * 27);
        ctx.restore();
    };
});
復(fù)制代碼
圖片裁剪
/**
 * 畫圓
 *
 * @export
 * @param {IDrawRound} options
 * @example
 * drawRound({
 *     ctx,
 *     r: 19,
 *     x: 22,
 *     y: 15,
 *     next() {
 *         ctx.fillStyle = '#F5F5F5';
 *         ctx.fill();
 *     }
 * });
 */
export function drawRound(options: IDrawRound) {
    let { ctx, r, x, y, next } = options;
    ctx.save(); // 保存之前的
    let cx = x + r; // 圓弧坐標(biāo)x
    let cy = y + r; // 圓弧坐標(biāo) y
    ctx.arc(cx, cy, r, 0, 2 * Math.PI);
    if (typeof next === 'function') {
        next();
    }
    ctx.restore(); // 返回上一狀態(tài)
}
// 繪制圓形頭像
drawRound({
    ctx,
    r: 27,
    x: 26,
    y: 615,
    next() {
        ctx.clip();
        ctx.drawImage(imgtag, 26, 615, 2 * 27, 2 * 27); // 畫頭像
    }
});
復(fù)制代碼
繪制圓角矩形
/**
 * 繪制圓角矩形,需自行填充顏色
 *
 * @export
 * @param {IDrawRound} options
 * 
 * @example
 * drawRoundRect({
 *     ctx,
 *     r: 13,
 *     x: 26,
 *     y: 80,
 *     w: 361,
 *     h: 361,
 *     next() {
 *         ctx.clip();
 *         ctx.drawImage(imgtag, 26, 80, 361, 361);
 *     }
 * });
 */
export function drawRoundRect(options: IDrawRoundRect) {
    let {ctx, x, y, w, h, r, next} = options;
    ctx.save();
    if (w < 2 * r) {
        r = w / 2;
    }
    if (h < 2 * r) {
        r = h / 2;
    }
    ctx.beginPath();
    ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 3 / 2);
    ctx.lineTo(w - r + x, y);
    ctx.arc(w - r + x, r + y, r, Math.PI * 3 / 2, Math.PI * 2);
    ctx.lineTo(w + x, h + y - r);
    ctx.arc(w - r + x, h - r + y, r, 0, Math.PI * 1 / 2);
    ctx.lineTo(r + x, h + y);
    ctx.arc(r + x, h - r + y, r, Math.PI * 1 / 2, Math.PI);
    ctx.closePath();
    if (typeof next === 'function') {
        next();
    }
    ctx.restore(); // 返回上一狀態(tài)
}
// 底部粉色圓角矩形
drawRoundRect({
    ctx,
    r: 15,
    x: 26,
    y: 687,
    w: 147,
    h: 23,
    next() {
        // 漸變填充
        var grd = ctx.createLinearGradient(0, 0, 200, 0);
        grd.addColorStop(0, '#E828FF');
        grd.addColorStop(0.7, '#FF1D74');
        grd.addColorStop(1, '#FFB050');
        ctx.fillStyle = grd;
        ctx.fill();
        ctx.strokeStyle = grd;
        ctx.stroke();
    }
});
復(fù)制代碼
繪制文字
/**
 * 繪制文字
 *
 * @export
 * @param {*} ctx canvas的 2d 對象
 * @param {string} t 繪制的文字
 * @param {number} x
 * @param {number} y
 * @param {number} w 文字寬度
 * @param {number} [l=30] 行高
 * @param {number} [limit=2] 行數(shù)
 */
export function drawText(ctx: any, t: string, x: number, y: number, w: number, l:number = 30, limit:number = 2) {
    // 參數(shù)說明
    // ctx:canvas的 2d 對象,t:繪制的文字,x,y:文字坐標(biāo),w:文字最大寬度
    let chr = t.split('');
    let temp = '';
    let row = [];
    let limitIndex = 0;
    let wordsNum = 0;

    for (let a = 0; a < chr.length; a++) {
        wordsNum++;
        if (ctx.measureText(temp).width < w && ctx.measureText(temp + (chr[a])).width <= w) {
            temp += chr[a];
        }
        else {
            // 行數(shù)+1
            limitIndex++;
            if (limitIndex < limit) {
                row.push(temp);
                temp = chr[a];
            }
            else {
                break;
            }
        }
    }
    // 最后一行超出最大字?jǐn)?shù)
    if (limitIndex === limit && chr.length > wordsNum) {
        temp = temp.substring(0, temp.length - 1) + '...';
    }

    row.push(temp);
    for (let b = 0; b < row.length; b++) {
        ctx.fillText(row[b], x, y + (b + 1) * l);// 每行字體y坐標(biāo)間隔30
    }
};
復(fù)制代碼

繪制完成導(dǎo)出圖片
export async function draw() {
    let { node: canvas, width, height } = await getCanvas();
    let ctx = setContext({ canvas, width, height });
    // 繪制前先清除,以防原有圖案被影響
    ctx.clearRect(0, 0, width, height);
    ctx.fillStyle = '#ffffff';
    ctx.fillRect(0, 0, 414, 736);
    // 底部灰色塊
    ctx.fillStyle = '#f5f5f5';
    ctx.fillRect(0, 596, 414, 140);
    // 底部粉色圓角矩形
    drawRoundRect({
        ctx,
        r: 15,
        x: 26,
        y: 687,
        w: 147,
        h: 23,
        next() {
            // 漸變填充
            var grd = ctx.createLinearGradient(0, 0, 200, 0);
            grd.addColorStop(0, '#E828FF');
            grd.addColorStop(0.7, '#FF1D74');
            grd.addColorStop(1, '#FFB050');
            ctx.fillStyle = grd;
            ctx.fill();
            ctx.strokeStyle = grd;
            ctx.stroke();
        }
    });
    // 推薦人
    ctx.fillStyle = '#666666';
    ctx.font = '13px/1.2 PingFangSC-Regular';
    ctx.fillText(`${nickName}`, 93, 635);

    // 推薦語
    ctx.fillStyle = '#222222';
    ctx.font = '15px/1.2 PingFangSC-Regular';
    ctx.fillText(`${recommendation || '推薦你一個(gè)超值的變美項(xiàng)目'}`, 93, 660);

    // 底部文字
    ctx.fillStyle = '#ffffff';
    ctx.font = '13px/1.2 PingFangSC-Regular';
    ctx.fillText('長按識(shí)別小程序購物', 43, 703);
  	// 省略部分圖片繪制代碼
    // 獲取圖片臨時(shí)路徑
    let { tempFilePath } = await Taro.canvasToTempFilePath({ canvas } as any);
    return Promise.resolve(tempFilePath);
};
復(fù)制代碼

以上導(dǎo)出的圖片地址可以直接給img標(biāo)簽賦值


圖片保存到相冊
const res = await Taro.saveImageToPhotosAlbum({
    filePath: tempFilePath
});
if (res.errMsg === 'saveImageToPhotosAlbum:ok') {
    Taro.showToast({
        title: '保存圖片成功',
        icon: 'success',
        duration: 2000
    });
}
復(fù)制代碼

小程序碼解析

小程序碼的解析后,在page里收到的參數(shù)在scene里

componentWillMount() {
  let params = this.$router.params;
  // 通過小程序碼進(jìn)入,參數(shù)在scene里
  if (params.scene) {
    let scene = decodeURIComponent(params.scene);
    let {id} = query2parmas(scene);
    this.setState({
      goodsId: id
    });
  }
  // 通過分享卡片進(jìn)入?yún)?shù)直接在params里 
  if (params.id) {
    this.setState({
      goodsId: params.id
    });
  }
}

相關(guān)案例查看更多