<text><tspan> 两个基本文本标签
text & tspan 标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>sin text</title>
<style>
html, body, svg {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<form style="width: 20%;position: absolute; right: 0; top: 10%;">
<fieldset>
<legend>参数设置</legend>
<label style="display: block">
振幅:<input max="150" min="10" oninput="h = this.value" type="range">
</label>
<label style="display: block">
周期:<input max="10000" min="1" oninput="w = this.value / 10000" type="range">
</label>
</fieldset>
</form>
<svg xmlns="http://www.w3.org/2000/svg">
<!--网格-->
<g>
<defs>
<pattern height="10" id="grid" patternContentUnits="userSpaceOnUse"
patternUnits="userSpaceOnUse" width="10" x="0"
y="0">
<rect fill="none" height="10.5" stroke="#f0f0f0" stroke-dasharray="2" stroke-width=".5"
width="10.5" x="0"
y="0"></rect>
</pattern>
<pattern height="50" id="bigGrid" patternContentUnits="userSpaceOnUse"
patternUnits="userSpaceOnUse" width="50" x="0"
y="0">
<rect fill="url(#grid)" height="50.5" stroke="#e0e0e0" stroke-width=".5"
width="50.5"></rect>
</pattern>
</defs>
<rect fill="url(#bigGrid)" height="100%" width="100%" x="0" y="0"></rect>
</g>
<g>
<text id="sinText" style="font-size: 20px" x="200" y="200"></text>
</g>
</svg>
<script>
// 获取文本对象
const textEle = document.getElementById('sinText');
// dx = [20, 20, 20, ...]
// y = λsin(ω * x + t),绝对位置
// 由于dy属性是相对于之前文字的位置设置的,相对位置的dy
// dy = λsin(ω * x + t) - λsin(ω * (x-1) + t)
// 由于 正弦函数具有周期性所有直接 dy = λsin(ω * x + t) 也是可以的
const text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let n = text.length,
dxDistance = 10,
// 振幅
h = 80,
// 周期
w = .02,
dxArr = new Array(n),
dyArr = new Array(n);
const frg = document.createDocumentFragment();
for (let i = 0; i < n; i++) {
dxArr[i] = dxDistance;
// 使用tspan设置每一个字符的单独颜色
const tspan = document.createElementNS('http://www.w3.org/2000/svg', 'tspan');
// 不能用这个属性
// tspan.innerText = text[i];
tspan.textContent = text[i];
tspan.setAttribute('fill', `hsl(${360 * i / n}, 100%, 80%)`);
frg.appendChild(tspan)
}
textEle.appendChild(frg);
// 计算dy数组
const render = (t = 0) => {
// 计算绝对的dy
const calcDy = x => {
return ~~(h * Math.sin(w * x + t))
};
for (let i = 0; i < n; i++) {
// dyArr[i] = calcDy(dxDistance * i)
// 计算相对 dy
dyArr[i] = calcDy(dxDistance * i) - calcDy(dxDistance * (i - 1))
}
// 设置dy
textEle.setAttribute('dx', dxArr.join(','));
textEle.setAttribute('dy', dyArr.join(','))
};
let t = 0;
const frame = () => {
render(t += .02);
requestAnimationFrame(frame)
};
frame()
</script>
</body>
</html>dy是一个相对参数,正确的计算应该减去上一个字符的dy
svg中文字也是作为图形来渲染,并且不支持排版