【微信小程序生成海报保存到相册】

微信小程序生成海报保存到相册

如图
需要先有设计图的尺寸
【微信小程序生成海报保存到相册】_第1张图片
【微信小程序生成海报保存到相册】_第2张图片

在canvas绘图时,通常会遇到的一种情况是用固定宽高来显示图片,如果直接把图片内容填充进去的话,显示出来的图片就会被压扁或者被挤瘦,其效果简直不忍直视!那么,就需要把图片进行拉伸、压缩或裁剪。

接下来,先给 drawImage 做个介绍:

canvas的drawImage函数可以 绘制图像到画布。

它有以下参数:

参数 类型 说明

参数 说明
imageResource 所要绘制的图片资源
sx 源图像的矩形选择框的左上角 x 坐标
sy 源图像的矩形选择框的左上角 y 坐标
sWidth 源图像的矩形选择框的宽度
sHeight 源图像的矩形选择框的高度
dx 图像的左上角在目标 canvas 上 x 轴的位置
dy 图像的左上角在目标 canvas 上 y 轴的位置
dWidth 在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放
dHeight 在目标画布上绘制图像的高度,允许对绘制的图像进行缩放

这里再来一张图
【微信小程序生成海报保存到相册】_第3张图片

它有三种写法:

  1. 只规定原始图片开始剪切的位置,默认填充剩余宽高到画布上

drawImage(imageResource, dx, dy)

  1. 从指定位置裁剪原始图片指定宽高,填充到画布上

drawImage(imageResource, dx, dy, dWidth, dHeight)

  1. 从指定位置裁剪原始图片指定宽高,从指定位置开始显示到画布上指定宽高

drawImage(imageResource, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

这里如果需要裁剪图片的话需要用到第三种。

因为分享商品图片的话,图片的大小不固定,需要裁剪。
裁剪图片,借鉴这里



<view class="container">
    <button catchtap="showPic">点击生成海报button>

    
    <view class="share-cover" wx:if="{{showSharePic}}" catchtouchmove='true' catchtap='closeShare'>
    view>
    <view class="share-pic-box" wx:if="{{showSharePic}}" >
        <view class="share-pic">
            <image src="{{sharePicUrl}}" class="sharePic">image>
        view>
        <button class="share-tips" catchtap='savePic'>保存图片button>
        
    view>
    

    
    <canvas canvas-id="shareFrends" class="canvas">canvas>
    
view>


/* fx */
.share-cover {
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    background: rgba(0, 0, 0, .5);
    z-index: 101;
}

.share-pic-box {
    width: 640rpx;
    height: 1080rpx;
    border-radius: 24rpx;
    left: 50%;
    top: 45%;
    transform: translate(-50%, -50%);
    position: absolute;
    z-index: 999;
}

.share-pic {
    width: 640rpx;
    height: 1080rpx;
    border-radius: 24rpx;
    background: #fff;
    margin-bottom: 40rpx;
    overflow: hidden;
}

.share-tips {
    width: 70% !important;
    height: 44px;
    box-sizing: border-box;
    background: #FF3B3B;
    opacity: 1;
    border-radius: 22px;
    font-size: 16px;
    font-family: PingFang SC;
    font-weight: 400;
    line-height: 44px;
    color: #FFFFFF;
    padding: 0 !important;
}

/* .close-share {
    width: 50rpx;
    height: 50rpx;
    position: absolute;
    top: -25rpx;
    right: -25rpx;
    border-radius: 50%;
    z-index: 101;
    background-color: #fff;
    background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASBAMAAACk4JNkAAAALVBMVEUAAAAzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMFCKs1AAAADnRSTlMAAwGYnKilo/Tpjn6RhfLwgGgAAAB3SURBVAjXY7hxiAEEhLsZ+p4oABmMcS8Z7N45AVmi714xiL8DCjLGvTNiYKx75wQUeqzAABJUBAkxgARdwUIgwXcgIbAgVAik8QmEJQqUdYIKmYEFQWYp5gEFIcaLAQUhxjOCBP3AZokBXdAHMgso+JJh5yKoSwHamjhPbLDp2gAAAABJRU5ErkJggg==);
    background-size: 18rpx 18rpx;
    background-repeat: no-repeat;
    background-position: center center;
} */

.sharePic {
    width: 640rpx;
    height: 1080rpx;
}

.canvas {
    width: 1280rpx;
    height: 2160rpx;
    position: fixed;
    top: -1000000rpx;
}
Page({

    /**
     * 页面的初始数据
     */
    data: {
        shareImg: '',
        shareTitle: '',
 // canvas 
        showSharePic: false, // 分享海报显示隐藏
        sharePicUrl: '', // 生成海报连接
        _selData: {
            logoUrl: 'https:166073915600099c29f.jpg', //分享图
            headIcon: 'https:1658494314000538a44.png', //头像
            codeLogo: 'https:xxx/1660812259000a6a8e7.png', //小程序码
            buyLogoUrl: 'https://xxx/1660814336000e3ccda.png', //采购图标
        },
        imgInfo: {},
    },
  

     // 生命周期函数--监听页面加载
    * //分享的主图,一进来就获取图片信息、或者在拿到该数据之后就获取信息

    onLoad: function (options) { {
      // 获取图片信息
      // var that = this;
      wx.getImageInfo({
          src: this.data.shareImg,//分享的主图,一进来就获取图片信息、或者在拿到该数据之后就获取信息
          success(res) {
              console.log(res);
              that.setData({
                  imgInfo: res,//存起来要用到
              })
          }
      })
   },
    
    showPic() {
        let sharePicUrl = this.data.sharePicUrl;
        if (sharePicUrl != '') {
            this.setData({
                showSharePic: true
            })
        } else {
            wx.showToast({
                title: '图片生成中',
                mask: true,
                icon: 'loading',
                duration: 100000
            })
            this.share = false
            let logo = '';
            let headIcon = '';
            let code = '';
            let buyLogo = '';
            this.getHead().then(headUrl => {
                headIcon = headUrl
                return this.getLogo()
            }).then(logoUrl => {
                logo = logoUrl;
                return this.getCode() //getBuyLogo
            }).then(codeUrl => {
                code = codeUrl
                // this.drawImg(logo, headIcon, code);
                return this.getBuyLogo() //getBuyLogo
            }).then(buyLogoUrl => {
                buyLogo = buyLogoUrl
                this.drawImg(logo, headIcon, code, buyLogo);
            })
        }
    },
    // 绘图
    drawImg(logo, headIcon, code, buyLogo) {
        console.log(logo)
        console.log(headIcon)
        console.log(code)
        console.log(buyLogo)

        // let title = '家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗家用小型熨烫机便携式蒸汽熨斗' // 标题
        let title = this.data.shareTitle // 标题
        let authorName = 'var 有缘' // 名称

        let w = 0
        wx.getSystemInfo({
            success: function (res) {
                w = res.screenWidth
            }
        })

        // 1
        let ctx = wx.createCanvasContext('shareFrends')
        ctx.fillStyle = '#ffffff';//---------------设置背景色
        ctx.fillRect(0, 0, w / 750 * 1080 * 2, w / 750 * 1080 * 2) //600*600


        //绘制logo--分享主图 
        //开始画 
       	var dw = 580 / this.data.imgInfo.width;
        var dh = 580 / this.data.imgInfo.height;


        // 裁剪图片中间部分
        if (this.data.imgInfo.width > 580 && this.data.imgInfo.height > 580 || this.data.imgInfo.width < 580 && this.data.imgInfo.height < 580) {
            if (dw > dh) {
                ctx.drawImage(logo, 0, (this.data.imgInfo.height - 580 / dw) / 2, this.data.imgInfo.width, 580 / dw, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
            } else {
                ctx.drawImage(logo, (this.data.imgInfo.width - 580 / dh) / 2, 0, 580 / dh, this.data.imgInfo.height, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
            }
        }
        // 拉伸图片
        else {
            if (this.data.imgInfo.width < 580) {
                ctx.drawImage(logo, 0, (this.data.imgInfo.height - 580 / dw) / 2, this.data.imgInfo.width, 580 / dw, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
            } else {
                ctx.drawImage(logo, (this.data.imgInfo.width - 580 / dh) / 2, 0, 580 / dh, this.data.imgInfo.height, 30, 30, w / 750 * 580 * 2, w / 750 * 580 * 2)
            }
        }


        // 标签 
        ctx.drawImage(buyLogo, w / 750 * 30 * 2, w / 750 * 640 * 2, w / 750 * 88 * 2, w / 750 * 40 * 2)

        //绘制标题
        ctx.setTextAlign('left');
        ctx.setFillStyle('#151521'); //title文字颜色
        ctx.setFontSize(w / 750 * 28 * 2);
        // ctx.fillText(title, w / 750 * 32 * 2, w / 750 * 780 * 2);
        let canvasTitleArray = title.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 > (w / 750 * 550 * 2)) {
                let secondWidth = ctx.measureText(secondTitle).width;
                //第二行字数超过,变为...
                if (secondWidth > (w / 750 * 550 * 2)) {
                    secondTitle += "...";
                    break;
                } else {
                    secondTitle += element;
                }
            } else {
                firstTitle += element;
            }
        }
        //第一行文字
        // ctx.fillText(firstTitle, 20, 278, 280) //绘制文本
        ctx.fillText(firstTitle, w / 750 * 28 * 2, w / 750 * 730 * 2);
        //第二行问题
        if (secondTitle) {
            // ctx.fillText(secondTitle, 20, 300, 280) //绘制文本
            ctx.fillText(secondTitle, w / 750 * 28 * 2, w / 730 * 758 * 2);
        }

        // 价格
        let price = this.data.sharePrice // 标题
        let num = this.data.shareNum // 标题
        ctx.setFontSize(w / 750 * 32 * 2)
        ctx.setFillStyle('#ff3b39');
        //绘制文本
        ctx.fillText(`${price?'¥'+price:''}    ${num?'库存'+num:''}`, w / 750 * 32 * 2, w / 750 * 860 * 2)

        ctx.drawImage(code, w / 750 * 30 * 2, w / 750 * 880 * 2, w / 750 * 580 * 2, w / 750 * 200 * 2)
        //绘制文本 

        ctx.draw(false, () => {
            //调用接口将画布转换为图片
            wx.canvasToTempFilePath({
                x: 0,
                y: 0,
                fileType: 'jpg',
                quality: 1,
                width: w / 750 * 640 * 2,
                height: w / 750 * 1080 * 2,
                destWidth: w / 750 * 640 * 2,
                destHeight: w / 750 * 1080 * 2,
                canvasId: 'shareFrends',
                success: res => {

                    wx.hideToast();

                    this.setData({
                        sharePicUrl: res.tempFilePath //生成的图片路径
                    }, () => {

                        //渲染完后再显示分享海报
                        this.setData({
                            share: false,
                            showSharePic: true
                        })

                    })
                },
                fail(err) {
                    wx.showToast({
                        title: '图片生成失败,请稍候再试!',
                        icon: 'none',
                        mask: true
                    })
                }
            })
        })
    },

    //获取头像
    getHead() {
        return new Promise((resolve, reject) => {
            wx.downloadFile({
                url: this.data._selData.headIcon,
                success: res => {
                    resolve(res.tempFilePath)
                }
            })
        })
    },

    //获取logo
    // this.data.shareTitle,  this.data.shareImg,
    getLogo() {
        return new Promise((resolve, reject) => {
            wx.downloadFile({
                // url: this.data._selData.logoUrl,
                url: this.data.shareImg,
                success: res => {
                    resolve(res.tempFilePath);
                },
                fail: (err) => {
                    console.log(er)
                }
            })
        })
    },

    //获取二维码
    getCode() {
        return new Promise((resolve, reject) => {
            let tid = this.data._selData.tid;

            wx.downloadFile({
                url: this.data._selData.codeLogo,
                success: res => {
                    resolve(res.tempFilePath);
                },
                fail: (err) => {
                    console.log(er)
                }
            })
        })
    },
    //获取buyLogo
    getBuyLogo() {
        return new Promise((resolve, reject) => {
            wx.downloadFile({
                url: this.data._selData.buyLogoUrl,
                success: res => {
                    resolve(res.tempFilePath);
                },
                fail: (err) => {
                    console.log(err)
                }
            })
        })
    },


    //关闭分享海报
    closeShare() {
        this.setData({
            showSharePic: false
        })
    },

    //保存图片
    savePic() {
        let sharePicUrl = this.data.sharePicUrl;
        wx.getSetting({
            success: res => {
                if (res.authSetting['scope.writePhotosAlbum'] == false) {
                    wx.showModal({
                        title: '提示',
                        content: '是否授权将图片保存到相册?',
                        confirmColor: '#2ca2ed',
                        success: res => {
                            //点击确定打开授权设置
                            if (res.confirm) {

                                wx.openSetting({
                                    success: res => {

                                        setTimeout(() => {
                                            if (res.authSetting['scope.writePhotosAlbum'] == true) {

                                                wx.saveImageToPhotosAlbum({
                                                    filePath: sharePicUrl,
                                                    success: res => {
                                                        this.closeShare();
                                                        wx.showToast({
                                                            title: '已成功保存到相册!',
                                                            icon: 'none',
                                                            duration: 3000,
                                                        })
                                                    },
                                                    fail: err => {
                                                        wx.showToast({
                                                            title: '保存失败!',
                                                            icon: 'none',
                                                            duration: 3000,
                                                        })
                                                    }
                                                })
                                            } else {
                                                wx.showToast({
                                                    title: '保存失败!',
                                                    icon: 'none',
                                                    duration: 3000,
                                                })
                                            }
                                        }, 500)
                                    }
                                })
                            }
                        }
                    })
                } else {

                    wx.saveImageToPhotosAlbum({
                        filePath: sharePicUrl,
                        success: res => {
                            this.closeShare();
                            wx.showToast({
                                title: '已成功保存到相册!',
                                icon: 'none',
                                duration: 3000,
                            })
                        }
                    })

                }
            }
        })

    },

})

你可能感兴趣的:(前端,微信小程序,微信小程序,小程序)