I'm making time(second) bar.
When opening page, bar's width should be (second/60)*100%.
I want to start from 50% instead of the beginning.
Using jquery or javascript.
Please tell me about.
#loader {
width: 50%;
height: 5px;
background-color: #fff;
animation-name: loadingBar;
animation-duration: 60s;
animation-timing-function: steps(60, end);
animation-direction: normal;
animation-play-state: running;
animation-iteration-count: infinite;
#keyframes loadingBar {
0% {
width: 0%;
}
100% {
width: 100%;
}
}
Hi Could you try this overwrite the style existing.And also remove it if required to get old behavior
function setStyle() {
let st = document.createElement("style");
st.id="RemoveMeInFuture";
const stext=`#keyframes loadingBar {
50% {
width: 0%;
}
100% {
width: 100%;
}
}
.foo{background:red}`;
document.querySelector("head").appendChild(st);
if (st.styleSheet){
// This is required for IE8 and below.
st.styleSheet.cssText = stext;
} else {
st.appendChild(document.createTextNode(stext));
}
}
Related
I created a simple HTML game, which disappears under the screen when I click on a moving box.
However, the animation that disappears starts at the original location, not where it was clicked.
I think 0% of the remove #keyframes should have the location of the click, but I couldn't find a way
How shall I do it?
(function () {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.remove(`f${target.dataset.id}`);
target.classList.add('f0');
target.classList.add('remove');
setTimeout(() => { stage.removeChild(target) }, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
0% {
transform: translateX(0);
}
100% {
transform: translateX(30vw);
}
}
#keyframes remove {
0% {
transform: translate(0);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
animation: moving infinite alternate;
}
.remove {
animation: remove 0.2s cubic-bezier(.68,-0.55,.27,1.55) forwards;
}
.f0 {
background-color: black;
animation-duration: 2s;
}
.f1 {
left: 5%;
bottom: 5%;
animation-duration: 2s;
background-color: red;
}
<div class="stage">
<div class="character f1" data-id="1"></div>
</div>
Change the first animation to consider left instead of translate then append both of them to the element initially and you simply toggle the animation-play-state when adding the remove class
(function() {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.add('remove');
setTimeout(() => {
stage.removeChild(target)
}, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
100% {
left:calc(95% - 50px);
}
}
#keyframes remove {
50% {
transform: translateY(-30vh);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background:red;
left: 5%;
bottom: 5%;
animation:
moving 2s infinite alternate,
remove 1s cubic-bezier(.68, -0.55, .27, 1.55) forwards paused;
}
.remove {
animation-play-state:paused,running;
background: black;
}
<div class="stage">
<div class="character f1" data-id="1"></div>
</div>
If your use case is to deal with a lot of such boxes and complexity, it's better to go with handling everything with pure JS but I tried to make this work with minimal changes in JS and CSS.
I have added comments to the new JS lines.
Also taken the liberty to have a separate class with name moving for animation moving so that we can remove it on click.
(function () {
const charactersGroup = document.querySelectorAll('.character');
const stage = document.querySelector('.stage')
const clickHandler = (e) => {
const target = e.target;
if (target.classList.contains('character')) {
target.classList.remove(`f${target.dataset.id}`);
target.classList.add('f0');
// remove the moving animation
target.classList.remove('moving');
// Get offsetWidth which is the half of width to substract later while calculating left for the target i.e our box.
const offsetWidth = parseInt(getComputedStyle(target).width)/2;
// e.clientX gives us the x coordinate of the mouse pointer
// target.getBoundingClientRect().left gives us left position of the bounding rectangle and acts as a good offset to get the accurate left for our box.
target.style.left = `${e.clientX -target.getBoundingClientRect().left - offsetWidth}px`;
target.classList.add('remove');
setTimeout(() => { stage.removeChild(target) }, 2000);
}
}
stage.addEventListener('click', clickHandler);
}());
.stage {
overflow: hidden;
position: relative;
background: #eeeeaa;
width: 40vw;
height: 20vw;
}
#keyframes moving {
0% {
transform: translateX(0);
}
100% {
transform: translateX(30vw);
}
}
#keyframes remove {
0% {
transform: translate(0vh);
}
100% {
transform: translateY(60vw);
}
}
.character {
position: absolute;
width: 50px;
height: 50px;
background-repeat: no-repeat;
background-position: 50% 50%;
background-size: contain;
}
.moving{
animation: moving infinite alternate;
}
.remove {
animation: remove 0.2s cubic-bezier(.68,-0.55,.27,1.55) forwards;
}
.f0 {
background-color: black;
animation-duration: 2s;
}
.f1 {
left: 5%;
bottom: 5%;
animation-duration: 2s;
background-color: red;
}
<div class="stage">
<div class="character moving f1" data-id="1"></div>
</div>
I'm still learning JavaScript, and not too familiar with it or I have just flat out forgotten it. But I have a button on my page that looks like this:
function hiddenjs() {
var x = document.getElementById("hiddenjs");
if (x.style.display === "block") {
x.style.display = "none";
} else {
x.style.display = "block";
}
}
.hiddenjsa {
margin: 0 auto;
background-color: red;
animation-name: expandz;
animation-duration: 1.5s;
animation-timing-function: ease-out;
animation-delay: 0;
animation-direction: alternate;
animation-fill-mode: both;
animation-play-state: running;
}
#keyframes expandz {
0% {
transform: scale(.3);
background-color: red;
border-radius: 100%;
}
50% {
background-color: rgb(71, 8, 8);;
}
100% {
transform: scale(1.5);
background-color: rgb(139, 139, 3);
}
}
<div class="btn4">
<button class="btn4a" onclick="hiddenjs()">List of Other Games I'm going to review!</button>
</div>
<div id="hiddenjs" class="hiddenjsa">
Note: These are NOT clickable links yet as I have yet to review them and add them to the site.
These are just references to which I am in the process of reviewing!
</div>
I was wondering, without jQuery, or any other forms of language if there is a way through JavaScript alone, that you can do a toggle button to do the animation (which I've done) and when you click said button again, it does the animation but in reverse?
I've read up a few things on it but can't find something without copy and pasting a jQuery snippet, and I don't want to do that because I want to understand what I'm doing.
You can set an animation on each click to either expand or reverse the expansion. Instead of display settings, set the scale at the start of the forward animation as 0.
This snippet deliberately has two keyframes which are identical but one set to run in reverse, just to make it clearer what is going on.
function hiddenjs() {
var x = document.getElementById("hiddenjs");
if ( x.style.animationDirection != "normal" ) {
x.style.animationDirection = "normal";
x.style.animationName = "expandz";
}
else {
x.style.animationDirection = "reverse";
x.style.animationName= "expandz1";
}
}
.hiddenjsa {
margin: 0 auto;
transform: scale(0);
background-color: red;
animation-duration: 1.5s;
animation-timing-function: ease-out;
animation-delay: 0;
animation-fill-mode: forwards;
}
#keyframes expandz {
0% { transform: scale(0); }
1% {
transform: scale(.3);
background-color: red;
border-radius: 100%;
}
50% {
background-color: rgb(71, 8, 8);;
}
100% {
transform: scale(1.5);
background-color: rgb(139, 139, 3);
}
}
#keyframes expandz1 {
0% { transform: scale(0); }
1% {
transform: scale(.3);
background-color: red;
border-radius: 100%;
}
50% {
background-color: rgb(71, 8, 8);;
}
100% {
transform: scale(1.5);
background-color: rgb(139, 139, 3);
}
}
<div class="btn4" style=“z-index:100;”>
<button class="btn4a" onclick="hiddenjs()">List of Other Games I'm going to review!</button>
</div>
<div id="hiddenjs" class="hiddenjsa">
Note: These are NOT clickable links yet as I have yet to review them and add them to the site.
These are just references to which I am in the process of reviewing!
</div>
According to the Mozilla Web Animations API docs, "The getAnimations() method of the Document interface returns an array of all Animation objects currently in effect whose target elements are descendants of the document. This array includes CSS Animations, CSS Transitions, and Web Animations."
Is there any way to use this to only add the Web animation objects to the array, excluding the CSS Animations and CSS transitions?
The following code returns all the animations on the document:
var allAnimations;
if (typeof document.getAnimations === 'function') {
allAnimations = document.getAnimations();
} else {
allAnimations = document.timeline.getAnimations();
}
allAnimations array result is this:
Array(72) [ CSSTransition, CSSTransition, CSSTransition, CSSTransition, CSSTransition, CSSTransition, Animation, Animation, Animation, Animation, … ]
I would like it to only consist of the web animations, so like this:
Array(66) [ Animation, Animation, Animation, Animation, Animation, Animation, Animation, Animation, Animation, Animation, … ]
You can check the type of animation you're looking at using instanceof, and use that to filter the list:
const animations = [
...document.getAnimations(),
new Animation(),
];
const isCSSAnimation = x => x instanceof CSSAnimation;
const onlyAnimations = animations.filter(x => x.constructor.name === 'Animation');
console.dir(animations);
console.dir(onlyAnimations);
.animated {
-webkit-animation-duration: .5s;
animation-duration: .5s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
animation-iteration-count: infinite;
-webkit-animation-iteration-count: infinite;
}
#-webkit-keyframes bounce {
0%, 100% {
-webkit-transform: translateY(0);
}
50% {
-webkit-transform: translateY(-5px);
}
}
#keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-5px);
}
}
.bounce {
-webkit-animation-name: bounce;
animation-name: bounce;
}
#animated-example {
width: 20px;
height: 20px;
background-color: red;
position: relative;
top: 100px;
left: 100px;
border-radius: 50%;
}
hr {
position: relative;
top: 92px;
left: -300px;
width: 200px;
}
<div id="animated-example" class="animated bounce"></div>
I am trying to change the animation-name in (loader--text: after) CSS with the help of js Or Jquery but I am only able to change (content) in CSS not able to change animation-name
I have tried:
code:
$('.loader--text').attr("data-content", "Connection Printer"); // It's Working
$('.loader--text').attr("data-animation", "connecting-text"); // But It's Not working
.loader--text:after {
content: attr(data-content);
font-weight: bold;
animation-name: attr(data-animation);
animation-duration: 3s;
animation-iteration-count: infinite;
}
#keyframes connecting-text {
0% {
content: "Connecting Printer";
}
25% {
content: "Connecting Printer.";
}
50% {
content: "Connecting Printer..";
}
75% {
content: "Connecting Printer...";
}
}
#keyframes fetching-text {
0% {
content: "Fetching Story";
}
25% {
content: "Fetching Story.";
}
50% {
content: "Fetching Story..";
}
75% {
content: "Fetching Story...";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='loader--text'></div>
after some research you can only change the content styling with attr method.
you can take a different approach to the task like turning the :after animation to only the dots and use innerHTML for the dom itself.
exmple:
const loader = document.querySelector(".loader--text");
loader.innerHTML = "Connecting Printer";
function changeText() {
loader.innerHTML = "Fetching Story";
}
.loader--text {
cursor: pointer;
}
.loader--text:after {
content: "";
font-weight: bold;
animation-name: dots;
animation-duration: 3s;
animation-iteration-count: infinite;
}
#keyframes dots {
0% {
content: "";
}
25% {
content: ".";
}
50% {
content: "..";
}
75% {
content: "...";
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='loader--text' onclick="changeText()"></div>
you can use attr() in css to pass only string values. animation-name is not a string value
more info : https://css-tricks.com/css-attr-function-got-nothin-custom-properties/
you can change the animation by changing the style.animationName property of the element.
let state = 1;
const square = document.getElementById('square')
document.getElementById('test').addEventListener("click", ()=>{
if(state == 1){
square.style.animationName = "second"
state = 2
} else{
square.style.animationName = "first"
state = 1
}
})
#square{
background: red;
padding: 50px;
width:50px;
height:50px;
/* animation-name: attr(data-animate); */
animation-name: first;
position:absolute;
animation-duration: 2s;
animation-iteration-count: infinite;
}
#keyframes first {
0% {
left: 0
}
100% {
left: 600px;
}
}
#keyframes second {
0% {
top: 0
}
100% {
top: 600px;
}
}
<div id="square" data-animate="first">
</div>
<button id="test">TOGGLE</button>
You can only use attr() for the content attribute in this case.
I'd advise to get rid of jQuery (no hate, I used to love using it), but since you're already using it, you can switch animation name like this:
$('div').css('animation-name', 'anim2');
This of course doesn't apply for pseudo elements (such as :after).
Anyway I think it's much easier to create two separated classes (each one of them applies a different animation) and then just toggle the classes, I think it's much easier to use.
.loader--text.one:after{animation: ...}
.loader--text.two:after{animation: ...}
$('.loader--text').removeClass('one').addClass('two');
I need to chain two animations in my interface HTML/CSS on user event (here just a click on the document). The first animation start correctly, but when I want to restart the second animation nothing move ?
I know if i remove the .rotaiotn class and with a timeout put other animation class for the element, the second animation start from the first position of the element.
I want to know if exist a solution to start the second animation from the position of the blue ball after the first animation ?
document.addEventListener('click', startAnimation, false);
var isFisrtAnim = false;
function startAnimation(evt) {
var elt = document.querySelector('#blue_ball');
if (!isFisrtAnim) {
elt.setAttribute('class', 'rotation');
} else {
elt.setAttribute('class', 'rotation2');
}
elt.addEventListener("animationend", animationAtEnd, false);
}
function animationAtEnd(evt) {
evt.preventDefault();
isFisrtAnim = !isFisrtAnim;
var elt = evt.target;
// todo here get new position of elt to start another animation
// from the new position after first animation
var new_margin_top = window.getComputedStyle(elt).getPropertyValue('margin-top');
var new_margin_left = window.getComputedStyle(elt).getPropertyValue('margin-left');
console.log('At end new margin-top : ' + new_margin_top + ' - new margin-left : ' + new_margin_left);
// positions are the same of start element ? they are not modify ?
}
#circleNav {
background: rgba(215, 229, 231, 0.4) !important;
margin-top: 100px;
margin-left: 120px;
border-radius: 50%;
width: 335px;
height: 335px;
border: 2px solid #0e6694;
}
img {
max-width: 100%;
}
#blue_ball {
position: absolute;
margin-top: -350px;
margin-left: 165px;
width: 70px;
height: 70px;
border: none;
z-index: 5;
transform-origin: 120px 180px;
}
.rotation {
-webkit-animation: rotation 3s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards !important;
}
#-webkit-keyframes rotation {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(240deg);
}
}
.rotation2 {
-webkit-animation: rotation 3s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards !important;
}
#-webkit-keyframes rotation2 {
from {
-webkit-transform: rotate(240deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
<h2>
CLICK ON THE BODY TO START ANIMATION
</h2>
<h4>
When the Blue ball stop click an other time to start second animation, but don't work ?
</h4>
<div id="circleNav"></div>
<div id="blue_ball">
<a href="#">
<img id="btn_menu" src="http://mascaron.net/img/mini_rond_logo.png">
</a>
</div>
smaple code on jsfiddle
thanks in advance.
Just one question, in css:
.rotation2 {
-webkit-animation: rotation 3s linear;
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards !important;
}
should not be:
.rotation2 {
-webkit-animation: rotation2 3s linear; /* <----- here, rotation2
animation-fill-mode: forwards;
-webkit-animation-fill-mode: forwards !important;
}
In js part, why not use elem.classList https://developer.mozilla.org/fr/docs/Web/API/Element/classList to manipulate css class property.