I have an svg <path> that I want scaled on mouse hover. The scaled path should be centered on top of its original location. I have read other similar posts but could not get it done.
I tried using transform-origin: 50% 50%;, transform-origin: 0 0;, and transform-origin: center; and also tried removing transform-origin all throughout, but none of them works as intended since the scaled path has an offset of several pixels:
path {
fill: #f00
}
path:hover {
fill: #000;
transform: scale(2);
-ms-transform: scale(2);
-webkit-transform: scale(2);
transform-origin: 50% 50%;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 881 571" pointer-events="fill" fill="none" fill-opacity="1">
<path d="M447 263h1-1 1v-1 1h1-1 1-1 1v1h1-1 2v1h1v1h-1 1-1v1h1v1h1-1v1h-1v1-1 1h-1v1h-1v3h-1v-1h-2v-1h-1v-1h-2v-2h-1v-3h-1v-1h1-1 1v-1h1v-2h1-1v1-2 1h1v1h1v-1h1v1h1z"/>
</svg>
Your SVG artbox seems enormous, and I believe this is part of the issue. I tried cleaning it up a bit to fit the content of the SVG, and I wrapped the element inside of a div.
Here's the SVG with a more proportionate artbox:
svg {
display: block;
width: 100%;
height: auto;
}
div {
fill: #f00;
width:127px;
height:150px;
margin-left: 50px;
margin-top: 50px;
}
div:hover {
fill: #000;
transform: scale(2);
-ms-transform: scale(2);
-webkit-transform: scale(2);
transform-origin: 50% 50%;
}
<div>
<svg xmlns="http://www.w3.org/2000/svg"><path d="M65.5 23.583h10.583H65.5h10.583V13v10.583h10.584-10.584 10.584-10.584 10.584v10.584H97.25 86.667h21.166V44.75h10.584v10.583h-10.584 10.584-10.584v10.584h10.584V76.5H129h-10.583v10.583h-10.584v10.584-10.584 10.584H97.25v10.583H86.667V140H76.083v-10.583H54.917v-10.584H44.333V108.25H23.167V87.083H12.583v-31.75H2V44.75h10.583H2h10.583V34.167h10.584V13H33.75 23.167v10.583V2.417 13H33.75v10.583h10.583V13h10.584v10.583H65.5z"/>
</svg>
</div>
Hope it helps!
Related
I am able to make this using css by simply applying styles to a div and applying keyframes for animation
the code looks something like this
.loader {
margin: 10px auto;
font-size: 5px;
position: relative;
text-indent: -9999em;
border-right: 0.75em solid #E0E3E9;
border-bottom: 0.75em solid #E0E3E9;
border-left: 0.75em solid #6B04A8;
border-top: 0.75em solid #6B04A8;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
border-radius: 50%;
width: 30px;
height: 30px;
}
#-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#keyframes load8 {
0% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
100% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
}
<div class="loader">Loading...</div>
so basically applied a two sets of border colours and a border-radius of 50% to make it look like a circle and applied transform on it.
I need to do the same in a svg , can someone point me in the right direction from where to start , thanks in advance
In this case I'm using 2 circles one over another. The first one (the base) has a silver stroke. The second one has a purple stroke and stroke-dasharray = "125.5" meaning that there are strokes of 125.5 and gaps the same size. Also 125.5 represents half total length of the circumference.
The center of the circle is in the origin of the svg canvas (0,0) Please observe the viewBox of the svg element: x:-50 y:-50 width:100 height:100
svg{width:50px;display:block; margin:0 auto;}
#theCircle{animation: load8 1s linear infinite;}
#keyframes load8 {
to {
transform: rotate(-1turn);
}
}
<svg viewBox="-50 -50 100 100">
<circle r="40" fill="none" stroke="silver" stroke-width="10" />
<circle id="theCircle" r="40" fill="none" stroke="rebeccapurple" stroke-width="10" stroke-dasharray = "125.5" />
</svg>
I want to animate a circle
#keyframes animation {
0% {
opacity: 0;
-webkit-transform: translate(0, 0);
transform: translate(0, 0);
}
100% {
opacity: 1;
-webkit-transform: translate(50%, 50%);
transform: translate(50%, 50%);
}
}
.circle {
animation: animation 1s ease-in;
fill: #ff0000;
}
<svg class="parent" width="500px" height="500px" viewBox="0 0 500 500">
<circle class="circle" r="150" cx="150" cy="150"></circle>
</svg>
The animation for opacity succeeded while the transform(translate) animation faild.
Any ideas on how to solve this?
IE 11 may supports the transform attribute, but it doesn't recognize the CSS style (and therefore also no CSS stylesheets or animations).
Will not work in IE11:
<circle style="transform:translate(50%, 50%)"></circle>
Will work in IE11:
<circle transform="translate(50%, 50%)"></circle>
I have four solutions for you:
Go the hard way: Animate the changes with jQuery manually by using var circles = jQuery('.circle'); to get the circles, circles.attr('transform', 'translate('+n+'%, '+n+'%)'); to set the attribute and jQuery.animate(...) to get the animation steps.
Handle the animation with width and height attributes.
Make the animation different if IE11.
Drop your IE11 support for that feature or your hole site.
The IE browser does not support CSS transforms on SVG elements, more detail information, please check this article.
As a workaround, you could try to display the circle using div, instead of SVG. Code like this:
<head>
<style>
div {
width: 100px;
height: 100px;
border-radius: 50%;
background-color: red;
position: relative;
animation-name: example;
animation-duration: 2s;
}
#keyframes example {
0% {background-color:red; left:0px; top:0px;-webkit-transform: translate(0, 0); transform: translate(0, 0);opacity: 0;}
100% {background-color:red; -webkit-transform: translate(100%, 100%); transform: translate(100%, 100%);opacity: 1;}
}
</style>
</head>
<body>
<div></div>
</body>
The output as below (use IE 11 browser):
I've been trying to achieve the effect seen here for one wave in a circle:
http://www.jquery-az.com/css/demo.php?ex=131.0_1
Unfortunately, I've been unable to get the animation to repeat smoothly with my own svg, seen here: http://jsbin.com/diserekigo/1/edit?html,css,output. You'll also notice that the bottom "rectangle" part isn't filled either.
My css is as follows:
.circle {
border-radius: 100%;
border: 1px solid black;
width: 200px;
height: 200px;
overflow: hidden;
position: relative;
perspective: 1px;
}
.liquid {
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 100%;
height: 100%;
-webkit-transform: translate(0, 80%);
transform: translate(0, 80%);
}
.wave {
left: 0;
width: 400%;
position: absolute;
bottom: 100%;
margin-bottom: -1px;
-webkit-animation: wave-front .7s infinite linear;
animation: wave-front 0.7s infinite linear;
}
#-webkit-keyframes wave-front {
100% {
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
}
#keyframes wave-front {
100% {
-webkit-transform: translate(-100%, 0);
transform: translate(-100%, 0);
}
}
How can I improve the repeating behavior, as well as make the wave fill up the entire space beneath it?
You're missing a lot from the original demo. Why not just copy and paste and make whatever local changes to the size and position you wanted? Most of your issues are a result of not having all the SVG elements - the original demo has 3, not just 1. I've added them into your jsbin to get it to work:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" style="display: none;">
<symbol id="wave">
<path d="M420,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C514,6.5,518,4.7,528.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H420z"></path>
<path d="M420,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C326,6.5,322,4.7,311.5,2.7C304.3,1.4,293.6-0.1,280,0c0,0,0,0,0,0v20H420z"></path>
<path d="M140,20c21.5-0.4,38.8-2.5,51.1-4.5c13.4-2.2,26.5-5.2,27.3-5.4C234,6.5,238,4.7,248.5,2.7c7.1-1.3,17.9-2.8,31.5-2.7c0,0,0,0,0,0v20H140z"></path>
<path d="M140,20c-21.5-0.4-38.8-2.5-51.1-4.5c-13.4-2.2-26.5-5.2-27.3-5.4C46,6.5,42,4.7,31.5,2.7C24.3,1.4,13.6-0.1,0,0c0,0,0,0,0,0l0,20H140z"></path>
</symbol>
</svg>
<div class="circle">
<div class="liquid"></div>
<div id="water" class="water">
<svg viewBox="0 0 560 20" class="water_wave water_wave_back">
<use xlink:href="#wave"></use>
</svg>
<svg viewBox="0 0 560 20" class="water_wave water_wave_front">
<use xlink:href="#wave"></use>
</svg>
</div>
</div>
You also need JavaScript to get the water to fill.
http://jsbin.com/pinowufeqe/edit?html,css,js,output
Is it possible to achieve perspective with 3d transforms on a SVG elements?
I'm talking about something similar with how the Star Wars opening titles look like with 3d perspective. This is a jsfiddle with the desired effect achieved using CSS3 3d transforms:
<section style="transform: perspective(200px) rotateX(-30deg); transform-origin: 50% 100%; text-align: justify; width: 100px;">
<p style="backface-visibility: hidden;">TEXTTEXTTEXT</p>
</section>
Update Nov 2018:
Testing the snipet from the question in latest chrome and Firefox works. Although support for 3d transforms on svg elements isn't very wide, browsers are implementing it more and more.
Origin answer :
3D transforms aren't supported on SVG elements. There are a few workarounds though :
If the svg doesn't contain elements that shouldn't be transformed, you can use CSS 3d transforms on the SVG element itself :
svg {
width: 70%;
margin: 0 auto;
display: block;
-webkit-transform: perspective(300px) rotateX(30deg);
transform: perspective(300px) rotateX(30deg);
}
<svg viewbox="0 0 100 20">
<text x="0" y="20">TEXTEXTEX</text>
</svg>
In case of polygons, you make a 2D polygon look like a 3D polygon. In the following example, the red rectangle is 3D rotated (rotateX(40deg)) and the black rectangle is a 2D SVG polygon made to look like a 3D rotated rectangle:
div{
display:inline-block;
width:200px; height:100px;
background:red;
transform:perspective(500px) rotateX(40deg);
}
svg{
display:inline-block;
width:220px; height:auto;
}
div, svg{
display:inline-block;
margin:0 10px;
}
<div></div>
<svg viewbox="0 0.5 10 4">
<polygon points="9.9 4.1 0.1 4.1 0.7 0.6 9.3 0.6" fill=""/>
</svg>
3D transforms are supported inside <svg> elements (f.e. on <circle>) (at least to some extent, it seems like perspective is isometric only).
For example, here's animation of transform: rotate3d applied to <circle> elements (tested in Chrome only):
body, html {
background: black;
width: 100%; height: 100%;
margin: 0;
padding: 0;
}
body {
display: flex;
}
svg {
width: 100%;
}
.gAExgp {
transform-origin: 50% 50% 0px;
animation-name: phEs, ipaUyp;
animation-duration: 4s, 7s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.PwswZ {
transform-origin: 50% 50% 0px;
animation-name: gcRPJT, ipaUyp;
animation-duration: 4s, 8s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
#keyframes phEs {
50% {
transform: rotate3d(0, 2, 1, 180deg);
}
100% {
transform: rotate3d(0, 2, 1, 360deg);
}
}
#keyframes gcRPJT {
50% {
transform: rotate3d(2, 0, 1, 180deg);
}
100% {
transform: rotate3d(2, 0, 1, 360deg);
}
}
#keyframes ipaUyp {
0% {
stroke: magenta;
}
33% {
stroke: cyan;
}
66% {
stroke: yellow;
}
100% {
stroke: magenta;
}
}
<!-- Logo from https://rebassjs.org -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" style="display:block;max-width:100%;margin:0;fill:none;stroke:cyan" vector-effect="non-scaling-stroke" class="sc-htoDjs hCHUAb"><circle cx="32" cy="32" r="32" fill="#000" stroke="none"></circle><circle cx="32" cy="32" r="30" stroke-width="1" vector-effect="non-scaling-stroke" opacity="0.5"></circle><g><circle cx="32" cy="32" r="24" stroke-width="2" vector-effect="non-scaling-stroke" class="sc-dnqmqq gAExgp"></circle><circle cx="32" cy="32" r="24" stroke-width="2" vector-effect="non-scaling-stroke" class="sc-iwsKbI PwswZ"></circle></g><text x="32" y="34" text-anchor="middle" font-family="system-ui, sans-serif" font-weight="bold" font-size="4" stroke="none" fill="white" style="text-transform:uppercase;letter-spacing:0.5em">Rebass</text></svg>
Also available here: https://codepen.io/anon/pen/MPeyEj
I have 2 DIV's as shown below and I've been trying to get the text between the two circles to wrap around the inner circle as shown on the attacthed image. I have not been able to achieve the desired result.
HTML
<div id="outer-circle">
This is just a test logo name
<div id="inner-circle">
</div><!-- End Inner Circle -->
</div><!-- End Outer Circle -->
CSS
* {
margin: 0 auto;
}
#inner-circle {
width: 200px;
height: 200px;
border-radius: 100%;
background-color: green;
margin-top: 28px;
position: relative;
}
#outer-circle {
width: 300px;
height: 300px;
border-radius: 100%;
background-color: blue;
margin-top: 50px;
text-align center;
text-align: left;
}
Click here to see current but undesired result
Example of desired result
See this post by Chris Coyier in which he separates each character of text into <span>s and rotates each one in turn using CSS rotation:
.char1 {
-webkit-transform: rotate(6deg);
-moz-transform: rotate(6deg);
-ms-transform: rotate(6deg);
-o-transform: rotate(6deg);
transform: rotate(6deg);
}
.char2 {
-webkit-transform: rotate(12deg);
-moz-transform: rotate(12deg);
-ms-transform: rotate(12deg);
-o-transform: rotate(12deg);
transform: rotate(12deg);
}
...etc
Or use Dirk Weber's csswarp.js Service which pretty much does the same but uses javascript to generate the html and css for you. (csswarp.js on GitHub)
Or use SVG text on a path as in this example from useragentman.com
<svg id="myShape" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<path id="path1"
fill="none" stroke="black" stroke-width="1"
d="M 212,65
C 276,81 292,91 305,103 361,155
363,245 311,302 300,314 286,324
271,332 248,343 227,347 202,347
190,346 174,343 163,339 143,333">
</path>
</defs>
<text id="myText">
<textPath xlink:href="#path1" >
<tspan dy="0.3em">C is for Cookie, That's Good Enough For Me!</tspan>
</textPath>
</text>
</svg>
Or...
Use an image.
Use base info from https://css-tricks.com/set-text-on-a-circle/
BUT with a simplifications and without any additional libs.
And it will work with any text you type...
var lettering = function(node,text){
var str = typeof text=='undefined'
?node.textContent
:text;
node.innerHTML='';
var openTag = '<span>';
var closeTag = '</span>';
var newHTML = openTag;
var closeTags = closeTag;
for(var i=0,iCount=str.length;i<iCount;i++){
newHTML+=str[i]+openTag;
closeTags+=closeTag;
}
node.innerHTML = newHTML+closeTags;
}
lettering(
document.getElementById('text'),
Math.round(Math.random()*1000) + ' : Hello world!!!'
);
.badge {
position: relative;
width: 400px;
border-radius: 50%;
transform: rotate(-50deg);
}
h1 span {
font: 26px Monaco, MonoSpace;
height: 200px;
position: absolute;
width: 20px;
left: 0;
top: 0;
transform-origin: bottom center;
transform: rotate(10deg);
}
<div class='badge'>
<h1 id="text">Any custom text you type...</h1>
</div>