svg width in morphing animation - javascript

Hell0, I can't get my svg to take the whole width of the screen!
it doesn't matter if they are distorted or not because the idea of this use is a kind of morphing to change the background color of my page
here is my css:
.container {
height: 5000px; /* hauteur de la page */
}
.img {
width: 100%;
height: 100vh;
object-fit: fill;
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
transition: opacity 0s ease-in-out;
opacity: 0;
}
.img.transition {
transition: opacity 0s ease-in-out;
}
.img.active {
opacity: 1;
}
the complete code is here : codepen
Thank you

I think adding viewBox parameter to your svg's might help. The 3th and 4th number give it a relative width and height. In the example below, giving it 100% w x h.
Check this out for more info -> https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
Also you cannot use the same CSS properties for HTML nodes, also for SVG. Properties like object-fit, margin, position,etc... wil not work on SVG elements, unfortunately.
More info on that here -> https://css-tricks.com/svg-properties-and-css/
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" />
</svg>

Related

Transform transition on button makes child SVG jump position at beginning and end of transition

I am currently creating a Stencil component library and one of the components is a navigation button which has an SVG icon that scales on hover to give a pop effect. To achieve this effect I put a scale transform on the SVG with an ease transition.
The problem is that when I hover over the button, just before the transitions starts, the icon jumps on some of the buttons instances (pretty randomly, depending on where on the page the button is on the page sometimes up, down, left and right) and then when the transient has ended it jumps back (sometimes not even the same amount or direction as the first jump)
<my-element></my-element>
<my-element></my-element>
<my-element></my-element>
<script>
customElements.define("my-element", class extends HTMLElement {
constructor() {
super()
.attachShadow({mode: "open"})
.innerHTML = `
<style>
:host {
display: inline-block;
}
button {
display: block;
border-radius: 8px;
margin: 0;
padding: 0.6rem;
border: none;
cursor: pointer;
}
svg {
display: block;
width: 4rem;
height: 4rem;
padding: 0;
margin: 0;
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
transform: scale(1);
}
:host(:not([active]):not([disabled])) button:hover svg {
transform: scale(1.2);
}
</style>
<button disabled={this.disabled}>
<svg>
<use href="#circ">
<?xml version="1.0" encoding="UTF-8"?>
<svg height="24" width="24">
<symbol viewBox="0 0 24 24" id="circ">
<circle cx="12" cy="12" r="12" stroke="none" stroke-width="3" fill="red" />
</symbol>
</svg>
</use>
</svg>
</button>`;
}
});
</script>
This problem is browser agnostic and I've tried for quite a few hours now to figure out what's causing it. It seems removing all padding and margins resolves the issue but that's not really a solution. What I find very strange is if I put the sag inside of a collared div and add the scale transition to the div instead of the SVG, the div scales smoothly without the jump, but the SVG inside the div does the same weird jumps.
Inline elements behave differently than block elements when it comes to transitions/animations. Your div is a block element whereas the svg is an inline one.
Try to make the svg an inline-block element, or stick on a block element to achieve it.
svg {
display: inline-block;
}

How to make half the border of a circle transparent

I have a minigame that the user has 60 seconds to solve. To indicate the remaining time, I use a number that will start at 60 and start going down 1 per second until reaching 0. This number will be inside a transparent circular div with a border:
.circle {
width: 100px;
height: 100px;
border: 3px solid #2F4491;
border-radius: 100%;
}
I'm trying to make the border dissapear proportionally to the remaining time: The border will be fully visible at the beginning (60s remaining), only the left side visible when the user only has 30s remaining, and so on.
Any idea on how to achieve this?
Try this.
var time = 60;
var initialOffset = '440';
var i = 1
/* Need initial run as interval hasn't yet occured... */
$('.circle_animation').css('stroke-dashoffset', initialOffset-(1*(initialOffset/time)));
var interval = setInterval(function() {
$('h2').text(i);
if (i == time) {
clearInterval(interval);
return;
}
$('.circle_animation').css('stroke-dashoffset', initialOffset-((i+1)*(initialOffset/time)));
i++;
}, 1000);
.item {
position: relative;
float: left;
}
.item h2 {
text-align:center;
position: absolute;
line-height: 125px;
width: 100%;
}
svg {
-webkit-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.circle_animation {
stroke-dasharray: 440; /* this value is the pixel circumference of the circle */
stroke-dashoffset: 440;
transition: all 1s linear;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="item html">
<h2>0</h2>
<svg width="160" height="160" xmlns="http://www.w3.org/2000/svg">
<g>
<title>Layer 1</title>
<circle id="circle" class="circle_animation" r="69.85699" cy="81" cx="81" stroke-width="8" stroke="#78cef1" fill="none"/>
</g>
</svg>
</div>
Set border-right-color and border-bottom-color to transparent when the time is below 30s. Also, you will have to rotate the object -45deg, so you will have it half-right and half-left.
When fade out, do the same with bottom and top.

How to animate a CSS-loaded SVG background with JavaScript

I have the following SVG (shortened version).
.line {
width: 100%;
height: 500vh;
margin-top: 100px;
opacity: 0.8;
background:
linear-gradient(to bottom, #fff, transparent) top/100% 1024px no-repeat,
linear-gradient(to top, #fff, transparent) bottom/100% 128px no-repeat,
url(line.svg) top/768px;
}
<?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 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="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">
<style>
path {
transition: opacity 512ms ease-in-out;
}
.rise {
opacity: 0.2;
}
.fall {
opacity: 1;
}
</style>
<g>
<path fill="#070707" d="M109.021,87.07c1.871,1.233,1.874,3.713,3.569,5.022c0.051-0.372,0.073-0.78,0.042-1.163l-0.426-0.236
c2.157-5.078-5.299-7.254-8.281-7.586c-2.127-0.236-4.292-0.489-6.372-1.008c-2.521-0.63-3.054-1.987-4.201-4.195
c-0.397,5.932,5.381,6.908,9.51,7.333C104.642,85.419,107.502,86.07,109.021,87.07z"/>
<path fill="#070707" d="M200,199.422c-0.219,0.195-0.438,0.391-0.664,0.58H200V199.422z"/>
</g>
<script type="text/javascript"><![CDATA[
var els = document.querySelectorAll('path')
for (var i = 0, n = els.length; i < n; i++) {
var el = els[i]
animateIn(el, Math.floor(Math.random() * 2048))
}
function animateIn(el, stagger) {
setTimeout(function(){
el.classList.add('rise')
animateOut(el, 512)
}, stagger)
}
function animateOut(el, stagger) {
setTimeout(function(){
el.classList.add('fall')
animateIn(el, 512)
}, stagger)
}
]]></script>
</svg>
I don't think that works, but it's the gist of the code. Basically, I have added some JavaScript straight to the SVG, to animate the opacity of each separate path in and out. I want it to sort of "sparkle".
But this isn't working if I style an element with this .line class. It successfully draws the SVG in a repeating fashion, but it doesn't do the animation. I'm wondering how to accomplish this. I don't want to use a purely inline SVG which I could directly animate in a similar way, because I want to use this SVG on multiple pages and don't want to load it inline on each page. But if that's the only way to do it that would be good to know.
Do I need something like this?
Basically my HTML document is like this:
<html>
<body>
<section>something</section>
<section class='line'></section>
<section>something else</section>
</body>
</html>
The .line class sets the CSS background-image to the line.svg file.
EDIT3 (FINAL): What I alluded to in EDIT2 below IS possible and here it is, since I don't have your "line.svg" and I wanted to show a working snippet, I just inlined svg binary into my css , this should be interchangeable with a proper svg file (as in: if .line had background: url("line.svg") it will work identically to my example)
Next time PLEASE post the whole question before publishing. That took way too many edits due to the question being changed.
#keyframes shine {
0% {
opacity: .2;
}
100% {
opacity: 1;
}
}
.line {
/*transition: opacity 512ms ease-in-out;*/
animation: shine 1s ease-in-out infinite;
width: 50px;
height: 50px;
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHg9IjBweCIgeT0iMHB4Igp3aWR0aD0iNTAiIGhlaWdodD0iNTAiCnZpZXdCb3g9IjAgMCA1MCA1MCIKc3R5bGU9IiBmaWxsOiMwMDAwMDA7Ij48ZyBpZD0ic3VyZmFjZTEiPjxwYXRoIHN0eWxlPSIgIiBkPSJNIDQ0Ljg2MzI4MSA3IEwgMzguMTY3OTY5IDcgQyAzNi4zOTQ1MzEgNyAzNSA4LjI1IDM1IDEwIEwgMzUgMTQgTCAxNSAxNCBMIDE1IDEwIEMgMTUgOC4yNSAxMy41ODU5MzggNyAxMS44MTI1IDcgTCA1LjEzNjcxOSA3IEMgMy40MDYyNSA3IDIgOC4zNzUgMiAxMC4xNzU3ODEgTCAyIDM5LjY0MDYyNSBDIDIgNDEuNTU4NTk0IDMuMzgyODEzIDQzIDUuMTEzMjgxIDQzIEwgNDQuODg2NzE5IDQzIEMgNDYuNjE3MTg4IDQzIDQ4IDQxLjU1ODU5NCA0OCAzOS43NjE3MTkgTCA0OCAxMC4xNzU3ODEgQyA0OCA4LjA1ODU5NCA0Ni41OTM3NSA3IDQ0Ljg2MzI4MSA3IFogTSAxNSAzMyBDIDEyLjI0MjE4OCAzMyAxMCAzMC43NTc4MTMgMTAgMjggQyAxMCAyNS4yNDIxODggMTIuMjQyMTg4IDIzIDE1IDIzIEMgMTcuNzU3ODEzIDIzIDIwIDI1LjI0MjE4OCAyMCAyOCBDIDIwIDMwLjc1NzgxMyAxNy43NTc4MTMgMzMgMTUgMzMgWiBNIDM1IDMzIEMgMzIuMjQyMTg4IDMzIDMwIDMwLjc1NzgxMyAzMCAyOCBDIDMwIDI1LjI0MjE4OCAzMi4yNDIxODggMjMgMzUgMjMgQyAzNy43NTc4MTMgMjMgNDAgMjUuMjQyMTg4IDQwIDI4IEMgNDAgMzAuNzU3ODEzIDM3Ljc1NzgxMyAzMyAzNSAzMyBaICI+PC9wYXRoPjwvZz48L3N2Zz4=') 50% 50% no-repeat;
background-size: 100%; }
}
<html>
<body>
<section>something</section>
<section class='line'></section>
<section>something else</section>
</body>
</html>
EARLIER (before Question-er updated question)
If I understand your question and code - you want to have that same 'fade-in and out' effect but without the inline javascript. You can seperate js from the html and add that svg path with js.
window.onload=function() {
var line=document.getElementsByClassName("line")[0];
console.log(line);
/* not sure why I had to concatonate the various pieces, prob because of the code snippet editor in SO */
line.innerHTML='<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="200px" height="200px" viewBox="0 0 200 200" enable-background="new 0 0 200 200" xml:space="preserve">'+
'<g>'+
'<path class="myPath" fill="#070707" d="M109.021,87.07c1.871,1.233,1.874,3.713,3.569,5.022c0.051-0.372,0.073-0.78,0.042-1.163l-0.426-0.236'+
'c2.157-5.078-5.299-7.254-8.281-7.586c-2.127-0.236-4.292-0.489-6.372-1.008c-2.521-0.63-3.054-1.987-4.201-4.195'+
'c-0.397,5.932,5.381,6.908,9.51,7.333C104.642,85.419,107.502,86.07,109.021,87.07z"/>' +
'<path class="myPath" fill="#070707" d="M200,199.422c-0.219,0.195-0.438,0.391-0.664,0.58H200V199.422z"/>'+
'</g>'+
'</svg>';
};
.line {
/*transition: opacity 512ms ease-in-out;*/
animation: shine 1s ease-in-out infinite;
}
#keyframes shine {
0% {
opacity: .2;
}
100% {
opacity: 1;
}
}
<html>
<body>
<section>something</section>
<section class='line'></section>
<section>something else</section>
</body>
</html>
NOTE: the above is the OLD snippet, please scroll up in same answer for the final answer which is in the first snippet
EDIT2: ...I believe it may be doable without js, by bringing in line.svg as the background for .line elements and using my css to animate it, but it's bed-time :)...

Animate dot after dot from an image using CSS3 or jQuery

I want to animate dot after dot from the below image but my problem is with the curved section of the image (bottom of the image).
At the start, all dots should be hidden and then one by one each dot should be animated into view.
I have the below code:
<div id="dots1"></div>
#dots1 {
-moz-transition: height 1s linear;
-o-transition: height 1s linear;
-webkit-transition: height 1s linear;
transition: height 1s linear;
position: absolute;
left: 50%;
z-index: 1;
margin: 0 0 0 -1px;
width: 3px;
height: 0;
background: url(image/pic.png) 0 0 no-repeat;
}
You can achieve this effect using two SVG path elements like in the below snippet. Two paths in the form of the curved line that you need is created. One path (which is at the bottom) has the dot pattern for the stroke (black colored) and another duplicate path which is on top. The duplicate path stroke is set such that for one full length of the path it is white in color and for another length it is transparent.
An animation is added on the duplicate path to animate stroke's offset. As offset is animated, the white portion of the stroke slowly moves out of view and the transparent portion starts coming into view. As the white portion starts going out of view, the black dots below it start getting revealed.
It is a bit complex to understand at start but once you get familiar with path, stroke-dasharray and stroke-dashoffset it will look simple.
svg {
height: 400px;
}
path {
fill: none;
}
path.dot {
stroke: black;
stroke-dasharray: 0.1 4;
stroke-linecap: round;
}
path.top {
stroke: white;
stroke-width: 2;
stroke-dasharray: 250;
stroke-linecap: round;
animation: dash 15s linear forwards;
}
#keyframes dash {
from {
stroke-dashoffset: 0;
}
to {
stroke-dashoffset: -250;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg viewBox='0 0 100 100'>
<path d='M1,1 1,45 C1,60 30,60 30,75 C30,90 1,90 1,100' class='dot' />
<path d='M1,1 1,45 C1,60 30,60 30,75 C30,90 1,90 1,100' class='top' />
</svg>
Try the following:
HTML
<div id="dots">
<img src="http://i.stack.imgur.com/oxUh8.png">
</div>
jQuery
$("#dots").css("height", "514px");
CSS
#dots{
overflow: hidden;
height: 10px;
transition: all 3s cubic-bezier(.5, 1, 0, .5);
}
See: https://jsfiddle.net/brezkryx/

Zoom Effect when Page is Loaded Doesn't Work as Wanted

I am trying to get an effect which is to zoom in on a logo centred on the page when the page is loaded. I am using the following HTML and JS code:
<div style="display: table-cell; vertical-align: middle; text-align: center;">
<img id="logo" src="images/logo2.png" style="zoom: 200%; transition: zoom 1s ease-in-out;"/>
</div>
JS
document.addEventListener("load", pageFullyLoaded, true);
function pageFullyLoaded()
{
var elem = document.getElementById("logo");
elem.style.zoom = "300%";
}
The result is really odd.
It display the logo in it's normal size,
then it jumps on a super zoomed in version of the logo (> 1000%),
zoom in on the logo even more (1000% to 1500% say) for the duration of the transition,
jump back to the normal logo size and position (which is correct, and this is the final positon and size I want).
So obviously this technique doesn't work:
the jump at the beginning is ugly but I only suppose this happens because 2) is incorrect anyway. As it should start by default with a zoom value of 200% (which is defined in the style of the div) and then the JS should make it zoom to 300%. So there should be no jump visible really.
I don't understand why I get this incredibly zoomed in version of the logo at the start of the animation. Basically it's almost like if the entire image was filling up the screen.
Any idea on how to do this reliably, please? Thank you.
I would do this in only CSS like so:
Set the image to scaleX and scaleY 0 (or hide it in some other way)
On $(window).load or $('document').ready add a class with keyframe animations
Do whatever you need afterwards.
Fiddle
$(window).load(function(){
$('img.zoom').addClass('element-animation');
});
You can also listen to animation end events like so https://github.com/daneden/animate.css#usage
That library (Animate.css) is also pretty handy and you might be able to find some useful effects in it.
If you're looking to scale an image, you don't need to use zoom or transform or anything. Just alter the width directly and the browser will scale the image for you:
http://jsfiddle.net/C4JZv/
HTML:
<div class="wrapper">
<img class="tiny" src="http://placehold.it/200x150" />
</div>
CSS:
.wrapper {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.wrapper img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
transition: width 1s ease-in-out;
width: 200px;
}
.wrapper img.tiny {
width: 10px;
}
JS:
document.querySelector('.wrapper img').className = "";
EDIT: You mentioned in the comments that you wanted to see this done using transform. Again, it's just a case of having a shrunken image (using transform's scale), having a transition property and then removing the CSS class that shrinks the image:
http://jsfiddle.net/C4JZv/1/
HTML & JS: Same
CSS: Mostly the same, but with a couple of changes (plus a load of vendor prefixes):
.wrapper img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
-webkit-transition: -webkit-transform 1s ease-out;
-moz-transition: -moz-transform 1s ease-out;
-ms-transition: -ms-transform 1s ease-out;
-o-transition: -o-transform 1s ease-out;
transition: transform 1s ease-out;
}
.wrapper img.tiny {
-moz-transform: scale(0.1);
-webkit-transform: scale(0.1);
-o-transform: scale(0.1);
-ms-transform: scale(0.1);
transform: scale(0.1);
}

Categories