在Vue流行的今天,许多应用中的特效和画板功能需要将SVG转换为图片以便用户下载。最近,在我负责的一个项目中,由于使用了自定义字体,遇到了一个问题:SVG无法以正确的方式转换为图片下载,导致缺失了自定义样式。
为解决这一问题,我最初采用了将SVG渲染到Canvas中的方案。通过利用Canvas的
toDataURL()
方法,可以获取到转换后的图片数据。随后,通过创建一个隐藏的
<a>
标签并设置其
href
属性为图片数据的URL,触发下载操作。以下是一个使用Vue 3的示例代码:
<template>
<!-- 假设你的SVG内容在这里 -->
<svg ref="svgElement" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<!-- SVG内容,包含自定义字体 -->
<text font-family="abc" font-size="22" x="20" y="20">自定义字体</text>
<button @click="downloadSvgAsImage">下载SVG为图片</button>
</template>
<script setup>
import {
} from 'vue';
const svgElement = ref(null);
// SVG 转图片并下载的函数
function downloadSvgAsImage() {
if (!svgElement.value) {
return;
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svgElement.value);
const blob = new Blob([svgStr], {
type: 'image/svg+xml;charset=utf-8'
const url = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
// 创建一个canvas元素
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
// 将canvas转换为图片
const dataUrl = canvas.toDataURL('image/png');
// 创建一个隐藏的a标签用于下载
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'custom-font-svg.png';
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
img.src = url;
</script>
<style scoped>
/* 在这里定义你的自定义字体 */
/* 推荐一个免费的字体库,部分收费:https://font.chinaz.com/ */
@font-face {
font-family: 'abc';
src: url('@/assets/fonts/abc.ttf');
font-weight: normal;
font-style: normal;
</style>
在上述情况中,当SVG中包含text标签并应用了自定义字体时,发现导出的图片并未正确呈现这些自定义样式。为了解决这个问题,曾尝试使用第三方库,如html2canvas或dom-to-image,期望通过截图的方式来实现。然而,令人遗憾的是,这种方法仍然未能有效解决问题。
经过我的深入剖析,问题的根源在于资源文件未能正确加载,因此需要确保在SVG的
defs
标签中对其进行定义。然而,令人遗憾的是,尽管我尝试了多次,却始终未能成功解决这个问题。网络上提供的案例虽然为我提供了一些思路,但并未能实际解决面临的问题。
最后,我灵光一闪,如果我们尝试以编程的方式直接绘制字体,而不是依赖外部资源文件,是否能够绕过这个难题呢?于是,我尝试编写了以下代码来实现这一想法:采用canvas的2D画笔实现
<template>
<!-- 假设你的SVG内容在这里 -->
<svg ref="svgElement" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<!-- SVG内容,包含自定义字体 -->
<text font-family="abc" font-size="22" x="20" y="20">自定义字体</text>
<button @click="downloadSvgAsImage">下载SVG为图片</button>
</template>
<script setup>
import {
} from 'vue';
const svgElement = ref(null);
// SVG 转图片并下载的函数
function downloadSvgAsImage() {
if (!svgElement.value) {
return;
// 提取所有text标签信息,根据自己实际情况修改
const texts = document.getElementsByTagName("text");
const serializer = new XMLSerializer();
let svgStr = serializer.serializeToString(svgElement.value);
//删除掉文字,解决自定义字体
svgStr = svgStr.replaceAll(/<text(?:\s+[^>]+)?>([\s\S]*?)<\/text>/g, '');
const blob = new Blob([svgStr], {
type: 'image/svg+xml;charset=utf-8'
const url = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
// 创建一个canvas元素
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, img.width, img.height);
// 关键代码
for (let i = 0; i < texts.length; i++) {
const text = texts[i];
// 重新绘制文本,这次在画布上
ctx.font = `${text.getAttribute('font-size')}px ${text.getAttribute('font-family')}`;
//ctx.fillStyle = 'black';// 颜色
// 如果是渐变颜色,创建一个线性渐变对象,svg对应defs下的linearGradient
//const lg = ctx.createLinearGradient(0, 0, img.width, 0);
// 添加颜色停止点
//lg.addColorStop(0, 'rgba(0, 0, 0,1)'); // 在%位置
//lg.addColorStop(1, 'rgba(255, 0, 0,1)'); // 在%位置
//ctx.fillStyle = lg;
ctx.fillText(text.textContent, text.getAttribute('x'), text.getAttribute('y'));
// 将canvas转换为图片
const dataUrl = canvas.toDataURL('image/png');
// 创建一个隐藏的a标签用于下载
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'custom-font-svg.png';
a.style.display = 'none';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
img.src = url;
</script>
<style scoped>
/* 在这里定义你的自定义字体 */
/* 推荐一个免费的字体库,部分收费:https://font.chinaz.com/ */
@font-face {
font-family: 'abc';
src: url('@/assets/fonts/abc.ttf');
font-weight: normal;
font-style: normal;
</style>
当然,这个解决方案提供了一个最原始且核心的实现方式,但我们可以进一步对代码进行优化以提升效率和用户体验。例如,在导出文件时,可以利用
file-saver
这一第三方库来简化文件保存的操作,并确保文件的正确性和完整性。通过整合
file-saver
库,我们可以更高效地处理文件导出过程,提升整体功能的稳定性和可靠性。
svg
2Font
将
SVG
转
换为TTF / EOT / WOFF / WOFF2 /
SVG
格式。
注意:
svg
->
svg
font-> ttf ttf-> EOT ttf-> WOFF ttf-> WOFF2 ttf->
svg
, ,
Unicode字符平面映射
始末字符值
U + 0000-U + FFFF
基本多文种平面
基本多语言平面,简称BMP
U + 10000-U + 1FFFF
多文种补充平面
补充多语言平面,简称SMP
U + 20000-U + 2FFFF
表意文字补充平面
表意补充平面,简称SIP
单个
svg
文件,与
svg
font文件不一样,
svg
字体
是特殊处理的图标集合,像文字一样组合好后,会有Unicode代码点,一般用工具处理获得
下载
SVG
图标https://www.iconfont.cn/
创建
SVG
fontshttps://icomoon.io/
参考链接:
1.
SVG
fonts(
SVG
字体
)https://cloud.tencent.com/deve...
今天来说一下将
svg
图片
转
化为
字体
图片
的办法,很简单,不啰嗦直接讲方法。一、 方法 11.讲
svg
图片
转
化
字体
图片
网站
icoMoon : https://icomoon.io
进入网站后点击右上角 icoMoom App 按钮进入后,它提供了一些
图片
,可以点击选中,如果不想可以点击左上角 import Icons 按钮,上传你做好的
svg
图片
。然后:下载好后的文件:需要解压可以看看例