SVG lines not rendering properly - javascript
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>
Related
Reverse radialGradient SVG animation on mouseout on hovered element
I want the radialGradient animation to apply to the single hexagon only that you are hovering over and then onmouseout I want the animation to reverse. How can I make the radialGradient trigger on the hexagon you hover on only (not all the hexagons) and then reverse the animation on mouseout/mouseleave? Thank you. I tried adding { fill: url(#myRadialGradient4);} to .filter-class But obviously as soon as mouseout happens the class is removed stopping the smooth reverse animation on mouseout. I have tried this: https://codepen.io/daneli84/pen/OJVZmeJ // var flagBlur = document.querySelector('.flag-blur'); var flags = document.querySelectorAll('.flag'); // function startPage() { flags.forEach(flag => { flag.onmouseover = function() { flag.classList.add('filter-class') TweenMax.fromTo(flagBlur, 19, { attr: { stdDeviation: 0.5 } }, { attr: { stdDeviation: 1 }, ease: Power1.easeInOut }); } flag.onmouseleave = function() { flag.classList.remove('filter-class') } }) } startPage(); /* grid styling */ use {-webkit-transition: 5s; -webkit-transition: all 5s ease; transition: all 5s ease; } use:hover { cursor: pointer; } g { fill: url(#myRadialGradient4);} #pod { -webkit-transition: all 5s ease; transition: all 5s ease;} text{pointer-events:none;color:white!important;} .filter-class { filter: url(#filter-1); } /* other styling */ svg { width: 800px!important; flex: 1; } body { display: flex; justify-content: center; align-items: center; flex-direction: column; margin: 0; height: 100vh; font-weight: 700; font-family: sans-serif; } <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <svg viewBox="0 0 100 100"> <defs> <radialGradient id="myRadialGradient4" fx="15%" fy="5%" r="65%" spreadMethod="pad"> <stop offset="0%" stop-color="#fff" ></stop> <stop offset="100%" stop-color="#50287C" ></stop> <animate attributeName="fy" dur="2s" from="90%" to="0%" begin="pod.mouseover" end="pod.mouseout;indefinite" fill="freeze"/> <animate attributeName="fy" dur="2s" from="0%" to="90%" begin="pod.mouseout" end="pod.mousover;indefinite" fill="freeze"/> </radialGradient> <filter id="innershadow" x0="20%" y0="5%" width="200%" height="200%"> <feGaussianBlur in="SourceAlpha" stdDeviation="1" result="blur"></feGaussianBlur> <feOffset dy="0.2" dx="-0.1"></feOffset> <feComposite in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowDiff"></feComposite> <feFlood flood-color="#E5E5C5" flood-opacity="-15"></feFlood> <feComposite in2="shadowDiff" operator="in"></feComposite> <feComposite in2="SourceGraphic" operator="over" result="firstfilter"></feComposite> <feGaussianBlur in="firstfilter" stdDeviation="0.9" result="blur2"></feGaussianBlur> <feOffset dy="0.1" dx="0.1"></feOffset> <feComposite in2="firstfilter" operator="arithmetic" k2="-1" k3="1" result="shadowDiff"></feComposite> <feFlood flood-color="#fff" flood-opacity="0.5"></feFlood> <feComposite in2="shadowDiff" operator="in"></feComposite> <feComposite in2="firstfilter" operator="over"></feComposite> </filter> </linearGradient> <linearGradient id="grad2" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color:rgb(20,0,12);stop-opacity:1;" /> <stop offset="100%" style="stop-color:rgb(8,20,128);stop-opacity:1" /> </linearGradient> <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="filter-1"> <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> <feGaussianBlur stdDeviation="1" class="flag-blur" in="shadowOffsetOuter1" result="shadowBlurOuter1"> </feGaussianBlur> <feColorMatrix values="200 150 255 0 0 255 255 200 0 0 255 0 0 0 0 0 0 0 1 0" in="shadowBlurOuter1" type="matrix" result="shadowMatrixOuter1"></feColorMatrix> <feMerge> <feMergeNode in="shadowMatrixOuter1"></feMergeNode> <feMergeNode in="SourceGraphic"></feMergeNode> </feMerge> </filter> <g id="pod"> <polygon stroke="#000000" stroke-width="0.1" points="5,-9 -5,-9 -10,0 -5,9 5,9 10,0" /> </g> <!-- a transparent grey drop-shadow that blends with the background colour --> </defs> <g class="pod-wrap"> <g transform="translate(65, 68)" filter="url(#innershadow)"> <use xlink:href="#pod" class="h1 flag"> </use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="2.3" fill="white">TRANSPORT</text> </g> <g transform="translate(50, 41)" filter="url(#innershadow)"> <use xlink:href="#pod" class="h1 flag"> </use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(35, 50)" filter="url(#innershadow)" > <use xlink:href="#pod" class="h1 flag"> </use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(65, 50)" filter="url(#innershadow)"> <use xlink:href="#pod" class="h1 flag"> </use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(50, 59)" filter="url(#innershadow)"> <use xlink:href="#pod" class="h1 flag"> </use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> </g> </svg>
The radial gradient you are animating would need to be a separate one from the one you are using for the rest of the hexagons. On hover you would switch to the alternate gradient and start the <animation> by calling beginElement() on it. You might also need a third <animation> for the reverse animation. But that approach is complicated, and I don't think it would produce a very satisfactory result. A different approach I would recommend a different approach. Make the background of each hexagon a rectangle that has the gradient applied to it then animate that background on hover use a hexagon shaped clipping path on that rect You can do that with pure CSS. And it is a lot simpler. Note: in the example below I've stripped out the filter to make things simpler to follow for this example. .pod-bg { -webkit-transition: 5s; -webkit-transition: all 5s ease; transition: all 5s ease; } .pod-bg:hover { transform: translate(0, -16px); } .h1.flag { fill: url(#myRadialGradient4); } .pod-stroke { stroke: #000000; stroke-width: 0.1; fill: none; pointer-events: none; cursor: pointer; } text { pointer-events: none; color: white; } /* other styling */ svg { width: 800px!important; flex: 1; } body { display: flex; justify-content: center; align-items: center; flex-direction: column; margin: 0; height: 100vh; font-weight: 700; font-family: sans-serif; } <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.6/gsap.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <svg viewBox="0 0 100 100"> <defs> <radialGradient id="myRadialGradient4h" fx="15%" fy="45%" r="65%" spreadMethod="pad"> <stop offset="0%" stop-color="#fff" ></stop> <stop offset="100%" stop-color="#50287C" ></stop> </radialGradient> <polygon id="pod" points="5,-9 -5,-9 -10,0 -5,9 5,9 10,0" /> <!-- a rect the same width and double the height of a pod hexagon --> <rect id="bg-rect" x="-10" y="-9" width="20" height="36" fill="url(#myRadialGradient4h)"/> <!-- a clipping path version of the pod hexagon --> <clipPath id="pod-clip"> <use xlink:href="#pod"></use> </clipPath> </defs> <g class="pod-wrap"> <g transform="translate(65, 68)"> <g clip-path="url(#pod-clip)"> <use xlink:href="#bg-rect" class="pod-bg"/> </g> <use xlink:href="#pod" class="pod-stroke"></use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="2.3" fill="white">TRANSPORT</text> </g> <g transform="translate(50, 41)"> <g clip-path="url(#pod-clip)"> <use xlink:href="#bg-rect" class="pod-bg"/> </g> <use xlink:href="#pod" class="pod-stroke"></use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(35, 50)"> <g clip-path="url(#pod-clip)"> <use xlink:href="#bg-rect" class="pod-bg"/> </g> <use xlink:href="#pod" class="pod-stroke"></use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(65, 50)"> <g clip-path="url(#pod-clip)"> <use xlink:href="#bg-rect" class="pod-bg"/> </g> <use xlink:href="#pod" class="pod-stroke"></use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> <g transform="translate(50, 59)"> <g clip-path="url(#pod-clip)"> <use xlink:href="#bg-rect" class="pod-bg"/> </g> <use xlink:href="#pod" class="pod-stroke"></use> <text class="h1" alignment-baseline="middle" text-anchor="middle" font-family="Verdana" font-size="5" fill="white">CNI</text> </g> </g> </svg>
Svg clipPath location
For the following image, I am trying to clip out everything that not located in the black box shown. But I perform the clipPath operation and feMorphology filter to show where the clipped box is being drawn. The clip path is not shown in the right position. This is the generated svg 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="SvgjsClipPath1017"> <rect id="SvgjsRect1014" width="315" height="600" x="120" y="27"></rect> </clipPath> <filter id="dilate_shape"> <feMorphology operator="dilate" in="SourceGraphic" radius="5" /> </filter> </defs> <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 transform="translate(285 325)"> <g filter="url("#dilate_shape")"> <rect x="-325" y="-325" height="650" width="650" fill="lightgreen" clip-path="url("#SvgjsClipPath1017")"></rect> </g> <image xlink:href="https://i.imgur.com/xOOB2O4.png" x="-325" y="-325" 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="650" height="650" clip-path="url("#SvgjsClipPath1017")"></image> </g> </svg> I can fix this if I remove the translate transform and add it's values into the x and y values of the child image tag. As shown in the following With the XML being <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="SvgjsClipPath1017"> <rect id="SvgjsRect1014" width="315" height="600" x="120" y="27"></rect> </clipPath> <filter id="dilate_shape"> <feMorphology operator="dilate" in="SourceGraphic" radius="5" /> </filter> </defs> <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 x="-40" y="0" height="650" width="650" fill="lightgreen" clip-path="url("#SvgjsClipPath1017")"></rect> </g> <image xlink:href="https://i.imgur.com/xOOB2O4.png" x="-40" y="0" 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="650" height="650" clip-path="url("#SvgjsClipPath1017")"></image> </g> </svg> So how to I fix this without having to add the transform values into the X and Y positions. One thing to note is that I am using fabricJs(which is a canvas library to convert from canvas to an svg output). So the transforms are automatically applied when the conversion happens. Thus tinkering with the transform values afterwards effects additional images when conversion happens
ClipPath and SVG Scaling
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>
Continuous wave like animation from wave line svg
Hello I have an svg that is a wavy line built with adobe illustrator and I'm trying to add a continuous wave like animation to it. I've tried vivus.js and was able to get the draw animation working but not coninuously. Does anyone have an idea on how to start something like this? I don't expect someone to do the problem for me but instead point me to the right direction, although im not opposed if someone has a quick answer. Any answer will work wether its pure css, js or both. Here is the svg <svg id="wave" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 456.7 39.9" style="enable-background:new 0 0 456.7 39.9;" xml:space="preserve"> <style type="text/css"> .st69{fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:10;} </style> <path class="st69" d="M4.2,33.2c0.1-0.1,7-6.9,15.9-13.8C27.7,13.7,38.7,6,47.5,6c7.5,0,14,6.6,20.3,12.9l0.4,0.4 c6.8,6.9,14.6,14.6,24.6,14.6c9.9,0,17.7-7.8,24.5-14.6l0.5-0.5C124,12.5,130.5,6,137.9,6c7.5,0,13.9,6.5,20.2,12.9l0.4,0.4 c6.8,6.9,14.6,14.6,24.5,14.6c10,0,17.8-7.8,24.6-14.6l0.5-0.5C214.4,12.5,220.9,6,228.4,6c7.5,0,14,6.5,20.2,12.9l0.4,0.4 c6.8,6.9,14.5,14.6,24.5,14.6c9.9,0,17.7-7.8,24.5-14.6l0.3-0.3c6.3-6.4,12.9-13,20.5-13c7.5,0,14.1,6.6,20.4,13l0.3,0.3 c6.8,6.9,14.6,14.6,24.5,14.6c9.9,0,17.6-7.8,24.5-14.6l0.2-0.2C395.1,12.6,401.6,6,409.2,6c8.7,0,19.8,7.7,27.3,13.4 c8.9,6.8,15.9,13.7,16,13.8"/> </svg> and the jsfiddle link here Thanks!!
I hope this will help you. Play a little bit with the values or add the SVG wave as background, repeat it and change the background-position. #keyframes wave { 0% { left: -80px; } 100% { left: 0; } } .container { width: 100px; overflow: hidden; } .container svg { position: relative; left: -50px; width: 200px; animation: wave 2s linear infinite; } <div class="container"> <svg id="wave" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 456.7 39.9" style="enable-background:new 0 0 456.7 39.9;" xml:space="preserve"> <style type="text/css"> .st69{fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:10;} </style> <path class="st69" d="M4.2,33.2c0.1-0.1,7-6.9,15.9-13.8C27.7,13.7,38.7,6,47.5,6c7.5,0,14,6.6,20.3,12.9l0.4,0.4 c6.8,6.9,14.6,14.6,24.6,14.6c9.9,0,17.7-7.8,24.5-14.6l0.5-0.5C124,12.5,130.5,6,137.9,6c7.5,0,13.9,6.5,20.2,12.9l0.4,0.4 c6.8,6.9,14.6,14.6,24.5,14.6c10,0,17.8-7.8,24.6-14.6l0.5-0.5C214.4,12.5,220.9,6,228.4,6c7.5,0,14,6.5,20.2,12.9l0.4,0.4 c6.8,6.9,14.5,14.6,24.5,14.6c9.9,0,17.7-7.8,24.5-14.6l0.3-0.3c6.3-6.4,12.9-13,20.5-13c7.5,0,14.1,6.6,20.4,13l0.3,0.3 c6.8,6.9,14.6,14.6,24.5,14.6c9.9,0,17.6-7.8,24.5-14.6l0.2-0.2C395.1,12.6,401.6,6,409.2,6c8.7,0,19.8,7.7,27.3,13.4 c8.9,6.8,15.9,13.7,16,13.8"/> </svg> </div>
Aside from css tricks, you could use Math.sin with interval, apply this to Bezier Curve (loop & join into attribute string) and it's done. function anim(){ document.querySelectorAll('svg circle').forEach((c,i)=>c.setAttribute('cy',50+Math.sin(performance.now()/1000+i)*25)) } setInterval(anim,20) <svg id="wave" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 456 100" style="enable-background:new 0 0 456 100;" xml:space="preserve"> <style type="text/css"> .st69{fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:10;} </style> <circle cx="50" cy="50" r="4" fill="red" /> <circle cx="100" cy="50" r="4" fill="red" /> <circle cx="150" cy="50" r="4" fill="red" /> <circle cx="200" cy="50" r="4" fill="red" /> <circle cx="250" cy="50" r="4" fill="red" /> <circle cx="300" cy="50" r="4" fill="red" /> <circle cx="350" cy="50" r="4" fill="red" /> <circle cx="400" cy="50" r="4" fill="red" /> </svg>
zooming into an svg viewbox of specific dimension
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>