巧用 html2canvas 与 file-saver:在 Vue 中实现图片文案快速导出

前言:家人们,大家好!今天分享一篇文章给大家!要是文章对你有帮助,激发了你的灵感,

求个收藏 + 关注啦~后续还有超多惊喜,别错过!

引言

在前端开发过程中,我们常常会遇到需要将网页内容导出为图片的需求,比如生成海报、保存页面快照等。今天,我们就来探讨如何借助 html2canvas 和 file-saver 这两个强大的工具,在 Vue 项目里实现图片文案的快速导出功能。

项目需求与目标

我们的目标是创建一个简单的工具,它允许用户选择颜色来定制文案的背景色,同时提供一个按钮,点击后能将特定区域的文案内容导出为带有水印的图片。

项目实现步骤

1. 项目准备

首先,我们需要创建一个 Vue 项目,并安装所需的依赖:

npm install html2canvas file-saver element-ui

 这里我们使用了 html2canvas 来将 HTML 元素转换为 Canvas,file-saver 用于保存生成的图片,element-ui 则提供了一些美观的 UI 组件,如按钮和颜色选择器。

2. 编写组件代码

以下是完整的组件代码:

<template>
  <div style="padding: 20px">
    <div class="flex">
      <el-button type="primary" @click="exportImage">保存图片</el-button>
      <div class="flex_item">
        <span class="demonstration">选择颜色</span>
        <el-color-picker v-model="color" @change="activeChange" />
      </div>
    </div>
    <div id="export-container">
      <div class="image-content">
        <div class="title_bg" :style="{ backgroundColor: color }">
          <div>{{ title }}场景提示词</div>
        </div>
        <ul>
          <li v-for="(item, index) in textList" :key="index" class="list_item" :style="{ backgroundColor: hexToRgba(color, 0.1) }">
            <div class="name_item">
              {{ index + 1 + ' . ' + item.name }}
            </div>
            <div class="content_item">
              {{ item.content }}
            </div>
            <div class="case_item">
              {{ item.case }}
            </div>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import html2canvas from 'html2canvas';
import { saveAs } from 'file-saver';

export default {
  data() {
    return {
      title: '进阶技巧',
      textList: [
        {
          name: '角色扮演指令',
          content: '你是一名有20年经验的刑侦法医,用专业术语分析以下现场描述,指出3处异常痕迹:[案件描述]',
          case: '(适用:专业场景模拟)',
        },
        {
          name: '多步推理指令',
          content: '已知:A>B, B>C, C≠D, D<E。请逐步推导A与E的关系,并用韦恩图解释推导过程',
          case: '(适用:逻辑训练)',
        },
        {
          name: '创意生成限制',
          content: '列举10种从未被发明过的厨房小工具,每个创意需满足:成本低于$5、无需用电、解决实际痛点',
          case: '(适用:产品设计)',
        },
        {
          name: '跨学科联想',
          content: '将唐诗《春晓》的意境转化为现代电子音乐创作元素,描述旋律特征、音色选择和节奏设计思路',
          case: '(适用:艺术创作)',
        },
      ],
      color: '#409eff',
      exportContainer: null,
    };
  },
  created() {
    this.color = localStorage.getItem('color');
    this.exportContainer = document.querySelector('#export - container');
  },
  methods: {
    activeChange(e) {
      console.log(e, 'dsdad');
      localStorage.setItem('color', e);
      this.color = e;
    },
    async exportImage() {
      try {
        const canvas = await html2canvas(this.exportContainer, {
          width: 520,
          height: 700,
          scale: 15,
        });
        this.addWatermark(canvas);
        canvas.toBlob((blob) => {
          saveAs(blob, 'AI文案.png');
        }, 'image/png');
      } catch (error) {
        console.error('导出图片失败', error);
        alert('导出图片失败,请稍后重试。');
      }
    },
    addWatermark(canvas) {
      const ctx = canvas.getContext('2d');
      const watermarkText = '码上前端';
      const font = '30px';
      const color1 = 'rgba(255, 255, 255, 0.5)';
      const canvasWidth = canvas.width;
      const canvasHeight = canvas.height;
      const x = canvasWidth - ctx.measureText(watermarkText).width - 10;
      const y = canvasHeight - 30;

      ctx.save();
      ctx.rotate((-45 * Math.PI) / 180);
      ctx.font = font;
      ctx.fillStyle = color1;
      ctx.fillText(watermarkText, x, y);
      ctx.restore();
    },
    hexToRgba(hex, alpha) {
      if (!hex || typeof hex!== 'string') {
        return 'rgba(0, 0, 0, 0)';
      }
      hex = hex.replace(/^#/, '');
      if (hex.length === 3) {
        hex = hex
          .split('')
          .map((char) => char + char)
          .join('');
      }
      const bigint = parseInt(hex, 16);
      const r = (bigint >> 16) & 255;
      const g = (bigint >> 8) & 255;
      const b = bigint & 255;
      return `rgba(${r}, ${g}, ${b}, ${alpha})`;
    },
  },
};
</script>

<style scoped lang="scss">
.flex {
  display: flex;
  align-items: center;
  margin-bottom: 20px;
  .flex_item {
    margin-left: 20px;
    color: blue;
    display: flex;
    gap: 10px;
    align-items: center;
  }
}
#export - container {
  width: 520px;
  height: 700px;
  box-sizing: border-box;
  padding: 25px 2px 0 2px;
  // background - color: rgb(244, 211, 162);
}

.image - content {
  width: 100%;
  .title_bg {
    border - radius: 25px;
    text - align: center;
    padding: 30px;
    font - size: 35px;
    font - weight: 400;
    color: #fff;
    background - color: #409eff;
  }
}

ul {
  list - style - type: none;
  padding: 10px;
  .list_item {
    margin - bottom: 10px;
    border - radius: 25px;
    line - height: 25px;
    padding: 15px 5px 10px 5px;
    background - color: #becede;
    .name_item {
      font - size: 18px;
      font - weight: 600;
    }
    .content_item {
      font - size: 14px;
    }
  }
}
</style>

3. 代码详细解释

模板部分
  • 我们使用了 element - ui 的按钮和颜色选择器。按钮点击触发 exportImage 方法,颜色选择器绑定 color 变量,颜色改变时触发 activeChange 方法。
  • #export-container 是要导出为图片的区域,包含标题和文案列表。
脚本部分
  • 数据部分:定义了文案标题、文案列表、颜色变量和要导出的容器元素。
  • created 钩子:从 localStorage 中获取之前保存的颜色,并缓存要导出的容器元素,避免后续重复查询 DOM。
  • activeChange 方法:当用户选择颜色时,将新颜色保存到 localStorage 并更新 color 变量。
  • exportImage 方法
    • 使用 html2canvas 将 #export-container 转换为 Canvas。
    • 调用 addWatermark 方法添加水印。
    • 将带有水印的 Canvas 转换为 Blob 对象,并使用 file-saver 保存为 AI文案.png
    • 若导出过程中出现错误,会在控制台打印错误信息并弹出提示框告知用户。
  • addWatermark 方法:在 Canvas 上添加旋转 45 度的半透明水印文字。
  • hexToRgba 方法:将十六进制颜色代码转换为 RGBA 格式,方便设置透明度。
样式部分

使用 SCSS 编写样式,设置了布局、背景色、字体大小等样式,使界面更加美观。

结语

通过 html2canvas 和 file-saver,我们可以在 Vue 项目中轻松实现图片文案的快速导出功能。结合 element-ui 提供的组件,还能打造出美观易用的界面。在实际开发中,我们要注意性能优化、代码结构优化和兼容性处理,以提供更好的用户体验。希望本文能帮助你在 Vue 项目中实现类似的功能。如果你在实践过程中遇到问题或有更好的建议,欢迎在评论区留言分享!

到这里,这篇文章就和大家说再见啦!我的过往文章里还藏着许多干货,感兴趣的话也可以点击我的主页看看,下面的文章也很精彩,可别错过。创作这篇内容花费了不少心血,要是它帮你解决了问题,或者带来了启发,就多多支持下 “码上前端” 吧~要是想转载,麻烦一定注明本文链接,感谢大家! 💕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值