vue中用canvas画图,实现动态显示数据生成图片

文章讲述了如何使用JavaScript和Canvas在网页上实现分页生成图片功能,根据数据量动态调整画布高度,以及调用接口获取数据并在画布上渲染,包括不分页和循环数据生成多张图片的示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.分页生成(每点击下一页则生成下一页的图片,数据多时使用)

1.在页面定义画布(数据不多可不进行分页生成图片)

<div id="firebox" >
      <canvas id="fire" ref="fire1" height="2000" width="700" >
      </canvas>
      <button @click="prevPage"  style="position: absolute; top: 10px; left: 10px;">上一页</button>
      <button @click="nextPage" style="position: absolute; top: 10px; right: 10px;">下一页</button>
      <span style="position: absolute; bottom: 10px; left: 10px;">当前页码: {{ currentPage }}</span>
    </div>

2.绘制图形的方法

  • 根据数据数量动态增加画布高度

  // 计算高度
  const height = minHeight + (num - 4) * heightIncrement;
    ctx.fillRect(0, 0, 700, height);


    creatfire(num) {
      
      const canvas = this.$refs.fire1;
      const ctx = canvas.getContext("2d");
      // 设置背景图片
      const backgroundImage = new Image();
      //   背景图片的位置
      backgroundImage.src = "";
      backgroundImage.onload = function () {
        ctx.drawImage(backgroundImage, 0, 0, 300, 610);
        // 在这里可以绘制其他内容或进行其他操作
      };
      ctx.fillStyle = "rgba(0, 0, 255, 0.5)"; 

  const minHeight = 250;
  const heightIncrement = 50;
 // console.log(num);
   // 计算高度
  const height = minHeight + (num - 4) * heightIncrement;
    ctx.fillRect(0, 0, 700, height);

      //   设置字体颜色
      ctx.fillStyle = "black";
      ctx.font = "20px 宋体";
      ctx.fillStyle = "white";
      ctx.globalCompositeOperation = "source-over";
    },

3.调接口数据渲染数据在画布中

FireData() {
      const canvas = this.$refs.fire1;
      const ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除之前的绘制
      ctx.font = "20px Arial";
      const token = localStorage.getItem("x-auth-token");
      const wdh = this.wdh
      FireData(token, wdh).then((res) => {
      // console.log('消防栓接口数据', res.data);
        if (res.data.length !== 0) {
          const tanker = res.data;
          if (res.data.length>15) {
          // this.itemsPerPage = Math.floor(res.data.length / 2);
          this.creatfire(this.itemsPerPage)
          }else{
            this.creatfire(res.data.length)
          }
              
          const itemsPerPage = this.itemsPerPage; // 每页显示的项数
          this.maxPage = Math.ceil(tanker.length / itemsPerPage); // 总页数
          const currentPage = this.currentPage || 1; // 当前页,默认为1
          const startIndex = (currentPage - 1) * itemsPerPage;//第xx条开始显示
          const endIndex = Math.min(startIndex + itemsPerPage, tanker.length);
          for (let i = startIndex; i < endIndex; i++) {
            const item = tanker[i];
            const offsetY = (i - startIndex) * 50; // 根据索引计算 Y 轴偏移
            const y = 40 + offsetY;
            ctx.fillText("消防资源",285, 40);
            ctx.fillText(item["device_name"], 260, y + 40);
            ctx.fillText("消防位置", 50, 40);
            ctx.fillText(item["position"], 55, y + 40);
            ctx.fillText("质保期限", 490, 40);
            ctx.fillText(item["warranty"], 465, y + 40);
          }
          const base64Str = canvas.toDataURL("image/png");//定义图片
          //   this.fireimage     图片的数组
          this.fireimage.push({ id: "fire"+this.currentPage, data: base64Str });//定义路径

          this.getfiredata()//调生成图片的接口
        }
      });
    },

4.调生成图片的方法

getfiredata() {
      const token = localStorage.getItem("x-auth-token");
      const fire = this.fireimage;
      const imageData = {
        wdh: this.wdh,
        address: fire,
      };
      getImage(token, imageData).then((res) => {
       console.log("消防栓信息图片地址", res);
      });
    },

5.分页按钮

    prevPage() {
      if (this.currentPage > 1) {
        this.currentPage--;
        this.FireData();
      }
    },
    nextPage() {
      if (this.currentPage < this.maxPage) {
        this.currentPage++;
        this.FireData();
        const canvas = this.$refs.fire1;
      const base64Str = canvas.toDataURL("image/png");
        this.fireimage.push({ id: "fire" + this.currentPage, data: base64Str });
      }
      this.getfiredata()

    },

6.在data中定义

     itemsPerPage: 15,//每页显示条数
      currentPage: 1,//当前页

      maxPage: '',//消防栓最大数量
      fireimage: [],//消防栓

二、不分页

 1.在页面定义画布(数据不多可不进行分页生成图片)


      <canvas id="fire" ref="fire1" height="2000" width="700" ></canvas>
     

2.绘制图形的方法

  • 根据数据数量动态增加画布高度

  // 计算高度
  const height = minHeight + (num - 4) * heightIncrement;
    ctx.fillRect(0, 0, 700, height);


    creatfire(num) {
      
      const canvas = this.$refs.fire1;
      const ctx = canvas.getContext("2d");
      // 设置背景图片
      const backgroundImage = new Image();
      //   背景图片的位置
      backgroundImage.src = "";
      backgroundImage.onload = function () {
        ctx.drawImage(backgroundImage, 0, 0, 300, 610);
        // 在这里可以绘制其他内容或进行其他操作
      };
      ctx.fillStyle = "rgba(0, 0, 255, 0.5)"; 

  const minHeight = 250;
  const heightIncrement = 50;
 // console.log(num);
   // 计算高度
  const height = minHeight + (num - 4) * heightIncrement;
    ctx.fillRect(0, 0, 700, height);

      //   设置字体颜色
      ctx.fillStyle = "black";
      ctx.font = "20px 宋体";
      ctx.fillStyle = "white";
      ctx.globalCompositeOperation = "source-over";
    },

3.调接口数据渲染数据在画布中,

FireData() {
      const canvas = this.$refs.fire1;
      const ctx = canvas.getContext("2d");
      ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除之前的绘制
      ctx.font = "20px Arial";
      const token = localStorage.getItem("x-auth-token");
      const wdh = this.wdh
      FireData(token, wdh).then((res) => {
     
        if (res.data.length !== 0) {
          const tanker = res.data;
    
            this.creatfire(res.data.length)//绘制图片,依照数据长度
   
        
          for (let i = 0; i < res.data.length; i++) {
            const item = tanker[i];
            const offsetY = i * 50; // 根据索引计算 Y 轴偏移
            const y = 40 + offsetY;
            ctx.fillText("消防资源",285, 40);
            ctx.fillText(item["device_name"], 260, y + 40);
            ctx.fillText("消防位置", 50, 40);
            ctx.fillText(item["position"], 55, y + 40);
            ctx.fillText("质保期限", 490, 40);
            ctx.fillText(item["warranty"], 465, y + 40);
          }
          const base64Str = canvas.toDataURL("image/png");//定义图片
          //   this.fireimage     图片的数组
          this.fireimage.push({ id: "fire" data: base64Str });//定义路径

          this.getfiredata()//调生成图片的接口
        }
      });
    },

4.调生成图片的方法

getfiredata() {
      const token = localStorage.getItem("x-auth-token");
      const fire = this.fireimage;
      const imageData = {
        wdh: this.wdh,
        address: fire,
      };
      getImage(token, imageData).then((res) => {
       console.log("消防栓信息图片地址", res);
      });
    },

5.在data中定义


      fireimage: [],//消防栓

三、循环数据同时生成多张图片

1.页面创建画布

    <canvas ref="card1" height="200" width="320"></canvas>
    <canvas ref="card2" height="200" width="320"></canvas>
    <canvas ref="card3" height="200" width="320"></canvas>
    <canvas ref="card4" height="200" width="320"></canvas>
    <canvas ref="card5" height="200" width="320"></canvas>
    <canvas ref="card6" height="200" width="320"></canvas>
    <canvas ref="card7" height="200" width="320"></canvas>
    <canvas ref="card8" height="200" width="320"></canvas>
    <canvas ref="card9" height="200" width="320"></canvas>
    <canvas ref="card10" height="200" width="320"></canvas>

2.绘制背景颜色图形,并渲染数据

    createCard(index) {
      const canvas = this.$refs["card" + index];
      const ctx = canvas.getContext("2d");
      ctx.font = "20px Arial";
      // 设置背景图片
      const backgroundImage = new Image();
      //   背景图片的位置
      backgroundImage.src = "";
      backgroundImage.onload = function () {
        ctx.drawImage(backgroundImage, 0, 0, 300, 280);
        // 在这里可以绘制其他内容或进行其他操作
      };
      // 设置矩形的填充颜色
      ctx.fillStyle = "rgba(0, 0, 255, 0.5)"; 

      ctx.fillRect(0, 0, 320, 210);
      ctx.globalCompositeOperation = "source-over";
      //   设置字体颜色
      ctx.fillStyle = "black";
      // ctx.font = "15px 宋体";
      ctx.fillStyle = "#ffffff";
      ctx.globalCompositeOperation = "source-over";
      ctx.font = "16px 黑体";
      const tanker = this.carddata[index - 1];
      const cardInfo = [
        { text: tanker["piont_name"] + '打卡详情', x: 85, y: 50 },
        { text: "人员", x: 20, y: 100 },
        { text: tanker["checker_name"], x: 65, y: 100 },
        { text: "时间", x: 20, y: 150 },
        { text: tanker["time"], x: 65, y: 150 },
      ];
      cardInfo.forEach((item) => {
        ctx.fillText(item.text, item.x, item.y);
      });
      const base64Str = canvas.toDataURL("image/png");
      this.list.push({ id: "xg" + index.toString().padStart(2, "0"), data: base64Str });

    },

3.调数据接口

    PatroInfo() {
      const token = localStorage.getItem("x-auth-token");
      const wdh = this.wdh
      const piontId = this.card
      PatroInfo(token, wdh, piontId).then((res) => {
      // console.log('巡更信息接口', res.data);
        this.carddata = res.data
        // 调用 createCard 函数根据卡片数量动态生成卡片
        for (let i = 1; i <= this.carddata.length; i++) {
          this.createCard(i);
        }
        this.getxungengList()//调生成图片接口

      });
    },

4.生成图片方法

 getxungengList() {
      const token = localStorage.getItem("x-auth-token");
      const list = this.list;
      const imageData = {
        wdh: this.card,
        address: list,
      };
      getImage(token, imageData).then((res) => {
      console.log("获取巡更图片", res);
      });
    },

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值