Optimize tspan’s - JSFiddle
Optimize tspan’s - JSFiddle (es6)
by denvdmj
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/highlight.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.11.0/styles/androidstudio.min.css">
<svg-example>
<svg viewBox="0 0 530 300"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<text>
<tspan x="145.2" y="61.6">b</tspan>
<tspan x="78.1" y="103.8">a</tspan>
<tspan x="78.8" y="146">s</tspan>
<tspan x="113.8" y="188.2">t</tspan>
<tspan x="145.7" y="103.8">e</tspan>
<tspan x="179" y="146">y</tspan>
<tspan x="212.7" y="103.8">h</tspan>
<tspan x="282.6" y="19.4">i</tspan>
<tspan x="213.2" y="146">e</tspan>
<tspan x="281.5" y="61.6">s</tspan>
<tspan x="246.5" y="103.8">n</tspan>
<tspan x="316.4" y="103.8">t</tspan>
<tspan x="381.6" y="61.6">o</tspan>
<tspan x="381.6" y="103.8">n</tspan>
<tspan x="349.5" y="146">f</tspan>
<tspan x="417" y="146">r</tspan>
<tspan x="451.5" y="103.8">t</tspan>
<tspan x="449.2" y="146">o</tspan>
</text>
<text>
<tspan x="74.1 83.5 91.7 109.1 118.4 124.3" y="230.5">as at </tspan>
<tspan x="140.5 151.1 160.4" y="230.5">be </tspan>
<tspan x="173.6 184.1 194.7" y="230.5">by </tspan>
<tspan x="208.1 218.6 228" y="230.5">he </tspan>
<tspan x="243.5 249.3 259.9" y="230.5">in </tspan>
<tspan x="278.4 284.3 292.5" y="230.5">is </tspan>
<tspan x="313.3 319.2 325.1" y="230.5">it </tspan>
<tspan x="344.3 354.9 361.9" y="230.5">of </tspan>
<tspan x="376.2 386.8 397.3" y="230.5">on </tspan>
<tspan x="411.9 422.4 429.4" y="230.5">or </tspan>
<tspan x="446.1 452" y="230.5">to</tspan>
</text>
<text>
<tspan x="4 18.3 24.8 36.6 48.3 57.4 67.8 73.7 85.4 91.3" y="282.5">Figure 2. </tspan>
<tspan x="103 117.3 123.1 129.7 140.1 149.2 160.9 172.7 181.8 192.2 198 207.2 217.6 229.3 238.4 248.8 260.6 266.4 272.9 282.1 292.5 302.9 308.7 315.2 327 336.1 341.9 353.7...
SCSS
@import url(https://typeof.net/Iosevka/fonts.css);
svg text { font-size: 21px }
svg path { stroke: black }
:root,
:root > body {
background: #464b51;
}
:root > body {
margin: auto;
padding: 1rem;
}
svg-example {
display: block;
text-align: center;
width: 100%;
}
svg {
display: inline-block;
background: white;
margin: 0 0 1em 0;
max-width: 800px;
}
button {
position: relative;
display: inline-block;
padding: 0 1.6em;
margin: 0 3px 6px 0;
height: 3em;
line-height: 3em;
border: none;
border-radius: 2px;
background: #3d4247;
color: #ccc;
text-shadow: #000 0 0 2px, #000 0 0 1px;
box-shadow: 0 2px 4px 0 rgba(0,0,0,.5);
outline: none;
user-select: none;
transition: all .2s ease-out;
}
button:hover {
background: hsla(0,100%,100%,.1);
box-shadow: 0px 4px 10px 0 rgba(0,0,0,1);
transition: all .5s ease-out;
}
button:active {
transition: all .08s ease-out;
background: hsla(0,100%,100%,.12);
color: #fff;
box-shadow: none;
box-shadow: 0 0 3px -1px #000;
left: 1px;
top: 1px;
}
pre, code {
font: 14px/1.5 "Iosevka WEB", "Condensed-Coding", "Consolas", monospace;
background: #1d1f21 !important;
color: #fff;
}
$fonturl: 'https://cdn.rawgit.com/frantisek-sodomka-gomorrka/fonts/3063e30b/condensed-coding.r-webfont.woff';
@font-face {
font-family: 'Condensed-Coding';
font-style: normal;
font-weight: 400;
src: url($fonturl + '2?raw=true') format('woff2'),
url($fonturl + '?raw=true') format('woff');
}
JavaScript
'use strict';
clickme.onclick = () => {
tspans_merge_y_equal_groups(
document.querySelectorAll('svg > text > tspan')
);
show();
};
// acc — the number of digits after the decimal point
const round = (num, acc = 2, k) =>
Math.round(num * (k = 10 ** acc)) / k;
const tspans_merge_y_equal_groups = tspans => {
for (let group of get_tspans_y_equal_groups(tspans)) {
group.sort((a, b) =>
round(a.getAttribute('x')) -
round(b.getAttribute('x'))
);
tspans_merge(group);
tspan_remove_spaces(group[0]);
}
};
const get_tspans_y_equal_groups = tspans => {
let groups = {};
for (let tspan of tspans) {
let y = round(tspan.getAttribute('y'));
if (!groups[y]) groups[y] = [];
groups[y].push(tspan);
}
return Object.values(groups);
};
const tspans_merge = tspans => {
let first = tspans[0];
let tlist = [];
let xlist = [];
for (let tspan of tspans) {
tlist.push(tspan.textContent);
xlist.push(tspan.getAttribute('x'));
if (tspan !== first)
tspan.parentNode.removeChild(tspan);
}
first.setAttribute('x', xlist.join(' '));
first.textContent = tlist.join('');
};
const tspan_remove_spaces = tspan => {
let chars = tspan.textContent.split('');
let xvals = tspan.getAttribute('x').split(/\s*,\s*|\s+|(?=\-)|(?=\+)/);
if (chars.length !== xvals.length)
return;
let new_chars = [];
let new_xvals = [];
for (let i = 0, len = chars.length; i < len; i++) {
if (/\S/.test(chars[i])) {
new_chars.push(chars[i]);
new_xvals.push(xvals[i]);
}
}
tspan.textContent = new_chars.join('');
tspan.setAttribute('x', new_xvals.join(' '));
};
//-------------------------------------------------
// show svg source code with syntax hightlighting
function show () {
const code = document.querySelector('pre > code');
code.textContent = document.querySelector('svg-example')
.innerHTML.replace(/(\n\s*\n)/g, '\n');
hljs.highlightBlock(code, hljs.tabReplace, false,...