I'm trying to build a webpage for a comic studio and I want one of the characters to come in from the side every so often. So far I have this in the css
.charc {
animation:peek 20s infinite;
left:-500px
}
#-webkit-keyframes peek{
1% {transform:translateX(-500px)}
10%{transform:translateX(100px)}
20% {transform:translateX(-200px)}
100% {transform:translateX(-500px)}
}
and the html
<img src="character.jpg" class="charc"/>
This means the character comes on over and over again. I don't know whether it is possible to get random figures in CSS but I thought if it is, You guys would know
p.s. I know this will only work in chrome but I will be changing that soon.
You need to use js/jQuery for that.
function move() {
$('.charc')
.animate({
left: '-500px'
}, 200)
.animate({
left: '100px'
}, 400)
.animate({
left: '50px'
}, 400)
.animate({
left: '-500px'
}, 100, function() {
var nextIn = Math.floor(Math.random() * 1000);
setTimeout('move()', nextIn);
})
}
$(document).ready(function() {
move();
});
#scene {
width: 500px;
height: 100px;
border: 2px solid black;
margin: 20px;
}
.charc {
position: absolute;
left: -500px;
top: 20px;
width: 20px;
height: 20px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="scene">
<div class="charc"></div>
</div>
It is possible with js :
var divElement = document.getElementsByClassName("charc")[0];
var maxValue = 20; //the random value won't exceed 20s
function randomTime(maxvalue){
return Math.round(Math.random() * maxvalue );
}
function changeAnimationTime(maxValue){
var random = randomTime(maxValue);
divElement.style.animation = "peek "+randomTime+"s infinite";
setTimeout(function(){
changeAnimationTime(maxValue);
},random);
}
changeAnimationTime(maxValue);
The advantage of this methode is that you won't use js for animation but just for generating values. So it consumes less ressources.
Not a random delay but you can use a tool I created called WAIT! Animate to add a pause between animations. Here's your animation with a 2 second pause between animations:
.peek.wait2.animated {
animation: peek-wait2 22s linear infinite;
transform-origin: 50% 50%
}
#keyframes peek-wait2 {
0% { transform:translateX(-500px) }
9.09091% { transform:translateX(100px) }
18.18182% { transform:translateX(-200px) }
90.90909% { transform:translateX(-500px) }
100% { transform:translateX(-500px) }
}
Use WAIT! Animate to change the pause duration.
PS. I suggest starting at 0% to avoid a flicker in the animation.
Related
I have created an animation for an element on my page and it always runs when the page is refreshed but i would like the animation to play when an element is clicked. How would i go about doing this?
CSS:
#login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
HTML:
<p id="clickMe">Element to click</p>
$('#clickMe').click(function () {
$(this).addClass('login-or-signup-selection');
$(this).on("animationend", function(event) {
$(this).removeClass('login-or-signup-selection')
});
});
.login-or-signup-selection {
display: flex;
animation-name: test;
animation-duration: 5s;
position: relative;
height: 70%;
}
#keyframes test {
0% {top: 0px;}
50% {top:300px}
100% {top: 0;}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="clickMe">Element to click</p>
If you want only css and don't even care about js onclick events for now,
use the :active pseudo selector.
The only downside is that it only plays while (=during) e.g. the mouse button is down.
You would need some JavaScript for this.
First off, separate the CSS animation properties, and anything else related to your animation, and add them to their own class.
Next up, the JavaScript. You'll want to add an event listener to your element to add the animation class when clicked, and a timeout to remove the class afterwards so it will animate when clicked again.
const yourElement = document.getElementById('clickMe');
yourElement.addEventListener('click', _=> {
yourElement.classList.add('animation-class');
setTimeout(
_=> yourElement.classList.remove('animation-class'),
5000
)
});
#clickMe {
display: flex;
position: relative;
height: 70%;
}
.animation-class {
animation-name: test;
animation-duration: 5s;
}
#keyframes test {
0% { top: 0px; }
50% { top: 300px; }
100% { top: 0; }
}
<p id="clickMe">Element to click</p>
You need JavaScript for this.
If you add an event listener on the p element to listen for a click, this can then add the animation name to the selection div.
But you need to also listen for the end of the animation, otherwise subsequent clicks will have no effect. On animation end this snippet removes the animation name.
Note also that in order to be absolutely sure that the first (onload) animation end is trapped, the first animation name is not set until the event listeners have been set up.
function init() {
const clickMe = document.querySelector('#clickMe');
const selection = document.querySelector('#login-or-signup-selection');
clickMe.addEventListener('click', function() {
selection.style.animationName = 'test';
});
selection.addEventListener('animationend', function() {
selection.style.animationName = '';
});
selection.style.animationName = 'test';
}
window.onload = init;
#login-or-signup-selection {
display: flex;
animation-duration: 5s;
animation-iteration-count: 1;
position: relative;
height: 70%;
}
#keyframes test {
0% {
top: 0px;
}
50% {
top: 300px
}
100% {
top: 0;
}
}
<p id="clickMe">Element to click</p>
<div id="login-or-signup-selection">Login or signup selection</div>
I want to make a flutter timer app which will fill the screen from bottom to top with a color. I think i can do that by incrementing the size of the container with respect to time but i want the text as shown in the image. Please someone help me with this.
It changes the color of the text as the size of the container, which fills the screen, increases.
I can offer a solution for css. The timer counter will be displayed with rule content: '', with a cycle of 10 seconds and a delay of 1 second before this animation starts.
.timer:after {
content: "0";
animation: timer 10s 1s forwards;
}
The complete css code shows how 10 seconds are distributed over a percentage of 100%.
#keyframes timer {
10% {
content: "1";
}
...
100% {
content: "10";
}
}
I used rule mix-blend-mode: difference to invert the background color.
The mix-blend-mode CSS property sets how an element's content should blend with the content of the element's parent and the element's background.
I changed the height of the dynamic background element using rule top, and animated it in a similar way using rule animation and #keyframes.
#keyframes background_top {
from {
top: 100%;
}
to {
top: 0%;
}
}
The #keyframes rule sets keyframes when animating an element. A keyframe is an element's properties (transparency, color, position, etc.) that should be applied to an element at a given moment in time. Thus, animation is a smooth transition of style properties from one keyframe to another. The calculation of intermediate values between such frames is taken over by the browser.
body {
margin: 0;
}
.wrapper {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: lightgrey;
position: relative;
}
.background {
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: brown;
mix-blend-mode: difference;
animation: background_top 10s 1s forwards;
}
.timer:after {
content: "0";
animation: timer 10s 1s forwards;
font-size: 10em;
color: lightseagreen;
}
#keyframes timer {
10% {
content: "1";
}
20% {
content: "2";
}
30% {
content: "3";
}
40% {
content: "4";
}
50% {
content: "5";
}
60% {
content: "6";
}
70% {
content: "7";
}
80% {
content: "8";
}
90% {
content: "9";
}
100% {
content: "10";
}
}
#keyframes background_top {
from {
top: 100%;
}
to {
top: 0%;
}
}
<div class="wrapper">
<div class="timer"></div>
<div class="background"></div>
</div>
There is a simple way of doing this in flutter with CustomPaint.
The only thing you have to change is the StatelessWidget to a StatefulWidget so that the animation is possible, however I would recommend using something like hooks this package can make animation pretty simple.
class TextWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: CustomPaint(
size: Size(MediaQuery.of(context).size.width,
MediaQuery.of(context).size.height),
painter: TimerPainter(text: "6", height: 500),
));
}
}
class TimerPainter extends CustomPainter {
TimerPainter({required this.text, required this.height});
final String text;
final double height;
#override
void paint(Canvas canvas, Size size) {
// ========================================== TextPainter
final TextPainter textPainter = TextPainter(
textDirection: TextDirection.ltr,
text: TextSpan(
text: text,
style: TextStyle(
color: Colors.greenAccent,
fontSize: 500,
),
))
..layout();
textPainter.paint(
canvas,
Offset(size.width / 2 - textPainter.width / 2,
size.height / 2 - textPainter.height / 2));
// ============================================== Rect
final rectPaint = Paint()
..color = Colors.greenAccent
..blendMode=BlendMode.difference;
canvas.drawRect(
Offset(0, size.height / 2) & Size(size.width, height), rectPaint);
final rectPaint2 = Paint()
..color = Colors.white
..blendMode=BlendMode.difference;
canvas.drawRect(
Offset(0, size.height / 2) & Size(size.width, height), rectPaint2);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
this is how it looks
I have an animation where a div slides out the view, however when the animation is completed, the div just returns to its origin position in the view. How do I totally remove the div or hide it after the animation ends using just CSS?
Here is the markup:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
and the css:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-image: url(../pics/red.png);
background-position: center;
background-size: cover;
background-repeat: no-repeat;
animation: slide 5s linear 1;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
overflow: hidden;
visibility: hidden;
}
}
I don't want it to fade out over the duration of the animation, i just want it to disappear once it hits 100% in the keyframe. Thanks ahead of time!
Use the animation-fill-mode option. Set it to forwards and the animation ends at it's final state and stay like that.
Altered based upon comments Set opacity fade to just last 1% of animation... simplified keyframes. Added a jquery option to literally remove the div from the DOM. CSS alone won't alter the markup, where jQuery will.
Although you can't animate the display property. If you want the div totally gone, after the opacity fades to zero, you can then add the display property to remove the div. If you don't wait for opacity to end, the div will just vanish without any transition.
/*
This jquery is added to really remove
the div. But it'll essentially be
VISUALLY gone at the end of the
animation. You can not use, or
delete the jquery, and you really
won't see any difference unless
you inspect the DOM after the animation.
This function is bound to animation
and will fire when animation ends.
No need to "guess" at timeout settings.
This REMOVES the div opposed to merely
setting it's style to display: none;
*/
$('.slide-box').bind('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function(e) { $(this).remove(); });
.slide-box {
display: block;
position: relative;
left: 0%;
opacity: 1;
width: 100px;
height: 100px;
background: #a00;
animation: slide 1s 1 linear forwards;
/*
animation-name: slide;
animation-duration: 1s;
animation-iteration-count: 1;
animation-timing-function: linear;
animation-fill-mode: forwards;
*/
}
#keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
#-webkit-keyframes slide {
0% {
left: 0%;
opacity: 1;
}
99% {
left: 99%;
opacity: 1;
}
100% {
left: 100%;
opacity: 0;
display: none;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="slide-box" id="slide-box"></div>
</div>
animation: slide 5s linear forwards;
at 100%
opacity: 0;
display: none;
Try this.
Working fiddle: https://jsfiddle.net/jbtfdjyy/1/
UPDATE: JS mani
var slideBox = document.getElementById('slide-box');
setTimeout(function(){
slideBox.style.display = 'none';
}, 5000);
Try this. https://jsfiddle.net/jbtfdjyy/2/
Add something at 99% or so to your keyframes, and set opacity to 1 in that. If you have opacity: 1 at the start, then it will stay that way until 99%. Only at 100% will it change.
It's not technically fired at 100%. If you want that, I'd recommend using some JavaScript here, but this will at least give the illusion you want.
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
99% {
opacity: 1;
}
100% {
left: 100%;
overflow: hidden;
opacity: 0;
display: none;
visibility: hidden;
}
}
UPDATE:
As per your request, here is a JavaScript version. Keep in mind, there are endless ways to accomplish such a task. I am using vanilla JS (no jQuery, etc.), and using ES6 syntax.
What we do here is set a timeout, and at the end of that timeout I broadcast an event animation_end. That event listener will handle the end of the animation (in this case, it adds a class which will handle the fading out). This is much more granular than you need it to be, you could simply do the adding of the class within the setTimeout, but I think it is slightly better this way as you can abstract you can do other things with events such as animation start, etc.
Here is the fiddle: https://jsfiddle.net/vmyzyd6p/
HTML:
<div class="container">
<div class="slide-box" id="slide-box""></div>
</div>
CSS:
.slide-box {
position: relative;
width: 100px;
height: 100px;
background-color: blue;
animation: slide 3s linear 1;
-webkit-transition: opacity 2s ease-in-out;
-moz-transition: opacity 2s ease-in-out;
transition: opacity 2s ease-in-out;
}
.animationEnd {
opacity: 0;
}
#keyframes slide {
0% {
left: 0;
}
20% {
left: 20%;
}
40% {
left: 40%;
}
60% {
left: 60%;
}
80% {
left: 80%;
}
100% {
left: 100%;
}
}
JavaScript:
// Create a function that handles the `animation_end` event
const animationEnd = () => {
// Grab the slidebox element
let slideBox = document.getElementById('slide-box');
// Get the class of the slidebox element
let slideClass = slideBox.getAttribute('class');
// Add the animation end class appended to the previous class
slideBox.setAttribute('class', slideClass + ' animationEnd');
};
// Create the animation end event
let animationEndEvent = new Event('animation_end');
// Cross browser implementation of adding the event listener
if (document.addEventListener) {
document.addEventListener('animation_end', animationEnd, false);
} else {
document.attachEvent('animation_end', animationEnd);
}
// Set the timeout with the same duration as the animation.
setTimeout(() => {
// Broadcast the animation end event
document.dispatchEvent(animationEndEvent);
}, 3000);
I have some CSS code that creates a typing animation (see snippet).
The two lines load simultaneously. How do I make them load one after another?
body{
background: #000;
color: lime;
}
div.a{
font-size: 14px;
margin: 30px;
white-space:nowrap;
overflow: hidden;
width: 30em;
animation: type 5s steps(50, end) 1;
}
#keyframes type{
from{ width: 0;}
}
#keyframes blink{
to{ opacity: .0;}
}
<div class="a">Supercalifragilisticexpialidocious<br /> Another sentence...</div>
Basically you can do that by checking whether the CSS3 Animation has ended or not like explained in this link
http://blog.teamtreehouse.com/using-jquery-to-detect-when-css3-animations-and-transitions-end
then create a function to apply the animation class and call it on jQuery ready, inside the function when the animation ended, check whether there's still another line of sentences that want to be animated
Here's the updated code that should work like what you wanted it to be
nb: this will work only if the sentences is only one line, and if it's more, you must separate it in another element like in the example, also the alert in the end is only to show that the function to animate the typing will not start anymore
nb2: I forgot that the question doesn't include the JavaScript or jQuery tag, but I hope this could help if by chance someone else needed to use the jQuery
var $typeAnimation;
$(function(){
$typeAnimation = $(".view").first();
if($typeAnimation.size() > 0) {
startAnimation();
}
});
function startAnimation() {
$typeAnimation.addClass("animate");
$typeAnimation.one('webkitAnimationEnd oanimationend msAnimationEnd animationend',
function(e) {
$typeAnimation = $typeAnimation.next(".view");
if($typeAnimation.size() > 0) {
startAnimation();
} else {
alert("No More Sentence to be animated");
}
});
}
body{
background: #000;
color: lime;
}
.view {
display: none;
}
.view.animate{
display: block;
font-size: 14px;
margin: 30px;
white-space:nowrap;
overflow: hidden;
width: 30em;
animation: type 5s steps(50, end) 1;
}
#keyframes type{
from{ width: 0;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<div class="view">Supercalifragilisticexpialidocious</div>
<div class="view">Another sentence...</div>
<div class="view">Yet Another sentences...</div>
<div class="view">And Also Another Final sentence...</div>
I am currently having a problem with CSS animations. A random background is called from an array, shows up and changes and so on. I applied two animation for the image caption id, a slide in and a delayed slide out. The slide in and out runs well for the first time, but when the second background shows up, the caption just appears to the screen without any animation.
This is my test page and below is my code.
HTML code:
<script type="text/javascript">
function loadRandomImage(imgs) {
var index = Math.floor(Math.random() * imgs.length);
console.log("loadRandomImages(): index = "+ index);
$.backstretch(imgs[index].url, {duration: 30000, fade: 1200});
$("#caption").html(imgs[index].caption);
}
var images = new Array(); //array of imgs objects
images[0] = {url: "https://s-media-cache-ak0.pinimg.com/736x/a5/47/45/a5474577f4a4ae93c85db719d0cbafd4.jpg", caption: "Caption0"};
images[1] = {url: "https://s-media-cache-ak0.pinimg.com/736x/e6/41/74/e64174e355f78a0f07e951bcec62ca96.jpg", caption: "Caption1"};
images[2] = {url: "https://media.giphy.com/media/3o7abHrsGbV10rCeze/giphy.gif", caption:"Caption2"};
images[3] = {url: "https://media.giphy.com/media/Bbt5FxRiArl3a/giphy.gif", caption:"Caption3"};
// Preload
setTimeout(loadRandomImage, 1000, images);
// Change images every 3 seconds
setInterval(loadRandomImage, 30000, images);
</script>
<div id="pattern"></div>
<div id="pattern2"></div>
<div id="caption"></div>
CSS code:
#caption {
position: relative;
font: 1.5em Trebuchet, sans-serif;
text-align: center;
margin-left: 75%;
z-index: 56;
color: #ffffff;
background: rgba(0, 0, 0, 0.7);
padding: 8px;
animation: slidein 3s, slideout 3s 27s;
}
#caption:empty
{
display: none;
}
#keyframes slidein {
0% {
margin-left: 100%;
width:100%;
visibility:hidden;
opacity: 0;
}
100% {
margin-left: 75%;
width:100%;
opacity: 1;
visibility:visible;
}
}
#keyframes slideout {
0% {
margin-left: 75%;
width:100%;
opacity: 1;
visibility:visible;
}
100% {
margin-left: 100%;
width:100%;
opacity:0;
visibility:hidden;
}
}
CSS animations have iteration count (animation-iteration-count) as only 1 when no value is given for that property. Here since you've not specified any value, the animation executes only once (that is on page load). There is no pure CSS way to re-trigger an animation once it has completed its cycle. It has to be removed from the element and then re-attached for it to start all over again.
So, for your case here is what you have to do - (a) Set the animations on #caption using JS on page load as it makes it easier to remove and re-add them (b) Upon completion of the slideout animation, remove both the animations from the element (that is, set animation-name: none) and also set html of #caption to none because :empty selector would only then hide it. (c) As soon as the next image is set on the element (using loadRandomImage function), set the animations back on the element. This would re-trigger the animation and so during each image switch, the caption would slide-in and out.
Note: I've changed some parts in the HTML and JS that are not relevant to this answer (like removing the two div and replacing them with 1, avoiding the $.backstretch and loading image using css() etc. But these are only auxiliary items and will not affect the crux of this answer (which is, to remove and add the animations).
function loadRandomImage(imgs) {
var index = Math.floor(Math.random() * imgs.length);
$('#img').css('background-image', 'url(' + images[index].url + ')');
$('#caption').css({
'animation-name': 'slidein, slideout',
'animation-duration': '3s, 3s',
'animation-delay': '0s, 7s'
});
$("#caption").html(imgs[index].caption);
}
var images = new Array(); //array of imgs objects
images[0] = {
url: "http://lorempixel.com/100/100/nature/1",
caption: "Caption0"
};
images[1] = {
url: "http://lorempixel.com/100/100/nature/2",
caption: "Caption1"
};
images[2] = {
url: "http://lorempixel.com/100/100/nature/3",
caption: "Caption2"
};
images[3] = {
url: "http://lorempixel.com/100/100/nature/4",
caption: "Caption3"
};
// Preload
setTimeout(loadRandomImage, 1000, images);
$('#caption').on('animationend', function(e) {
if (e.originalEvent.animationName == 'slideout') {
$('#caption').css('animation-name', 'none');
$('#caption').html('');
setTimeout(function() { /* dummy timeout to make sure browser sees animation as none before adding it again */
loadRandomImage(images);
}, 0);
}
});
#caption {
position: relative;
font: 1.5em Trebuchet, sans-serif;
text-align: center;
margin-left: 75%;
z-index: 56;
color: #ffffff;
background: rgba(0, 0, 0, 0.7);
padding: 8px;
}
#caption:empty {
display: none;
}
#keyframes slidein {
0% {
margin-left: 100%;
width: 100%;
visibility: hidden;
opacity: 0;
}
100% {
margin-left: 75%;
width: 100%;
opacity: 1;
visibility: visible;
}
}
#keyframes slideout {
0% {
margin-left: 75%;
width: 100%;
opacity: 1;
visibility: visible;
}
100% {
margin-left: 100%;
width: 100%;
opacity: 0;
visibility: hidden;
}
}
/* Just for demo */
#img {
height: 100px;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="img"></div>
<div id="caption"></div>
The animationend event still requires vendor prefixes in some browsers.
You need to use a callback, which is explained here:
How do create perpetual animation without freezing?
I think the animation direction needs to be altered.
These are the possibilities:
animation-direction: normal|reverse|alternate|alternate-reverse|initial|inherit;
I think you need to do one of these:
alternate
The animation will be played as normal every odd time (1,3,5,etc..) and in reverse direction every even time (2,4,6,etc...)
alternate-reverse
The animation will be played in reverse direction every odd time (1,3,5,etc..) and in a normal direction every even time (2,4,6,etc...)
At the moment it is set as
animation-direction: initial, initial;
Seen here: http://www.w3schools.com/cssref/css3_pr_animation-direction.asp
Rather than the Javascript suggestions already provided, you could do a straight CSS solution.
Just set animation-iteration-count to "infinite" (to continuously alternate the 2 elements, or an integer for a set number of repeats)
If you want staggered / alternating animations:
Use an animation-delay (matching the animation-duration) on the second element so it doesn't appear until the first element animation has completed
Build a delay onto the end of your animation (revert to original state # 50%) so that the first element stays hidden while the second animates.