小程序生成海报保存分享

    <view class='imagePathBox' v-if="savePoster == true">
     <image :src="posters" class='shengcheng'></image>
      <button class='baocun' @click='baocun'>保存相册,分享到朋友圈</button>
    </view>
    <view v-if="savePoster == true" class="mask"></view> 
    <view class="canvas-box">
      <canvas style="width: 375px;height: 600px;position:fixed;top:9999px" canvas-        
         id="posterCanvas"/>
    </view>

    <!-- 在页面中添加 loading 动画 -->
    <view v-if="showLoading == true" class="loading-icon">
      <div class="loading-circle"></div>
      <text class="loading-text">海报制作中...</text>
    </view>
 data() {
   return {
      // 海报图片
      posters: "",
      logo: "",  // logo图片 
      currentBackgroundIndex: 0, // 当前背景图片索引
      showLoading: false, // 显示在生成中
      logoPosition: 0, // logo位置
      qcCodePosition: 0, // 二维码位置
      savePoster: false, // 显示保存相册

   }    
 }
// 生成海报
    async generatePoster() {
      this.showLoading = true;

      wx.getImageInfo({ // 网络图片无法直接通过画布使用,先使用 wx.getImageInfo 转成本地 
   图片地址
        src: this.backgroundImages[this.currentBackgroundIndex].posterUrl,
        success: (res) => {
          const canvasWidth = 370; // 你的canvas的默认宽度
          const canvasHeight = 600; // 你的canvas的默认高度
          const bgImageWidth = res.width; // 背景图片原始宽度
          const bgImageHeight = res.height; // 背景图片原始高度

          // 计算背景图片按比例缩放后的高度
          const scaledHeight = (canvasWidth / bgImageWidth) * bgImageHeight;

          // 计算绘制的起始位置使背景图片居中
          const startX = 0; // 保持起始位置为左上角,只调整高度
          const startY = (canvasHeight - scaledHeight) / 2;

          this.generatePosterForBackground(res.path, canvasWidth, scaledHeight, startX, startY)
            .then((poster) => {
              this.posters = poster;
              this.showLoading = false;
              this.savePoster = true;
            })
            .catch((error) => {
              this.showLoading = false;
            });
        },
        fail: (error) => {
          this.$u.toast("生成失败,请重试");
          this.showLoading = false;
        },
      });
    },

    generatePosterForBackground(bgImagePath, scaledWidth, scaledHeight, startX, startY) {
      return new Promise((resolve, reject) => {
        const ctx = wx.createCanvasContext("posterCanvas");

        // 绘制背景图片,确保它覆盖整个画布
        ctx.drawImage(bgImagePath, startX, startY, scaledWidth, scaledHeight);

        if (this.backgroundImages[this.currentBackgroundIndex].logoColor == "0") {
          this.logo = "/static/img/logo.png"
        }else {
          this.logo = "/static/img/logo2.png"
        }
        const logoImagePath = this.logo;
        const logoPosition =
          this.backgroundImages[this.currentBackgroundIndex].direction;
        if (logoPosition == "左上角") {
          this.logoPosition = 10;
        } else if (logoPosition == "右上角") {
          this.logoPosition = scaledWidth - 10 - 80; // Adjusted to fit logo width
        }
        const logoWidth = 80;
        const logoHeight = 40;
        const logoX = this.logoPosition;
        const logoY = 10;

        ctx.drawImage(logoImagePath, logoX, logoY, logoWidth, logoHeight);

        // 设置文字颜色为白色和字体大小
        ctx.setFillStyle("#fff"); // 设置文字颜色为白色
        ctx.setFontSize(16); // 设置字体大小为14px
        const str = this.post.optPostResVO.postTitle;
        const index = str.indexOf("(");
        let dataBeforeParentheses;

        if (index !== -1) {
          dataBeforeParentheses = str.substring(0, index);
        } else {
          dataBeforeParentheses = str;
        }
        // 绘制参数信息
        ctx.fillText("职位:" + dataBeforeParentheses, 20, 510);
        ctx.fillText(
          "薪资:" +
            this.post.optPostResVO.salaryMin +
            "~" +
            this.post.optPostResVO.salaryMax +
            "元",
          20,
          540
        );

        var wechatId = this.userinfo.wechatId;
        const currentTimestampMilliseconds = Date.now();
        const timestamp = Math.floor(currentTimestampMilliseconds / 1000);
        if (this.recordParentId == undefined) {
          this.recordParentId = "";
        }
        if (this.shareId == undefined) {
          this.shareId = "";
        }
        // 获取生成二维码的
        var params = {
          scene:
            this.postId +
            "&" +
            this.recordParentId +
            "&" +
            this.shareId +
            "&" +
            this.storeySum +
            "&" +
            timestamp +
            "&" +
            wechatId,
          is_hyaline: true,
        };
        this.$u.api.getQrCode(params).then((res) => {
          let base64 = res.data.fileName;
          this.images = this.$BASE_URL + base64;
          if (this.backgroundImages[this.currentBackgroundIndex].posterHyaline == "1") {
            const qrCodeSize = 120;  // 二维码尺寸
            const whiteCircleSize = qrCodeSize;  // 圆形白底尺寸保持与二维码一致
            // 绘制白色圆形背景
            ctx.setFillStyle('#fff');  // 设置填充颜色为白色
            ctx.setStrokeStyle('#cccc00');  // 设置边框颜色为黑色
            ctx.beginPath();  // 开始绘制路径
            ctx.arc(280, 510, whiteCircleSize / 2, 0, 2 * Math.PI);  // 绘制圆形路径,半径为 whiteCircleSize / 2
            ctx.closePath();  // 关闭路径
            ctx.fill();  // 填充圆形
            ctx.stroke();  // 绘制边框
          }

          // 绘制二维码
          const qrCodeUrl = this.images;
          if (qrCodeUrl) {
            wx.getImageInfo({
              src: qrCodeUrl,
              success: (res) => {
                ctx.drawImage(res.path, 220, 450, 120, 120);
                // 绘制完后保存生成的图片
                setTimeout(() => {
                  ctx.draw(false, () => {
                    wx.canvasToTempFilePath({
                      x: 0,
                      y: 0,
                      width: scaledWidth,
                      height: scaledHeight,
                      canvasId: "posterCanvas",
                      success: (res) => {
                        resolve(res.tempFilePath);
                      },
                      fail: (err) => {
                        console.error("canvasToTempFilePath failed: ", err);
                        reject(err);
                      },
                    });
                  });
                }, 2000); // 添加setTimeout,防止未加载好久直接画了,可以自己调整时间
              },
              fail: (err) => {
                console.error("getImageInfo failed: ", err);
                reject(err);
              },
            });
          }
        });
      });
    },
<style scoped lang="scss">
.imagePathBox {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.7);
  position: fixed;
  top: 50;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10;
}
.shengcheng {
  width: 80%;
  height: 75%;
  position: fixed;
  top: 150rpx;
  left: 50%;
  margin-left: -40%;
  z-index: 10;
}
.arrow-iconLeft {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  left: 20rpx;
}
.arrow-iconRight {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  cursor: pointer;
  right: 20rpx;
}
.arrow {
  font-size: 30px;
  color: white;
}
.quehuan {
  display: block;
  width: 80%;
  height: 80rpx;
  padding: 0;
  line-height: 80rpx;
  text-align: center;
  position: fixed;
  bottom: 180rpx;
  left: 10%;
  background: #ffe200;
  color: #333;
  font-size: 32rpx;
  border-radius: 44rpx;
}
.baocun {
  display: block;
  width: 80%;
  height: 80rpx;
  padding: 0;
  line-height: 80rpx;
  text-align: center;
  position: fixed;
  bottom: 50rpx;
  left: 10%;
  background: #ffe200;
  color: #333;
  font-size: 32rpx;
  border-radius: 44rpx;
}
button[class="baocun"]::after {
  border: 0;
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.loading-icon {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  background: rgba(0, 0, 0, 0.5); /* 半透明背景 */
  padding: 20px;
  border-radius: 8px;
}

.loading-circle {
  width: 40px;
  height: 40px;
  border: 4px dashed #3498db; /* 明显的虚线边框 */
  border-radius: 50%;
  animation: rotate 1.5s linear infinite;
}

.loading-text {
  margin-top: 10px;
  text-align: center;
  color: white; /* 文字颜色为白色 */
}
</style>

生成如下,代码里设置了多张背景图,进行选择,设置了logo显示位置,左上角或者右上角

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值