我正在嘗試在我的 React Web 應用程式中轉換text為svg,但我得到的結果 svg 代碼不正確,t 沒有顯示 svg。
代碼:
import opentype from "opentype.js"
async function textToPath(){
const text = "Hello"
const size = {x: 50, y: 25}
const fontFile = "https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf"
let params = {
string: text,
font: fontFile,
fontSize: size.x,
decimals: 1,
singleGylyphs: false
}
const font = await opentype.load(params.font);
let options = params.options;
let unitsPerEm = font.unitsPerEm;
let ratio = params.fontSize / unitsPerEm;
let ascender = font.ascender;
let descender = Math.abs(font.descender);
let ratAsc = ascender / unitsPerEm;
let ratDesc = descender / unitsPerEm;
let yOffset = params.fontSize * ratAsc;
let lineHeight = params.fontSize params.fontSize * ratDesc;
let singleGylyphs = params.singleGylyphs;
let teststring = params.string.split("");
let glyphs = font.stringToGlyphs(params.string);
let leftSB = glyphs[0].leftSideBearing * ratio;
let textPath = "";
//individual paths for each glyph
if (singleGylyphs) {
let paths = font.getPaths(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
paths.forEach(function (path, i) {
let pathEl = path.toSVG(params.decimals);
textPath = pathEl.replaceAll(
"d=",
'hljs-string">'" d='
);
});
}
//word (all glyphs) merged to one path
else {
let path = font.getPath(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
textPath = path
.toSVG(params.decimals)
.replaceAll("d=", ' d=');
}
// render
let fontSvgWrp = document.createElement("div");
fontSvgWrp.classList.add("fontSvgWrp");
let fontSvg = document.createElementNS(
"http://www.w3.org/2000/svg",
"svg"
);
fontSvg.classList.add("svgText");
fontSvg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
fontSvg.innerHTML = textPath;
fontSvgWrp.appendChild(fontSvg);
// adjust bbox
let bb = fontSvg.getBBox();
let stringWidth = Math.ceil(bb.width bb.x);
fontSvg.setAttribute("viewBox", "0 0 " stringWidth " " lineHeight);
fontSvg.setAttribute("width", size.x);
fontSvg.setAttribute("data-asc", ratAsc);
console.log(fontSvg); // getting svg code
let textPathSvg = fontSvg.querySelector(".glyph");
let textPathLength = textPathSvg.getTotalLength();
return textPathLength
}
它正在生成這個不起作用的 svg:
<svg class="svgText" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 0 5013.25" width="50" data-asc="0.935"><path class="glyph" d="M24 46.8L19.3 46.8L19.3 30.6L4.8 30.6L4.8 46.8L0 46.8L0 12.3L4.8 12.3L4.8 26.7L19.3 26.7L19.3 12.3L24 12.3L24 46.8ZM53.7 32.8Q53.7 34.0 53.5 35.1L53.5 35.1L36.8 35.1Q37.0 39.5 39.0 41.5Q40.9 43.6 43.9 43.6L43.9 43.6Q45.8 43.6 47.4 43.0Q49.0 42.5 50.7 41.3L50.7 41.3L52.7 44.0Q48.5 47.4 43.5 47.4L43.5 47.4Q38 47.4 34.9 43.8Q31.9 40.1 31.9 33.9L31.9 33.9Q31.9 29.8 33.2 26.6Q34.5 23.4 37.0 21.6Q39.5 19.8 42.8 19.8L42.8 19.8Q48.0 19.8 50.9 23.3Q53.7 26.7 53.7 32.8L53.7 32.8ZM49.1 31.8L49.1 31.4Q49.1 27.5 47.5 25.5Q46 23.4 42.9 23.4L42.9 23.4Q37.3 23.4 36.8 31.8L36.8 31.8L49.1 31.8ZM66.3 47.4Q63.7 47.4 62.2 45.8Q60.8 44.3 60.8 41.5L60.8 41.5L60.8 9.8L65.3 9.3L65.3 41.5Q65.3 42.5 65.7 43.0Q66.1 43.5 67 43.5L67 43.5Q68.0 43.5 68.7 43.3L68.7 43.3L69.9 46.5Q68.3 47.4 66.3 47.4L66.3 47.4ZM80.9 47.4Q78.4 47.4 76.9 45.8Q75.4 44.3 75.4 41.5L75.4 41.5L75.4 9.8L80 9.3L80 41.5Q80 42.5 80.4 43.0Q80.8 43.5 81.7 43.5L81.7 43.5Q82.6 43.5 83.4 43.3L83.4 43.3L84.6 46.5Q82.9 47.4 80.9 47.4L80.9 47.4ZM100.2 19.8Q105.8 19.8 108.8 23.5Q111.9 27.2 111.9 33.5L111.9 33.5Q111.9 37.6 110.5 40.8Q109.1 43.9 106.5 45.6Q103.8 47.4 100.2 47.4L100.2 47.4Q94.6 47.4 91.5 43.6Q88.4 40.0 88.4 33.6L88.4 33.6Q88.4 29.5 89.8 26.4Q91.2 23.3 93.9 21.5Q96.5 19.8 100.2 19.8L100.2 19.8ZM100.2 23.5Q93.4 23.5 93.4 33.6L93.4 33.6Q93.4 43.6 100.2 43.6L100.2 43.6Q107.0 43.6 107.0 33.5L107.0 33.5Q107.0 23.5 100.2 23.5L100.2 23.5Z"></path></svg>
我嘗試并搜索了很多,但我沒有得到任何東西來解決這個問題以及為什么轉換后的 svg 不起作用。有人可以幫忙嗎?
uj5u.com熱心網友回復:
svg 輸出實際上還可以,但您viewBox的計算不正確。
viewBox 的寬度值為 0——因此您的路徑完全被裁剪/不可見。
腳本中的主要問題:您需要將 svg 附加到 DOM 否則getBBox()將回傳一個空物件(或寬度:0,高度:0)。
它應該看起來像這樣:
fontSvgWrp.appendChild(fontSvg);
document.body.appendChild(fontSvgWrp);
// adjust bbox
let bb = fontSvg.getBBox();
示例:在 getBBox() 之前附加 svg
let fontSVG = textToPath();
async function textToPath(){
const text = "Hello"
const size = {x: 50, y: 25}
const fontFile = "https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf"
let params = {
string: text,
font: fontFile,
fontSize: size.x,
decimals: 1,
singleGylyphs: false
}
const font = await opentype.load(params.font);
let options = params.options;
let unitsPerEm = font.unitsPerEm;
let ratio = params.fontSize / unitsPerEm;
let ascender = font.ascender;
let descender = Math.abs(font.descender);
let ratAsc = ascender / unitsPerEm;
let ratDesc = descender / unitsPerEm;
let yOffset = params.fontSize * ratAsc;
let lineHeight = params.fontSize params.fontSize * ratDesc;
let singleGylyphs = params.singleGylyphs;
let teststring = params.string.split("");
let glyphs = font.stringToGlyphs(params.string);
let leftSB = glyphs[0].leftSideBearing * ratio;
let textPath = "";
//individual paths for each glyph
if (singleGylyphs) {
let paths = font.getPaths(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
paths.forEach(function (path, i) {
let pathEl = path.toSVG(params.decimals);
textPath = pathEl.replaceAll(
"d=",
'hljs-string">'" d='
);
});
}
//word (all glyphs) merged to one path
else {
let path = font.getPath(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
textPath = path
.toSVG(params.decimals)
.replaceAll("d=", ' d=');
}
// render
let fontSvgWrp = document.createElement("div");
fontSvgWrp.classList.add("fontSvgWrp");
let fontSvg = document.createElementNS(
"http://www.w3.org/2000/svg",
"svg"
);
fontSvg.classList.add("svgText");
fontSvg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
fontSvg.innerHTML = textPath;
fontSvgWrp.appendChild(fontSvg);
document.body.appendChild(fontSvgWrp);
// adjust bbox
let bb = fontSvg.getBBox();
//console.log(bb)
let stringWidth = Math.ceil(bb.width bb.x);
//let stringWidth = Math.ceil(bb.width);
fontSvg.setAttribute("viewBox", "0 0 " stringWidth " " lineHeight);
//fontSvg.setAttribute("width", size.x);
fontSvg.setAttribute("data-asc", ratAsc);
console.log(fontSvg); // getting svg code
let textPathSvg = fontSvg.querySelector(".glyph");
let textPathLength = textPathSvg.getTotalLength();
return textPathLength
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/opentype.js/1.3.4/opentype.min.js"></script>
替代方案:根據字形資料計算總寬度
如果您不想附加 svg,您還可以使用字形 AdvanceWidth 資料計算 viewBox 寬度:
//calculate viewBox width by glyphs' advanceWidths
let totalWidth = 0;
let lastGlyph = glyphs[glyphs.length-1];
let lastSideBearing = (lastGlyph.leftSideBearing) * ratio;
glyphs.forEach(function (glyph, i) {
let advanceWidth = glyph.advanceWidth;
totalWidth = advanceWidth * ratio;
});
let stringWidth = Math.ceil(totalWidth - leftSB - lastSideBearing);
顯示代碼片段
let fontSVG = textToPath();
async function textToPath() {
const text = "Hello";
const size = { x: 50, y: 25 };
const fontFile =
"https://fonts.gstatic.com/s/firasans/v15/va9E4kDNxMZdWfMOD5Vvl4jO.ttf";
let params = {
string: text,
font: fontFile,
fontSize: size.x,
decimals: 1,
singleGylyphs: false
};
const font = await opentype.load(params.font);
let options = params.options;
let unitsPerEm = font.unitsPerEm;
let ratio = params.fontSize / unitsPerEm;
let ascender = font.ascender;
let descender = Math.abs(font.descender);
let ratAsc = ascender / unitsPerEm;
let ratDesc = descender / unitsPerEm;
let yOffset = params.fontSize * ratAsc;
let lineHeight = params.fontSize params.fontSize * ratDesc;
let singleGylyphs = params.singleGylyphs;
let teststring = params.string.split("");
let glyphs = font.stringToGlyphs(params.string);
let leftSB = glyphs[0].leftSideBearing * ratio;
let textPath = "";
//individual paths for each glyph
if (singleGylyphs) {
let paths = font.getPaths(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
paths.forEach(function (path, i) {
let pathEl = path.toSVG(params.decimals);
textPath = pathEl.replaceAll(
"d=",
'hljs-string">'" d='
);
});
}
//word (all glyphs) merged to one path
else {
let path = font.getPath(
params.string,
-leftSB,
yOffset,
params.fontSize,
options
);
textPath = path
.toSVG(params.decimals)
.replaceAll("d=", ' d=');
}
// render
let fontSvgWrp = document.createElement("div");
fontSvgWrp.classList.add("fontSvgWrp");
let fontSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
fontSvg.classList.add("svgText");
fontSvg.setAttribute("xmlns", "http://www.w3.org/2000/svg");
fontSvg.innerHTML = textPath;
fontSvgWrp.appendChild(fontSvg);
//calculate viewBox width by glyphs' advanceWidths
let totalWidth = 0;
let lastGlyph = glyphs[glyphs.length-1];
let lastSideBearing = (lastGlyph.leftSideBearing) * ratio;
glyphs.forEach(function (glyph, i) {
let advanceWidth = glyph.advanceWidth;
totalWidth = advanceWidth * ratio;
});
let stringWidth = Math.ceil(totalWidth - leftSB - lastSideBearing);
// adjust bbox
let bb = fontSvg.getBBox();
//console.log(bb)
//let stringWidth = Math.ceil(bb.width bb.x);
//let stringWidth = Math.ceil(bb.width);
fontSvg.setAttribute("viewBox", "0 0 " stringWidth " " lineHeight);
//fontSvg.setAttribute("width", size.x);
fontSvg.setAttribute("data-asc", ratAsc);
//console.log(fontSvg); // getting svg code
let textPathSvg = fontSvg.querySelector(".glyph");
let textPathLength = textPathSvg.getTotalLength();
document.body.appendChild(fontSvgWrp);
return textPathLength;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/opentype.js/1.3.4/opentype.min.js"></script>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/486830.html
標籤:javascript 反应 svg 小路 开放式
