Why are my SVG marker and gradient defs being overwritten? - svg

The gradient and marker definitions for my SVG appear to get overwritten when my SVG is inside my webpage. There are no other SVGs on the page.
But when I take the SVG out of the page, it looks just fine.
Here is the SVG in this example.
<svg xmlns="http://www.w3.org/2000/svg" height="500" width="800">
<style>
svg .node.species {
stroke: #FFB800;
stroke-width: 3px;
size: 300px;
}
svg .node.reaction {
stroke: #8089F7;
opacity: 0;
stroke-width: 1.5px;
}
svg .link {
stroke: black;
stroke-width: 3px;
}
svg .link.modifier {
stroke-dasharray: 5, 5;
}
svg .node-label {
font-size: 14px;
font-family: Georgia;
font-weight: bolder;
text-anchor: middle;
dominant-baseline: middle;
}
/* svg .node.selected {
stroke: #FF0000;
}
svg .link.selected {
stroke: #FF0000;
}*/
svg marker {
overflow: visible;
}
svg .null-symbol {
fill: none;
stroke: black;
stroke-width: 3px;
}
</style>
<defs>
<linearGradient id="gradient">
<stop offset="5%" stop-color="#FFDC9E"></stop>
<stop offset="95%" stop-color="#FFF"></stop>
</linearGradient>
<linearGradient id="markerGradient">
<stop offset="5%" stop-color="rgb(97, 116, 255)"></stop>
<stop offset="95%" stop-color="#FFF"></stop>
</linearGradient>
<linearGradient id="reactionGradient">
<stop offset="5%" stop-color="#B0C0FF"></stop>
<stop offset="95%" stop-color="#FFF"></stop>
</linearGradient>
<marker case-sensitive="refX,refY" id="production" viewBox="0 0 10 10" markerWidth="10" markerHeight="10" orient="auto" refx="-2" refy="0" refX="-2" refY="0">
<path fill="url(#markerGradient)" stroke="#0013FF" transform="rotate(-90)" d="M0,2.0808957251439084L2.4028114141347543,-2.0808957251439084 -2.4028114141347543,-2.0808957251439084Z"></path>
</marker>
<marker case-sensitive="refX,refY" id="degradation" viewBox="0 0 10 10" markerWidth="10" markerHeight="10" orient="auto" refx="-2" refy="0" refX="-2" refY="0">
<path fill="url(#markerGradient)" stroke="#0013FF" transform="rotate(-90)" d="M0,2.0808957251439084L2.4028114141347543,-2.0808957251439084 -2.4028114141347543,-2.0808957251439084Z"></path>
</marker>
<marker case-sensitive="refX,refY" id="modifier" viewBox="0 0 10 10" markerWidth="30" markerHeight="30" orient="auto" refx="-0.4" refy="0" refX="-0.4" refY="0">
<path stroke="black" stroke-width="0.3" fill="none" d="M0,0.5641895835477563A0.5641895835477563,0.5641895835477563 0 1,1 0,-0.5641895835477563A0.5641895835477563,0.5641895835477563 0 1,1 0,0.5641895835477563Z"></path>
</marker>
</defs>
<g transform="translate(, )scale(1)">
<g>
<line class="reaction production link" marker-end="url(#production)" x1="449.9996697164325" y1="218.45791860388687" x2="451.42692033038736" y2="246.7481154723436">
</line><line class="reaction production link" marker-end="url(#production)" x1="399.21583821133174" y1="309.0153067725509" x2="345.33989421522693" y2="338.2824980727582">
</line>
</g>
<g>
<line class="reaction reactant link" x1="446.9075572254284" y1="157.1677217354301" x2="449.9996697164325" y2="218.45791860388687">
</line><line class="reaction reactant link" x1="453.0917822074366" y1="279.7481154723436" x2="399.21583821133174" y2="309.0153067725509">
</line>
</g>
<g>
</g>
<g draggable="" transform="translate(446.9075572254284,157.1677217354301)" style="position: relative; border: 1px solid red; background-color: rgb(211, 211, 211); cursor: pointer;">
<rect class="species node" fill="url(#gradient)" x="-50" y="-15" width="100" height="30" ry="15">
<title>ID: S1, Name: S1</title>
</rect>
<text class="node-label">S1</text>
</g><g draggable="" transform="translate(453.0917822074366,279.7481154723436)" style="position: relative; border: 1px solid red; background-color: rgb(211, 211, 211); cursor: pointer;">
<rect class="species node" fill="url(#gradient)" x="-50" y="-15" width="100" height="30" ry="15">
<title>ID: S2, Name: S2</title>
</rect>
<text class="node-label">S2</text>
</g><g draggable="" transform="translate(345.33989421522693,338.2824980727582)" style="position: relative; border: 1px solid red; background-color: rgb(211, 211, 211); cursor: pointer;">
<rect class="species node" fill="url(#gradient)" x="-50" y="-15" width="100" height="30" ry="15">
<title>ID: S3, Name: S3</title>
</rect>
<text class="node-label">S3</text>
</g>
<g draggable="" transform="translate(473.4770117242872,216.74146493626216)" style="position: relative; border: 1px solid red; background-color: rgb(211, 211, 211); cursor: pointer;">
<circle class="node reaction" fill="url(#reactionGradient)" r="5">
<title>ID: reaction1, Name: reaction1</title>
</circle>
<text class="node-label"></text>
</g><g draggable="" transform="translate(409.9633485910613,329.9478703486097)" style="position: relative; border: 1px solid red; background-color: rgb(211, 211, 211); cursor: pointer;">
<circle class="node reaction" fill="url(#reactionGradient)" r="5">
<title>ID: reaction2, Name: reaction2</title>
</circle>
<text class="node-label"></text>
</g>
</g>
</svg>
EDIT 1
Here is the style of the linearGradient element
EDIT 2
Style of the defs element
EDIT 3
I found that when I remove the head tag, and then reapply it, the SVG is then correctly rendered. Weird.

Turns out I had <base href="/"> in head which was messing things up.

Related

Reusing SVG elements while inserting different text?

I want to display balls with 1,2,3,4 inside. Can I use <use>? or I must duplicate the stone <g>?
#stone text {
fill: grey;
dominant-baseline: middle;
text-anchor: middle;
font-size: 0.33pt;
}
#pane {
background-color: yellow;
width: 100%;
height: 100%;
}
.stone-white {
fill: #F2F4F4;
}
.stone-black {
fill: #273746;
}
<svg id="pane" viewBox="0 0 22 22" preserveAspectRatio="none">
<defs>
<g id="stone">
<circle cx="0" cy="0" r="0.45" />
<text>333</text>
</g>
</defs>
<use href="#stone" class="stone-white" x="1" y="1"/>
<use href="#stone" class="stone-white" x="2" y="2"/>
<use href="#stone" class="stone-black" x="3" y="2"/>
<use href="#stone" class="stone-black" x="2" y="4"/>
</svg>

css rotate introduces outline when using SVG clip-path or mask

Is there a way to stop this outline in firefox?
#blob { background: red; width: 500px; height: 500px; clip-path: url(#myClip); transform: rotate(20deg);}
<div id="blob"></div>
<svg>
<defs>
<path d="M320.403196,424.677624 C426.787532,365.585154 447.310044,306.188587 433.45394,197.28033 C419.597836,88.3720737 316.997962,53.8862578 227.347416,40.9086547 C144.650118,28.9375873 104.472702,88.6407456 69.862267,131.812053 C15.52584,199.588564 48.3439099,300.905451 80.8563197,361.757908 C110.80391,417.809872 214.018859,483.770094 320.403196,424.677624 Z" id="path-1"></path>
<clipPath id="myClip"><use href="#path-1"></use></clipPath>
</defs>
</svg>
This renders correctly in other browsers, just need some work around for this firefox bug
same outline appears using either clip-path or mask
As a workaround you could rotate the clipPath instead:
#blob {
background: red;
width: 500px;
height: 500px;
clip-path: url(#myClip);
}
<div id="blob"></div>
<svg viewBox="0 0 397 409">
<defs>
<path d="M320.403196,424.677624 C426.787532,365.585154 447.310044,306.188587 433.45394,197.28033 C419.597836,88.3720737 316.997962,53.8862578 227.347416,40.9086547 C144.650118,28.9375873 104.472702,88.6407456 69.862267,131.812053 C15.52584,199.588564 48.3439099,300.905451 80.8563197,361.757908 C110.80391,417.809872 214.018859,483.770094 320.403196,424.677624 Z" id="path-1" />
<clipPath id="myClip" transform="rotate(20)" transform-origin="center">
<use href="#path-1"></use>
</clipPath>
</defs>
</svg>

Drawing parallel connections on SVG

I need to generate multiple parallel connections from an original one, as shown in code:
Code:
<svg width="800" height="800">
<!-- one filter -->
<g transform="translate(50,50)">
<text y="50">Original</text>
<path d="m 0,0L0,100 L100,100 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
</g>
<g transform="translate(250,50)">
<text y="50">Generated</text>
<path d="m 0,0L0,100 L100,100 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
<path d="m 10,0L10,90 L100,90 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
<path d="m 20,0L20,80 L100,80 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
</g>
<g transform="translate(50,250)">
<text y="50">Original</text>
<path d="m 0,0L10,90 L100,70 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
</g>
<g transform="translate(250,250)">
<text y="50">Generated</text>
<path d="m 0,0L10,90 L100,70 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
<path d="m 10,0L20,80 L100,60 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
</g>
</svg>
https://codepen.io/anon/pen/wyObNr
Is there any easy way to do it? Something like cloning and just making it fit along the original one would be perf
regards
Svg provides the means for reuse of partial drawings with the defs element. It may contain groups (g element) that contain an arbitrarily complex scene. These may be referenced thereafter with the use element which effectively produces a clone which can then be subjected to transformations (an arbitrary mix of rotations, scalings, translations).
What follows is a reformulation of your sample scene:
<svg
width="800" height="800"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<g id="angle">
<path d="m 0,0L0,100 L100,100 " style="fill: none; stroke-width: 2px; stroke: blueviolet; stroke-linejoin: round; marker-end: url("#sequenceflow-end-white-black-0ctpawyb4xrqoyjc7rrbh92fl");"></path>
</g>
<g id="multi">
<use xlink:href="#angle" />
<use xlink:href="#angle" transform="translate(10,-10)"/>
<use xlink:href="#angle" transform="translate(20,-20)"/>
</g>
</defs>
<!-- base case -->
<g transform="translate(50,50)">
<text x="50" y="50">Original</text>
<use xlink:href="#angle"/>
</g>
<g transform="translate(50,50) translate(200,0)">
<text x="50" y="50">Generated</text>
<use xlink:href="#multi" />
</g>
<!-- rotated -->
<g transform="translate(50,50) translate(0,200)">
<text x="50" y="50">Original</text>
<g transform="rotate(-20)">
<use xlink:href="#angle"/>
</g>
</g>
<g transform="translate(50,50) translate(200,200)">
<text x="75" y="25">Generated</text>
<g transform="rotate(-20)">
<use xlink:href="#multi"/>
</g>
</g>
</svg>

Issue when zooming in on SVG donut chart in Safari

I'm attempting to create a donut chart using SVG, and am running into a problem when viewing it in Safari. Here's a fiddle that shows the issue; I'll describe it in detail below:
https://jsfiddle.net/nijhazer/phy2ossh/
This fiddle shows a graphic comprised of two circles overlaid atop one another. The problem becomes apparent when a Safari user increases zoom size in her browser:
Relevant HTML from the example:
<div class="donut-chart">
<svg width="200" height="200">
<circle class="backdrop" cx="100" cy="100" r="65" fill="#d5d8d5" stroke="none" stroke-width="0"></circle>
<circle class="progress" cx="100" cy="100" r="75" fill="none" stroke="lightgreen" stroke-width="20" style="stroke-dashoffset: 353.428875px;"></circle>
<circle class="outer-ring" cx="100" cy="100" r="85" fill="none" stroke="#d5d8d5" stroke-width="1"></circle>
</svg>
</div>
Relevant CSS from the example:
body {
background-color: white;
}
.donut-chart {
width: 200px;
height: 200px;
position: relative;
}
svg {
width: 200px;
height: 200px;
}
.progress {
stroke-dasharray: 471.24;
transform: rotate(-90deg);
transform-origin: 50% 50%;
background-color: transparent;
}
I don't know if this helps, but at I can read from the comments that people are blaming the CSS property transform-origin. In this example I moved the styling to attributes on the circle element. I also added pathLength to make it easier to control the progress bar.
body {
background-color: white;
}
.donut-chart {
width: 200px;
height: 200px;
position: relative;
}
svg {
width: 200px;
height: 200px;
}
<div class="donut-chart">
<svg viewBox="0 0 200 200" xmlns="http//www.w3.org/2000/svg">
<circle class="backdrop" cx="100" cy="100" r="65" fill="#d5d8d5"
stroke="none" stroke-width="0" />
<circle class="progress" cx="100" cy="100" r="75" fill="none"
stroke="lightgreen" stroke-width="20" stroke-dasharray="25 100"
transform="rotate(-90 100 100)" pathLength="100" />
<circle class="outer-ring" cx="100" cy="100" r="85" fill="none"
stroke="#d5d8d5" stroke-width="1" />
</svg>
</div>
I can confirm chrwahl's approach is working (at least in MacOS/IOS safari versions (15.4) I've tested - Unfortunately, the support of functions may vary from version to version)
Another workaround could be to add a translateX offset before rotating like so:
.donut-chart {
width: 200px;
height: 200px;
position: relative;
display: block;
}
svg {
width: 200px;
height: 200px;
}
.progress {
stroke-dasharray: 471.24;
background-color: transparent;
transform: translate(0px, 200px) rotate(-90deg);
}
<div class="donut-chart">
<svg width="200" height="200" viewBox="0 0 200 200">
<circle class="backdrop" cx="50%" cy="50%" r="65" fill="#d5d8d5" stroke="none" stroke-width="0"></circle>
<circle class="progress" cx="50%" cy="50%" r="75" fill="none" stroke="lightgreen" stroke-width="20" style="stroke-dashoffset: 353.428875px;"></circle>
<circle class="outer-ring" cx="100" cy="100" r="85" fill="none" stroke="#d5d8d5" stroke-width="1"></circle>
</svg>
</div>
This "hack" won't work combined with transform-origin: 50% 50%

Why SVG's stroke width is different from border width?

Why <svg>'s 1px stroke-width is wider than <div>'s 1px border-width?
Is it possible to create an <svg> that looks exactly like the <div>below?
<svg>
<rect x="10" y="10" width="100" height="100" stroke-width="1" stroke="red" fill="white" />
</svg>
<div style="margin: 0 0 10px 10px; width: 100px; height: 100px; border: 1px solid red">
</div>
That's just antialiasing. You can turn it off if you want via the shape-rendering CSS property. Adjusting the co-ordinates by 0.5px may also work.
<svg>
<rect x="10" y="10" width="100" height="100" stroke-width="1" stroke="red" fill="white" shape-rendering="crispEdges" />
</svg>
<div style="margin: 0 0 10px 10px; width: 100px; height: 100px; border: 1px solid red">
</div>

Resources