<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中文字也是作为图形来渲染,并且不支持排版