JavaScript在图片绘制文字两种方法的实现与对比

 更新时间:2024年03月07日 10:41:19   作者:进阶的鱼  
这篇文章主要为大家详细介绍了前端实现在图片上绘制文字的两种思路,支持即粘即贴即用,文中的示例代码讲解详细,需要的小伙伴可以了解下

序言

本文实现了在图片上绘制文字的两种思路,并通过demo的方式,去具体实现,实现代码为组件形式,支持即粘即贴即用

效果展示

需求简介

遇到一个这样的需求,产品要求根据B端用户上传的图片模板,在C端绘制上个性字体且展示,最后也支持C端用户下载绘制后的图片

解决思路

我们先梳理一下这个需求的一些关键的点,即图片来源、图片传递路径、获取图片、图片绘制文字、下载图片

那最关键的步骤就是图片绘制

我这里想到了两种方案:

方案一:定位+html2canvas

将图片用Image渲染出来并放在一个DOM中,然后将文字再单独写一个DOM,通过定位的形式将其定位到对应的位置,最后通过html2canvas,将整个DOM绘制成一个canvas,转成图片下载下来。

代码实现

import React from "react";
import html2Canvas from "html2canvas";
import { Button, Image } from "antd-mobile";

type LoadCanvasImgProps = {
  containerStyle?: React.CSSProperties; // 最外层父组件的样式

  backgroundImageSrc?: string; // 背景图
  ImageWidth?: string | number;

  text?: string; // 需要写的值
  textStyle?: React.CSSProperties; // 渲染文本的样式

  buttonValue?: string; // button值
  onClickButton?: () => void; // 点击下载前执行的函数

  loadName?: string; // 下载后的文件名称
};

const LoadCanvasImg: React.FC<LoadCanvasImgProps> = ({
  text = "我是名字",
  loadName = "load",
  buttonValue = "点击下载",
  backgroundImageSrc = "",
  textStyle = { position: "absolute", top: "0px", left: "0px" },
  containerStyle,
  ImageWidth = 100,
  onClickButton,
}) => {
  const onHtml2Canvas = async () => {
    try {
      const loadBody = document.getElementById("loadBody") as HTMLElement;
      const canvas = await html2Canvas(loadBody, {
        useCORS: true,
        allowTaint: false,
      });
      downloadCanvasImg(canvas);
      onClickButton && onClickButton();
    } catch (error) {
      console.error("Error generating canvas image:", error);
    }
  };

  // 下载canvas
  const downloadCanvasImg = (canvas: HTMLCanvasElement) => {
    const dataURL = canvas.toDataURL("image/png") || "";
    const downloadLink = document.createElement("a");
    downloadLink.href = dataURL;
    downloadLink.download = `${loadName}.png`;

    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  };

  return (
    <div className="loadCanvasImg" style={containerStyle}>
      <div id="loadBody">
        <div style={textStyle}>{text}</div>
        <Image src={backgroundImageSrc} width={ImageWidth} alt="Background" />
      </div>
      <Button onClick={onHtml2Canvas} color="primary">
        {buttonValue}
      </Button>
    </div>
  );
};

export default LoadCanvasImg;

使用方式

import React from "react";
import LoadCanvasImg from "..."; // 这里的路径是你的组件路径

const Demo1 = () => {
  return (
    <div>
      <LoadCanvasImg
        backgroundImageSrc={""} // 图片的url
        text={"我是名字"} // 需要绘制的值
        containerStyle={{ position: "relative" }}
        textStyle={{
          position: "absolute",
          top: "10px",
          left: "100px",
          fontSize: "20px",
        }}
        buttonValue="保存证书"
        onClickButton={() => {}} // 点击下载前执行的函数
        ImageWidth={200}
      />
    </div>
  );
};

方案二:canvas绘制

先用canvas绘制图片,再用canvas绘制字体,最后转成图片下载下来。

代码实现

import React, { useEffect, useRef } from "react";
import { Button } from "antd-mobile";

interface CanvasFontSizeProps {
  text?: string; // 要绘制的文字
  backgroundImageSrc?: string; // 图片的url链接
  x?: number; // 图片的x轴定位
  y?: number; // 图片的y轴定位
  textStyle?: React.CSSProperties; // 绘制的文字样式
  fillStyle?: string | CanvasGradient | CanvasPattern; // canvas绘制文字的样式
  canvasStyle?: React.CSSProperties; // canvas的样式
}

const CanvasFontSize: React.FC<CanvasFontSizeProps> = ({
  text = "姓名",
  backgroundImageSrc = "",
  x = 100,
  y = 100,
  textStyle = { fontFamily: "e1kcQpNW_GBK_ry", fontSize: "22px" },
  fillStyle = "#000",
  canvasStyle = { width: 800, height: 600 },
}) => {
  const canvasRef = useRef<HTMLCanvasElement>(null);

  const downloadCanvasImage = () => {
    const canvas = canvasRef.current;
    const dataURL = canvas?.toDataURL("image/png") || "";

    const downloadLink = document.createElement("a");
    downloadLink.href = dataURL;
    downloadLink.download = "canvas_image.png";

    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  };

  useEffect(() => {
    const canvas = canvasRef.current as HTMLCanvasElement;
    const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;

    const backgroundImage = new Image();
    backgroundImage.setAttribute('crossOrigin', 'Anonymous'); // 跨域的时候加上
    backgroundImage.src = backgroundImageSrc;
    backgroundImage.onload = () => {
      ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);

      ctx.font = `${textStyle.fontSize} ${textStyle.fontFamily}`;
      ctx.fillStyle = fillStyle;
      ctx.fillText(text, x, y);
    };
  }, [text, x, y, backgroundImageSrc, textStyle, fillStyle]);

  return (
    <div>
      <canvas ref={canvasRef} style={canvasStyle} />
      <Button onClick={downloadCanvasImage} color="primary">
        下载链接
      </Button>
    </div>
  );
};

export default CanvasFontSize;

使用方式

import React from "react";
import CanvasFontSize from "..."; // 这里的路径是你的组件路径

const Demo1 = () => {
  return (
    <div>
      <CanvasFontSize
        backgroundImageSrc={""} // 图片的url
        text={"我是名字"} // 需要绘制的值
        x={10} // x轴坐标
        y={10}  // y轴坐标
        textStyle = { fontFamily: "e1kcQpNW_GBK_ry", fontSize: "22px" } // 文字样式
        fillStyle = "#000" // 文字颜色
        canvasStyle = { width: 800, height: 600 } // canvas样式
      />
    </div>
  );
};

两种思路的优缺点对比

优点缺点
定位+html2canvas对绘制复杂样式支持友好需要安装第三方依赖
canvas绘制使用简单,canvas原生支持遇到复杂样式绘制较为困难

遇到的一些坑

图片跨域

使用canvas画图片的时候,当图片域名与项目域名不一致的时候,浏览器会报跨域错误,或执行到const dataURL = canvas?.toDataURL("image/png") || ""这一步报错

解决办法:在使用 Image对象时添加上backgroundImage.setAttribute('crossOrigin', 'Anonymous')

到此这篇关于JavaScript在图片绘制文字两种方法的实现与对比的文章就介绍到这了,更多相关JavaScript图片绘制文字内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript的一些小技巧分享

    JavaScript的一些小技巧分享

    这篇文章主要介绍了JavaScript的一些小技巧分享,帮助大家更好的理解和使用JavaScript,感兴趣的朋友可以了解下
    2021-01-01
  • 动态加载js、css的简单实现代码

    动态加载js、css的简单实现代码

    下面小编就为大家带来一篇动态加载js、css的简单实现代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-05-05
  • JS实现图片放大镜效果的方法

    JS实现图片放大镜效果的方法

    这篇文章主要介绍了JS实现图片放大镜效果的方法,实例分析了magnifier.js插件的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 几种响应式文字详解

    几种响应式文字详解

    本文主要介绍了几种响应式文字的相关知识。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-05-05
  • d3.js入门教程之数据绑定详解

    d3.js入门教程之数据绑定详解

    这篇文章主要介绍了关于d3.js数据绑定的相关资料,文中通过示例代码介绍的非常详细,对大家学习只d3.js具有一定的参考价值,需要的朋友下面来一起看看吧。
    2017-04-04
  • JavaScript数字精度丢失问题的解决方案

    JavaScript数字精度丢失问题的解决方案

    JavaScript使用64位浮点数表示数字(基于IEEE 754标准),这导致某些十进制数字在计算过程中出现精度丢失,所以本文给大家介绍了JavaScript数字精度丢失问题的解决方案,需要的朋友可以参考下
    2024-10-10
  • ie8下修改input的type属性报错的解决方法

    ie8下修改input的type属性报错的解决方法

    当用户勾选显示明文复选框时,要以明文显示用户输入的密码,去掉勾选时要变回密文,问题是ie8中是不允许修改input的type属性
    2014-09-09
  • 使用plupload自定义参数实现多文件上传

    使用plupload自定义参数实现多文件上传

    这篇文章主要介绍了使用plupload自定义参数实现多文件上传的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-07-07
  • javascript修改表格背景色实例代码分享

    javascript修改表格背景色实例代码分享

    这篇文章主要介绍了javascript修改表格背景色实例,代码简单,大家参考使用吧
    2013-12-12
  • Js实现双击鼠标自动滚动屏幕的示例代码

    Js实现双击鼠标自动滚动屏幕的示例代码

    这篇文章主要介绍了Js实现双击鼠标自动滚动屏幕的示例代码。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12

最新评论