read width of d3 text element - d3.js

I would like to read the width of <text> elements, created in d3, after they're created.
I have tried
svg.selectAll("text")
.each(function () {
console.log('text', d3.select(this).style("width"));
}); // 'auto'
and
svg.selectAll("text")
.each(function () {
console.log('text', $(this).css("width"));
}); // '0px'
Thanks in advance

In a selection method (such as attr) :
this.getComputedTextLength().
In a selection of one element, you can say
selection.node().getComputedTextLength().
You can also use getBBox for the width and height

You may use:
var wh = {w:-1,h:-1};
Array.from(document.querySelectorAll('text')).map(function(ele) {
var bbox = ele.getBoundingClientRect();
wh = {
w: (wh.w<bbox.width) ? bbox.width :wh.w,
h: (wh.h<bbox.height) ? bbox.height :wh.h
}
})
After this wh.w will contain largest width and wh.h will contain largest height of any text. You should then enter a more precise CSS selector to match your needs.

Example based on Rachel Gallen using getComputedTextLength() function created in 2020 and that works on Chrome.
<svg xmlns="http://www.w3.org/2000/svg" version="2.0" width="800px" height="600px">
<script type="text/javascript" href="https://d3js.org/d3.v5.min.js"></script>
<script type="text/JavaScript">
// select Tooltip <text> element by 'id' using d3 library
var tooltip = d3.select("#tooltip-text");
// change Tooltip text
var sTooltip = "tooltip string with more information";
tooltip.node().innerHTML = sTooltip;
// compute text length
var iTextLength = tooltip.node().getComputedTextLength();
</script>
<rect id='tooltip-rect' x='20' y='20' width='100' height='25' fill="yellow"/>
<text id='tooltip-text' x='0' y='0'>
Tooltip: ?
</text>
</svg>
Using this technic, I have now tooltip when dragging mouse over some device.
document.addEventListener("DOMContentLoaded", function(event) {
var tooltip = d3.select("#tooltip-text");
var toolrec = d3.select("#tooltip-rect");
var iTextLength = 0;
d3.select("svg").selectAll("use")
.on("mouseover", function ()
{
var sTooltip = "";
var e = this.nextElementSibling;
if (e != null)
{
if (e.className.baseVal == "info")
{
sTooltip = e.innerHTML;
}
}
if (sTooltip == "")
{
sTooltip = this.href.baseVal;
}
if (sTooltip == "")
{
sTooltip = "? Tooltip";
}
tooltip.node().innerHTML = sTooltip;
iTextLength = tooltip.node().getComputedTextLength();
tooltip.style("opacity", "1");
toolrec.style("opacity", "1");
})
.on("mousemove", function ()
{
toolrec.attr("x", d3.select(this).attr("x") - 5);
toolrec.attr("y", d3.select(this).attr("y") - 12);
toolrec.attr("width", iTextLength + 10);
tooltip.attr("x", d3.select(this).attr("x"));
tooltip.attr("y", d3.select(this).attr("y"));
})
.on("mouseout", function ()
{
tooltip.style("opacity", "0");
toolrec.style("opacity", "0");
return true;
});
});
:root {
--line-color: black;
--line-width: 2;
}
line, polyline, rect, circle, path {
stroke-width: var(--line-width);
stroke: var(--line-color);
}
#tooltip-text {
max-width: 800px;
text-align:left;
transition: opacity 0.4s;
pointer-events:none;
opacity: 0;
padding: 4px;
font-family: Arial;
font-size: 14;
}
#tooltip-rect {
background: yellow;
border:solid gray;
max-width: 800px;
transition: opacity 0.4s;
pointer-events:none;
opacity: 0;
}
svg {
margin:10px 20px;
overflow:visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js"></script>
<svg xmlns="http://www.w3.org/2000/svg" version="2.0" width="8000px" height="6000px">
<defs>
<g id="differentiel">
<rect x="-5" y="0" width="40" height="40" style="opacity:0" />
<g transform="rotate(-20,0,0)">
<polyline points="0 0 0 40 5 40 5 35 0 35" fill="none" />
</g>
</g>
<g id="disjoncteur" transform="rotate(-20,0,0)">
<polyline points="0 0 0 40 5 40 5 35 0 35" fill="none" />
</g>
<g id="prise">
<path d="m40,-20 a20,20 0 0,0 0,40 z" fill="white" style="stroke:white" />
<line x1="0" y1="0" x2="20" y2="0" />
<line x1="20" y1="-15" x2="20" y2="15" />
<path d="m40,-20 a20,20 0 0,0 0,40" fill="none" />
<line x1="40" y1="-20" x2="40" y2="-28" />
<line x1="40" y1="20" x2="40" y2="28" />
</g>
<g id="connexion">
<rect x="0" y="-10" width="20" height="20" fill="white" />
</g>
<g id="lampe">
<circle cx="0" cy="0" r="15" stroke="none" style="opacity:0" />
<line x1="-10" y1="-10" x2="10" y2="10" />
<line x1="10" y1="-10" x2="-10" y2="10" />
</g>
<g id="interrupteur">
<circle cx="10" cy="0" r="10" fill="white" />
<g transform="rotate(-60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
</g>
</g>
<g id="int-sans-fil">
<rect x="0" y="-5" width="10" height="10" fill="white" />
</g>
<g id="int-wifi">
<rect x="0" y="-5" width="10" height="10" fill="white" />
</g>
<g id="int-radio">
<rect x="0" y="-5" width="10" height="10" fill="white" />
</g>
<g id="int-unipolaire">
<circle cx="10" cy="0" r="10" fill="white" />
<g transform="rotate(-60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
<line x1="50" y1="0" x2="50" y2="5" />
</g>
</g>
<g id="int-bipolaire">
<circle cx="10" cy="0" r="10" fill="white" />
<g transform="rotate(-60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
<line x1="50" y1="0" x2="50" y2="5" />
<line x1="45" y1="0" x2="45" y2="5" />
</g>
</g>
<g id="int-va-et-vient">
<circle cx="10" cy="0" r="10" fill="white" />
<g transform="rotate(-60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
<line x1="50" y1="0" x2="50" y2="5" />
<line x1="0" y1="0" x2="-30" y2="0" />
<line x1="-30" y1="0" x2="-30" y2="-5" />
</g>
</g>
<g id="inverseur">
<g transform="translate(w²²0 0)">
<circle cx="10" cy="0" r="10" fill="white" />
<g transform="rotate(-60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
<line x1="50" y1="0" x2="50" y2="5" />
<line x1="0" y1="0" x2="-30" y2="0" />
<line x1="-30" y1="0" x2="-30" y2="-5" />
</g>
<g transform="rotate(60 10 0)">
<line x1="20" y1="0" x2="50" y2="0" />
<line x1="50" y1="0" x2="50" y2="-5" />
<line x1="0" y1="0" x2="-30" y2="0" />
<line x1="-30" y1="0" x2="-30" y2="5" />
</g>
</g>
</g>
<g id="machine-à-laver">
<rect x="0" y="-20" width="40" height="40" fill="white" fill-opacity="0.0" />
<circle cx="20" cy="0" r="12" stroke="blue" fill="none" />
<circle cx="20" cy="0" r="5" stroke="blue" fill="red" />
</g>
<g id="séchoir">
<rect x="0" y="-20" width="40" height="40" fill="white" fill-opacity="0.0" />
<circle cx="15" cy="-8" r="5" fill="none" />
<circle cx="25" cy="-8" r="5" fill="none" />
<circle cx="20" cy="8" r="5" fill="black" />
</g>
<g id="chauffe-eau">
<circle cx="20" cy="0" r="20" fill="white" fill-opacity="0.0" />
<circle cx="20" cy="0" r="15" fill="cyan" />
<path d="m5,0 l 5,-5 l 10,10 l 10,-10 l 5,5" fill="none" />
</g>
<g id="chauffe-eau-direct">
<circle cx="20" cy="0" r="20" fill="cyan" />
<path d="m0,0 l 5,-5 l 10,10 l 10,-10 l 10,10 l 5,-5" fill="none" />
</g>
<g id="télérupteur">
<rect x="0" y="-10" width="40" height="20" fill="white" />
<path d="m5,5 h10 v-10 m20,10 h-10 v-10" fill="none" />
</g>
<g id="télérupteur-radio">
<rect x="0" y="-10" width="40" height="20" fill="none" />
<path d="m5,5 h10 v-10 m20,10 h-10 v-10" fill="none" />
<path d="M25,15 A5,5 0 0,1 15,15" fill="none" stroke-width="1" />
<path d="M30,15 A10,10 0 0,1 10,15" fill="none" stroke-width="1" />
<path d="M35,15 A15,15 0 0,1 5,15" fill="none" stroke-width="1" />
</g>
<g id="télérupteur-wifi">
<rect x="0" y="-10" width="40" height="20" fill="none" />
<path d="m5,5 h10 v-10 m20,10 h-10 v-10" fill="none" />
</g>
<g id="bouton-poussoir">
<circle cx="10" cy="0" r="10" fill="none" />
<circle cx="10" cy="0" r="5" fill="red" />
</g>
<g id="transformateur">
<circle cx="10" cy="0" r="10" fill="none" />
<circle cx="20" cy="0" r="10" fill="none" />
</g>
<g id="lave-vaisselle">
<rect x="0" y="-20" width="40" height="40" fill="white" />
<line x1="0" y1="-20" x2="40" y2="20" />
<line x1="0" y1="20" x2="40" y2="-20" />
<circle cx="20" cy="0" r="10" fill="white" />
</g>
<g id="plaque-cuisson">
<rect x="0" y="-20" width="40" height="40" fill="white" />
<circle cx="30" cy="-10" r="5" stroke="blue" fill="none" />
<circle cx="30" cy="10" r="5" stroke="blue" fill="none" />
<circle cx="10" cy="10" r="5" stroke="blue" fill="none" />
</g>
<g id="télévision">
<rect x="0" y="-20" width="60" height="40" fill="white" />
<rect x="5" y="-15" width="50" height="30" fill="none" />
<line x1="30" y1="20" x2="30" y2="25" />
<line x1="20" y1="25" x2="40" y2="25" />
</g>
<g id="ordinateur">
<rect x="0" y="-20" width="40" height="30" fill="white" />
<rect x="5" y="-15" width="30" height="20" fill="none" />
<rect x="0" y="15" width="40" height="10" fill="none" />
<line x1="20" y1="20" x2="35" y2="20" />
</g>
<g id="four-classique">
<rect x="0" y="-20" width="40" height="40" fill="white" />
<line x1="0" y1="-10" x2="40" y2="-10" />
<circle cx="20" cy="5" r="5" fill="none" />
</g>
<g id="four-pyrolyse">
<rect x="0" y="-20" width="40" height="40" fill="white" />
</g>
<g id="micro-onde">
<rect x="0" y="-20" width="40" height="40" fill="white" fill-opacity="0.0" />
<g transform="scale(0.2 0.2)">
<path d="M20 -30 C 40 -80 , 80 -80 , 100 -30 S 160 30, 180 -30" stroke="black" fill="none" />
<path d="M20 0 C 40 -50 , 80 -50 , 100 0 S 160 50, 180 0" stroke="black" fill="none" />
<path d="M20 30 C 40 -20 , 80 -20 , 100 30 S 160 80, 180 30" stroke="black" fill="none" />
</g>
</g>
<g id="frigo">
<rect x="0" y="-20" width="40" height="40" fill="white" />
<text x="20" y="6" dominant-baseline="middle" text-anchor="middle" font-size="24">*</text>
</g>
<g id="congélateur">
<rect x="0" y="-20" width="40" height="40" fill="white" />
<text x="20" y="4" dominant-baseline="middle" text-anchor="middle">***</text>
</g>
<g id="radiateur">
<rect x="0" y="-15" width="60" height="30" fill-opacity="0.0" />
<path d="m0,0 l5,0 l 5,-10 l 10,20 l 10,-20 l 10,20 l 10,-20 l 5,10 l5,0" fill="none" stroke="black" stroke-width="1" />
</g>
<g id="volet">
<rect x="0" y="-20" width="40" height="40" fill-opacity="0.0" />
<path d="M0,-15 h 40 M0,-10 h 40 M0,-5 h 40 M0,0 h 40 M0,5 h40" fill="none" stroke="black" stroke-width="1" />
</g>
<g id="spot">
<path d="m10,-10 a10,10 0 0,0 0,20" fill="none" />
<circle cx="10" cy="0" r="5" fill="yellow" />
<g transform="rotate(-45,10,0)">
<line x1="5" y1="0" x2="15" y2="0" stroke-width="1" />
<line x1="10" y1="-5" x2="10" y2="5" stroke-width="1" />
</g>
</g>
<g id="neon-simple">
<line x1="0" y1="-5" x2="0" y2="5" stroke="black" />
<line x1="40" y1="-5" x2="40" y2="5" stroke="black" />
<rect x="0" y="-2" width="40" height="4" fill="yellow" stroke="black" stroke-width="1" />
</g>
<g id="neon-double">
<line x1="0" y1="-7" x2="0" y2="7" stroke="black" />
<line x1="40" y1="-7" x2="40" y2="7" stroke="black" />
<rect x="0" y="-6" width="40" height="4" fill="yellow" stroke="black" stroke-width="1" />
<rect x="0" y="2" width="40" height="4" fill="yellow" stroke="black" stroke-width="1" />
</g>
<g id="compteur">
<rect x="0" y="-20" width="40" height="40" fill="none" />
<line x1="0" y1="-10" x2="40" y2="-10" />
<text x="20" y="5" dominant-baseline="middle" text-anchor="middle" font-family="Arial" font-size="16">kWh</text>
</g>
</defs>
<line x1='100' y1='50' x2='100' y2='90'/>
<text x ='110' y='70' fill='black' font-family='Arial' font-size='20'>Différenciel PRINCIPAL</text>
<text x ='110' y='100' fill='black' font-family='Arial' font-size='12'>Δ300 mA</text>
<use href='#differentiel' x='100' y='90'/>
<line x1='100' y1='130' x2='100' y2='170'/>
<line x1='100' y1='170' x2='100' y2='210'/>
<text x ='110' y='190' fill='black' font-family='Arial' font-size='20'>B</text>
<text x ='110' y='220' fill='black' font-family='Arial' font-size='12'>10A</text>
<use href='#differentiel' x='100' y='210'/>
<desc class='info'>
B: éclairage Etage + Cave + Hall + WC + cagibi +
</desc>
<line x1='100' y1='250' x2='100' y2='330'/>
<text x='90' y='334' fill='black' font-family='Arial' font-size='16' text-anchor='end'>B1</text>
<line x1='100' y1='330' x2='120' y2='330'/>
<use href='#int-va-et-vient' x='120' y='330'/>
<desc class='info'>
hall: interrupteur à droite des escaliers
</desc>
<use href='#int-va-et-vient' x='140' y='330'/>
<desc class='info'>
hall: interrupteur à gauche de la porte de la cuisine
</desc>
<line x1='160' y1='330' x2='200' y2='330'/>
<use href='#lampe' x='200' y='330'/>
<desc class='info'>
lampe Hall dans l'entrée
</desc>
<line x1='100' y1='330' x2='100' y2='410'/>
<text x='90' y='414' fill='black' font-family='Arial' font-size='16' text-anchor='end'>B7</text>
<line x1='100' y1='410' x2='120' y2='410'/>
<use href='#int-unipolaire' x='120' y='410'/>
<desc class='info'>
chambre Est: interrupteur à gauche de la porte
</desc>
<line x1='140' y1='410' x2='180' y2='410'/>
<use href='#lampe' x='180' y='410'/>
<desc class='info'>
lampe chambre Est (Musson)
</desc>
<line x1='100' y1='410' x2='100' y2='490'/>
<text x='90' y='494' fill='black' font-family='Arial' font-size='16' text-anchor='end'>B8</text>
<line x1='100' y1='490' x2='120' y2='490'/>
<use href='#int-va-et-vient' x='120' y='490'/>
<desc class='info'>
interrupteur à gauche de l'escalier
</desc>
<line x1='140' y1='490' x2='170' y2='490'/>
<use href='#inverseur' x='170' y='490'/>
<desc class='info'>
interrupteur à droite du passage entre caves
</desc>
<line x1='190' y1='490' x2='220' y2='490'/>
<use href='#int-va-et-vient' x='220' y='490'/>
<desc class='info'>
interrupteur à droite de la porte de garage
</desc>
<line x1='240' y1='490' x2='280' y2='490'/>
<use href='#lampe' x='280' y='490'/>
<desc class='info'>
lampes cave petit garage
</desc>
<line x1='100' y1='490' x2='100' y2='570'/>
<text x ='90' y='574' fill='black' font-family='Arial' font-size='16' text-anchor='end'>B12</text>
<line x1='100' y1='570' x2='120' y2='570'/>
<use href='#télérupteur-radio' x='120' y='570'/>
<use href='#int-radio' x='140' y='610'/>
<use href='#int-radio' x='160' y='610'/>
<use href='#int-radio' x='180' y='610'/>
<line x1='160' y1='570' x2='200' y2='570'/>
<use href='#lampe' x='200' y='570'/>
<desc class='info'>
lampe couloir étage Ouest (Signeulx)
</desc>
<line x1='100' y1='170' x2='350' y2='170'/>
<line x1='350' y1='170' x2='350' y2='210'/>
<text x ='360' y='190' fill='black' font-family='Arial' font-size='20'>C</text>
<text x ='360' y='220' fill='black' font-family='Arial' font-size='12'>25A</text>
<use href='#differentiel' x='350' y='210'/>
<desc class='info'>
C: triphasé cuisine
</desc>
<line x1='350' y1='250' x2='350' y2='330'/>
<text x ='340' y='334' fill='black' font-family='Arial' font-size='16' text-anchor='end'>C1</text>
<line x1='350' y1='330' x2='370' y2='330'/>
<use href='#connexion' x='370' y='330'/>
<desc class='info'>
connection directe
</desc>
<line x1='390' y1='330' x2='410' y2='330'/>
<line x1='410' y1='330' x2='430' y2='330'/>
<use href='#four-classique' x='430' y='330'/>
<desc class='info'>
four Siemens
</desc>
<line x1='350' y1='330' x2='350' y2='410'/>
<text x ='340' y='414' fill='black' font-family='Arial' font-size='16' text-anchor='end'>C2</text>
<line x1='350' y1='410' x2='370' y2='410'/>
<use href='#connexion' x='370' y='410'/>
<desc class='info'>
connection directe
</desc>
<line x1='390' y1='410' x2='410' y2='410'/>
<line x1='410' y1='410' x2='430' y2='410'/>
<use href='#micro-onde' x='430' y='410'/>
<desc class='info'>
micro-onde Siemens
</desc>
<line x1='350' y1='170' x2='530' y2='170'/>
<line x1='530' y1='170' x2='530' y2='210'/>
<text x ='540' y='190' fill='black' font-family='Arial' font-size='20'>Différentiel SECONDAIRE</text>
<text x ='540' y='220' fill='black' font-family='Arial' font-size='12'>Δ30 mA</text>
<use href='#differentiel' x='530' y='210'/>
<line x1='530' y1='250' x2='530' y2='290'/>
<line x1='530' y1='290' x2='530' y2='330'/>
<text x ='540' y='310' fill='black' font-family='Arial' font-size='20'>E</text>
<text x ='540' y='340' fill='black' font-family='Arial' font-size='12'>16A</text>
<use href='#differentiel' x='530' y='330'/>
<desc class='info'>
E: éclairage et 2 prises dans salle de bain principale
</desc>
<line x1='530' y1='370' x2='530' y2='450'/>
<text x='520' y='454' fill='black' font-family='Arial' font-size='16' text-anchor='end'>E1</text>
<line x1='530' y1='450' x2='550' y2='450'/>
<use href='#int-unipolaire' x='550' y='450'/>
<desc class='info'>
interrupteur à gauche de la colonne de descente d'eau
</desc>
<line x1='570' y1='450' x2='610' y2='450'/>
<use href='#lampe' x='610' y='450'/>
<desc class='info'>
lampe salle de bain
</desc>
<line x1='530' y1='450' x2='530' y2='530'/>
<text x ='520' y='534' fill='black' font-family='Arial' font-size='16' text-anchor='end'>E2</text>
<use href='#prise' x='530' y='530'/>
<desc class='info'>
bloc prises à gauche de la colonne de descente d'eau
</desc>
<use href='#prise' x='550' y='530'/>
<desc class='info'>
bloc prises à gauche de la colonne de descente d'eau
</desc>
<line x1='530' y1='290' x2='680' y2='290'/>
<line x1='680' y1='290' x2='680' y2='330'/>
<text x ='690' y='310' fill='black' font-family='Arial' font-size='20'>F</text>
<text x ='690' y='340' fill='black' font-family='Arial' font-size='12'>16A</text>
<use href='#differentiel' x='680' y='330'/>
<desc class='info'>
F: Salle-de-bain ETAGE + prise TV + prise PC bureau
</desc>
<line x1='680' y1='370' x2='680' y2='450'/>
<text x ='670' y='454' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F1</text>
<use href='#prise' x='680' y='450'/>
<desc class='info'>
prise TV au Salon
</desc>
<line x1='680' y1='450' x2='720' y2='450'/>
<line x1='720' y1='450' x2='740' y2='450'/>
<use href='#télévision' x='740' y='450'/>
<desc class='info'>
TV Philips
</desc>
<line x1='680' y1='450' x2='680' y2='530'/>
<text x ='670' y='534' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F2</text>
<use href='#prise' x='680' y='530'/>
<desc class='info'>
prise PC au Bureau
</desc>
<line x1='680' y1='530' x2='720' y2='530'/>
<line x1='720' y1='530' x2='740' y2='530'/>
<use href='#ordinateur' x='740' y='530'/>
<desc class='info'>
ordinateur Dell
</desc>
<line x1='680' y1='530' x2='680' y2='610'/>
<text x ='670' y='614' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F3</text>
<line x1='680' y1='610' x2='700' y2='610'/>
<use href='#télérupteur-radio' x='700' y='610'/>
<use href='#int-radio' x='720' y='650'/>
<line x1='740' y1='610' x2='780' y2='610'/>
<use href='#lampe' x='780' y='610'/>
<desc class='info'>
Salle-de-bain: lampe plafond
</desc>
<line x1='680' y1='610' x2='680' y2='690'/>
<text x ='670' y='694' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F4</text>
<use href='#prise' x='680' y='690'/>
<desc class='info'>
Salle-de-bain: lampe meuble
</desc>
<line x1='680' y1='690' x2='680' y2='770'/>
<text x ='670' y='774' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F5</text>
<use href='#prise' x='680' y='770'/>
<desc class='info'>
Salle-de-bain: prise radiateur
</desc>
<line x1='680' y1='770' x2='720' y2='770'/>
<line x1='720' y1='770' x2='740' y2='770'/>
<use href='#radiateur' x='740' y='770'/>
<desc class='info'>
radiateur Jaga
</desc>
<line x1='680' y1='770' x2='680' y2='850'/>
<text x ='670' y='854' fill='black' font-family='Arial' font-size='16' text-anchor='end'>F6</text>
<use href='#prise' x='680' y='850'/>
<desc class='info'>
Salle-de-bain: bloc de prises sous le meuble
</desc>
<use href='#prise' x='700' y='850'/>
<desc class='info'>
Salle-de-bain: bloc de prises sous le meuble
</desc>
<line x1='680' y1='290' x2='860' y2='290'/>
<line x1='860' y1='290' x2='860' y2='330'/>
<text x ='870' y='310' fill='black' font-family='Arial' font-size='20'>G</text>
<text x ='870' y='340' fill='black' font-family='Arial' font-size='12'>16A</text>
<use href='#differentiel' x='860' y='330'/>
<desc class='info'>
G: Salle-de-bain PRINCIPALE + Bloc machines à laver
</desc>
<line x1='860' y1='370' x2='860' y2='450'/>
<text x ='850' y='454' fill='black' font-family='Arial' font-size='16' text-anchor='end'>G1</text>
<use href='#prise' x='860' y='450'/>
<desc class='info'>
bloc de prises à l'évier
</desc>
<use href='#prise' x='880' y='450'/>
<desc class='info'>
bloc de prises à l'évier
</desc>
<line x1='860' y1='450' x2='860' y2='530'/>
<text x ='850' y='534' fill='black' font-family='Arial' font-size='16' text-anchor='end'>G2</text>
<use href='#prise' x='860' y='530'/>
<desc class='info'>
lampe meuble
</desc>
<line x1='860' y1='530' x2='860' y2='610'/>
<text x ='850' y='614' fill='black' font-family='Arial' font-size='16' text-anchor='end'>G3</text>
<use href='#prise' x='860' y='610'/>
<desc class='info'>
bloc de prises au petit garage à gauche de l'évier
</desc>
<use href='#prise' x='880' y='610'/>
<desc class='info'>
bloc de prises au petit garage à gauche de l'évier
</desc>
<use href='#prise' x='900' y='610'/>
<desc class='info'>
bloc de prises au petit garage à gauche de l'évier
</desc>
<use href='#prise' x='920' y='610'/>
<desc class='info'>
bloc de prises au petit garage à gauche de l'évier
</desc>
<line x1='920' y1='610' x2='960' y2='610'/>
<line x1='960' y1='610' x2='980' y2='610'/>
<use href='#machine-à-laver' x='980' y='610'/>
<desc class='info'>
machine à laver
</desc>
<line x1='530' y1='170' x2='1080' y2='170'/>
<line x1='1080' y1='170' x2='1080' y2='210'/>
<text x ='1090' y='190' fill='black' font-family='Arial' font-size='20'>I</text>
<text x ='1090' y='220' fill='black' font-family='Arial' font-size='12'>16A</text>
<use href='#differentiel' x='1080' y='210'/>
<desc class='info'>
I: chambre étage Ouest (Signeulx)
</desc>
<line x1='1080' y1='250' x2='1080' y2='330'/>
<text x ='1070' y='334' fill='black' font-family='Arial' font-size='16' text-anchor='end'>I1</text>
<use href='#prise' x='1080' y='330'/>
<desc class='info'>
prise à gauche de la porte
</desc>
<line x1='1080' y1='330' x2='1080' y2='410'/>
<text x ='1070' y='414' fill='black' font-family='Arial' font-size='16' text-anchor='end'>I2</text>
<use href='#prise' x='1080' y='410'/>
<desc class='info'>
prise radiateur en dessous de la fenêtre
</desc>
<line x1='1080' y1='410' x2='1120' y2='410'/>
<line x1='1120' y1='410' x2='1140' y2='410'/>
<use href='#radiateur' x='1140' y='410'/>
<desc class='info'>
radiateur Siemens
</desc>
<line x1='1080' y1='410' x2='1080' y2='490'/>
<text x ='1070' y='494' fill='black' font-family='Arial' font-size='16' text-anchor='end'>I3</text>
<line x1='1080' y1='490' x2='1100' y2='490'/>
<use href='#connexion' x='1100' y='490'/>
<desc class='info'>
volet chambre étage Ouest
</desc>
<line x1='1120' y1='490' x2='1140' y2='490'/>
<line x1='1140' y1='490' x2='1160' y2='490'/>
<use href='#volet' x='1160' y='490'/>
<desc class='info'>
volet
</desc>
<line x1='1080' y1='490' x2='1080' y2='570'/>
<text x ='1070' y='574' fill='black' font-family='Arial' font-size='16' text-anchor='end'>I4</text>
<use href='#prise' x='1080' y='570'/>
<desc class='info'>
bloc de prises à gauche de la paque de cuisson en vitrocéramique
</desc>
<use href='#prise' x='1100' y='570'/>
<desc class='info'>
bloc de prises à gauche de la paque de cuisson en vitrocéramique
</desc>
<use href='#prise' x='1120' y='570'/>
<desc class='info'>
bloc de prises à gauche de la paque de cuisson en vitrocéramique
</desc>
<line x1='1080' y1='170' x2='1260' y2='170'/>
<line x1='1260' y1='170' x2='1260' y2='210'/>
<text x ='1270' y='190' fill='black' font-family='Arial' font-size='20'>J</text>
<text x ='1270' y='220' fill='black' font-family='Arial' font-size='12'>16A</text>
<use href='#differentiel' x='1260' y='210'/>
<desc class='info'>
J: Prises bloc de cuisson
</desc>
<line x1='1260' y1='250' x2='1260' y2='330'/>
<text x ='1250' y='334' fill='black' font-family='Arial' font-size='16' text-anchor='end'>J1</text>
<use href='#prise' x='1260' y='330'/>
<desc class='info'>
bloc de prises à droite de la plaque de cuisson en vitrocéramique
</desc>
<use href='#prise' x='1280' y='330'/>
<desc class='info'>
bloc de prises à droite de la plaque de cuisson en vitrocéramique
</desc>
<use href='#prise' x='1300' y='330'/>
<desc class='info'>
bloc de prises à droite de la plaque de cuisson en vitrocéramique
</desc>
<rect id='tooltip-rect' x='20' y='20' width='100' height='25' fill="yellow"/>
<text id='tooltip-text' x='20' y='20' dominant-baseline="middle" text-anchor="start">
Tooltip: ?
</text>
</svg>

Related

Svg legend: line not shown

I am using d3-svg-legend ( https://d3-legend.susielu.com/) to create a legend based on size. I want to replicate this example: https://d3-legend.susielu.com/#size-line
The code I am using is:
let svg = d3.select(this.refs.canvas).append('svg');
const g = svg.append("g");
var lineSize = d3.scaleLinear().domain([0,10]).range([2, 10]);
g.attr("transform", "translate(20,20)")
.call(legendSize()
.scale(lineSize)
.shape("line")
.orient("horizontal")
.shapeWidth(40)
.labelAlign("start")
.shapePadding(10)
);
This code produces the following output:
<div style="margin-left: auto; margin-right: 20px;">
<svg>
<g transform="translate(20,20)">
<g class="legendCells"><g class="cell" transform="translate(0, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="2" style="fill: rgb(153, 216, 201);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">0.0</text></g><g class="cell" transform="translate(50, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="4" style="fill: rgb(211, 74, 65);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">2.5</text>
</g>
<g class="cell" transform="translate(100, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="6" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">5.0</text>
</g>
<g class="cell" transform="translate(150, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="8" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">7.5</text>
</g>
<g class="cell" transform="translate(200, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="10" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">10.0</text>
</g>
</g>
</g>
</svg>
</div>
But it doesn't display any legend other than the labels (i.e. it doesn't display the line elements):
If you look at the same example, you'll see that she's setting the stroke using a <style> tag in the <head>:
.legendSizeLine line {
stroke: rgb(46, 73, 123);
}
That's necessary because the default <line> stroke is "none".
Here is your SVG with that style:
line {
stroke: rgb(46, 73, 123);
}
text {
font: 12px sans-serif;
}
<div style="margin-left: auto; margin-right: 20px;">
<svg>
<g transform="translate(20,20)">
<g class="legendCells">
<g class="cell" transform="translate(0, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="2" style="fill: rgb(153, 216, 201);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">0.0</text>
</g>
<g class="cell" transform="translate(50, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="4" style="fill: rgb(211, 74, 65);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">2.5</text>
</g>
<g class="cell" transform="translate(100, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="6" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">5.0</text>
</g>
<g class="cell" transform="translate(150, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="8" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">7.5</text>
</g>
<g class="cell" transform="translate(200, 5)">
<line class="swatch" x1="0" x2="40" y1="0" y2="0" stroke-width="10" style="fill: rgb(255, 0, 0);"></line>
<text class="label" transform="translate( 0,15)" style="text-anchor: start;">10.0</text>
</g>
</g>
</g>
</svg>
</div>

svg rect fill background image performance issue

I want to draw an image as a background for SVG rect. I did as follows,
<pattern id = "HappySmile" width="97" height="40" >
<image width="97" height="30" xlink:href="resources/images/HappySmile.png"></image>
</pattern>
It works but performance has drastically dropped.I am applying on 36 rects. Any suggestions will be very helpful.
The image explaing the scenario can be found in the following link.
http://i.stack.imgur.com/Jo6b2.png
Thanks.
If patterns are proving too slow for you. Try using a <mask> or a <clipPath> instead.
Below is an example of how to use a mask to make your "brick" shape. In your case, you would replace the sample I have used with your "HappySmile" image.
<svg width="600" height="400">
<defs>
<mask id="lozenge">
<circle cx="15" cy="15" r="15" fill="white"/>
<rect x="15" y="0" width="67" height="30" fill="white"/>
<circle cx="82" cy="15" r="15" fill="white"/>
</mask>
<image id="brick1" width="97" height="30" xlink:href="http://lorempixel.com/output/abstract-q-c-97-30-9.jpg" mask="url(#lozenge)"/>
</defs>
<use xlink:href="#brick1" x="50" y="50"/>
<use xlink:href="#brick1" x="150" y="50"/>
<use xlink:href="#brick1" x="250" y="50"/>
<use xlink:href="#brick1" x="350" y="50"/>
<use xlink:href="#brick1" x="450" y="50"/>
<use xlink:href="#brick1" x="50" y="100"/>
<use xlink:href="#brick1" x="150" y="100"/>
<use xlink:href="#brick1" x="250" y="100"/>
<use xlink:href="#brick1" x="350" y="100"/>
<use xlink:href="#brick1" x="450" y="100"/>
<use xlink:href="#brick1" x="50" y="150"/>
<use xlink:href="#brick1" x="150" y="150"/>
<use xlink:href="#brick1" x="250" y="150"/>
<use xlink:href="#brick1" x="350" y="150"/>
<use xlink:href="#brick1" x="450" y="150"/>
</svg>

Why has my SMIL animation stopped working?

I did a simple loading icon with six rectangles that darken in series, my image is:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 60 60">
<g transform="translate(30,30)">
<g transform="rotate(0)">
<rect id="rect1" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animateColor id="a1b" begin="0s;a6b.end" attributeName="fill" values="white;black" fill="freeze" dur=".5s" />
<animateColor id="a1w" begin="1s;a6w.end" attributeName="fill" values="black;white" fill="freeze" dur=".5s" />
</rect>
</g>
<g transform="rotate(60)">
<rect id="rect2" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animateColor id="a2b" begin="a1b.end" attributeName="fill" values="white;black" fill="freeze" dur=".5s" />
<animateColor id="a2w" begin="a1w.end" attributeName="fill" values="black;white" fill="freeze" dur=".5s" />
</rect>
</g>
⋮
<g transform="rotate(300)">
<rect id="rect6" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animateColor id="a6b" begin="a5b.end" attributeName="fill" values="white;black" fill="freeze" dur=".5s" />
<animateColor id="a6w" begin="a5w.end" attributeName="fill" values="black;white" fill="freeze" dur=".5s" />
</rect>
</g>
</g>
</svg>
When I initially created the document, this structure worked. Now it doesn't. Anyone know why?
The <animateColor> elements was deprecated in SVG 1.1 and is being completely removed for SVG 2. Some browsers are removing it already.
To achieve the same effect, just use <animate> with all the same attributes.
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 60 60" style="width:100vmin">
<defs>
<title>Loading Icon</title>
<style type="text/css">
rect {
stroke: black;
stroke-width: .75;
fill: transparent;
}
</style>
<rect id="bar" x="-3" y="9" rx="3" ry="3" width="6" height="20"/>
</defs>
<g transform="translate(30,30)">
<g transform="rotate(0)">
<rect id="rect1" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a1b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="0s;a6b.end" />
<animate id="a1w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="1s;a6w.end" />
</rect>
</g>
<g transform="rotate(60)">
<rect id="rect2" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a2b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="a1b.end" />
<animate id="a2w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="a1w.end" />
</rect>
</g>
<g transform="rotate(120)">
<rect id="rect3" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a3b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="a2b.end" />
<animate id="a3w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="a2w.end" />
</rect>
</g>
<g transform="rotate(180)">
<rect id="rect4" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a4b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="a3b.end" />
<animate id="a4w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="a3w.end" />
</rect>
</g>
<g transform="rotate(240)">
<rect id="rect5" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a5b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="a4b.end" />
<animate id="a5w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="a4w.end" />
</rect>
</g>
<g transform="rotate(300)">
<rect id="rect6" x="-3" y="9" rx="3" ry="3" width="6" height="20">
<animate id="a6b" attributeName="fill" values="white;black" fill="freeze" dur=".5s" begin="a5b.end" />
<animate id="a6w" attributeName="fill" values="black;white" fill="freeze" dur=".5s" begin="a5w.end" />
</rect>
</g>
</g>
</svg>

Firefox renders SVG rotated patterns with lines along the seams

So the goal here is to have a 2 color diagonal hatch pattern that can be rotated to arbitrary angles dynamically (fyi it's being applied to a D3 map w/zooming).
I found the "SVG Pattern Contains Whitespace Between Repetitions in Firefox(1) question, however the solution is not very flexible rotation-wise and I couldn't make it work with the 2 colors bars.
Here's a jsfiddle test case.. The first 4 are my technique rotated differently. The last one is an attempt to adapt follow the previously mentioned answer's advice.
Chrome renders it fine(2) (as does Safari and IE).
But Firefox has these nasty lines where it tiles, but only when the pattern is rotated to something other than 90deg increments.
Any ideas?
Here's the contents of the Jsfiddle:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/SVG/DTD/svg10.dtd">
<svg xml:space="preserve" width="925" height="810" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<pattern id="hatch" width="10" height="10" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:16" />
<line x1="13" y1="0" x2="13" y2="10" style="stroke:gray; stroke-width:16" />
</pattern>
<pattern id="hatch45" width="10" height="10" patternTransform="rotate(5 0 0)" patternUnits="userSpaceOnUse">
<line x1="-2" y1="-2" x2="-2" y2="12" style="stroke:black; stroke-width:16" overflow="visible" />
<line x1="12" y1="-2" x2="12" y2="12" style="stroke:gray; stroke-width:16" overflow="visible" />
</pattern>
<pattern id="hatch80" width="10" height="10" patternTransform="rotate(80 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:16" />
<line x1="13" y1="0" x2="13" y2="10" style="stroke:gray; stroke-width:16" />
</pattern>
<pattern id="hatch90" width="10" height="10" patternTransform="rotate(90 0 0)" patternUnits="userSpaceOnUse">
<line x1="0" y1="0" x2="0" y2="10" style="stroke:black; stroke-width:16" />
<line x1="13" y1="0" x2="13" y2="10" style="stroke:gray; stroke-width:16" />
</pattern>
<pattern x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse" id="line-fill" viewBox="0 0 20 20" overflow="visible" patternTransform="rotate(80 0 0)">
<g stroke-width="20">
<line x1="0" y1="-10" x2="0" y2="30" stroke="black" />
<line x1="20" y1="-10" x2="20" y2="30" stroke="gray" />
</g>
</pattern>
</defs>
<g>
<rect style="fill:url(#hatch45);" x="10" y="0" width="200" height="130" />
<rect style="fill:url(#hatch80);" x="10" y="150" width="200" height="130" />
<rect style="fill:url(#hatch90);" x="10" y="300" width="200" height="130" />
<rect style="fill:url(#hatch);" x="10" y="450" width="200" height="130" />
<rect style="fill:url(#line-fill);" x="10" y="600" width="200" height="130" />
</g>
</svg>
1: stackoverflow.com/questions/19391071/svg-pattern-contains-whitespace-between-repetitions-in-firefox
2: imgur.com/c8SxdGG

Does SVG support embedding of bitmap images?

Is an SVG image purely vectorial or can we combine bitmap images into an SVG image ?
How about transforms applied on the bitmap images (perspective, mappings, etc.) ?
Edit: Images may be included in an SVG by link reference. See http://www.w3.org/TR/SVG/struct.html#ImageElement. My question was in fact if bitmap images may be included inside the svg so that the svg image would be self contained. Otherwise, whenever the svg image is displayed the link must be followed and the image downloaded. Apparently .svg files are simply xml files.
Yes, you can reference any image from the image element. And you can use data URIs to make the SVG self-contained. An example:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
...
<image
width="100" height="100"
xlink:href="data:image/png;base64,IMAGE_DATA"
/>
...
</svg>
The svg element attribute xmlns:xlink declares xlink as a namespace prefix and says where the definition is. That then allows the SVG reader to know what xlink:href means.
The IMAGE_DATA is where you'd add the image data as base64-encoded text. Vector graphics editors that support SVG usually have an option for saving with images embedded. Otherwise there are plenty of tools around for encoding a byte stream to and from base64.
Here's a full example from the SVG testsuite.
I posted a fiddle here, showing data, remote and local images embedded in SVG, inside an HTML page:
http://jsfiddle.net/MxHPq/
<!DOCTYPE html>
<html>
<head>
<title>SVG embedded bitmaps in HTML</title>
<style>
body{
background-color:#999;
color:#666;
padding:10px;
}
h1{
font-weight:normal;
font-size:24px;
margin-top:20px;
color:#000;
}
h2{
font-weight:normal;
font-size:20px;
margin-top:20px;
}
p{
color:#FFF;
}
svg{
margin:20px;
display:block;
height:100px;
}
</style>
</head>
<body>
<h1>SVG embedded bitmaps in HTML</h1>
<p>The trick appears to be ensuring the image has the correct width and height atttributes</p>
<h2>Example 1: Embedded data</h2>
<svg id="example1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="5" height="5" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
</svg>
<h2>Example 2: Remote image</h2>
<svg id="example2" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="275" height="95" xlink:href="http://www.google.co.uk/images/srpr/logo3w.png" />
</svg>
<h2>Example 3: Local image</h2>
<svg id="example3" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="0" width="136" height="23" xlink:href="/img/logo.png" />
</svg>
</body>
</html>
You could use a Data URI to supply the image data, for example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="20" height="20" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="/>
</svg>
The image will go through all normal svg transformations.
But this technique has disadvantages, for example the image will not be cached by the browser
You can use a data: URL to embed a Base64 encoded version of an image. But it's not very efficient and wouldn't recommend embedding large images. Any reason linking to another file is not feasible?
If you want to use that image multiple times inside SVG (Ref.):
<image id="img" xlink:href="data:image/png;base64,BASE64_DATA" />
<use href="#img" />
<use href="#img" />
It is also possible to include bitmaps. I think you also can use transformations on that.
I've come up with multiple solutions for drawing a space invader in SVG:
The first method makes use of a path with stroke-width="1". By repeatedly stopping and starting the line we can construct a bitmap image by traversing the scanlines. This has the drawback that the y-coordinate of each "dot" is shifted up by 0.5 pixels because the "y" coordinate is treated as the middle of stroke-width="1".
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path
stroke="black"
fill="none"
d="M 4 4 l 1 0
M 10 4 l 1 0
M 5 5 l 1 0
M 9 5 l 1 0
M 4 6 l 7 0
M 3 7 l 2 0
M 6 7 l 3 0
M 10 7 l 2 0
M 2 8 l 11 0
M 2 9 l 1 0
M 4 9 l 7 0
M 12 9 l 1 0
M 2 10 l 1 0
M 4 10 l 1 0
M 10 10 l 1 0
M 12 10 l 1 0
M 5 11 l 2 0
M 8 11 l 2 0"
/>
</svg>
The second is through the use of <marker> with marker-start, marker-mid, and marker-end attributes:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<marker
id="dot"
viewBox="0 0 1 1"
refX="0.5"
refY="0.5"
markerWidth="1"
markerHeight="1">
<rect width="1" height="1" />
</marker>
</defs>
<polyline
points="4 4 10 4
5 5 9 5
4 6 5 6 6 6 7 6 8 6 9 6 10 6
3 7 4 7 6 7 7 7 8 7 10 7 11 7
2 8 3 8 4 8 5 8 6 8 7 8 8 8 9 8 10 8 11 8 12 8
2 9 4 9 5 9 6 9 7 9 8 9 9 9 10 9 12 9
2 10 4 10 10 10 12 10
5 11 6 11 8 11 9 11"
fill="none"
stroke="none"
marker-start="url(#dot)"
marker-mid="url(#dot)"
marker-end="url(#dot)" />
</svg>
The third method is by defining a <rect> and then refer to it repeatedly with <use>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g fill="none"><rect id="dot" width="1" height="1"/></g>
<g fill="black">
<use href="#dot" x="4" y="4"/>
<use href="#dot" x="10" y="4"/>
<use href="#dot" x="5" y="5"/>
<use href="#dot" x="9" y="5"/>
<use href="#dot" x="4" y="6"/>
<use href="#dot" x="5" y="6"/>
<use href="#dot" x="6" y="6"/>
<use href="#dot" x="7" y="6"/>
<use href="#dot" x="8" y="6"/>
<use href="#dot" x="9" y="6"/>
<use href="#dot" x="10" y="6"/>
<use href="#dot" x="3" y="7"/>
<use href="#dot" x="4" y="7"/>
<use href="#dot" x="6" y="7"/>
<use href="#dot" x="7" y="7"/>
<use href="#dot" x="8" y="7"/>
<use href="#dot" x="10" y="7"/>
<use href="#dot" x="11" y="7"/>
<use href="#dot" x="2" y="8"/>
<use href="#dot" x="3" y="8"/>
<use href="#dot" x="4" y="8"/>
<use href="#dot" x="5" y="8"/>
<use href="#dot" x="6" y="8"/>
<use href="#dot" x="7" y="8"/>
<use href="#dot" x="8" y="8"/>
<use href="#dot" x="9" y="8"/>
<use href="#dot" x="10" y="8"/>
<use href="#dot" x="11" y="8"/>
<use href="#dot" x="12" y="8"/>
<use href="#dot" x="2" y="9"/>
<use href="#dot" x="4" y="9"/>
<use href="#dot" x="5" y="9"/>
<use href="#dot" x="6" y="9"/>
<use href="#dot" x="7" y="9"/>
<use href="#dot" x="8" y="9"/>
<use href="#dot" x="9" y="9"/>
<use href="#dot" x="10" y="9"/>
<use href="#dot" x="12" y="9"/>
<use href="#dot" x="2" y="10"/>
<use href="#dot" x="4" y="10"/>
<use href="#dot" x="10" y="10"/>
<use href="#dot" x="12" y="10"/>
<use href="#dot" x="5" y="11"/>
<use href="#dot" x="6" y="11"/>
<use href="#dot" x="8" y="11"/>
<use href="#dot" x="9" y="11"/>
</g>
</svg>
A refinement of the <rect> <use> solution above is to define binary permutations that can be reused later. This style kinda harks back to the days of 8-bit programming with sprites:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<g fill="none">
<g id="s0001"><rect x="3" width="1" height="1"/></g>
<g id="s0010"><rect x="2" width="1" height="1"/></g>
<g id="s0011"><rect x="2" width="2" height="1"/></g>
<g id="s0100"><rect x="1" width="1" height="1"/></g>
<g id="s0110"><rect x="1" width="2" height="1"/></g>
<g id="s1000"><rect width="1" height="1"/></g>
<g id="s1011"><rect width="1" height="1"/><rect x="2" width="2" height="1"/></g>
<g id="s1100"><rect width="2" height="1"/></g>
<g id="s1101"><rect width="2" height="1"/><rect x="2" width="1" height="1"/></g>
<g id="s1110"><rect width="3" height="1"/></g>
<g id="s1111"><rect width="4" height="1"/></g>
</g>
<g fill="black">
<use href="#s1000" x="4" y="4"/>
<use href="#s0010" x="8" y="4"/>
<use href="#s0100" x="4" y="5"/>
<use href="#s0100" x="8" y="5"/>
<use href="#s1111" x="4" y="6"/>
<use href="#s1110" x="8" y="6"/>
<use href="#s0001" x="0" y="7"/>
<use href="#s1011" x="4" y="7"/>
<use href="#s1011" x="8" y="7"/>
<use href="#s0011" x="0" y="8"/>
<use href="#s1111" x="4" y="8"/>
<use href="#s1111" x="8" y="8"/>
<use href="#s1000" x="12" y="8"/>
<use href="#s0010" x="0" y="9"/>
<use href="#s1111" x="4" y="9"/>
<use href="#s1101" x="8" y="9"/>
<use href="#s1000" x="12" y="9"/>
<use href="#s0010" x="0" y="10"/>
<use href="#s1000" x="4" y="10"/>
<use href="#s0010" x="8" y="10"/>
<use href="#s1000" x="12" y="10"/>
<use href="#s0110" x="4" y="11"/>
<use href="#s1100" x="8" y="11"/>
</g>
</svg>

Resources