SVG scale transform has motion - css

Can anybody tell me why this SVG has a motion animation? Only the scale should animate.
http://codepen.io/anon/pen/HbLkm/

They are scaling in relation to the origin 0,0.
You can override that moving the circles to the origin 0,0, and then use an enclosing g object to move them back to where they should be:
<g transform="translate(391.1,22.9)">
<circle class="pulse2" ... cx="0" cy="0" r="9"/>
</g>
<g transform="translate(457.6,22.9)">
<circle class="pulse2" ... cx="0" cy="0" r="9"/>
</g>
See: Updated CodePen 1
Another is to use transform-origin: center in CSS:
.pulse2 {
transform-origin: center;
-webkit-transform-origin: center;
}
See: Updated CodePen 2

Related

Draw a circle in svg with preserveAspectRatio="none"

I have an svg with viewBox="0 0 100 100" preserveAspectRatio="none" since I need to draw some elements with reference to percentages.
If I now draw a <circle cx="30" cy="50" r="0.5" stroke="white"/> though it becomes stretched/distorted as well.
Is there a way to tell the circle element to preserve its own aspect ratio?
If all you need is a circle you can use a very short, very wide line like in the following example.
This will work because
stroke-linecap="round" will give the illusion of a circle and because
strokes can take a vector-effect="non-scaling-stroke".
non-scaling-stroke
This value modifies the way an object is stroked. Normally stroking involves calculating stroke outline of the shape's path in current user coordinate system and filling that outline with the stroke paint (color or gradient). The resulting visual effect of this value is that the stroke width is not dependent on the transformations of the element (including non-uniform scaling and shear transformations) and zoom level.
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<!--<circle cx="30" cy="50" r="20"></circle>-->
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>
If you need a white stroke too you can add a white line behind the black one with a bigger stroke width
div {
width: 300px;
height: 50px;
background-color: lime;
}
svg {
width:100%;
height:100%;
}
<div>
<svg viewBox="0 0 100 100" preserveAspectRatio="none">
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="45" stroke="white" stroke-linecap="round" vector-effect="non-scaling-stroke" />
<line x1="30" y1="50" x2="30.1" y2="50" stroke-width="40" stroke="black" stroke-linecap="round" vector-effect="non-scaling-stroke" />
</svg>
</div>

How to change svg path width on hover

I have an issue I can't find an helpful answer. I have a svg arrow, the arrow has to grow when the user hovers over with the mouse. The problem is that only the line has to change size not the arrow head. I just want the line to grow horizontally.
This is the svg code
<svg width="51" height="8" viewBox="0 0 51 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M50.3536 4.35355C50.5488 4.15829 50.5488 3.84171 50.3536 3.64645L47.1716 0.464466C46.9763 0.269204 46.6597 0.269204 46.4645 0.464466C46.2692 0.659728 46.2692 0.976311 46.4645 1.17157L49.2929 4L46.4645 6.82843C46.2692 7.02369 46.2692 7.34027 46.4645 7.53553C46.6597 7.7308 46.9763 7.7308 47.1716 7.53553L50.3536 4.35355ZM0 4.5H50V3.5H0V4.5Z" fill="black"/>
</svg>
And this is the code the I have working right now
svg {
width: 50px;
overflow: visible;
transition: width 0.5s ease;
}
svg:hover {
width: 100px;
}
I also have a Codepen link
https://codepen.io/godhandkiller/pen/xxRZeYv
The problem here is that I'm manipulating the whole SVG but I only need to change the like size.
A possible solution: you can use a line path with a marker-end. The marker is the tip of the arrow. For the animation I'm using SMIL animations changing the d attribute of the path from M1,4L25,4 to M1,4L50,4. The animate element has a begin attribute making the animation to begin when you mouse over the overlaying rectangle: begin="theRect.mouseover". Another animate element animates the path on mouse out: begin="theRect.mouseout"
svg {
border: 1px solid red;
transition: width 0.5s ease;
}
<svg id="theSVG" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 8" stroke="#000" stroke-linecap="round">
<defs>
<marker id="m" overflow="visible" markerUnits="userSpaceOnUse">
<path d="M-3,-3L0,0 -3,3" />
</marker>
</defs>
<path d="M1,4L25,4" marker-end="url(#m)">
<animate attributeName="d" to="M1,4L50,4" dur="1s" begin="theRect.mouseover" repeatCount="1" fill="freeze" />
<animate attributeName="d" to="M1,4L25,4" dur="1s" begin="theRect.mouseout" repeatCount="1" fill="freeze" />
</path>
<rect width="100%" height="100%" stroke="none" pointer-events="all" id="theRect" />
</svg>

Animating Sketch' Generated SVG using CSS3

I have the following SVG code for an exported asset from a Sketch file
<?xml version="1.0" encoding="UTF-8"?>
<svg width="116px" height="117px" viewBox="0 0 116 117" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="loader_circles">
<!-- Generator: Sketch 47.1 (45422) - http://www.bohemiancoding.com/sketch -->
<title>Group 2</title>
<desc>Created with Sketch.</desc>
<defs>
<circle id="path-1" cx="58.5" cy="58.5" r="58.5"></circle>
<mask id="mask-2" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="117" height="117" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<circle id="path-3" cx="59" cy="59" r="36"></circle>
<mask id="mask-4" maskContentUnits="userSpaceOnUse" maskUnits="objectBoundingBox" x="0" y="0" width="72" height="72" fill="white">
<use xlink:href="#path-3"></use>
</mask>
</defs>
<g id="Common-elements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-dasharray="78,34">
<g id="Group-2" stroke="#4A90E2" stroke-width="14">
<use id="Oval-8" mask="url(#mask-2)" xlink:href="#path-1"></use>
<use id="Oval-8" mask="url(#mask-4)" xlink:href="#path-3"></use>
</g>
</g>
</svg>
It is a loading spinner with two circles one inside of another, now my aim is to use CSS3 Keyframe animation to animate the two circles, mainly rotate it using transform property.
I am not an expert with SVG so I searched for ways to animate SVG with CSS and found that it is simply animating the elements inside of the SVG code for a particular path.
So I did this
#path-1 {
transform-origin: center;
animation: rotateClockwise 0.6s infinite linear;
}
#path-3 {
transform-origin: center;
animation: rotateAntiClockwise 0.6s infinite linear;
}
#keyframes rotateClockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
#keyframes rotateAntiClockwise {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
The animation works, the two circles spins as it should but somehow the circles just gets malformed, the strokes of the circles just gets paler and thicker. The spinner looks like this when I don't do the transformation, I think the issue is mainly with the transform property
Here's a live demo:
http://jsbin.com/zipecefune
I am not sure why its happening, any ideas?
I'm not sure what is the source of the problem, but it seems wrong to animate something within defs as these are references, from MDN:
SVG allows graphical objects to be defined for later reuse. It is
recommended that, wherever possible, referenced elements be defined
inside of a <defs> element. Objects created inside a <defs> element
are not rendered immediately; instead, think of them as templates or
macros created for future use.
If instead of animating your circle elements you animate use, the problem is fixed (you need to rename the id property because they must be unique.
http://jsbin.com/qonokufimo/edit?html,css,js,output

Animated growing arrow link

Hi, I was wondering how one would go about animating an svg arrow like above (on hover).
I have tried playing around with CSS transforms, but they also scale the arrow-head which is no good. I assume the correct way to do this is using SVGs animations, but I don't know where to start.
For example I would the following arrow (line only) to grow and arrow head to move accordingly.
<svg width="600px" height="100px">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
<path d="M0,0 L0,6 L9,3 z" fill="#f00" />
</marker>
</defs>
<line x1="50" y1="50" x2="100" y2="50" stroke="#000" stroke-width="5" marker-end="url(#arrow)" />
</svg>
Any help is very much appreciated!
You can create growing arrow by using "respoinsive" SVG like this.
svg{
width: 20px;
height: 20px;
transition:width 2s ease;
overflow: visible;
}
svg:hover{
width: 100px;
}
<svg>
<defs>
<marker id="m" markerWidth="4" markerHeight="8"
refX="0" refY="1" viewBox="0 0 1 2">
<polygon points="0,0 1,1 0,2" fill="black"/>
</marker>
</defs>
<line x1="0" y1="50%" x2="100%" y2="50%"
stroke-width="2" marker-end="url(#m)" stroke="black"/>
</svg>
There are some points to implement.
svg has no viewBox (so it is "responsive" SVG).
Line of arrow is defined by relative position of (root) svg size.
Arrow head is defined by marker element.
Growing animation is defined by CSS transition which animate width of svg. So, arrow grows with svg size.
In order to animate the individual SVG elements like HTML elements, you'll need to embed the SVG directly into the page like this:
<svg 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"
width="612px" height="502.174px" viewBox="0 65.326 612 502.174" enable-background="new 0 65.326 612 502.174"
xml:space="preserve" class="logo">
<ellipse class="ground" cx="283.5" cy="487.5" rx="259" ry="80"/>
<path class="kiwi" d="M210.333,65.331C104.367,66.105-12.349,150.637,1.056,276.449c4.303,40.393,18.533,63.704,52.171,79.03
c36.307,16.544,57.022,54.556,50.406,112.954c-9.935,4.88-17.405,11.031-19.132,20.015c7.531-0.17,14.943-0.312,22.59,4.341
c20.333,12.375,31.296,27.363,42.979,51.72c1.714,3.572,8.192,2.849,8.312-3.078c0.17-8.467-1.856-17.454-5.226-26.933
c-2.955-8.313,3.059-7.985,6.917-6.106c6.399,3.115,16.334,9.43,30.39,13.098c5.392,1.407,5.995-3.877,5.224-6.991
c-1.864-7.522-11.009-10.862-24.519-19.229c-4.82-2.984-0.927-9.736,5.168-8.351l20.234,2.415c3.359,0.763,4.555-6.114,0.882-7.875
c-14.198-6.804-28.897-10.098-53.864-7.799c-11.617-29.265-29.811-61.617-15.674-81.681c12.639-17.938,31.216-20.74,39.147,43.489
c-5.002,3.107-11.215,5.031-11.332,13.024c7.201-2.845,11.207-1.399,14.791,0c17.912,6.998,35.462,21.826,52.982,37.309
c3.739,3.303,8.413-1.718,6.991-6.034c-2.138-6.494-8.053-10.659-14.791-20.016c-3.239-4.495,5.03-7.045,10.886-6.876
c13.849,0.396,22.886,8.268,35.177,11.218c4.483,1.076,9.741-1.964,6.917-6.917c-3.472-6.085-13.015-9.124-19.18-13.413
c-4.357-3.029-3.025-7.132,2.697-6.602c3.905,0.361,8.478,2.271,13.908,1.767c9.946-0.925,7.717-7.169-0.883-9.566
c-19.036-5.304-39.891-6.311-61.665-5.225c-43.837-8.358-31.554-84.887,0-90.363c29.571-5.132,62.966-13.339,99.928-32.156
c32.668-5.429,64.835-12.446,92.939-33.85c48.106-14.469,111.903,16.113,204.241,149.695c3.926,5.681,15.819,9.94,9.524-6.351
c-15.893-41.125-68.176-93.328-92.13-132.085c-24.581-39.774-14.34-61.243-39.957-91.247
c-21.326-24.978-47.502-25.803-77.339-17.365c-23.461,6.634-39.234-7.117-52.98-31.273C318.42,87.525,265.838,64.927,210.333,65.331
z M445.731,203.01c6.12,0,11.112,4.919,11.112,11.038c0,6.119-4.994,11.111-11.112,11.111s-11.038-4.994-11.038-11.111
C434.693,207.929,439.613,203.01,445.731,203.01z"/>
<filter id="pictureFilter" >
<feGaussianBlur stdDeviation="15" />
</filter>
</svg>
After doing this, you can use CSS animations on any of the individual SVG elements, just like HTML elements. For example, you could do the following:
svg ellipse { animate: grow 3s infinite; }
Without having the exact SVG code for your arrow, I can't give you more specific direction than that, but can point you in the direction of this article: https://css-tricks.com/using-svg/

SVG g element height with css transition

I am stuck with an issue. my goal is to create a blinking eye in svg. I created the graphic converted into svg. Now i planned to put a css animation on it so it looks like its blinking. I spent lot of time on it but not able to solve the issue.
my approach to achieve this effect is to change its g element height with css transition so it will looks like blinking but when i put css on it it just disappear :( below is the css code I used:
#svg_7 path{
transform:scale(0, -1);
-webkit-transform:scale(0, -1);
}
svg code
<g id="svg_7">
<path id="svg_8" d="m35.99502,49.21692c-11.88306,0 -22.25696,5.59302 -27.80701,13.90399c5.55103,8.31104 15.92505,13.90302 27.80701,13.90302c11.88306,0 22.25696,-5.59198 27.80896,-13.90302c-5.55299,-8.31097 -15.92701,-13.90399 -27.80896,-13.90399z" stroke-miterlimit="10" stroke-width="1.4434" stroke="#fa5400" fill="transparent" />
<circle id="svg_9" r="9.83801" cy="63.12191" cx="35.995" stroke-miterlimit="10" stroke-width="1.4434" stroke="#fa5400" fill="transparent" />
Main purpose is to create a blinking eye that keeps blinking after every few seconds. please do suggest me a solution. even we can use js/jquery if required.
jsfiddle link
thanks in advance
Kax
In fact to have the closest effect (to reality) of blinking eye, I think you have to redesign the eye. Such as we need to animate the upper eyelid only (not both). Also the inner pupil should be covered by the eye lid. Doing so is not easy, at least I feel like that it can be done more easily with CSS than with SVG. However the time of shutting the eye lid is short, we can just animate both the eyelid and the inner pupil. Scaling down the vertical size of both to nearly 0 should do the job. However we can notice that the stroke-width becomes thinner at such a small scaling (may create some visible dashed lines instead of a solid one). So we also have to animate (increase) the stroke-width. Here is the CSS code (please run it in webkit-based browsers, it should work for all browsers):
#svg_7 path{
-webkit-transform-origin:50%;
-webkit-animation:blink 3s infinite alternate;
}
#svg_9 {
-webkit-transform-origin:50%;
-webkit-animation:coreblink 3s infinite alternate;
}
#-webkit-keyframes blink {
0%, 96% {
-webkit-transform:scale(1,1);
stroke-width:1.4434px;
}
100% {
-webkit-transform:scale(1,0.05);
stroke-width:6px;
}
}
#-webkit-keyframes coreblink {
0%, 96% {
-webkit-transform:scale(1,1);
}
100% {
-webkit-transform:scale(1,0.05);
}
}
Note that, if you increase the animation-duration (it's 3s in the demo), you should also increase the key percentage (it's 96% in the demo) so that the time of shutting the eye lid is not considerably large. I know this is not perfect (as what I said before), but it's at least acceptable in some use case and hope you are satisfied with it.
Demo.
UPDATE: If you want to save the SVG code into a file, you should also ship the CSS code (used to animate the SVG) along with the SVG file by using <style> tag like this:
<svg width="99" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
<style>
#svg_7 path{
-webkit-transform-origin:50%;
-webkit-animation:blink 3s infinite alternate;
}
#svg_9 {
-webkit-transform-origin:50%;
-webkit-animation:coreblink 3s infinite alternate;
}
#-webkit-keyframes blink {
0%, 96% {
-webkit-transform:scale(1,1);
stroke-width:1.4434px;
}
100% {
-webkit-transform:scale(1,0.05);
stroke-width:6px;
}
}
#-webkit-keyframes coreblink {
0%, 96% {
-webkit-transform:scale(1,1);
}
100% {
-webkit-transform:scale(1,0.05);
}
}
</style>
<g id="svg_1">
<rect id="svg_2" height="71.991" width="71.99" stroke-miterlimit="10" stroke-width="1.4434" stroke="#ffffff" fill="transparent" y="0.71191" x="26.195"/>
<line id="svg_3" y2="0.71191" x2="26.195" y1="27.12591" x1="0" stroke-miterlimit="10" stroke-width="1.4434" stroke="#ffffff" fill="transparent"/>
<line id="svg_4" y2="72.70391" x2="26.195" y1="99.11691" x1="0" stroke-miterlimit="10" stroke-width="1.4434" stroke="#ffffff" fill="transparent"/>
<rect id="svg_5" height="71.991" width="71.992" stroke-miterlimit="10" stroke-width="1.4434" stroke="#ffffff" fill="#000000" y="27.12491" x="0"/>
<g id="svg_6">
<g id="svg_7">
<path id="svg_8" d="m35.99502,49.21692c-11.88306,0 -22.25696,5.59302 -27.80701,13.90399c5.55103,8.31104 15.92505,13.90302 27.80701,13.90302c11.88306,0 22.25696,-5.59198 27.80896,-13.90302c-5.55299,-8.31097 -15.92701,-13.90399 -27.80896,-13.90399z" stroke-miterlimit="10" stroke-width="1.4434" stroke="#fa5400" fill="transparent">
</path>
<circle id="svg_9" r="9.83801" cy="63.12191" cx="35.995" stroke-miterlimit="10" stroke-width="1.4434" stroke="#fa5400" fill="transparent" />
</g>
</g>
<polygon id="svg_10" points="98.1849594116211,72.70391845703125 71.9919662475586,99.116943359375 71.9919662475586,27.12591552734375 98.1849594116211,0.7119140923023224 " stroke-miterlimit="10" stroke-width="1.4434" stroke="#ffffff" fill="transparent"/>
</g>
</svg>
Another approach is try using pure SVG animate. However I find it hard to have an equivalent of SVG animation to CSS animation.

Resources