首页 > 其他分享 >纯前端Canvas绘制海报

纯前端Canvas绘制海报

时间:2024-09-04 15:14:56浏览次数:9  
标签:Canvas const 海报 number context canvas return height 绘制

封装类:

/**
 * Canvas绘制海报
 */
class Poster {
  canvas: HTMLCanvasElement;
  context: CanvasRenderingContext2D;

  constructor(el: string, width: number, height: number) {
    const canvas = document.querySelector<HTMLCanvasElement>(el);
    if (canvas === null) {
      throw new Error("获取canvas失败");
    }
    canvas.width = width;
    canvas.height = height;
    this.canvas = canvas;

    const context = canvas.getContext("2d");
    if (context === null) {
      throw new Error("获取context失败");
    }
    this.context = context;
  }

  setFillStyle(style: string) {
    this.context.fillStyle = style;
    return this;
  }

  setStrokeStyle(style: string) {
    this.context.strokeStyle = style;
    return this;
  }

  setFont(font: string) {
    this.context.font = font;
    return this;
  }

  fillCanvas() {
    this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
    return this;
  }

  clearCanvas() {
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
    return this;
  }

  loadImage(src: string) {
    return new Promise<HTMLImageElement>((resolve, reject) => {
      const img = new Image();
      img.src = src;
      img.crossOrigin = "anonymous";
      img.onload = function () {
        resolve(img);
      };
    });
  }

  drawImage(image: CanvasImageSource, x: number, y: number, width: number, height: number) {
    this.context.drawImage(image, x, y, width, height);
    return this;
  }

  drawText(text: string, x: number, y: number, limitWidth?: number, lineHeight?: number) {
    if (limitWidth != undefined) {
      let measureTextWidth = 0;
      let lastSubstringIndex = 0;
      for (let i = 0; i < text.length; i++) {
        const metrics = this.context.measureText(text[i]);
        measureTextWidth += metrics.width;
        if (measureTextWidth > limitWidth) {
          this.context.fillText(text.substring(lastSubstringIndex, i), x, y);
          measureTextWidth = 0;
          lastSubstringIndex = i;
          y += lineHeight ?? metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
        }
        if (i === text.length - 1) {
          this.context.fillText(text.substring(lastSubstringIndex, i + 1), x, y);
        }
      }
    } else {
      this.context.fillText(text, x, y);
    }
    return this;
  }

  drawLine(x1: number, y1: number, x2: number, y2: number) {
    this.context.moveTo(x1, y1);
    this.context.lineTo(x2, y2);
    this.context.stroke();
    return this;
  }

  toDataURL(type?: string, quality?: any) {
    return this.canvas.toDataURL(type, quality);
  }

  download(filename: string = Date.now().toString()) {
    let ext = "png";
    if (filename.includes(".")) {
      const filenameSplit = filename.split(".");
      ext = filenameSplit[filenameSplit.length - 1].toLowerCase();
    }
    let mime = "image/png";
    if (ext === "jpg" || ext === "jpeg") {
      mime = "image/jpeg";
    }
    const base64 = this.toDataURL(mime);
    const aEl = document.createElement("a");
    aEl.href = base64;
    aEl.setAttribute("download", filename);
    aEl.click();
  }
}

export default Poster;

 

使用示例:

<script setup lang="ts">
import Poster from "@/utils/poster";
import QRCode from "qrcode";
import { onMounted, ref } from "vue";

defineOptions({
  name: "Poster",
});

// 获取本地图片
function getAssetImg(name: string) {
  return new URL(`../../assets/poster/${name}`, import.meta.url).href;
}

async function generatePoster() {
  const width = 750;
  const height = 1334;
  const poster = new Poster("#canvas", width, height);
  const bgImg = await poster.loadImage(getAssetImg("bg.jpeg"));
  // 生成二维码base64图片
  const qrcodeUrl = await QRCode.toDataURL(`https://www.baidu.com`);
  const qrcodeImg = await poster.loadImage(qrcodeUrl);
  // 开始绘制
  poster
    .drawImage(bgImg, 0, 0, width, height)
    .drawImage(qrcodeImg, width - 150, height - 150, 100, 100)
    .setFillStyle("#fff")
    .setFont("14px bold 黑体")
    .drawText("打开爱奇艺app,扫码领取积分,赢取豪华大礼,惊喜等着你~", 50, height - 100, 250, 20);

  return poster;
}

const posterObj = ref();
const isLoading = ref(true);

onMounted(async () => {
  posterObj.value = await generatePoster();
  isLoading.value = false;
});
</script>

<template>
  <div>
    <div v-if="isLoading">生成中。。。</div>
    <div v-show="!isLoading">
      <canvas id="canvas"></canvas>
      <div>
        <button type="button" @click="posterObj.download()">保存海报</button>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped></style>

 

 

标签:Canvas,const,海报,number,context,canvas,return,height,绘制
From: https://www.cnblogs.com/cshaptx4869/p/18396575

相关文章

  • IPKISS 绘制 Euler Fixed Bend 的创建方法
    IPKISS绘制EulerFixedBend的创建方法正文正文在IPKISS使用Si_fabPDK创建EulerBend波导结构并导入Lumerical中产生对应仿真结构一文中我们介绍了如何使用IPKISS中的si_fab包创建EulerBend波导。这里我们介绍如何使用si_fab包创建EulerF......
  • DevExpress WinForms中文教程:Data Grid - 如何自定义绘制?
    在本教程中,您将学习如何使用DevExpressgridView(网格视图)的CustomDraw…事件,您将从一个显示普通任务数据的网格开始。首先使用事件来自定义单元格外观,然后修改相同的事件处理程序,来根据网格数据更改单个单元格中显示的文本。接下来将进一步扩展处理程序来在特定单元格中绘制图像,......
  • (3-5)绘制散点图和折线图:Flask+pygal+SQLite实现数据分析
    3.5 Flask+pygal+SQLite实现数据分析在本节的内容中,将使用Flask+pygal+SQLite3实现数据分析功能。将需要分析的数据保存在SQLite3数据库中,然后在FlaskWeb网页中使用库pygal绘制出对应的统计图。3.5.1 创建数据库首先使用PyCharm创建一个FlaskWeb项目,然后通过文件model......
  • vue2+html2canvas+jspdf 导出网页
    `asynchandlePreview(){constpdf=awaitthis.exportToPdf()//使用浏览器预览PDF-安全策略有缺陷constpdfDataURI=pdf.output('datauristring')window.open(pdfDataURI,'_blank','location=no');},asynchandleDown(){constpdf=awai......
  • 【Canvas与艺术】五种函数化回文边纹纹饰荟萃
    【成图】【代码】<!DOCTYPEhtml><htmllang="utf-8"><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><head><title>五种函数化回文边纹纹饰荟萃</title><styletype="text/css&......
  • Android UI绘制流程
     UI绘制流程,Activity、Dialog、PopupWindow等--android系统的事件分发流程分为很多部分: Native层–>ViewRootImpl层–>DecorView层–>Activity层–>ViewGroup层–>View层。  其实Toast窗口和Activity、Dialog、PopupWindow有一个不太一样的地方,就是Toast窗......
  • canvas作图,动图练习
    代码:<!Doctypehtml><htmllang="zh_cn"><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><title>Canvas</title><metaname="K......
  • 最近写贪吃蛇有些上瘾,canvas版本贪吃蛇,贪吃蛇是逻辑最简单的游戏了
    代码:<!Doctypehtml><htmllang="zh_cn"><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><title>贪吃蛇</title><metaname="Keyw......
  • 【Canvas与艺术】十边螺线动态顺时针扩大光阑
    【成图】【代码】<!DOCTYPEhtml><htmllang="utf-8"><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><head><title>十边螺线动态扩大光阑</title><styletype="text/css&quo......
  • 【Canvas与艺术】十边螺线动态缩小光阑
    【成图】【代码】<!DOCTYPEhtml><htmllang="utf-8"><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><head><title>十边螺线动态缩小光阑</title><styletype="text/css&quo......