Page transition with CSS transform problems - javascript

I want to do a simple transition between two pages. The animation should be a movement from right to left to go to the second page, and then, left to right to return to the first page.
I've made this, but the problem is that duplicates the width of the page.
const screen1 = document.getElementsByClassName('screen1')[0];
const screen2 = document.getElementsByClassName('screen2')[0];
document.getElementById('toggle1').addEventListener('click', () => {
screen1.style.transform = 'translatex(-100%)';
screen2.style.transform = 'translatex(0)';
});
document.getElementById('toggle2').addEventListener('click', () => {
screen1.style.transform = 'translatex(0)';
screen2.style.transform = 'translatex(100%)';
});
body {
margin: 0;
}
.container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.screen1 {
position: absolute;
width: 100%;
height: 100%;
background-color: blue;
transition: transform .5s;
}
.screen2 {
position: absolute;
width: 100%;
height: 100%;
background-color: red;
transform: translatex(100%);
transition: transform .5s;
}
<div class="container">
<div class="screen1">
<button id="toggle1">Toggle</button>
</div>
<div class="screen2">
<button id="toggle2">Toggle</button>
</div>
</div>
The problems that I've with this:
In an element with 100% of width I must to use the viewport units. In other case, the 100% will be two screens.
An element with fixed position, positioned to the right of the screen, will take the right value of the second screen. So it won't be displayed.
I can hide the scroll bar with overflow-x: hidden but the user can scroll to the next screen anytime.
There is some way to fix this problems and maintain the "slide" transition?

Just add overflow: hidden to your container.
const screen1 = document.getElementsByClassName('screen1')[0];
const screen2 = document.getElementsByClassName('screen2')[0];
document.getElementById('toggle1').addEventListener('click', () => {
screen1.style.transform = 'translatex(-100%)';
screen2.style.transform = 'translatex(0)';
});
document.getElementById('toggle2').addEventListener('click', () => {
screen1.style.transform = 'translatex(0)';
screen2.style.transform = 'translatex(100%)';
});
body {
margin: 0;
}
.container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
}
.screen1 {
position: absolute;
width: 100%;
height: 100%;
background-color: blue;
transition: transform .5s;
}
.screen2 {
position: absolute;
width: 100%;
height: 100%;
background-color: red;
transform: translatex(100%);
transition: transform .5s;
}
<div class="container">
<div class="screen1">
<button id="toggle1">Toggle</button>
</div>
<div class="screen2">
<button id="toggle2">Toggle</button>
</div>
</div>

Add overflow:hidden property to your .container

Related

Transition for Text on reset

I tried to find a solution for this one but I can't. There s something that I keep missing... not sure what.
I have a project that when I click a image, the image will get an translate and also a text description.
The text description has a smooth transition and it looks cool.
Well, the question is.. how to make the reset(click on body or another image) to have the same transition for that text description?
This is how it look right now: https://im3.ezgif.com/tmp/ezgif-3-5150d8ffbf.gif
function resetEnlargeEntityImage() {
if(enlargedEntity != null) {
enlargedEntity.style.transform = null;
enlargedEntity.style.transition = null;
enlargedEntity.classList.add("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = null;
document.getElementById("planets-description-paragraph").classList.add("entity-description-js");
document.getElementById("planets-description-paragraph").classList.remove("entity-description-appear-js");
}
}
function enlargeEntityImage(clickedImage, clickedImageId) {
let mediaQuery = window.matchMedia('(max-width: 375px)');
if(mediaQuery.matches) {
window.location.href = `./${planetsName[clickedImageId]}.html`;
} else {
resetEnlargeEntityImage();
var xToMove = 260 - 130 * clickedImageId; //260
clickedImage.style.transform = "translate(" + xToMove + "px, 320px) scale(4.0)";
clickedImage.style.transition = "transform 1s ease-in-out";
clickedImage.classList.remove("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = descriptionSpaceObjects[clickedImageId];
document.getElementById("planets-description-paragraph").classList.remove("entity-description-js");
document.getElementById("planets-description-paragraph").classList.add("entity-description-appear-js");
enlargedEntity = clickedImage;
}
}
.planets-description {
color: white;
font-family: "Barlow";
font-size: 30px;
width: 600px;
position: relative;
top: 100px;
left: 700px;
}
.entity-description-js {
position: absolute;
transition-delay: 1s;
transition: 1s;
width: 600px;
left: 0;
visibility: hidden;
opacity: 0;
}
.entity-description-appear-js {
position: absolute;
transition: 1s;
width: 600px;
left: 100px;
visibility: visible;
opacity: 1;
}
<div class="planets-description">
<p id="planets-description-paragraph" class="entity-description-js"></p>
</div>
The Code you provided isnt showing anything, but maybe you could try uesing the "transition" property in css.

Translation animation when moving child from one parent to another parent

I am trying to make connect4 HTML game and I know I will be better off using canvas elements instead of a grids of divs but is it possible to make transition translate type of css animation when moving HTML elements around like this (using appendChild)
const row1 = document.getElementById("row1")
const row2 = document.getElementById("row2")
const ball = document.getElementById("TheBall")
ball.addEventListener("click", (event, element) => {
let rowNum = parseInt(ball.dataset.row)
if(rowNum==1) {
row2.appendChild(ball)
ball.dataset.row = 2
} else {
row1.appendChild(ball)
ball.dataset.row = 1
}
})
#main {
left:100px;
width: 100px;
height: 100px;
display: flex;
flex-direction: column;
}
#main div {
margin: 50px 0;
width: 50px;
height: 50px;
}
#TheBall {
width: auto;
height: auto;
background-color: red;
border-radius: 100%;
}
<div id="main">
<div id="row1"> </div>
<div id="row2">
<div id="TheBall" data-row=2></div>
</div>
</div>
Click on the red dot to toggle position of ball
You can use animationend to check when the animation end and move the ball element between the divs
const row1 = document.getElementById("row1")
const row2 = document.getElementById("row2")
const ball = document.getElementById("TheBall")
ball.addEventListener('animationend', () => {
ball.classList.remove("animate-ball");
ball.style.animation = "";
let rowNum = parseInt(ball.dataset.row)
if (rowNum == 1) {
row2.appendChild(ball)
ball.dataset.row = 2
} else {
row1.appendChild(ball)
ball.dataset.row = 1
}
});
ball.addEventListener("click", (event, element) => {
let rowNum = parseInt(ball.dataset.row)
if (rowNum == 1) {
ball.style.animation = "MoveDown 1s linear";
} else {
ball.style.animation = "MoveUp 1s linear";
}
ball.classList.add("animate-ball");
})
#main {
left: 100px;
width: 100px;
height: 100px;
display: flex;
flex-direction: column;
}
#main div {
margin: 50px 0;
width: 50px;
height: 50px;
}
#TheBall {
position: relative;
width: auto;
height: auto;
background-color: red;
border-radius: 100%;
}
.animate-ball {
animation-iteration-count: 1;
position: absolute;
bottom: 0;
}
#keyframes MoveUp {
0% {
top: -50px;
}
100% {
top: -100px;
}
}
#keyframes MoveDown {
0% {
top: 0;
}
100% {
top: 50px;
}
}
<div id="main">
<div id="row1"> </div>
<div id="row2">
<div id="TheBall" data-row=2></div>
</div>
</div>

disable scrolling untill animation is done

I have a simple animation and I want to disable scrolling on the website
until this animation is done, it should be like a loader basically
UPDATE
thank you so much, but I have an issue with that sorry for not mention because I'm using a fixed position on a container to be fixed to do smooth scrolling, so when I use 'fixed' position for any element it doesn't seem to stick in the same place here is the full code
html
<main id="app">
<div id="scroll-container" class="scroll-container">
<div class="loader">
<div class="loader__block"></div>
</div>
</div>
</main>
CSS
body {
overflow-x: hidden;
overflow-y: scroll;
background: $bg-color;
user-select: none;
font-family: 'Platform Regular';
}
#app {
overflow: hidden;
position: fixed;
height: 100vh;
width: 100vw;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.scroll-container {
position: absolute;
overflow: hidden;
z-index: 10;
display: flex;
justify-content: center;
backface-visibility: hidden;
}
.loader {
width: 100vw;
height: 100vh;
position: absolute;
z-index: 999999;
overflow: hidden;
}
.loader__block {
position: absolute;
width: 0%;
height: 100vh;
background: #111111;
animation: go-left 4s cubic-bezier(.74, .06, .4, .92) forwards;
}
#keyframes go-left {
0% {
left: 0;
width: 0%;
}
50% {
left: 0;
width: 100%;
}
100% {
left: 100%;
width: 0;
}
these containers have a fixed position and overflow hidden because I'm making smooth page transition while scrolling and moving the 'y' position
here is also the js if it's going to help
function smoothScrolling() {
const html = document.documentElement;
const { body } = document;
const scroller = {
target: document.querySelector('#scroll-container'),
ease: 0.06, // <= scroll speed
endY: 0,
y: 0,
resizeRequest: 1,
scrollRequest: 0,
};
let requestId = null;
TweenLite.set(scroller.target, {
rotation: 0.01,
force3D: true,
});
function updateScroller() {
const resized = scroller.resizeRequest > 0;
if (resized) {
const height = scroller.target.clientHeight;
body.style.height = `${height}px`;
scroller.resizeRequest = 0;
}
const scrollY = window.pageYOffset || html.scrollTop || body.scrollTop || 0;
scroller.endY = scrollY;
scroller.y += (scrollY - scroller.y) * scroller.ease;
if (Math.abs(scrollY - scroller.y) < 0.05 || resized) {
scroller.y = scrollY;
scroller.scrollRequest = 0;
}
TweenLite.set(scroller.target, {
y: -scroller.y,
});
requestId = scroller.scrollRequest > 0 ? requestAnimationFrame(updateScroller) : null;
}
function onScroll() {
scroller.scrollRequest += 1;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
}
function onResize() {
scroller.resizeRequest += 1;
if (!requestId) {
requestId = requestAnimationFrame(updateScroller);
}
}
function onLoad() {
updateScroller();
window.focus();
window.addEventListener('resize', onResize);
document.addEventListener('scroll', onScroll);
}
window.addEventListener('load', onLoad);
}
Use the CSS rule position: fixed; on your div with class loader which makes it to always stay in the same place even if the page is scrolled.
as so:
.loader {
width: 100vw;
height: 100vh;
position: absolute;
z-index: 999999;
overflow: hidden;
position: fixed;
}
.loader__block {
position: absolute;
width: 0%;
height: 100vh;
background: #111111;
animation: go-left 4s cubic-bezier(.74, .06, .4, .92) forwards;
}
#keyframes go-left {
0% {
left: 0;
width: 0%;
}
50% {
left: 0;
width: 100%;
}
100% {
left: 100%;
width: 0;
}
}
<main id="app">
<div id="scroll-container" class="scroll-container">
<div class="loader">
<div class="loader__block"></div>
</div>
</div>

is there a way to make a background scroll down while some content stay in the middle at all time?

I'm trying to do something like (in js, html, sass) :
when I scroll the page down my layers (ground, sky, space, ...) go down
my content (that will be a rocket going in the sky) stay in the middle of the screen and will move to the sides like if it were to be flying (that will be for later)
some elements will move on the layers (like asteroids going from right to left or something) (for later)
So here are some ideas of code I tried but this seem odd and do not work as intended; as you can see, the layers are scrolling as intended, but they are not all showing for whatever reason, they seem to fill all the page size but they shouldn't and i'm going round and round about this on the internet and no one seem to have done something like this.
// Functions
detectPageVerticalPosition = () => {
pageVerticalPosition = pageYOffset;
};
getDivs = () => {
for (
let div = document.getElementsByTagName("div"), i = 0; i < div.length; i++
) {
div[i].getAttribute("class") == "layer-vertical" &&
layerVerticalArray.push(div[i]);
}
console.log("layerVerticalArray: ", layerVerticalArray);
};
moveLayers = () => {
for (let i = 0; i < layerVerticalArray.length; i++) {
layerVerticalArray[i].style.bottom = -1 * pageVerticalPosition + "px";
}
};
// End Functions
// Variables
var pageVerticalPosition = 0,
layerVerticalArray = new Array();
// End Variables
// Events
window.onload = e => {
getDivs();
// console.log(layerVerticalArray);
};
window.onscroll = e => {
detectPageVerticalPosition();
moveLayers();
};
// End Events
body {
margin: 0;
}
#page {
position: relative;
height: 20000px;
width: 100%;
}
#rocket-container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
#rocket-container #rocket {
position: absolute;
width: 100px;
height: 100px;
left: calc(50% - 50px);
top: calc(50% - 50px);
}
#background-container {
position: fixed;
height: 100%;
width: 100%;
background-color: red;
overflow: hidden;
}
#background-container .layer-vertical {
width: 100%;
height: 3500px;
}
#background-container #layer-vertical-1 {
position: absolute;
background-color: blue;
}
#background-container #layer-vertical-1 #cloud-1 {
outline-style: dashed;
right: 0px;
}
#background-container #layer-vertical-1 #cloud-2 {
outline-style: dotted;
bottom: 0px;
}
#background-container #layer-vertical-2 {
background-color: green;
}
#background-container #layer-vertical-3 {
background-color: purple;
}
.cloud {
position: absolute;
width: 180px;
height: 120px;
background-image: url(../images/cloud.png);
}
<div class="page">
<div class="background-container">
<div class="layer-vertical" id="layer-vertical-1">
Layer 1
<div class="cloud" id="cloud-1"></div>
<div class="cloud" id="cloud-2"></div>
</div>
<div class="layer-vertical" id="layer-vertical-2">
Layer 2
</div>
<div class="layer-vertical" id="layer-vertical-3">
Layer 3
</div>
</div>
<div id="rocket-container">
<div id="rocket">STAY MIDDLE</div>
</div>
</div>
[1]: https://via.placeholder.com/180/120
So, here's what i found in order to fix this (jsfiddle: http://jsfiddle.net/kjrte2sd/2/)
i used some jquery to make the background-container scroll down as intended instead of each elements scrolling down by himself.
now the page div is gone and the body handle the sizing of the whole thing.
i guess the answer was simpler than i expected it to be.
var winHeight = $(window).innerHeight();
$(document).ready(() => {
$(".layer-vertical").height(winHeight);
$("body").height(winHeight * $(".layer-vertical").length);
});
window.addEventListener("resize", e => {
$(".layer-vertical").height($(window).innerHeight());
});
$(window).on("scroll", () => {
$("#background-container").css("bottom", $(window).scrollTop() * -1);
});
body {
margin: 0;
padding: 0;
}
#rocket-container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
#rocket-container #rocket {
position: absolute;
width: 100px;
height: 100px;
left: calc(50% - 50px);
top: calc(50% - 50px);
}
#background-container {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
#background-container .layer-vertical {
width: 100%;
}
#background-container .layer-vertical h1 {
width: 100px;
position: relative;
display: block;
margin: 0 auto;
text-align: center;
top: 50%;
}
#background-container #layer-vertical-1 {
background-color: green;
}
#background-container #layer-vertical-2 {
background-color: red;
}
#background-container #layer-vertical-3 {
background-color: white;
}
#background-container #layer-vertical-4 {
background-color: pink;
}
#background-container #layer-vertical-5 {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="background-container">
<div class="layer-vertical" id="layer-vertical-5">
<h1>5</h1>
</div>
<div class="layer-vertical" id="layer-vertical-4">
<h1>4</h1>
</div>
<div class="layer-vertical" id="layer-vertical-3">
<h1>3</h1>
</div>
<div class="layer-vertical" id="layer-vertical-2">
<h1>2</h1>
</div>
<div class="layer-vertical" id="layer-vertical-1">
<h1>1</h1>
</div>
</div>
<div id="rocket-container">
<div id="rocket">STAY MIDDLE</div>
</div>

Changing CSS Div Position Value Given in % Using Javascript

I want to be able to click a button and change a div value given in % to move the div off screen at the click of a button.
However, the code below produces no result when the button is clicked. I really appreciate any advice I can get.
function Shift() {
var x = document.getElementById("Lac");
if (x.style.left === "0%" && x.style.top === "0%") {
x.style.left = "100%";
x.style.top = "100%";
}
}
#Lac {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
left: 0%;
top: 0%;
background-color: #0062FF;
transition-duration: 0.3s;
}
<div id="Lac">
<button onclick="Shift()">Button</button>
</div>
Solution 1: I suggest you remove the if-statement. It doesn't do any good.
function Shift() {
var x = document.getElementById("Lac");
x.style.left = "100%";
x.style.top = "100%";
}
#Lac {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
left: 0%;
top: 0%;
background-color: #0062FF;
transition-duration: 0.3s;
}
<div id="Lac">
<button onclick="Shift()">Button</button>
</div>
Solution 2: Add a className instead of all that JavaScript.
#Lac {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
left: 0%;
top: 0%;
background-color: #0062FF;
transition-duration: 0.3s;
}
#Lac.hide {
left: 100%;
top: 100%;
}
<div id="Lac">
<button onclick="this.parentNode.className='hide';">Button</button>
</div>
You cannot retrieve the value from .style.left you need to do the following:
var style = window.getComputedStyle(document.getElementById("Lac"))
console.log(style.left); //outputs 0px
var left = parseInt(style.left); //0
if ( !left ){
//do the animation
}

Categories

Resources