Animate elements with same classes, but individuallly - javascript

I am trying to animate elements individually that have the sames classes.
I am a complete jQuery noob, and can't figure out how to achieve that and would please need your help.
Here is the current code I have: (but once I hover on a card/blurb, every single one is animating)
I would like to only target the current element hovered to animate.
Best regards,
Joevin
/*add perspective to row for 3d perspective of child elements*/
.et_pb_blurb {
perspective: 1000px;
}
/*preserve-3d needed for 3d effect on card elements*/
.et_pb_blurb_content {
transform-style: preserve-3d;
transition: all 100ms linear !important;
}
/*transition timing function and duration for card elements*/
.et_pb_main_blurb_image,
.et_pb_module_header,
.et_pb_blurb_description,
.et-mousemove-card .et_pb_button_module_wrapper {
transition: all 750ms ease-out !important;
}
/*transform styles for card elements*/
.et_pb_main_blurb_image.transform-3d {
transform: translateZ(150px) rotateZ(10deg) !important;
}
.et_pb_module_header.transform-3d {
transform: translateZ(150px) !important;
}
.et_pb_blurb_description.transform-3d {
transform: translateZ(50px) !important;
}
.et-mousemove-card .et_pb_button_module_wrapper.transform-3d {
transform: translateZ(150px) rotateX(20deg) !important;
}
</style>
This is my script
//Items
var $hoverContainer = $(".et_pb_blurb");
var $mousemoveCard = $(".et_pb_blurb_content");
var $cardImage = $(".et_pb_main_blurb_image");
var $cardHeading = $(".et_pb_module_header");
var $cardInfo = $(".et_pb_blurb_description");
var $cardButton = $(".et-mousemove-card .et_pb_button_module_wrapper");
//Moving Animation Event
$hoverContainer.on("mousemove", function (e) {
let xAxis = (window.innerWidth / 2 - e.clientX) / 25;
let yAxis = (window.innerHeight / 2 - e.clientY) / 25;
$mousemoveCard.css(
"transform",
`rotateY(${xAxis}deg) rotateX(${yAxis}deg)`
);
});
//Animate on Hover
$hoverContainer.hover(function () {
$mousemoveCard.toggleClass("transform-3d");
$cardHeading.toggleClass("transform-3d");
$cardImage.toggleClass("transform-3d");
$cardButton.toggleClass("transform-3d");
$cardInfo.toggleClass("transform-3d");
});
//Pop Back on mouseleave
$hoverContainer.on("mouseleave", function () {
$mousemoveCard.css("transform", `rotateY(0deg) rotateX(0deg)`);
});

Related

How to animate text via CSS with vertically centered anchor point

I have a simple JS script which listens to keyboard input and displays, at a random position, a short animation of every typed letter fading out and getting smaller.
'use strict'
const body = document.querySelector('body')
const ignoreKeys = [
'Alt', 'Shift', 'Control', 'CapsLock', 'Tab', 'Backspace', 'Escape', 'Meta',
'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'
]
document.addEventListener('keydown', function(e) {
if (!ignoreKeys.includes(e.key)) {
// Values 400 & 200 keep the div completely inside the window
const maxHeight = window.innerHeight - 400
const maxWidth = window.innerWidth - 200
const div = document.createElement('div')
div.className = 'anim'
div.textContent = e.key
div.style.top = getRandomInt(0, maxHeight) + 'px'
div.style.left = getRandomInt(0, maxWidth) + 'px'
body.append(div)
setTimeout(function() { div.remove() }, 3000)
}
})
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min) + min)
}
.anim {
position: fixed;
text-align: center;
animation-name: fade;
animation-duration: 2s;
animation-timing-function: ease-in-out;
opacity: 0%;
}
#keyframes fade {
0% { opacity: 100%; font-size: 300px;}
100% { opacity: 0%; font-size: 100px;}
}
By animating the font-size property, each letter gets smaller. However, since its "anchor point" is the top of the div, the visible effect is a letter getting smaller and moving slightly upwards. I would like each letter to shrink towards the vertical center of the div instead.
I can calculate the center the div easily and add the proper top coordinate to the #keyframe property, but I don't know how to modify that property in JS, individually for each div. Is this possible at all via CSS? Or should I rewrite the whole thing in pure JS?
You don't need to adjust the div's top value at all. As there is no border or anything else displayed for the DIV tag itself - just the letter within it - you can adjust either the margin, the border and/or the padding to achieve the same effect as increasing the top value for the DIV. As each of these can be handled within the css transition, you could do something like:
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min) + min)
}
document.addEventListener('keydown', function(e) {
const body = document.querySelector('body')
const ignoreKeys = [
'Alt', 'Shift', 'Control', 'CapsLock', 'Tab', 'Backspace', 'Escape', 'Meta',
'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'
]
if (!ignoreKeys.includes(e.key)) {
// Values 400 & 200 keep the div completely inside the window
const maxHeight = window.innerHeight - 400
const maxWidth = window.innerWidth - 200
const div = document.createElement('div')
div.className = 'anim'
div.textContent = e.key;
div.style.top = getRandomInt(0, maxHeight) + 'px'
div.style.left = getRandomInt(0, maxWidth) + 'px'
body.append(div)
setTimeout(function() { div.remove() }, 3000)
}
})
.anim {
display:block;
position: fixed;
text-align: center;
width:200px;
animation-name: fade;
animation-duration: 2s;
animation-timing-function: ease-in-out;
opacity: 0;
margin:0px;
}
#keyframes fade {
0% { opacity:1; font-size: 300px;}
100% { opacity:0; font-size: 100px; margin-top:100px;}
}
The initial state of the DIV is with margin:0px. Adding a margin-top setting to the keyframes css, increases this from 0 to 100 during the transition. The effect of that is to push the DIV down - and, as noted above, as nothing is being displayed for the DIV itself, the user will not see it move. Note that I have fixed the width of the DIV at 200px so ensure that everything is always centered horizontally - otherwise the DIV width is based on the width of the character, so would change during transition and the character would move to the left as the centre line changes. I've moved some of the code around to make it easier to test - but the only actual change is in the CSS styling. Also note that opacity is a value from 0 to 1, so should not be shown as a percentage.
UPDATE
Have a look at the following snippet. I think that it may be possible to have random font sizes AND random positions using transform rather than animate.
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min) + min)
}
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split("");
function zoomOUT(){
let d = document.getElementById("test");
d.classList.remove("zoomIN");
d.classList.add("zoomOUT");
}
function zoomIN(){
let d = document.getElementById("test");
let dletter = document.getElementById("testletter");
let t = getRandomInt(20, 60) * 10;
let l = getRandomInt(20, 100) * 10;
let fs = getRandomInt(10, 20) * 10;
dletter.innerHTML = letters[getRandomInt(0, 61)];
d.style.top = t + "px";
d.style.left = l + "px";
d.style.fontSize = fs + "%";
d.classList.remove("zoomOUT");
d.classList.add("zoomIN");
}
#test {
position:absolute;
padding: 50px;
margin: 0 auto;
text-align:center;
vertical-align:middle;
}
.zoomIN {
opacity:1;
transform: scale(3);
transition: transform 2s;
}
.zoomOUT {
opacity:0.5;
transform: scale(0.1);
transition: transform 3s;
}
<button onclick="zoomOUT();" z-index=1>Play</button><button onclick="zoomIN();" z-index=1>Restart</button>
<div id="test" class="zoomIN" style="top:300px; left:300px;" z-index=0><div id="testletter" style="font-size:600%; width:100%; height:100%">A</div></div>
Transform seems to keep things in the same place, so there is no need to adjust any top/margin/border/padding settings at all. In fact, the only things that change are the font-size (using scale(..)) and opacity. The size of the font is determined by the code. Note that this requires the character to be in a div within a div. This is just a test, but should give you enough to convert things into your code requirements.

Why doesn't the following element rotate?

I have the following code that aims to rotate a hamburger icon by 90 deg when it is clicked, but it doesn't work why?
var menu = document.getElementById("menu");
let rotate = function() {
document.getElementById("menu").style.transform = "rotate(90deg)";
};
menu.addEventListener("click", rotate);
#menu {
text-decoration: none;
color: white;
font-size: 5vw;
color: #66fcf1;
cursor: default;
position: fixed;
margin-left: 2.5%;
}
☰
Also on Codepen: https://codepen.io/greatscams/pen/ZEQrYog
Note: It only works once.
You need to check if the element is already rotated or not. It does not happen like just rotating the paper. rotate(90deg) means you are assigning the property and not actually rotating the element.
var rotated = false;
let rotate = function () {
if(rotated) {
document.getElementById("menu").style.transform = "rotate(0deg)";
rotated = false;
} else {
document.getElementById("menu").style.transform = "rotate(90deg)";
rotated = true;
}
};
It's only rotating once as it's being rotated by 90deg, not an additional 90deg each time.
To keep rotating each time the function runs you need something along the lines of this:
let deg = 0
let rotate = function () {
deg = deg + 90;
document.getElementById("menu").style.transform = `rotate(${deg}deg)`
};
So the first invocation will be rotate(90deg) the next rotate(180deg) etc
The demo works only once because you're applying the same transform function over and over again.
The first state of the element is transform: none.
When first clicking on it, you're switching it to transform: rotate(90deg).
The transform works relatively to the initial state, not the current one (it's actually stateless), so the code above will not rotate it again and again.
What you can do, depending on what you want, is:
remember the state and toggle the animation (from rotate(0) to rotate(90deg) and back)
or
count the number of rotations and then multiply 90deg by that number on every click.
It only works once because the second time, you're just telling it to transform the way it's already transformed (rotated 90deg). To rotate it further, you have to tell it to rotate further. It's not additive.
For instance, extracting the angle with a regex and adding 90 to it each time, with wrap-around at 360:
let rotate = function() {
const menuStyle = document.getElementById("menu").style;
const current = /rotate\((\d+)deg\)/.exec(menuStyle.transform);
let angle = current ? +current[1] : 0;
angle = angle + 90 % 360;
menuStyle.transform = `rotate(${angle}deg)`;
};
menu.addEventListener("click", rotate);
#menu {
text-decoration: none;
color: white;
font-size: 5vw;
color: #66fcf1;
cursor: default;
position: fixed;
margin-left: 2.5%;
}
☰

CSS transform: translateX( to the right );

I want to make a particle system for my home page. Blue little circular dots should go from left to right and then reapear in the left so that it makes a loop.
Image of particles
The code below will generate 150 dots that all have different properties as speed color and size and will apear at random positions when loading the page. Either by looping the animation or by adding new dots I want to continue the animation infinitely.
// ========== JAVASCRIPT ==========
function Dot(){
var colors = [
"#313146",
"#36364f",
"#3d3d5c",
"#404066"
];
var speed = Math.floor(Math.random() * 20) + 2;
this.obj = document.createElement("div");
this.obj.classList.add("dot");
this.obj.style.top = (window.innerHeight * Math.random()) + 'px'; // random Y-position after page load
this.obj.style.left = (window.innerWidth * Math.random()) + 'px'; // random X-position after page load
this.size = Math.floor(Math.random() * 5) + 4; // random size
this.obj.style.height = this.size + 'px';
this.obj.style.width = this.size + 'px';
this.obj.style.backgroundColor = colors[Math.floor(Math.random()*colors.length)]; // random color
this.obj.style.animation = `move ${speed}s linear`; // start animation
document.body.appendChild(this.obj);
setTimeout(del, speed*1000, this.obj); // THIS FUNCTION SHOULD BE REMOVED IF ANIMATION GETS A LOOP
function del(element) {
element.parentNode.removeChild(element);
};
};
for(var i = 0 ; i < 151 ; i++ ){ // creating 150 dots
new Dot();
};
// ========== CSS ==========
.dot {
border-radius: 50%;
z-index: -1;
}
#keyframes move {
0% {
transform: translateX(0vw);
}
100% {
transform: translateX(100vw);
}
}
My problem is that as the dots apear with random positions, and all of them get a transform: translateX(100vw);, they will move out of the screen for a while before being deleted or reapeared at the beginning. My second image shows in red where the dot is moving to, and where it should move to.
image
What I tried allready:
1.
JS:
this.obj.style.animation = `move ${speed}s linear infinite`; added infinite and deleted the code that deletes the dots.
CSS:
#keyframes move {
0% {
transform: translateX(0vw);
}
100% {
transform: translateX(right);
}
}
<= Does not exist, and couldn't find working code equal to this idea.
This would have been a solution.
2.
Adding a second animation with dots coming from the left when other ones where deleted.
Ended in a gap between the 150 dots of the first animation and the incoming dots of the second animation.
Is there any other possibility of moving the dots from left to right with different properties?
best regards
Since you are setting the position with JS so you can know exactly where each element will appear and use this information to adjust the animation.
Here is a basic example to illustrate:
.dot {
background: blue;
position:fixed;
width: 50px;
height: 50px;
border-radius: 50%;
z-index: -1;
left:var(--x,0px);
animation:move 2s linear infinite;
}
#keyframes move {
0% {
transform: translateX(0vw);
}
100% {
transform: translateX(calc(100vw - var(--x,0px)));
}
}
<div class="dot" style="top:10px;--x:80px;"></div>
<div class="dot" style="top:20px;--x:150px;"></div>
<div class="dot" style="top:100px;--x:350px;"></div>
The variable --x will define left and will get substracted from the 100vw
For better support and since you are using JS, you can get rid of calc() and CSS variables. Simply do a small calculation to find the value of transform.
Here is an example where I am using jQuery for simplicity but you can easily make it a JS-only code:
$('.dot').each(function() {
$(this).css('transform','translateX('+ ($(window).width() - parseInt($(this).css('left')))+'px)');
});
.dot {
background: blue;
position:fixed;
width: 50px;
height: 50px;
border-radius: 50%;
z-index: -1;
animation:move 2s linear infinite;
}
#keyframes move {
0% {
transform: translateX(0px);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="dot" style="top:10px;left:80px;"></div>
<div class="dot" style="top:20px;left:150px;"></div>
<div class="dot" style="top:100px;left:350px;"></div>
Worth to note that you need to update the value on window resize
Another idea to keep the loop effect is to have the same position and the same animation for all and you adjust the delay to simulate the different position:
.dot {
background: blue;
position:fixed;
width: 50px;
height: 50px;
border-radius: 50%;
z-index: -1;
left:0;
animation:move 2s linear infinite;
}
#keyframes move {
0% {
transform: translateX(0px);
}
100% {
transform: translateX(100vw);
}
}
<div class="dot" style="top:10px;animation-delay:-1s;"></div>
<div class="dot" style="top:20px;animation-delay:-0.1s;animation-duration:1s"></div>
<div class="dot" style="top:100px;animation-delay:-0.5s;animation-duration:4s"></div>
The calculation is easy. If the animation duration is D then a delay of -D/2 will place the element in the center intially. -D*0.1 will place the image at 10% and so on.
I would suggest you to use requestAnimationFrame to animate your particles. Take a look at the following example. I've added the move method to the particle which is called from the animation loop and changing the particle's position. It also checks if the particle has reached the end of the screen and resets its position to -10 in this case.
function Dot(){
var colors = [
"yellow",
"red",
"green",
"black"
];
this.x = window.innerWidth * Math.random();
this.speed = Math.floor(Math.random() * 20) + 2;
this.obj = document.createElement("div");
this.obj.classList.add("dot");
this.obj.style.position = "fixed";
this.obj.style.top = (window.innerHeight * Math.random()) + 'px';
this.obj.style.left = this.x + 'px';
this.size = Math.floor(Math.random() * 5) + 4; // random size
this.obj.style.height = this.size + 'px';
this.obj.style.width = this.size + 'px';
this.obj.style.background = colors[Math.floor(Math.random()*colors.length)]; // random color
document.body.appendChild(this.obj);
this.move = function() {
this.x += this.speed;
if (this.x > window.innerWidth) {
this.x = -10;
}
this.obj.style.left = this.x + 'px';
};
};
var dots = Array.apply(null, Array(150)).map(a => new Dot());
requestAnimationFrame(paint);
function paint() {
requestAnimationFrame(paint);
for (dot of dots) {
dot.move();
}
}
.dot {
border-radius: 50%;
z-index: -1;
}
I also recommend you this great book about particle systems. It shows how to implement forces, interaction and complex behavior.

Move transform-origin back to the center of the element in CSS

When CSS elements are transformed out of their original location the transform-origin doesn't move with them; making all subsequent transforms and rotations still originate from it's original transform-origin ( example below ).
There is one way around this that I know of... and that's to keep adding all new transforms to the right of the previous ones. like this: transform: translateY ( -5rem ) rotate( 45deg ) translateY( -10rem ) rotate( 15deg )... etc. This seems to always start the new transforms from the center of the current element as desired.
the problem
When you are transforming an element based on user input using this technique you will keep adding transforms to the DOM...endlessly. Taking up a lot of memory and causing other unwanted sliding effects ( possibly ).
Here is an animation showing how the transform-origin doesn't move to the center of the element after each transform:
'use strict';
function firstRotation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'First, the V is rotated around it\'s central axis.\
The <b>transform-origin</b> is centered.';
v.classList.add( 'first-rotation' );
status.classList.add( 'update' );
}, 1000 );
}
function firstTranslation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'Next, the element is translated forward in it\'s \
current orientation. The <b>transform-origin</b> stays\
behind where it was.';
v.classList.remove( 'first-rotation' );
v.classList.add( 'first-translation' );
}, 6000 );
}
function info() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'This next animation is where it\'s evident that\
the <b>transform-origin</b> is no longer centered, but\
back where it was at the beginning of these transforms';
}, 11000 );
}
function lastRotation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'This last rotation is far wider than desired because the\
transform origin is back where it started.'
v.classList.remove( 'first-translation' );
v.classList.add( 'last-rotation' );
}, 16000 );
}
function end() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.classList.remove( 'update' );
}, 21000 );
}
function start() {
firstRotation();
firstTranslation();
info();
lastRotation();
end();
}
start();
/* / / / / / / / / / / / / / ANIMATION DEFINITIONS / / / / / / / / / / / / / */
.first-rotation, .first-translation, .update, .last-rotation {
animation-duration: 5s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
.first-rotation {
animation-name: first-rotation;
}
.first-translation {
animation-name: first-translation;
}
.update {
animation-name: update;
animation-iteration-count: infinite;
}
.last-rotation {
animation-name: last-rotation;
}
/*/ / / / / / / / / / / / / / ANIMATION KEYFRAMES / / / / / / / / / / / / / /*/
#keyframes first-rotation {
100% {
transform: rotate( 315deg );
}
}
#keyframes first-translation {
0% {
transform: rotate( 315deg );
}
100% {
transform: rotate( 315deg ) translate( 0, -5rem );
}
}
#keyframes update {
0% {
background-color: mediumslateblue;
}
}
#keyframes last-rotation {
0% {
transform: rotate( 315deg ) translate( 0, -5rem );
}
100% {
transform: rotate( 400deg ) translate( 0, -5rem );
}
}
<head>
<style>
#import url( "https://fonts.googleapis.com/css?family=Nunito" );
html {
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-family: "Nunito", sans-serif;
}
html,
body {
margin: 0;
padding: 0;
}
.v {
display: block;
font-size: 2rem;
transform: rotate( 180deg );
}
p {
width: 100%;
padding: 0.5rem;
position: absolute;
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<div id="v-wrp" class="v-wrp">
<b class="v">V</b>
</div>
<p id="status" class="status"></p>
</body>
the question
I need to find a way in CSS or JS to reset the position of the transform-origin or move it back to the center of the transformed element. Adding more transforms to the right is one technique that isn't working for me in a real time interactive environment. An attempt can be seen here: Transforms are added...endlessly.
How can I either calculate the location of a transformed element and move the transform-origin back to it's center OR how can I take multiple transform values and condense them into one value that keeps the element in it's same place?
You will be able to make use of JavaScript's DOMMatrix or your own values to keep track of the translation and rotation values.
Here is a very basic example like your asteroids game:
https://jsfiddle.net/omjktrsh/
The matrix provides you with functions to manipulate it without having to learn all the math. The 2D variant has six properties which are part of a 3x3 matrix:
a c e
b d f
0 0 1
where:
a = x axis scale
b = y axis shear
c = x axis shear
d = y axis scale
e = x axis translate
f = y axis translate
You can use rotateSelf(deg) to have the matrix perform a rotation on its current values, or rotate(deg) to have the matrix return a new matrix with the added rotation (leaving the original matrix with the same values).
You can use translateSelf(x, y) to move it around, relative to its current rotation. If you want to move it around not relative to its current rotation, you can manipulate the e and f values directly like so:
matrix.e += x; // x axis translation amount
matrix.f += y; // y axis translation amount
You can easily apply as many rotations as you want without needing to stack them in CSS, and then use toString() to output the matrix in its CSS form:
const matrix = new DOMMatrix();
const el = document.getElementById("transform-me");
// manipulate matrix as much as you want
...
matrix.translateSelf(...);
...
matrix.rotateSelf(...);
...
// apply matrix to elements css -> matrix(a, b, c, d, e, f)
el.style.transform = matrix.toString();
The drawback is DOMMatrix has less browser support: https://caniuse.com/dommatrix
If you would like to support browsers that do not support DOMMatrix, you can still use your own maths and the transform: matrix(a, b, c, d, e, f) syntax in these browsers: https://caniuse.com/transforms2d
If you would like to know the maths behind 2d transformation matrices, there are examples on Wikipedia. Note that some resources use a flipped matrix to the one above:
a b 0
c d 0
e f 1
You can also use top and left to translate the #v-wrp. And you can create an animation in the transform-origin property. Try it in the <b> element. I hope it will be working right now.
Your issue is a structural one. Keep your point of reference (transform-origin) as is and separate your rotate and translate transforms by layer (a containing element that is translated from it's origin and an interior containing element that rotates as you wish).
Structurally separating these elements of transform will prevent "cross-origin" issues such as these from the outset.
If anyone is still looking for something like this.
#jmcgrory is right, it would be really convenient to have separate layers. But for certain scenario following will work.
If you can use svg then transform-box may help.
But if you are using any other element than it will be difficult as reference box (can be considered as initial position of element) does not change after applying transform, and transform-origin will be treated according to its reference box. transform-origin needs to be moved along with translate, it gets more complicated with transform: rotate as you will have to calculate the x and y length of movement of an element and based on that you will need to replace transform (if used for any one axis) to x and y and update the transform origin accordingly, this method is very tricky but it works well and depends totally on mathematical calculations of movement of element (you won't need to write too much css but will have to do some calculations).
I've copied the snippet from question and make it work as expected. Please check the below code for reference.
'use strict';
function firstRotation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'First, the V is rotated around it\'s central axis.\
The <b>transform-origin</b> is centered.';
v.classList.add( 'first-rotation' );
status.classList.add( 'update' );
}, 1000 );
}
function firstTranslation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'Next, the element is translated forward in it\'s \
current orientation. The <b>transform-origin</b> stays\
behind where it was.';
v.classList.remove( 'first-rotation' );
v.classList.add( 'first-translation' );
}, 6000 );
}
function info() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'This next animation is where it\'s evident that\
the <b>transform-origin</b> is no longer centered, but\
back where it was at the beginning of these transforms';
}, 11000 );
}
function lastRotation() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.innerHTML = 'This last rotation is working correctly with calculated transform-origin.'
v.classList.remove( 'first-translation' );
v.classList.add( 'last-rotation' );
}, 16000 );
}
function end() {
var v = document.getElementById( 'v-wrp' ),
status = document.getElementById( 'status' )
setTimeout( function() {
status.classList.remove( 'update' );
}, 21000 );
}
function start() {
firstRotation();
firstTranslation();
info();
lastRotation();
end();
}
start();
/* / / / / / / / / / / / / / ANIMATION DEFINITIONS / / / / / / / / / / / / / */
.first-rotation, .first-translation, .update, .last-rotation {
animation-duration: 5s;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
.first-rotation {
animation-name: first-rotation;
}
.first-translation {
animation-name: first-translation;
}
.update {
animation-name: update;
animation-iteration-count: infinite;
}
.last-rotation {
animation-name: last-rotation;
}
/*/ / / / / / / / / / / / / / ANIMATION KEYFRAMES / / / / / / / / / / / / / /*/
#keyframes first-rotation {
100% {
transform: rotate( 315deg );
}
}
#keyframes first-translation {
0% {
transform: rotate( 315deg );
}
100% {
transform-origin: calc(-3.536em + 10px) calc(-3.536em + 22px);
transform: rotate( 315deg ) translate( -3.536rem, -3.536rem );
}
}
#keyframes update {
0% {
background-color: mediumslateblue;
}
}
#keyframes last-rotation {
0% {
transform-origin: calc(-3.536em + 10px) calc(-3.536em + 22px);
transform: rotate( 315deg ) translate( -3.536rem, -3.536rem );
}
100% {
transform-origin: calc(-3.536em + 10px) calc(-3.536em + 22px);
transform: rotate( 400deg ) translate( -3.536rem, -3.536rem );
}
}
<head>
<style>
#import url( "https://fonts.googleapis.com/css?family=Nunito" );
html {
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
font-family: "Nunito", sans-serif;
}
html,
body {
margin: 0;
padding: 0;
}
.v {
display: block;
font-size: 2rem;
transform: rotate( 180deg );
}
p {
width: 100%;
padding: 0.5rem;
position: absolute;
bottom: 0;
left: 0;
}
</style>
</head>
<body>
<div id="v-wrp" class="v-wrp">
<b class="v">V</b>
</div>
<p id="status" class="status"></p>
</body>

Javascript transition works only after second hover

I am new to Javascript. I want to make my image gradually get smaller, and then resize back to its original size. What I have works, but only after hovering over the image 2 times or more.
To be clearer, when I hover my mouse over the image for the first time, it makes a very abrupt transition, but works after that. It did the same thing when using CSS instead.
What I have is this:
function enlargeImage() {
var logo = document.getElementById('logoname');
logo.style.opacity = '0.7';
logo.style.height = 'auto';
logo.style.width = '800px';
logo.style.transition = '0.7s';
}
function resizeImage() {
var logo = document.getElementById('logoname');
logo.style.opacity = '1';
logo.style.height = 'auto';
logo.style.width = '900px';
}
Should this work? Or have I coded in a way in which I shouldn't have?
Personally I like to leave animations and effects like these to CSS and leave the functionality to Javascript.
#yourImage {
width: 150px;
height: 150px;
transition: transform .25s ease, opacity .5s ease;
}
#yourImage:hover {
opacity: 0.5;
transform: scale(0.5);
}
<img src="http://www.w3schools.com/css/trolltunga.jpg" alt="" id="yourImage">
When the image is hovered over I transform and resize the image to 0.5% of it's original size and 0.5% of it's original opacity.
I am also using the transition property to set how fast the image transitions when it is resized or when the opacity is changed.
The abruption was because of the height tag inside javascript code. change this
height: auto
Into height:400px or some value instead of auto.
function enlargeImage() {
var logo = document.getElementById('logoname');
logo.style.opacity = '0.7';
logo.style.height = '300px';
logo.style.width = '400px';
logo.style.transition = '0.7s';
}
function resizeImage() {
var logo = document.getElementById('logoname');
logo.style.opacity = '1';
logo.style.height = '600px';
logo.style.width = '600px';
logo.style.transition = '0.7s';
}
img {
height:300px;
width:400px;
}
<img onmouseover="resizeImage()" onmouseout="enlargeImage()" src='http://imgsv.imaging.nikon.com/lineup/lens/zoom/normalzoom/af-s_dx_18-140mmf_35-56g_ed_vr/img/sample/sample1_l.jpg' id="logoname">

Categories

Resources