Why are succesive SVG's sized after the first one? - html

I'm trying to build a dashboard with overview of a series of build jobs from Azure.
The badges provided by Azure are rendered differently depending on the sequence of the badges.
It can be boiled down to a very simple piece of HTML, which is available in this jsfiddle
If you change the order of the three div's it is obvious that the first div is limiting the width of the successive div's.
I have tried with Chrome, Edge, Edge Beta, FireFox and IE, all with the same (mis)behaviour.
<div>
<svg width="135.0" height="20.0" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0.0" stop-opacity="0.0" stop-color="#000" />
<stop offset="1.0" stop-opacity="0.2" stop-color="#000" />
</linearGradient>
<clipPath id="c">
<rect width="135.0" height="20.0" rx="3.0" />
</clipPath>
<g clip-path="url(#c)">
<rect width="135.0" height="20.0" fill="#555555" />
<rect width="70.8" height="20.0" fill="#4da2db" x="64.2" />
<rect width="135.0" height="20.0" fill="url(#a)" />
</g>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" x="5" y="4">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9H1V11H3L3 12H0V9Z" fill="#fff" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M0.666656 4H3.7352L6.20309 0.444336C6.38861 0.166992 6.70068 0 7.03479 0H11.5C11.7762 0 12 0.224609 12 0.5V4.96484C12 5.29883 11.8332 5.61133 11.5553 5.79688L8 8.26465V11.333C8 11.7012 7.70154 12 7.33334 12H5L4 11L5.25 9.75L4.25 8.75L2.99997 10L1.99997 9L3.25 7.75L2.25 6.75L1 8L0 7V4.66699C0 4.29883 0.298462 4 0.666656 4ZM10.5 3C10.5 3.82812 9.82843 4.5 9.00003 4.5C8.1716 4.5 7.50003 3.82812 7.50003 3C7.50003 2.17188 8.1716 1.5 9.00003 1.5C9.82843 1.5 10.5 2.17188 10.5 3Z"
fill="#fff" />
</g>
</svg>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="41.1" y="15.0" fill="#000" fill-opacity="0.3">Short</text>
<text x="41.1" y="14.0" fill="#fff">Short</text>
<text x="98.6" y="15.0" fill="#000" fill-opacity="0.3">never built</text>
<text x="98.6" y="14.0" fill="#fff">never built</text>
</g>
</svg>
</div>
<div>
<svg width="155.9" height="20.0" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0.0" stop-opacity="0.0" stop-color="#000" />
<stop offset="1.0" stop-opacity="0.2" stop-color="#000" />
</linearGradient>
<clipPath id="c">
<rect width="155.9" height="20.0" rx="3.0" />
</clipPath>
<g clip-path="url(#c)">
<rect width="155.9" height="20.0" fill="#555555" />
<rect width="70.8" height="20.0" fill="#4da2db" x="85.1" />
<rect width="155.9" height="20.0" fill="url(#a)" />
</g>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" x="5" y="4">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9H1V11H3L3 12H0V9Z" fill="#fff" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M0.666656 4H3.7352L6.20309 0.444336C6.38861 0.166992 6.70068 0 7.03479 0H11.5C11.7762 0 12 0.224609 12 0.5V4.96484C12 5.29883 11.8332 5.61133 11.5553 5.79688L8 8.26465V11.333C8 11.7012 7.70154 12 7.33334 12H5L4 11L5.25 9.75L4.25 8.75L2.99997 10L1.99997 9L3.25 7.75L2.25 6.75L1 8L0 7V4.66699C0 4.29883 0.298462 4 0.666656 4ZM10.5 3C10.5 3.82812 9.82843 4.5 9.00003 4.5C8.1716 4.5 7.50003 3.82812 7.50003 3C7.50003 2.17188 8.1716 1.5 9.00003 1.5C9.82843 1.5 10.5 2.17188 10.5 3Z"
fill="#fff" />
</g>
</svg>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="51.6" y="15.0" fill="#000" fill-opacity="0.3">Longer title</text>
<text x="51.6" y="14.0" fill="#fff">Longer title</text>
<text x="119.5" y="15.0" fill="#000" fill-opacity="0.3">never built</text>
<text x="119.5" y="14.0" fill="#fff">never built</text>
</g>
</svg>
</div>
<div>
<svg width="255.9" height="20.0" xmlns="http://www.w3.org/2000/svg">
<linearGradient id="a" x2="0" y2="100%">
<stop offset="0.0" stop-opacity="0.0" stop-color="#000" />
<stop offset="1.0" stop-opacity="0.2" stop-color="#000" />
</linearGradient>
<clipPath id="c">
<rect width="255.9" height="20.0" rx="3.0" />
</clipPath>
<g clip-path="url(#c)">
<rect width="255.9" height="20.0" fill="#555555" />
<rect width="68.9" height="20.0" fill="#4EC820" x="187.0" />
<rect width="255.9" height="20.0" fill="url(#a)" />
</g>
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg" x="5" y="4">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 9H1V11H3L3 12H0V9Z" fill="#fff" />
<path fill-rule="evenodd" clip-rule="evenodd"
d="M0.666656 4H3.7352L6.20309 0.444336C6.38861 0.166992 6.70068 0 7.03479 0H11.5C11.7762 0 12 0.224609 12 0.5V4.96484C12 5.29883 11.8332 5.61133 11.5553 5.79688L8 8.26465V11.333C8 11.7012 7.70154 12 7.33334 12H5L4 11L5.25 9.75L4.25 8.75L2.99997 10L1.99997 9L3.25 7.75L2.25 6.75L1 8L0 7V4.66699C0 4.29883 0.298462 4 0.666656 4ZM10.5 3C10.5 3.82812 9.82843 4.5 9.00003 4.5C8.1716 4.5 7.50003 3.82812 7.50003 3C7.50003 2.17188 8.1716 1.5 9.00003 1.5C9.82843 1.5 10.5 2.17188 10.5 3Z"
fill="#fff" />
</g>
</svg>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="102.5" y="15.0" fill="#000" fill-opacity="0.3">Very very very very long title</text>
<text x="102.5" y="14.0" fill="#fff">Very very very very long title</text>
<text x="220.5" y="15.0" fill="#000" fill-opacity="0.3">succeeded</text>
<text x="220.5" y="14.0" fill="#fff">succeeded</text>
</g>
</svg>
</div>

Badges from Azure are not intended to be displayed alongside other badges in the same context, as they make use of Id's that are not unique.
I am building a C# Razor page app, so I load the SVG's before inserting them in the Razor page.
To solve this issue, I run the SVG through this ReplaceIds method, before passing them to the Razor page:
private static string ReplaceIds(string text)
{
string pattern = " id=\"(\\w)\"";
while (true)
{
var res = Regex.Match(text, pattern, RegexOptions.IgnoreCase);
if (res.Success && res.Groups.Count > 0)
{
var id = res.Groups[1];
Guid g = Guid.NewGuid();
text = Regex.Replace(text, $" id=\"{id}\"", $" id=\"{g}\"");
text = Regex.Replace(text, #$"url\(#{id}\)", $"url(#{g})");
}
else
return text;
}
}

Related

SVG text not horizontally center aligning

I generated a SVG using Adobe XD. They use transform for positioning things but the text in my mini computer screen is not always the same width (it is dynamically generated). I have tried anchored, anything I could find but it still didn't work. This is how it looks with the current code:
Here is the code:
<svg xmlns="http://www.w3.org/2000/svg" width="903.5" height="860.5" viewBox="0 0 1200 1041">
<g transform="translate(-397)">
<g
transform="translate(507 975)"
fill="#fff"
stroke="#707070"
strokeWidth="1"
>
<rect width="907" height="66" rx="33" stroke="none" />
<rect x="0.5" y="0.5" width="906" height="65" rx="32.5" fill="none" />
</g>
<rect width="119" height="395" transform="translate(901 613)" fill="#fff" />
<g
transform="translate(397)"
fill="#232323"
stroke="#fff"
stroke-width="30"
>
<rect width="1127" height="627" rx="103" stroke="none" />
<rect x="15" y="15" width="1097" height="597" rx="88" fill="none" />
</g>
<text
fill="white"
fontSize="96"
fontFamily="Fredoka"
>
{screenText}
</text>
</g>
</svg>
You can use transform/translate, text-anchor and dominant-baseline to place a text in the middle of something.
body {
background: gray;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1041">
<g
transform="translate(600 975)"
fill="#fff"
stroke="#707070"
stroke-width="1">
<rect x="-453.5" width="907" height="66" rx="33" stroke="none" />
<rect x="-454" y="0.5" width="906" height="65" rx="32.5" fill="none" />
</g>
<rect width="119" height="395" transform="translate(545.5 613)" fill="#fff" />
<g transform="translate(50)"
fill="#232323"
stroke="#fff"
stroke-width="30">
<rect width="1127" height="627" rx="103" stroke="none" />
<rect x="15" y="15" width="1097" height="597" rx="88" fill="none" />
</g>
<text
fill="#fff"
font-size="96"
font-family="Fredoka"
transform="translate(600 300)"
text-anchor="middle"
dominant-baseline="middle">
{screenText}
</text>
</svg>
Thanks to Buhan Yu's comment I learned that you need to specify x and y to center align it. I set x="50%" and it worked!

Shifting SVG by fixed number of pixels

The SVG example currently visually looks perfect except I want to achieve the same result without padding.
The padding's purpose is to force the red/blue lines 40px to the right to make space for the axis whilst also stopping it from overflowing on the right side of the graph.
I'm trying to remove the padding, but then I need to find a new way to shift JUST the "lines" 40px to the right without using x="40px" width="calc(100% - 40px)" because this syntax also isn't compatible with Sharp, or older browsers.
Is there any way to remove the padding and shift the lines 40px right whilst also constraining it within the box model of the SVG?
(final note: I don't want to use 'responsive' units in any logic that moves the lines)
JSFiddle of line graph: https://jsfiddle.net/Lefsqo3j/14/
<div style="height:148px;width:300px;overflow:hidden;resize:both">
<svg overflow="visible" style="padding:24px 0px 24px 40px" height="100%" width="100%">
<svg role="img" viewBox="0 0 300 100" preserveAspectRatio="none">
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<line y1="0" y2="100" x1="0" x2="0" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="75" x2="75" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="150" x2="150" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="225" x2="225" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="300" x2="300" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="0" y2="0" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="25" y2="25" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="50" y2="50" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="75" y2="75" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="100" y2="100" stroke-width="0.2" stroke="black"></line>
</svg>
</svg>
<svg x="100%" overflow="visible">
<text text-anchor="end" dy="-8px">
<tspan fill="red"> ⬤</tspan>
Line A<tspan fill="blue"> ⬤</tspan>
Line B
</text>
</svg>
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<path
d="M 0 75 M 0 75 L 75 50 L 150 15 L 225 67 L 300 67 L 300 67"
stroke-width="3"
stroke="red"
fill="transparent"
vector-effect="non-scaling-stroke"
></path>
<path
d="M 0 92 M 0 92 L 75 72 L 150 80 L 225 50 L 300 50 L 300 50"
stroke-width="3"
stroke="blue"
fill="transparent"
></path>
</svg>
<svg overflow="visible">
<text x="0%" text-anchor="end" y="0%">
40
</text>
<text x="0%" text-anchor="end" y="25%">
30
</text>
<text x="0%" text-anchor="end" y="50%">
20
</text>
<text x="0%" text-anchor="end" y="75%">
10
</text>
<text x="0%" text-anchor="end" y="100%">
0
</text>
<g style="transform: translateX(0%);">
<text y="100%" dy="16px">
5
</text>
</g>
<g style="transform: translateX(25%);">
<text y="100%" dy="16px">
10
</text>
</g>
<g style="transform: translateX(50%); ">
<text y="100%" dy="16px">
15
</text>
</g>
<g style="transform: translateX(75%); ">
<text y="100%" dy="16px">
20
</text>
</g>
<g text-anchor="end" style="transform: translateX(100%);">
<text y="100%" dy="16px">
25
</text>
</g>
</svg>
</svg>
</div>
I've modified the SVG and brought the content inside the content box. Dimensions scale uniformly maintaining aspect ratio.
<div style="height:148px;
width:300px;
overflow:hidden;
resize:both;
background-color: wheat;
">
<svg class="chart" overflow="visible">
<style>
.chart {
width: 100%;
height: 100%;
font-size: 14px;
padding-bottom: 24px;
}
/* background color for entire chart */
.chart-background {
fill: rgb(230, 249, 255);
}
/* styling for only the graph part */
.graph {
background-color: transparent;
}
/* grid lines style */
.chart .grid>line {
stroke-width: 0.5;
stroke: green;
}
.legend {
background-color: wheat;
}
.labels {
background-color: transparent !important;
}
.back {
background-color: wheat;
}
</style>
<rect class="chart-background" height="100%" width="100%" />
<svg viewBox="0 0 340 140" x="40" y="24" preserveAspectRatio="none">
<g class="grid">
<line y1="0" y2="100" x1="0" x2="0"></line>
<line y1="0" y2="100" x1="75" x2="75"></line>
<line y1="0" y2="100" x1="150" x2="150"></line>
<line y1="0" y2="100" x1="225" x2="225"></line>
<line y1="0" y2="100" x1="300" x2="300"></line>
<line x1="0" x2="300" y1="0" y2="0"></line>
<line x1="0" x2="300" y1="25" y2="25"></line>
<line x1="0" x2="300" y1="50" y2="50"></line>
<line x1="0" x2="300" y1="75" y2="75"></line>
<line x1="0" x2="300" y1="100" y2="100"></line>
</g>
</svg>
<svg>
<g class="legend">
<text x="100%" text-anchor="end" dy="16">
<tspan fill="red"> ⬤</tspan>Line A<tspan fill="blue"> ⬤</tspan>Line B
</text>
</g>
</svg>
<svg overflow="visible" x="40" y="24" height="70%" width="88%" style="margin-bottom: 24px;">
<g class="labels" style="font-size: 12px;">
<text x="0%" text-anchor="end" y="0%">40</text>
<text x="0%" text-anchor="end" y="25%">30</text>
<text x="0%" text-anchor="end" y="50%">20</text>
<text x="0%" text-anchor="end" y="75%">10</text>
<text x="0%" text-anchor="end" y="100%">0</text>
<text y="100%" dy="16px">5</text>
<text y="100%" dy="16px" x="22%">10</text>
<text y="100%" dy="16px" x="48%">15</text>
<text y="100%" dy="16px" x="74%">20</text>
<text y="100%" dy="16px" dx="-20px" x="100%">25</text>
</g>
</svg>
<svg viewBox="0 0 340 140" x="40" y="24" preserveAspectRatio="none">
<g class="plot">
<path d="M 0 75 M 0 75 L 75 50 L 150 15 L 225 67 L 300 67 L 300 67" stroke-width="3" stroke="red"
fill="transparent" vector-effect="non-scaling-stroke"></path>
<path d="M 0 92 M 0 92 L 75 72 L 150 80 L 225 50 L 300 50 L 300 50" stroke-width="3" stroke="blue"
fill="transparent"></path>
</g>
</svg>
</svg>
</div>
Sharpjs:
const svgBuffer = Buffer.from(svgImage);
const image = await sharp(svgBuffer, {})
.resize({ width: 500, fit: sharp.fit.inside, position: 'centre' })
.toFile('e:/svg-image.png');
Old answer
We can wrap the original svg content in a new <svg> tag. And with custom styles the original svg can be positioned such that overflow will be visible:
const sharp = require('sharp');
async function svgToImage(svgImage) {
try {
const wrapped = `<svg id='wrapper' width="600" height="400">
<style>
#wrapper > svg{
transform: scale(.9) translate(25px, 25px) ;
}
</style>
${svgImage}
</svg>`;
const svgBuffer = Buffer.from(wrapped);
//const image = await sharp(svgBuffer, {}).resize(500).toFile('e:/svg-image.png');
const image = await sharp({
create: {
width: 600,
height: 400,
channels: 4,
background: { r: 220, g: 255, b: 220, alpha: 1 },
},
})
.composite([{ input: svgBuffer, top: 0, left: 0 }])
.png()
.toFile('e:/svg-image.png');
} catch (error) {
console.log(error);
}
}
const svgImage = `
<svg overflow="visible" style="padding:24px 0px 24px 40px">
<svg role="img" viewBox="0 0 300 100" preserveAspectRatio="none">
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<line y1="0" y2="100" x1="0" x2="0" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="75" x2="75" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="150" x2="150" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="225" x2="225" stroke-width="0.2" stroke="black"></line>
<line y1="0" y2="100" x1="300" x2="300" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="0" y2="0" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="25" y2="25" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="50" y2="50" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="75" y2="75" stroke-width="0.2" stroke="black"></line>
<line x1="0" x2="300" y1="100" y2="100" stroke-width="0.2" stroke="black"></line>
</svg>
</svg>
<svg x="100%" overflow="visible">
<text text-anchor="end" dy="-8px">
<tspan fill="red"> ⬤</tspan>
Line A<tspan fill="blue"> ⬤</tspan>
Line B
</text>
</svg>
<svg viewBox="0 0 300 100" preserveAspectRatio="none">
<path
d="M 0 75 M 0 75 L 75 50 L 150 15 L 225 67 L 300 67 L 300 67"
stroke-width="3"
stroke="red"
fill="transparent"
vector-effect="non-scaling-stroke"
></path>
<path
d="M 0 92 M 0 92 L 75 72 L 150 80 L 225 50 L 300 50 L 300 50"
stroke-width="3"
stroke="blue"
fill="transparent"
></path>
</svg>
<svg overflow="visible">
<text x="0%" text-anchor="end" y="0%">40</text>
<text x="0%" text-anchor="end" y="25%">30</text>
<text x="0%" text-anchor="end" y="50%">20</text>
<text x="0%" text-anchor="end" y="75%">10</text>
<text x="0%" text-anchor="end" y="100%">0</text>
<text y="100%" dy="16px">5</text>
<text y="100%" dy="16px" x="25%">10</text>
<text y="100%" dy="16px" x="50%">15</text>
<text y="100%" dy="16px" x="75%">20</text>
<text y="100%" dy="16px" x="100%">25</text>
</svg>
</svg>`;
svgToImage(svgImage);
Output:
On x axis the labels didn't behave because of bug and bug related to transform. So I had to modify the x label tags.

How to draw an arc inside another circle using svg

I am trying to achieve The following image:
How do I achieve this fill?
How do I end my circle at the edge of the outer circle? My attempt to adjust the position of the canvas is not to be working.
<svg width="173" height="172" xmlns="http://www.w3.org/2000/svg">
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="175" width="175" y="-1" x="-1"/>
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse stroke="#000" ry="85" rx="85" id="svg_1" cy="86" cx="86" stroke-width="1.5" fill="#fff"/>
<ellipse stroke="#000" ry="88" rx="88" id="svg_5" cy="88" cx="15" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none"/>
<line stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_3" y2="170" x2="86" y1="2" x1="82" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none"/>
</g>
</svg>
The code above produces the following:
Here's how you should do it, explainatory comments attatched:
<svg width="173" height="172" xmlns="http://www.w3.org/2000/svg">
<defs>
<!-- clip path-->
<clipPath id="clip">
<ellipse id="circle" ry="85" rx="85" cy="86" cx="86" />
</clipPath>
<!-- gradient -->
<linearGradient id="gradient" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#000" />
<stop offset="100%" stop-color="#fff" />
</linearGradient>
</defs>
<g>
<title>background</title>
<rect fill="none" id="canvas_background" height="175" width="175" y="-1" x="-1" />
<g display="none" overflow="visible" y="0" x="0" height="100%" width="100%" id="canvasGrid">
<rect fill="url(#gridpattern)" stroke-width="0" y="0" x="0" height="100%" width="100%" />
</g>
</g>
<g>
<title>Layer 1</title>
<!-- same shape of the #circle in #clip, adding stroke and fill -->
<use xlink:href="#circle" stroke="#000" stroke-width="1.5" fill="#fff" />
<!-- using clip path, same shape of above -->
<ellipse clip-path="url(#clip)" stroke="#000" ry="88" rx="88" id="svg_5" cy="88" cx="15" stroke-width="1.5" fill="url(#gradient)" />
<line clip-path="url(#clip)" stroke="#000" stroke-linecap="null" stroke-linejoin="null" id="svg_3" y2="170" x2="86" y1="2" x1="82" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" fill="none" />
</g>
</svg>
use this, I created this with adobe Illustrator.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="165px"
height="165px" viewBox="0 0 165 165" style="enable-background:new 0 0 165 165;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#000000;stroke-width:1.5;}
.st1{fill:url(#SVGID_1_);stroke:#000000;stroke-width:1.5;}
.st2{fill:none;stroke:#000000;stroke-width:1.5;}
.st3{fill:url(#SVGID_2_);stroke:#000000;stroke-width:1.5;}
</style>
<defs>
</defs>
<path class="st0" d="M164.3,82.5c0,45.1-36.6,81.8-81.8,81.8c-10.8,0-21.2-2.1-30.6-5.9c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7c9.5-3.8,19.8-5.9,30.6-5.9C127.6,0.8,164.3,37.3,164.3,82.5z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="51.875" y1="158.32" x2="51.875" y2="6.68">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#000000"/>
</linearGradient>
<path class="st1" d="M103,82.5c0,20.8-7.7,39.7-20.5,54.1c-8.3,9.4-18.8,16.9-30.6,21.7c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7C63.7,11.5,74.2,19,82.5,28.4C95.3,42.8,103,61.7,103,82.5z"/>
<line class="st2" x1="82.5" y1="0.8" x2="82.5" y2="164.3"/>
</svg>
<!-- Generator: Adobe Illustrator 24.0.1, SVG Export Plug-In -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="165px"
height="165px" viewBox="0 0 165 165" style="enable-background:new 0 0 165 165;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;stroke:#000000;stroke-width:1.5;}
.st1{fill:url(#SVGID_1_);stroke:#000000;stroke-width:1.5;}
.st2{fill:none;stroke:#000000;stroke-width:1.5;}
.st3{fill:url(#SVGID_2_);stroke:#000000;stroke-width:1.5;}
</style>
<defs>
</defs>
<path class="st0" d="M164.3,82.5c0,45.1-36.6,81.8-81.8,81.8c-10.8,0-21.2-2.1-30.6-5.9c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7c9.5-3.8,19.8-5.9,30.6-5.9C127.6,0.8,164.3,37.3,164.3,82.5z"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="51.875" y1="158.32" x2="51.875" y2="6.68">
<stop offset="0" style="stop-color:#FFFFFF"/>
<stop offset="1" style="stop-color:#000000"/>
</linearGradient>
<path class="st1" d="M103,82.5c0,20.8-7.7,39.7-20.5,54.1c-8.3,9.4-18.8,16.9-30.6,21.7c-30-12.1-51.1-41.5-51.1-75.8
S21.9,18.8,51.9,6.7C63.7,11.5,74.2,19,82.5,28.4C95.3,42.8,103,61.7,103,82.5z"/>
<line class="st2" x1="82.5" y1="0.8" x2="82.5" y2="164.3"/>
</svg>

how to pass clear html elements(as text format) to backend(express js)

I need to pass an <svg></svg> element to backend as clear text using angular HTTP.
for example, I have an angular-html page with a <svg> element,
<div>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 540 320">
<defs>
<path id="Triangle" d="M120 20 L 220 193.205 L 20 193.205 Z" stroke="red" fill="url(#radial)"/>
<path id="Maths" d="M250,50C380,50 350,150 480,150" stroke="green" fill="none"/>
<path id="Chemistry" transform="translate(-200,0) scale(1.5)" d="M250,50C380,50 350,150 480,150" stroke="blue" fill="none"/>
<path id="Path" d="M20,240 C40,280 60,280 200,230 A100 100 0 0 1 300,260 L 330,280 Q 400,320 500,200" stroke="orange" fill="none"/>
<linearGradient id="linear" x1="0" x2="1" gradientUnits="objectBoundingBox">
<stop stop-color="green" offset="0"/>
<stop stop-color="red" offset="1"/>
</linearGradient>
<radialGradient id="radial" cx="0.5" cy="0.6667" r="0.6" gradientUnits="objectBoundingBox">
<stop stop-color="orange" offset="0.2"/>
<stop stop-color="yellow" offset="1"/>
</radialGradient>
<pattern id="pattern" width="4" height="4" patternUnits="userSpaceOnUse">
<rect width="4" height="4"/>
<rect width="2" height="2" fill="red"/>
<rect x="2" y="2" width="2" height="2" fill="red"/>
</pattern>
</defs>
<rect x="2%" y="2%" width="96%" height="96%" fill="url(#linear)" fill-opacity="0.3" stroke="orange" stroke-width="2" stroke-dasharray="5 2 2 2 5 5"/>
<use xlink:href="#Triangle"/>
<use xlink:href="#Maths"/>
<use xlink:href="#Chemistry"/>
<use xlink:href="#Path"/>
<text textLength="600px" lengthAdjust="spacingAndGlyphs" fill="url(#pattern)">
<textPath xlink:href="#Triangle" font-size="20" font-family="serif" font-weight="bold" textLength="600px" lengthAdjust="spacingAndGlyphs">Text adjusted around a triangle</textPath>
</text>
<text font-family="sans-serif">
<textPath xlink:href="#Maths" font-size="30" fill="blue" text-anchor="middle" startOffset="50%">Maths x<tspan font-size="20" baseline-shift="super">2</tspan> + y<tspan font-size="20" baseline-shift="super">2</tspan> = z<tspan font-size="20" baseline-shift="super">2</tspan>!</textPath>
<textPath xlink:href="#Chemistry" font-size="30" fill="green" text-anchor="middle" startOffset="50%">Chemistry 2H<tspan font-size="20" baseline-shift="sub">2</tspan> + O<tspan font-size="20" baseline-shift="sub">2</tspan> -> 2H<tspan font-size="20" baseline-shift="sub">2</tspan>O</textPath>
<textPath xlink:href="#Path" font-size="30" fill="purple" dominant-baseline="middle" text-anchor="middle" startOffset="50%">Text centered on a complex path</textPath>
</text>
</svg>
</div>
Is it possible to pass the svg to backend with angular HTTP.
You can use ViewChild for selecting svg element and then by outerHTML access the HTML.
Demo
Set reference to svg in HTML,
<svg #svgElement ...
Get data from reference,
#ViewChild('svgElement', {static: true}) svgElement: ElementRef;
onClick() {
console.log(this.svgElement.nativeElement.outerHTML)
}

Putting an outline on a mask in a SVG

Is it possible to put an outline or something on a mask so that you can actually see where the mask is? I have an element that I'm trying to mask, but I can't actually see if lining up to where it should.
What I'm trying to do is use the endScreen ID as a mask and using the startOrder ID for the object being masked. Right not it's masking it, but not correctly and it would be nice to visibly be able to see the mask where it is in the design.
<svg id="demo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 337.32 386.57">
<style>
.st0 {
fill: #fff
}
.st5 {
fill: #c32034
}
</style>
<defs>
<mask id="button-mask" width="1" height="1">
<path d="M51.24 372.52V52.27c0-15.4 12.6-28 28-28h180.79c15.4 0 28 12.6 28 28v320.25" fill="white" />
</mask>
</defs>
<path id="endScreen" class="st0" d="M51.24 372.52V52.27c0-15.4 12.6-28 28-28h180.79c15.4 0 28 12.6 28 28v320.25" />
<circle id="startScreen" class="st0" cx="167.67" cy="199.37" r="91" />
<path id="base" fill="none" stroke="#c1a88b" stroke-width="4" stroke-linecap="round" stroke-miterlimit="10" d="M6 374.88h326.27" />
<path id="phoneOutline" d="M302.12 372.43V55.31c0-25.15-21.05-45.73-46.78-45.73H82.26c-25.73 0-46.78 20.58-46.78 45.73v317.13" fill="none" stroke="#c1a88b" stroke-width="7.358" stroke-linecap="round" stroke-miterlimit="10" />
<circle id="speakerSmall" cx="204.78" cy="43.04" r="4.4" fill="#c1a88b" />
<path id="speakerLarge" fill="none" stroke="#c1a88b" stroke-width="9" stroke-linecap="round" stroke-miterlimit="10" d="M132.04 43.23h59.45" />
<path id="startOrder" class="st5" d="M236.62 337.2H99.44c-6.6 0-12-5.4-12-12v-20.48c0-6.6 5.4-12 12-12h137.17c6.6 0 12 5.4 12 12v20.48c.01 6.6-5.39 12-11.99 12z" mask="url(#button-mask)" />
<path id="star" class="st5" d="M168.66 91.97l4.94 10.01 11.04 1.6-7.99 7.79 1.89 11.01-9.88-5.2-9.89 5.2 1.89-11.01-7.99-7.79 11.05-1.6z" />
<circle id="endOrder" cx="165.72" cy="313.53" r="36.5" fill="#89bd40" />
<path id="check" fill="none" stroke="#fdfeff" stroke-width="7" stroke-miterlimit="10" d="M147.32 255.76l12.88 11.5 23.93-23.46" />
</svg>
Define the path you want to use for the mask first as a template by itself, without any presentation attribute, and then reference it twice: first, inside the mask with fill="white", and then again with fill="none" stroke="blue" on top off your grafic.
You'll note your path isn't closed, but obviously a fill will create an implicit close between the endpoints, which the stroke doesn't show. An easy solution that changes effectively nothing for your mask is to add a z command at the end of the path definition.
.st0 {
fill: #fff
}
.st5 {
fill: #c32034
}
<svg id="demo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 337.32 386.57">
<defs>
<path id="shape" d="M51.24 372.52V52.27c0-15.4 12.6-28 28-28h180.79c15.4 0 28 12.6 28 28v320.25" fill="white" />
<mask id="button-mask" width="1" height="1">
<use href="#shape" fill="white" />
</mask>
</defs>
<path id="endScreen" class="st0" d="M51.24 372.52V52.27c0-15.4 12.6-28 28-28h180.79c15.4 0 28 12.6 28 28v320.25" />
<circle id="startScreen" class="st0" cx="167.67" cy="199.37" r="91" />
<path id="base" fill="none" stroke="#c1a88b" stroke-width="4" stroke-linecap="round" stroke-miterlimit="10" d="M6 374.88h326.27" />
<path id="phoneOutline" d="M302.12 372.43V55.31c0-25.15-21.05-45.73-46.78-45.73H82.26c-25.73 0-46.78 20.58-46.78 45.73v317.13" fill="none" stroke="#c1a88b" stroke-width="7.358" stroke-linecap="round" stroke-miterlimit="10" />
<circle id="speakerSmall" cx="204.78" cy="43.04" r="4.4" fill="#c1a88b" />
<path id="speakerLarge" fill="none" stroke="#c1a88b" stroke-width="9" stroke-linecap="round" stroke-miterlimit="10" d="M132.04 43.23h59.45" />
<path id="startOrder" class="st5" d="M236.62 337.2H99.44c-6.6 0-12-5.4-12-12v-20.48c0-6.6 5.4-12 12-12h137.17c6.6 0 12 5.4 12 12v20.48c.01 6.6-5.39 12-11.99 12z" mask="url(#button-mask)" />
<path id="star" class="st5" d="M168.66 91.97l4.94 10.01 11.04 1.6-7.99 7.79 1.89 11.01-9.88-5.2-9.89 5.2 1.89-11.01-7.99-7.79 11.05-1.6z" />
<circle id="endOrder" cx="165.72" cy="313.53" r="36.5" fill="#89bd40" />
<path id="check" fill="none" stroke="#fdfeff" stroke-width="7" stroke-miterlimit="10" d="M147.32 255.76l12.88 11.5 23.93-23.46" />
<use href="#shape" fill="none" stroke="blue" />
</svg>
It might be worth noting that this is a solution only fitting for your specific situation. If the mask had a stroke defined, another stroke around that one cannot be shown like that. Effectively, the technique is more fit for a clip-path (that is pure form) than a mask (which is a arbitrary grafical structure).