vue canvas 拼接图片制作海报简易版

<template>
  <div>
    <div style="margin-bottom: 20px">
      <el-button style="margin-left: 20px" @click="add">添加</el-button>
      <el-button style="margin-left: 20px" type="success" @click="handleDown"
        >下载
      </el-button>
    </div>

    <canvas id="myCanvas"></canvas>
  </div>
</template>
<script setup lang="ts">
import { onMounted } from "vue";
import { baseImgUrl } from "@/api/utils";

onMounted(() => {
  initCancas();
});

let product_list = [
  {
    cover: "product/6455efe66a52a51a98642da71690451253763.jpg",
    name: "云南元谋冬枣9kg装一级泡沫箱装大果",
    width: 100,
    height: 100,
    price: 100
  },
  {
    cover: "product/6455efe66a52a51a98642da71719627894157.jpg",
    name: "曲靖华硕苹果21kg筐装一级",
    width: 100,
    height: 100,
    price: 120
  },
  {
    cover: "product/6455efe66a52a51a98642da71705285150862.jpg",
    name: "陕西甜王西瓜22kg纸箱装一级",
    width: 100,
    height: 100,
    price: 68
  },
  {
    cover: "product/6455efe66a52a51a98642da71705285150862.jpg",
    name: "陕西甜王西瓜22kg纸箱装一级",
    width: 100,
    height: 100,
    price: 68
  },
  {
    cover: "product/6455efe66a52a51a98642da71705285150862.jpg",
    name: "陕西甜王西瓜22kg纸箱装一级",
    width: 100,
    height: 100,
    price: 68
  },
  {
    cover: "product/6455efe66a52a51a98642da71705285150862.jpg",
    name: "陕西甜王西瓜22kg纸箱装一级",
    width: 100,
    height: 100,
    price: 68
  },
  {
    cover: "product/6455efe66a52a51a98642da71705285150862.jpg",
    name: "陕西甜王西瓜22kg纸箱装一级",
    width: 100,
    height: 100,
    price: 68
  }
];

function initCancas() {
  let canvas = document.getElementById("myCanvas");
  let ctx = canvas.getContext("2d");
  let width = 400;

  canvas.width = width;
  let imgW = 300;
  let canvasStyleH = 0;
  let dpi = window.devicePixelRatio;
  product_list.forEach(ele => {
    if (ele.name.length > 7) {
      ele.name_1 = ele.name.substring(0, 10);
      ele.name_2 = ele.name.substring(10);
    } else {
      ele.names = "";
    }
    ele.src = baseImgUrl + ele.cover;
    let ratio = ele.height / ele.width;
    if (imgW * ratio > canvasStyleH) {
      canvasStyleH = imgW * ratio;
    }
  });

  // ctx.rect(0, 0, canvas.width, canvas.height);

  let row = Math.ceil(product_list.length / 3);
  let group = new Array(row);
  let temp_list = [];
  product_list.forEach((res, index) => {
    let i = parseInt(index / 3);
    if (index % 3 == 0) {
      temp_list = [];
    }
    temp_list.push(res);
    group[i] = temp_list;
  });

  let row_height = 180;
  let bottom_height = 120;

  let height = row * row_height;
  canvas.height = height + bottom_height + 120;

  ctx.lineJoin = "round";
  ctx.lineWidth = 10;
  ctx.fillStyle = "#ff9f3360"; //矩形填充色
  ctx.fillRect(0, 0, width, height + 120);

  let headImg = new Image();
  headImg.onload = function () {
    ctx.drawImage(headImg, 0, 0, 400, 120);
  };
  headImg.src =
    "https://image.guoshut.top/topic/648bce7e7a9b75ca6f4258501713859985246.png";

  headImg.setAttribute("crossOrigin", "Anonymous");

  group.forEach((item, row_index) => {
    item.forEach((res, index) => {
      let img = new Image();
      img.crossOrigin = "Anonymous";

      let x = index * 106 + 20;

      if (index > 0) {
        x += index * 20;
      }

      let y = row_index * 175 + 120;
      if (row_index > 0) {
      }

      img.onload = function () {
        // 绘制产品被包裹的矩形
        ctx.lineJoin = "round";
        ctx.lineWidth = 10;
        ctx.strokeStyle = "#eee";
        ctx.fillStyle = "rgba(238, 238, 238, 1)"; //矩形填充色
        ctx.fillRect(x, y + 20, 106, 155);
        ctx.strokeRect(x, y + 20, 106, 155);
        // ctx.stroke();

        // 上部分产品里字体颜色
        let gradients = ctx.createLinearGradient(0, 0, 10, 0);
        gradients.addColorStop("0", "#707171");
        ctx.fillStyle = gradients;
        ctx.font = "12px Arial";
        ctx.fillText(res.name_1, x, y + 140);
        ctx.fillText(res.name_2, x, y + 155);

        let gradientss = ctx.createLinearGradient(0, 0, 10, 0);
        gradientss.addColorStop("0", "red");
        ctx.fillStyle = gradientss;
        ctx.font = "16px Arial";
        ctx.fillText("¥" + res.price, x + 10, y + 175);

        ctx.font = "12px normal";
        ctx.drawImage(img, x, y + 20, 106, 106);
      };

      img.src = res.src;

      img.setAttribute("crossOrigin", "Anonymous");
    });
  });

  const iconImg = new Image();
  iconImg.src = baseImgUrl + "icon/mini_qr_430.jpg";
  ctx.stroke();
  ctx.fill();
  ctx.lineJoin = "round";
  ctx.lineWidth = 10;
  ctx.strokeStyle = "red";
  ctx.fillStyle = "#ff9f33"; //矩形填充色
  ctx.fillRect(0, row * row_height + 120, 400, 120);

  iconImg.onload = () => {
    ctx.drawImage(iconImg, 40, row * row_height + 140, 80, 80);

    // 二维码字体颜色
    let gradient = ctx.createLinearGradient(0, 0, 10, 0);
    gradient.addColorStop("0", "#eee");
    ctx.fillStyle = gradient;

    ctx.font = "14px Arial";
    ctx.fillText("果蔬团服务", 150, row * row_height + 160);
    ctx.fillText("长按图片前往小程序", 150, row * row_height + 190);
  };
  iconImg.setAttribute("crossOrigin", "Anonymous");

  // ctx.save();
}

function handleDown() {
  let canvas = document.getElementById("myCanvas");
  let b64 = canvas.toDataURL("image/jpeg", 1);

  const blob = base64ToBlob(b64.split(",")[1], "image/jpeg");
  const objectURL = URL.createObjectURL(
    new Blob([blob], { type: "image/png" })
  );
  const anchor = document.createElement("a");
  anchor.href = objectURL;
  anchor.download = "Filename.png";
  anchor.click();
}

function base64ToBlob(base64, mimeType) {
  const byteCharacters = atob(base64);
  const byteArrays = [];

  for (let offset = 0; offset < byteCharacters.length; offset += 512) {
    const slice = byteCharacters.slice(offset, offset + 512);
    const byteNumbers = new Array(slice.length);

    for (let i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    const byteArray = new Uint8Array(byteNumbers);
    byteArrays.push(byteArray);
  }

  return new Blob(byteArrays, { type: mimeType });
}

function add() {}
</script>

<style scoped></style>
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值