I'm trying to draw a rectangle as four lines. The problem is that the top and left lines appear to be thinner and there is a missing pixel at the right bottom corner (See Screenshot).
HTML svg element :
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="500" height="500" style="
padding: 20px;
box-sizing: border-box;
">
<line x1="0" y1="0" x2="20" y2="0" class="line"></line>
<line x1="20" y1="0" x2="20" y2="20" class="line"></line>
<line x1="20" y1="20" x2="0" y2="20" class="line"></line>
<line x1="0" y1="20" x2="0" y2="0" class="line"></line></svg>
</svg>
rendered result in the browser :
[
Only the stroke of a line is visible and it extends equally each side of it. So if you draw a single line from 0, 0 to 100, 0 and the line has width 2 then that line will actually occupy a rectangle with corners (-1, -1), (101, -1), (101, 1), (-1, 1).
So your rectangle's lines are partially outside the drawing canvas and those parts that are outside are not visible.
Also if you want to draw a square you'll need to draw some of the lines longer so that you get a square effect at the corners. Alternatively use a <path> and it will handle the corners without you having to worry about it.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="500" height="500" viewBox="0 0 40 40" style="
padding: 20px;
box-sizing: border-box;
">
<path d="M0,0 20,0 20,20 0,20Z" fill="none" stroke="black" transform="translate(1,1)" />
</svg>
or you could just move the canvas e.g.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="500" height="500" viewBox="-2 -2 40 40" style="
padding: 20px;
box-sizing: border-box;
">
<path d="M0,0 20,0 20,20 0,20Z" fill="none" stroke="black" />
</svg>
Or, in the shortest possible form:
<svg width="250" height="250" viewBox="-1 -1 22 22">
<path d="M0,0H20V20H0z" fill="none" stroke="black"/>
</svg>
I've re-written your SVG with a few small changes and it seems to be working fine.
There are four main changes:
<line /> is a self-closing element.
I have explicitly given each line a stroke-width of 1
Wherever you have used a co-ordinate of 0, I have used 1
I have given each line a stroke-linecap of square
I have also reduced the viewBox to 100 x 100 so you can see the square much larger.
Working Example:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 100 100">
<defs>
<style type="text/css"><![CDATA[
svg {
background-color: rgb(255, 0, 0);
padding: 20px;
box-sizing: border-box;
}
.line {
stroke: rgb(255, 255, 255);
stroke-width: 1;
stroke-linecap: square;
}
]]></style>
</defs>
<line x1="1" y1="1" x2="21" y2="1" class="line" />
<line x1="21" y1="1" x2="21" y2="21" class="line" />
<line x1="21" y1="21" x2="1" y2="21" class="line" />
<line x1="1" y1="21" x2="1" y2="1" class="line" />
</svg>
I want to change the fill (onclick) of all elements in a group from a svg file. At the moment, I use javascript to set an attribute to an id. This seems to only change one of the elements.
I have tried inline of svg using onclick. it didnĀ“t seem to work. So i started with javascript. Now, it fills only one trianlge, whilst I set the function to call from the group.
function callred(){
document.getElementById('btn1').setAttribute('fill', '#ff00ff');
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
I expect all elements in the group to change to another color when clicked on any element of the group and for them to stay this color.
This works
function callred() {
[...document.getElementById('btn1').querySelectorAll('*')].forEach((e) => {
e.setAttribute('fill', '#ff00ff');
});
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
not sure it's a good answer
You can also use CSS
function callred() {
document.getElementById('btn1').classList.toggle("forcecolor");
}
.forcecolor * {
fill: blue;
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
Whilst what you are doing is correct, you are trying to apply a fill to the group and not the elements within it - simply looping through the elements within the clicked svg will allow you to fill them all the same colour. I used a for loop for browser support.
Also worth noting that after the click it won't show until after you've moved your mouse off the element, because despite you setting a fill there is still a hover property set in your css.
function callred(){
const children = document.getElementById('btn1').children;
for(let i = 0; i < children.length; i++ ){
children[i].setAttribute('fill','#ff00ff');
}
}
g:hover > polygon{
fill: yellow;
}
b:hover > polygon{
fill: yellow;
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
Use document.getElementsByTagName('polygon') to get all the polygons and then loop over them, setting the fill of each one:
function callred(){
var els = document.getElementsByTagName('polygon')
for (var i=0; i < els.length; i++) {
els[i].setAttribute('fill', '#ff00ff');
}
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
Personally I'd probably just toggle a css class to hit the children;
function callred(){
document.getElementById("btn1").classList.toggle("new-style");
}
#svg-object{
height: 100vh;
width: 100%;
background-size: cover;
background-position: center center;
border: 15px antiquewhite;
position: absolute;
}
.new-style polygon {
fill: red!important;
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg id="svg-object" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="800px" height="754px" viewBox="0 0 800 754" enable-background="new 0 0 800 754" xml:space="preserve">
<g id="btn1" onclick="callred()">
<polygon fill="#FF0013" points="366.699,131 410,56 453.301,131 "/>
<polygon fill="#07FF00" points="323.699,656 367,581 410.301,656 "/>
<polygon fill="#0000FF" points="409.699,656 453,581 496.301,656 "/>
<polygon points="366.699,581 410,656 453.301,581 "/>
</g>
</svg>
In HTML with SVG you can create a rect with fading color:
<svg>
<rect width="100%" height="100%">
<animate attributeName="fill" values="red;blue;red" dur="10s" repeatCount="indefinite" />
</rect>
</svg>
Now in my code I have a path like that:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="247pt" height="543pt" viewBox="0.00 0.00 246.86 543.19">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 539.1859)">
<!-- c->e -->
<g id="a1124" class="edge">
<title>c->e</title>
<path fill="none" stroke="#ff0000" stroke-width="3" d="M208.109,-297.8625C205.1217,-279.2357 200.2512,-248.8658 195.5911,-219.8076" />
<polygon fill="#ff0000" stroke="#ff0000" stroke-width="3" points="198.9943,-218.9251 193.9549,-209.6055 192.0827,-220.0336 198.9943,-218.9251" />
</g>
</g>
</svg>
I am looking for a way to fade the color of the path along the path so that it illustrates some kind of data flow. Is there a way to accomplish that? (via CSS or Javascript).
Try this
#keyframes fade {
0% {
stroke: red;
fill: red;
}
50% {
stroke: blue;
fill: blue;
}
100% {
stroke: red;
fill: red;
}
}
#fade {
animation-name: fade;
animation-duration: 10s;
animation-iteration-count: infinite;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="247pt" height="543pt" viewBox="0.00 0.00 246.86 543.19">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 539.1859)">
<!-- c->e -->
<g id="a1124" class="edge">
<title>c->e</title>
<path id="fade" stroke="#ff0000" stroke-width="3" d="M208.109,-297.8625C205.1217,-279.2357 200.2512,-248.8658 195.5911,-219.8076" />
<polygon id="fade" stroke-width="3" points="198.9943,-218.9251 193.9549,-209.6055 192.0827,-220.0336 198.9943,-218.9251" />
</g>
</g>
</svg>
I am trying to get a scaled svg image to clip the pattern if it goes out side the blue container. But when I apply the clip path to the pattern for the exact same position. The pattern's X and Y position change and it ends up outside the container in the case shown below for the exact same positions and transformations applied. I also applied a feMorphology filter to show where the clipped path is being drawn.
SVG (Non clipped)
XML
<svg id="SvgjsSvg1006" width="550" height="650" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1007">
<clipPath id="SvgjsClipPath1019">
<rect id="SvgjsRect1016" width="315" height="600" x="120" y="27"></rect>
</clipPath>
<filter id="dilate_shape">
<feMorphology operator="dilate" in="SourceGraphic" radius="5" />
</filter>
</defs><!--?xml version="1.0" encoding="UTF-8" standalone="no" ?-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="550" height="650" viewBox="0 0 550 650" xml:space="preserve">
<g >
<g filter="url("#dilate_shape")">
<rect width="315" height="600" x="120" y="27" fill="blue" fill-opacity="0.2" clip-path="url("#SvgjsClipPath1019")"></rect>
</g>
<image xlink:href="https://www.dropbox.com/pri/get/697%20%5BConverted%5D.svg?_subject_uid=360738345&raw=1&size=1280x960&size_mode=3&w=AADJZ7-5-jq5Qyh2urbHo_G1FCn0ADHB-Li1KOFGuAEEQQ" transform="translate(278.34 410.34) scale(1.66 1.66)" x="-75" y="-75" style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" width="150" height="150" ></image>
</g>
</svg>
SVG (Clipped)
XML
<svg id="SvgjsSvg1006" width="550" height="650" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs">
<defs id="SvgjsDefs1007">
<clipPath id="SvgjsClipPath1019">
<rect id="SvgjsRect1016" width="315" height="600" x="120" y="27"></rect>
</clipPath>
<filter id="dilate_shape">
<feMorphology operator="dilate" in="SourceGraphic" radius="5" />
</filter>
</defs><!--?xml version="1.0" encoding="UTF-8" standalone="no" ?-->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="550" height="650" viewBox="0 0 550 650" xml:space="preserve">
<g >
<g filter="url("#dilate_shape")">
<rect width="315" height="600" x="120" y="27" fill="blue" fill-opacity="0.2" clip-path="url("#SvgjsClipPath1019")"></rect>
</g>
<image xlink:href="https://www.dropbox.com/pri/get/697%20%5BConverted%5D.svg?_subject_uid=360738345&raw=1&size=1280x960&size_mode=3&w=AADJZ7-5-jq5Qyh2urbHo_G1FCn0ADHB-Li1KOFGuAEEQQ" transform="translate(278.34 410.34) scale(1.66 1.66)" x="-75" y="-75" style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: rgb(0,0,0); fill-rule: nonzero; opacity: 1;" width="150" height="150" clip-path="url("#SvgjsClipPath1019")"></image>
</g>
</svg>
With the only difference being is that I added clip-path="url("#SvgjsClipPath1019")" to the image tag of the second svg
The error lies in the order in which the transform and clip-path attributes are applied. transform is always the last operation, and the clip-path is applied to the non-transformed element.
This snippet
<image xlink:href="..." x="-75" y="-75"
transform="translate(278.34 410.34) scale(1.66 1.66)"
clip-path="url(#SvgjsClipPath1019)" />
is equivalent to
<g transform="translate(278.34 410.34) scale(1.66 1.66)">
<image xlink:href="..." x="-75" y="-75"
clip-path="url(#SvgjsClipPath1019)" />
</g>
while you wanted to achieve this:
<g clip-path="url(#SvgjsClipPath1019)">
<image xlink:href="..." x="-75" y="-75"
transform="translate(278.34 410.34) scale(1.66 1.66)"> />
</g>
I have this svg, but I can't zoom in and zoom out using this. I found svg-pan-zoom.js file and tried in it. Still not working.
<svg id="no.1" viewBox="0 0 2500 2500" transform="translate(100 100)">
<svg viewBox="0 0 2500 2500" id="raptor" style="position:absolute; top: 40px; left: 40px;">
<rect id="rapt" x="50" y="60" rx="20" ry="20" width="90" height="140" style="fill:#FFB3B3;stroke:black;stroke-width:5;">
</rect>
</rect>
</svg>