如何对齐单独的 svg 文本元素,如 word 中的字符对齐
How to align separate svg text elements like character alignment in word
我正在使用 svg text
元素,我需要为特定单词的每个字符创建单独的 <text></text>
元素,在本例中为 Lorem
。
例如,
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
for (var i = 0; i < txtArray1.length; i++) {
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', textX);
text1.setAttribute('y', textY);
text1.setAttribute('fill','green');
text1.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text1.setAttribute('text-anchor', 'middle'); //positions text in the middle
text1.textContent = txtArray1[i];
svg.appendChild(text1);
var el = document.getElementById(`t0${i}`);
var width = el.getBBox().width;
textX = textX + width;
}
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
如果这些单独的字符被创建为单词,我希望它们对齐
class="word"
在设计时,我最初的想法是获取立即创建的角色的BBox().width
并将下一个元素的x
增加相同的值。但是最后一个元素与 class="word"
.
中的元素相距甚远
创建单个文本元素并将它们对齐(绿色)的最佳策略是什么,因为它们将出现在一个句子(棕色)中?
Update
我已经尝试了@Robert Longson 的建议。不知道是不是做错了,但是不准确
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
// append the new rectangle to the svg
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
for (var i = 0; i < txtArray1.length; i++) {
var x = document.getElementById('word');
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', x.getStartPositionOfChar(i).x);
text1.setAttribute('y', x.getStartPositionOfChar(i).y);
text1.setAttribute('fill','green');
text1.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text1.setAttribute('text-anchor', 'middle'); //positions text in the middle
text1.textContent = txtArray1[i];
svg.appendChild(text1);
}
text2.setAttribute('y', 75);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
调用 getStartPositionOfChar 找出每个字符的位置。
制作副本时不需要设置text-anchor或dominant-baseline,因为原始字符位置已经包含了。
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
// append the new rectangle to the svg
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
for (var i = 0; i < txtArray1.length; i++) {
var x = document.getElementById('word');
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', x.getStartPositionOfChar(i).x);
text1.setAttribute('y', x.getStartPositionOfChar(i).y);
text1.setAttribute('fill','green');
text1.textContent = txtArray1[i];
svg.appendChild(text1);
}
text2.setAttribute('y', 75);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
我正在使用 svg text
元素,我需要为特定单词的每个字符创建单独的 <text></text>
元素,在本例中为 Lorem
。
例如,
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
for (var i = 0; i < txtArray1.length; i++) {
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', textX);
text1.setAttribute('y', textY);
text1.setAttribute('fill','green');
text1.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text1.setAttribute('text-anchor', 'middle'); //positions text in the middle
text1.textContent = txtArray1[i];
svg.appendChild(text1);
var el = document.getElementById(`t0${i}`);
var width = el.getBBox().width;
textX = textX + width;
}
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
如果这些单独的字符被创建为单词,我希望它们对齐
class="word"
在设计时,我最初的想法是获取立即创建的角色的BBox().width
并将下一个元素的x
增加相同的值。但是最后一个元素与 class="word"
.
创建单个文本元素并将它们对齐(绿色)的最佳策略是什么,因为它们将出现在一个句子(棕色)中?
Update
我已经尝试了@Robert Longson 的建议。不知道是不是做错了,但是不准确
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
// append the new rectangle to the svg
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
for (var i = 0; i < txtArray1.length; i++) {
var x = document.getElementById('word');
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', x.getStartPositionOfChar(i).x);
text1.setAttribute('y', x.getStartPositionOfChar(i).y);
text1.setAttribute('fill','green');
text1.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text1.setAttribute('text-anchor', 'middle'); //positions text in the middle
text1.textContent = txtArray1[i];
svg.appendChild(text1);
}
text2.setAttribute('y', 75);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>
调用 getStartPositionOfChar 找出每个字符的位置。
制作副本时不需要设置text-anchor或dominant-baseline,因为原始字符位置已经包含了。
const svg = document.querySelector("svg");
const svgns = "http://www.w3.org/2000/svg"
//vboxDim
var vboxW = 200;
var vboxH = 200;
//assigning svg element attribute
svg.setAttribute('class', 'layer1');
svg.setAttribute('xmlns', svgns);
svg.setAttribute('viewBox', `0 0 ${vboxW} ${vboxH}`);
//make background
var fill1 = '#F1C40F';
let bg = document.createElementNS(svgns, 'rect');
bg.setAttribute('class', 'bg');
bg.setAttribute('id', 'bg');
bg.setAttribute("width", `${vboxW}`);
bg.setAttribute("height", `${vboxH}`);
bg.setAttribute("fill", fill1);
// append the new rectangle to the svg
svg.appendChild(bg);
var txtArray1 = ['L', 'o', 'r', 'e', 'm'];
var textX = svg.viewBox.baseVal.width / 2;
var textY = svg.viewBox.baseVal.height / 2;
let text2 = document.createElementNS(svgns, "text")
text2.setAttribute('class', 'word')
text2.setAttribute('id', 'word');
text2.setAttribute('x', (svg.viewBox.baseVal.width / 2));
text2.setAttribute('y', (svg.viewBox.baseVal.height / 2) - 50);
text2.setAttribute('fill','brown');
text2.setAttribute('dominant-baseline', 'middle'); //positions text in the middle
text2.setAttribute('text-anchor', 'middle'); //positions text in the middle
text2.textContent = 'Lorem';
svg.appendChild(text2);
for (var i = 0; i < txtArray1.length; i++) {
var x = document.getElementById('word');
let text1 = document.createElementNS(svgns, "text")
text1.setAttribute('class', 't0' + i)
text1.setAttribute('id', 't0' + i);
text1.setAttribute('x', x.getStartPositionOfChar(i).x);
text1.setAttribute('y', x.getStartPositionOfChar(i).y);
text1.setAttribute('fill','green');
text1.textContent = txtArray1[i];
svg.appendChild(text1);
}
text2.setAttribute('y', 75);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style></style>
</head>
<body>
<link rel="stylesheet" href="style.css">
</link>
<svg>
<script href="index.js"></script>
</svg>
</body>
</html>