How to tame negative CSS rotation? [duplicate] - svg

This question already has answers here:
How to use transform-origin in conjunction with SVGs? [duplicate]
(1 answer)
CSS transform origin issue on svg sub-element
(1 answer)
Closed 1 year ago.
Seems that it is not possible to let two rectangles spin in the opposite direction. This leads to the output that the rectangle rotating in the reverse direction is placed lower.
#keyframes gspin {
from {transform:rotateZ(110deg);}
to {transform:rotateZ(100deg);}
}
#keyframes spin {
from {transform:rotateZ(70deg);}
to {transform:rotateZ(80deg);}
}
#spinner {
animation: spin 10s infinite;
transform-origin: 50% 50%;
}
#gspinner {
animation: gspin 10s infinite;
transform-origin: 50% 50%;
z-index:0;
}
<svg width="500" height="500" viewBox="0 0 600 600">
<g id="spinner">
<rect rx="10" height="20" width="400" y="195" x="160" fill="darkgrey"/>
</g>
<g id="gspinner">
<rect rx="10" height="20" width="400" y="195" x="160" fill="darkgrey"/>
</g>
</svg>

Related

Replicating an svg animation

When this site first loads there’s this animation where there’s a triangle that traces over another triangle.
Image
http://nueuphoria.com/
How would I replicate the same thing?
Where the triangle traces over the other triangle.
Can someone provide a jsfiddle of how it's done.
I found this from the site, but I don't know how to put it together.
https://jsfiddle.net/s2z3xyd8/6/
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 47.96 51.66">
<defs>
<style>
.cls-1{fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:4px;}</style>
</defs>
<g id="Слой_2" data-name="Слой 2">
<g id="play">
<path class="cls-1" d="M2,25.83V4.11A2.11,2.11,0,0,1,5.13,2.27L44.88,24.45a2.11,2.11,0,0,1,0,3.7L5.1,49.41A2.11,2.11,0,0,1,2,47.55V25.83"></path>
</g>
</g>
</svg>
</div>
It is just using the common line drawing technique of animating the stroke-dashoffset. The bit you were missing was the #keyframes` definition(s).
.logo-load_w svg path {
stroke: #08f9ff;
stroke-dasharray: 150;
stroke-dashoffset: 1500;
-webkit-animation: draw 20s infinite linear;
animation: draw 20s infinite linear;
}
#-webkit-keyframes draw {
to {
stroke-dashoffset: 0;
}
}
#keyframes draw {
to {
stroke-dashoffset: 0;
}
}
<div class="logo-load_w">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 47.96 51.66"><defs><style>.cls-1{fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:4px;}</style></defs><g id="Слой_2" data-name="Слой 2"><g id="play"><path class="cls-1" d="M2,25.83V4.11A2.11,2.11,0,0,1,5.13,2.27L44.88,24.45a2.11,2.11,0,0,1,0,3.7L5.1,49.41A2.11,2.11,0,0,1,2,47.55V25.83"></path></g></g></svg>
</div>
The dark triangle in the background is just a second copy of the SVG, with the stroke colour set to a different colour.
Update
The simplest way to have a darker triangle behind the blue one, is not the way the original site does it. It is easier just to add a second copy of the triangle into the SVG. You put it earlier in the SVG, so that it is drawn first. And make its stroke colour black.
.logo-load_w svg .play {
stroke: #08f9ff;
stroke-dasharray: 150;
stroke-dashoffset: 1500;
-webkit-animation: draw 20s infinite linear;
animation: draw 20s infinite linear;
}
#-webkit-keyframes draw {
to {
stroke-dashoffset: 0;
}
}
#keyframes draw {
to {
stroke-dashoffset: 0;
}
}
<div class="logo-load_w">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" viewBox="0 0 47.96 51.66">
<defs>
<style>.cls-1{fill:none;stroke:#fff;stroke-miterlimit:10;stroke-width:4px;}</style>
</defs>
<g class="cls-1">
<path stroke="black"
d="M2,25.83V4.11A2.11,2.11,0,0,1,5.13,2.27L44.88,24.45a2.11,2.11,0,0,1,0,3.7L5.1,49.41A2.11,2.11,0,0,1,2,47.55V25.83"/>
<path class="play"
d="M2,25.83V4.11A2.11,2.11,0,0,1,5.13,2.27L44.88,24.45a2.11,2.11,0,0,1,0,3.7L5.1,49.41A2.11,2.11,0,0,1,2,47.55V25.83"/>
</g>
</g>
</svg>
</div>

SVG - have line centered vertically without knowing svg height

I have different SVGs in the project. I need to be able to programatically add a line element at the exact vertical middle of each SVG.
I tried to set the y1 and y2 coordinates as ‘50%’ but that is not honored when the SVG is scaled either by transform scale or viewBox. One of my other requirements is to have those SVGs scaled often.
I could ,of course, start calculating bounding box of each SVG on each scale change, and from there the vertical input but that sounds not elegant
The example is just something to work on. It has a line vertical coordinates set to 50% which are not honoured when a viewBox is set (button click). The blue line is no longer at the middle of the SVG when scaled...
function myFunction(){
document.getElementById("maxi").setAttribute("viewBox","0,0,492,124");
}
<svg id="maxi" version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="246" height="62" font-size="23px" xml:space="preserve" >
<line id="greenline" x1="0" y1="31" x2="232" y2="31" stroke="#00FF00" stroke-width="4"/>
<line id="blueline" x1="0" y1="50%" x2="232" y2="50%" stroke="#0000FF"/>
<path class="cutContour" fill="none" stroke="#EC008C" stroke-miterlimit="3.8637" d="M6.8,2.3H225
c2.3,0,4.3,1.9,4.3,4.3v48.2c0,2.3-1.9,4.3-4.3,4.3H6.8c-2.3,0-4.3-1.9-4.3-4.3V6.6C2.5,4.2,4.4,2.3,6.8,2.3z"/>
</svg>
<input type="button" value="Click Me" onClick="myFunction();">
If the position of the line in the image doesn't need to vary - in other words if it's a static image - then transforms or viewBox manipulation is not required to resize the image. You can vary the CSS (or HTML attributes) of the SVG tag itself to resize the image. It is common to express the coordinates of the line as absolute values rather than percentages, but as you can see from #line2 below, the effect is identical:
For example (with jQuery):
<style>
svg {
outline: 1px dotted grey;
width: 300px;
}
#shrink {
display: none;
}
#line1 {
stroke: red;
stroke-width: 5px;
}
#line2 {
stroke: white;
stroke-width: 2px;
}
</style>
<p>
<button id="grow">Grow</button>
<button id="shrink">Shrink</button>
</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-100 0 300 100">
<line x1="-50" y1="50" x2="150" y2="50" id="line1"/>
<line x1="-40" y1="50%" x2="140" y2="50%" id="line2"/>
</svg>
<script>
$(function() {
$('#grow').click(function() {
$('svg').animate({
width: "800px"
}, 500, function() {
$('#grow').hide();
$('#shrink').show();
});
});
$('#shrink').click(function() {
$('svg').animate({
width: "300px"
}, 500, function() {
$('#shrink').hide();
$('#grow').show();
});
});
});
</script>
Codepen: https://codepen.io/MSCAU/pen/eLMOVj with additional CIRCLE and RECT behind the lines.
I'm not very sure I understand what you are asking. Please take a look & tell me if this is what you need.
function myFunction(){
let newWidth = 492;
document.getElementById("maxi").setAttribute("viewBox",`0,0,${newWidth},124`);
blueline.setAttributeNS(null,"x1", newWidth/2);
blueline.setAttributeNS(null,"x2", newWidth/2);
blueline.setAttributeNS(null,"y2", 124);
}
svg{border:1px solid;}
<svg id="maxi" version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="246" height="62" font-size="23px" xml:space="preserve" >
<line id="greenline" x1="0" y1="31" x2="232" y2="31" stroke="#00FF00" stroke-width="4"/>
<line id="blueline" x1="123" y1="0" x2="123" y2="62" stroke="#0000FF"/>
<path class="cutContour" fill="none" stroke="#EC008C" stroke-miterlimit="3.8637" d="M6.8,2.3H225
c2.3,0,4.3,1.9,4.3,4.3v48.2c0,2.3-1.9,4.3-4.3,4.3H6.8c-2.3,0-4.3-1.9-4.3-4.3V6.6C2.5,4.2,4.4,2.3,6.8,2.3z"/>
</svg>
<input type="button" value="Click Me" onClick="myFunction();">

Responsive SVG sizing

I have the following SVG:
body {
background-color: #dad9c7;
svg {
position: absolute;
width: 100%;
height: 400px;
margin: 0 auto;
display: block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.
<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g>
<rect width="1000" height="151" x="0" y="0" fill="#d5835b" />
<rect width="1000" height="151" x="0" y="150" fill="#d47966" />
<rect width="1000" height="126" x="0" y="300" fill="#b66961" />
<rect width="1000" height="101" x="0" y="425" fill="#d17385" />
<rect width="1000" height="101" x="0" y="525" fill="#aa617c" />
<rect width="1000" height="101" x="0" y="625" fill="#a36d8f" />
<rect width="1000" height="101" x="0" y="725" fill="#736d87" />
<rect width="1000" height="176" x="0" y="825" fill="#313d53" />
</g>
</svg>
Which looks like this:
How can I do the following?
Keep heights of colored strips the same when scaling the window (not scale).
Stretch colored strips horizontally to the edges of the viewport on either side left and right.
Stretch the top-most rectangle to the top of the screen so the upper third of the viewport is orange and stretch the bottom-most rectangle to the bottom of the viewport so that the lower third of the viewport is purple.
Always keep the "square" centered vertically which already works with CSS, but however the SVG is manipulated to solve would have to keep this into account.
Here is an example of how this would look: As the window gets taller, the colored rectangles will stay in the middle, but the top orange and bottom purple would be cut off based on the height of the viewport.
How can I do the following?
Keep heights of colored strips the same when scaling the window (not scale).
You are already doing this by setting height to 400px.
Stretch colored strips horizontally to the edges of the viewport on either side left and right.
Set preserveAspectRatio="none" on the SVG. See below.
body {
background-color: #dad9c7;
}
svg {
position: absolute;
width: 100%;
height: 400px;
margin: 0 auto;
display: block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<svg viewBox="0 0 1000 1000" preserveAspectRatio="none">
<g>
<rect width="1000" height="151" x="0" y="0" fill="#d5835b" />
<rect width="1000" height="151" x="0" y="150" fill="#d47966" />
<rect width="1000" height="126" x="0" y="300" fill="#b66961" />
<rect width="1000" height="101" x="0" y="425" fill="#d17385" />
<rect width="1000" height="101" x="0" y="525" fill="#aa617c" />
<rect width="1000" height="101" x="0" y="625" fill="#a36d8f" />
<rect width="1000" height="101" x="0" y="725" fill="#736d87" />
<rect width="1000" height="176" x="0" y="825" fill="#313d53" />
</g>
</svg>
Stretch the top-most rectangle to the top of the screen so the upper third of the viewport is orange and stretch the bottom-most rectangle to the bottom of the viewport so that the lower third of the viewport is purple.
You cannot automatically stretch the rectangle itself with CSS. But one way you could do it is to use pseudo elements to colour the top and bottom halves of the parent element with matching colours.
body {
background-color: #dad9c7;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0;
margin: 0;
}
svg {
position: absolute;
width: 100%;
height: 400px;
margin: 0 auto;
display: block;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
body::before {
content: "";
display: block;
position: absolute;
width: 100%;
top: 0;
bottom: 50%;
background-color: #d5835b;
}
body::after {
content: "";
display: block;
position: absolute;
width: 100%;
top: 50%;
bottom: 0;
background-color: #313d53;
z-index: -1;
}
<svg viewBox="0 0 1000 1000" preserveAspectRatio="none">
<g>
<rect width="1000" height="151" x="0" y="0" fill="#d5835b" />
<rect width="1000" height="151" x="0" y="150" fill="#d47966" />
<rect width="1000" height="126" x="0" y="300" fill="#b66961" />
<rect width="1000" height="101" x="0" y="425" fill="#d17385" />
<rect width="1000" height="101" x="0" y="525" fill="#aa617c" />
<rect width="1000" height="101" x="0" y="625" fill="#a36d8f" />
<rect width="1000" height="101" x="0" y="725" fill="#736d87" />
<rect width="1000" height="176" x="0" y="825" fill="#313d53" />
</g>
</svg>
Always keep the "square" centered vertically which already works with CSS, but however the SVG is manipulated to solve would have to keep this into account.
N/A here.
Alternate pure-SVG solution
There is also a pure SVG solution using nested <svg> elements. The only CSS we are using is just to ensure the SVG occupies the full size of the page.
It works by making the top and bottom rectangles extend outside the viewBox by an extra 1000 pixels. To make sure they are visible, we set overflow="visible". 1000 is an arbitrary value. If you want to support screens > 2400 pixels high, then you could choose a larger value.
The inner SVG gets centred vertically using a combination of a y offset and a transform that shifts it up by 200px. This is equivalent to the common top: 50%; transform: translate(0,-50%)" trick to vertically centre CSS block elements.
body {
background-color: #dad9c7;
padding: 0;
margin: 0;
}
#mysvg {
position: absolute;
display: block;
width: 100%;
height: 100%;
}
<svg id="mysvg">
<g transform="translate(0, -200)">
<svg width="100%" height="400px"
y="50%" transform="translate(0, -200)"
viewBox="0 0 1000 1000" preserveAspectRatio="none"
overflow="visible">
<g>
<rect width="1000" height="1151" x="0" y="-1000" fill="#d5835b" />
<rect width="1000" height="151" x="0" y="150" fill="#d47966" />
<rect width="1000" height="126" x="0" y="300" fill="#b66961" />
<rect width="1000" height="101" x="0" y="425" fill="#d17385" />
<rect width="1000" height="101" x="0" y="525" fill="#aa617c" />
<rect width="1000" height="101" x="0" y="625" fill="#a36d8f" />
<rect width="1000" height="101" x="0" y="725" fill="#736d87" />
<rect width="1000" height="1176" x="0" y="825" fill="#313d53" />
</g>
</svg>
</g>
</svg>
You cannot use media queries or css styling for that since a svg does not support that. If you really need to that with an SVG, you will need some Javascript to accomplish your desired effect. In your case, I guess it is simpler to create that using html and css with some media queries.
The only thing you can control when scaling/displaying a SVG is the preserveAspectRatio attribute. A detailed description can be found here.

SVG moves out of position when screen size changes or doesn't scale

I've created an SVG and put the width as a percentage because I want it to resize to fit different screen widths, but when I resize the screen, the svg moves up and down and doesn't move left/right to stay in the centre. If I use pixels instead of percentages, it doesn't resize with the screen.
Preview didn't work on here so here's the codepen link
.
HTML
<svg height="100%" width="100%" id="main">
<circle class="graph line line-1" cx="50%" cy="50%" r="25%" stroke-width="5%" stroke="#f1c40f" fill="none" />
<circle class="graph line line-2" cx="50%" cy="50%" r="20%" stroke-width="5%" stroke="#e67e22" fill="none" />
<circle class="graph line line-3" cx="50%" cy="50%" r="15%" stroke-width="5%" stroke="#00c0df" fill="none" />
</svg>
CSS
#main {
padding: 100px 0;
margin-top: 100px;
height: 200px;
background-color: pink;
}
.graph {
transform: rotate(270deg);
}
.graph.line {
transform-origin: center;
stroke-dasharray: 160%;
animation: graph 1.5s ease-in-out infinite alternate;
}
#keyframes graph {
from {
stroke-dashoffset: 160%;
}
to {
stroke-dashoffset: 90%;
}
}
That's what viewBox is for. With a viewBox, you establish a local coordinate system, which scales with your image. In your svg you simply use your local coordinates, and the image scales to any size...
#main {
position:absolute;
top:0px;left:0px;
right:0px;bottom:0px;
background:pink
}
.graph {
transform: rotate(270deg);
}
.graph.line {
transform-origin: center;
stroke-dasharray: 160%;
animation: graph 1.5s ease-in-out infinite alternate;
}
#keyframes graph {
from {
stroke-dashoffset: 160%;
}
to {
stroke-dashoffset: 90%;
}
}
<svg viewBox="0 0 100 100" id="main">
<circle class="graph line line-1" cx="50" cy="50" r="25" stroke-width="5" stroke="#f1c40f" fill="none" />
<circle class="graph line line-2" cx="50" cy="50" r="20" stroke-width="5" stroke="#e67e22" fill="none" />
<circle class="graph line line-3" cx="50" cy="50" r="15" stroke-width="5" stroke="#00c0df" fill="none" />
</svg>

Simple SVG and CSS Animation

I am learning to create and use SVG's, so far it has been pretty straightforward. I am having two issues that keep setting me back. (1) Animations only seem to work in FF. Chrome and IE are static. (2) I can make the SVG scale responsively, but when I do the animation centers will not scale. I tried using percentages in the "transform-origin" property but it does not seem to work as expected.
http://codepen.io/Shift2Design/pen/azgVRz
<style>
html, body {
background-color:#C2B59B;
padding:0;
margin:0;
width:100%;
height:100%;
position:relative; }
/*svg {width:100%; height:100%;}*/
#spinner {
animation: infinite-spinning 12s infinite linear;
transform-origin: 23.8px 133.2px 0;}
#spinnerSm {
animation: infinite-spinning 1s infinite linear;
transform-origin: 23.8px 133.2px 0;}
#gear {
animation: infinite-spinning-reversed 8s infinite linear;
transform-origin: 23.8px 133.2px 0;}
#keyframes infinite-spinning {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
#keyframes infinite-spinning-reversed {
0% { transform: rotate(360deg); }
100% { transform: rotate(0deg); }
}
<style>
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.2" baseProfile="tiny" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" width="420" height="158" viewBox="-186.3 54.2 420 158" xml:space="preserve">
<g id="background">
<rect x="-186.3" y="54.2" fill="#C2B59B" width="420" height="158"/>
</g>
<g id="horizontalBar">
<rect x="-186.3" y="126.9" fill="#D65F1D" width="420" height="12.6"/>
</g>
<g id="outerCircle">
<circle fill="#D65F1D" cx="23.8" cy="133.2" r="69"/>
</g>
<g id="circlemask">
<circle fill="#C2B59B" cx="23.8" cy="133.2" r="65"/>
</g>
<g id="spinner">
<g>
<path d="M23.8,194.4c-34,0-61.6-27.6-61.6-61.6c0-31,23-56.7,52.8-61v17.9c-20.1,4.1-35.2,21.9-35.2,43.1c0,24.3,19.7,44,44,44
c24.3,0,44-19.7,44-44c0-21.2-15.1-39-35.2-43.1V71.9c29.8,4.3,52.8,30,52.8,61C85.4,166.9,57.8,194.4,23.8,194.4z"/>
</g>
</g>
<g id="gear">
<g>
<path fill="#D65F1D" d="M66.5,139.4c0,0.8-0.7,1.8-1.6,2L54.6,143c-0.6,1.8-1.3,3.5-2.2,5.1c1.9,2.7,3.9,5.2,6,7.7
c0.3,0.4,0.6,0.9,0.6,1.4c0,0.5-0.2,0.9-0.5,1.3c-1.3,1.8-8.8,10-10.7,10c-0.5,0-1-0.2-1.4-0.5l-7.7-6c-1.6,0.8-3.3,1.6-5.1,2.1
c-0.4,3.4-0.7,7-1.6,10.3c-0.2,0.9-1,1.6-2,1.6H17.6c-1,0-1.9-0.7-2-1.7L14,164c-1.7-0.6-3.4-1.2-5-2.1l-7.8,5.9
c-0.4,0.3-0.9,0.5-1.4,0.5c-0.5,0-1-0.2-1.4-0.6c-2.9-2.7-6.8-6.1-9.2-9.3c-0.3-0.4-0.4-0.8-0.4-1.3c0-0.5,0.2-0.9,0.4-1.3
c1.9-2.6,3.9-5,5.8-7.6c-0.9-1.8-1.7-3.6-2.3-5.5l-10.2-1.5c-0.9-0.2-1.6-1.1-1.6-2v-12.3c0-0.8,0.7-1.8,1.5-2l10.3-1.6
c0.6-1.8,1.3-3.4,2.2-5.1c-1.9-2.7-3.9-5.2-6-7.7c-0.3-0.4-0.6-0.8-0.6-1.3c0-0.5,0.2-0.9,0.5-1.3c1.3-1.8,8.8-10,10.7-10
c0.5,0,1,0.2,1.4,0.6l7.7,5.9c1.6-0.8,3.3-1.6,5.1-2.1c0.4-3.4,0.7-7,1.6-10.3c0.2-0.9,1-1.6,2-1.6h12.3c1,0,1.9,0.7,2,1.7
l1.6,10.2c1.7,0.6,3.4,1.2,5,2.1l7.9-5.9c0.3-0.3,0.8-0.5,1.3-0.5c0.5,0,1,0.2,1.4,0.6c2.9,2.7,6.8,6.2,9.2,9.5
c0.3,0.3,0.4,0.8,0.4,1.2c0,0.5-0.2,0.9-0.4,1.3c-1.9,2.6-3.9,5-5.8,7.6c0.9,1.8,1.7,3.6,2.3,5.5l10.2,1.6c0.9,0.2,1.6,1.1,1.6,2
V139.4z M23.8,118.9c-7.8,0-14.2,6.4-14.2,14.2c0,7.8,6.4,14.2,14.2,14.2c7.8,0,14.2-6.4,14.2-14.2
C38,125.3,31.6,118.9,23.8,118.9z"/>
</g>
</g>
<g id="spinnerSm">
<g>
<path d="M23.8,145.1c-6.6,0-12-5.4-12-12c0-6,4.5-11,10.3-11.8v3.5c-3.9,0.8-6.8,4.2-6.8,8.4c0,4.7,3.8,8.5,8.6,8.5
c4.7,0,8.5-3.8,8.5-8.5c0-4.1-2.9-7.6-6.8-8.4v-3.5c5.8,0.8,10.3,5.8,10.3,11.8C35.7,139.7,30.4,145.1,23.8,145.1z"/>
</g>
</g>
</svg>
Thoughts/help? Thanks for reading.
You forgot to add the vendor prefix for webkit:
#spinnerSm {
animation: infinite-spinning 1s infinite linear;
-webkit-animation: infinite-spinning 1s infinite linear;
transform-origin: 23.8px 133.2px 0;}
#-webkit-keyframes infinite-spinning {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
etc...

Resources