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
}
Related
I am working with JavaScript to move an HTML div across the page. Below is the movement that I want the element to follow:
It should be starting and following routes 1, 2, 3 and 4. It should only change the route once the element reaches the max width/height of the page. I am using the below code and I am stuck on how to continue further.
var box = document.getElementById("box");
var height = document.getElementById("container").offsetHeight;
var widht = document.getElementById("container").offsetWidth;
window.setInterval(() => {
let addPosition = (parseInt(box.style.top) + 10);
let subPosition = (parseInt(box.style.top) - 10);
if (addPosition > height)
box.style.top = subPosition + 'px';
else
box.style.top = addPosition + 'px';
}, 100);
#container {
position: absolute;
background: purple;
width: 100%;
height: 100%;
}
#box {
position: absolute;
background: red;
width: 30px;
height: 30px;
}
<div id="container">
<div id="box" style="top: 0px; left: 0px;"></div>
</div>
No JS is needed to make this animation. You can use CSS-Animations for this.
For that, you use keyframes and change the position where the element should move to. You can define the speed with the animation-duration property and repeat it with animation-iteration-count
body {
margin: 0;
height: 100vh;
}
div {
height: 50px;
width: 50px;
background-color: red;
position: fixed;
animation-name: moveBox;
animation-duration: 5s;
animation-iteration-count: infinite;
}
#keyframes moveBox {
0% { top: 0; left: 0; }
20% { top: calc(100% - 50px); left: 0; }
50% { top: 0; left: calc(100% - 50px); }
70% { top: calc(100% - 50px); left: calc(100% - 50px); }
100% { top: 0; left: 0; }
}
<div></div>
As someone else mentioned, this is normally done with CSS animations, but if you have to use javascript you basically want a state system that keeps track of what your current target is.
Here's roughly how you could do it:
let box = document.getElementById("box");
let height = document.getElementById("container").offsetHeight;
let width = document.getElementById("container").offsetWidth;
let getAngle=function(x1,y1,x2,y2)
{
return Math.atan2(y2-y1,x2-x1);
}
let state=0;
let speed=10;//how many pixels to move per interval
let x=0,y=0;
let xTarget=0,yTarget=0;
window.setInterval(() => {
//we do not account for the box's size here, but if we needed to we could add or subtract it to the target as needed
switch(state) {
case 0:
xTarget=0;
yTarget=height;
break;
case 1:
xTarget=width;
yTarget=0;
break;
case 2:
xTarget=width;
yTarget=height;
break;
case 3:
xTarget=0;
yTarget=0;
break;
}
//do we still have more steps left? calculate the angle to the target, then step in that direction
if (state<4)
{
var angle=-getAngle(x,y,xTarget,yTarget)+Math.PI/2;
x+=Math.sin(angle)*speed;
y+=Math.cos(angle)*speed;
}
//are we close enough to the target? snap to the target, then switch to the next state
//note: you may want to calculate the actual distance here instead
if (Math.abs(xTarget-x)<speed && Math.abs(yTarget-y)<speed)
{
x=xTarget;
y=yTarget;
state++;
}
if (state>=4) state=0;//if you want the movement to loop
box.style.left=x+'px';
box.style.top=y+'px';
}, 100);
#container {
position: absolute;
background: purple;
width: 300px;
height: 200px;
}
#box {
position: absolute;
background: red;
width: 30px;
height: 30px;
}
<div id="container">
<div id="box" style="top: 0px; left: 0px;"></div>
</div>
I have two problems:
Animation issue(moving while scrolling):
My HTML:
<body>
<header class="stable">
<div id="object">
<img src="img/object.png">
</div>
</header>
</body>
My CSS:
#object{
position: absolute;
left: 0;
right: 0;
margin:auto;
bottom: 0%;
width: 45.9%;
height: auto;
animation: animation 1s ease-out;
z-index: 99;
}
#keyframes animation{
from{
left: -200%;
}
}
My JS:
var object = document.querySelector('#object');
window.addEventListener('scroll', function() {
var s = $(document).scrollTop();
var percent_from_top = s/this.innerHeight;
if(0 <= percent_from_top <= 1){
object.style.left = 150*(percent_from_top)+'%';
object.style.transition = "0.75s linear";
}
});
Problem with strip:
My HTML:
<section id="first_section">
<div class="strip"></div>
</section>
My CSS:
#first_section > .strip{
left: 0%;
right:0;
margin: auto;
margin-top:-30%;
width: 40%;
height: 130%;
transform: rotate(70deg);
background: rgba(0,0,0, 0.9);
}
It all works...
but it doesn't seem effective enough, because
it slows down, and
it partially appears
I tried to use clip-path for example, but it works the same way.
Is there a way to create a page more "evenly"?
I want to make the 'box' in the code move to the right and then go back to the left. I tried to use 2 setInterval but it didn't works (or maybe i don't know how to use 2 setInterval).
var box = document.getElementById("box");
var pos = 0;
var toRight = setInterval(move, 10);
function move() {
if (pos >= 150) {
clearInterval(toRight);
} else {
pos++;
box.style.left = pos + "px";
}
}
#container {
width: 200px;
height: 200px;
background-color: red;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
}
<div id="container">
<div id="box"></div>
</div>
<p id="demo"></p>
I tried so many ways and the code still doesn't run, can some one show me the way to make the 'box' move back from the right side. Thank you.
Your code was a good start, and #j08691's comment is the right direction to take it.
Use 1 interval function but keep track of which direction the box is moving and toggle it when desired.
let box = document.getElementById("box");
let pos = 0, right = true;
setInterval(() => {
pos += right * 2 - 1;
if (pos === 0 || pos === 150)
right = !right;
box.style.left = pos + "px";
}, 10);
#container {
width: 200px;
height: 200px;
background-color: red;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
}
<div id="container">
<div id="box"></div>
</div>
As an alternative you could also use css animations and skip the javascript part entirely:
#keyframes move {
from { left: 0; }
to { left: calc(100% - 50px); }
}
#container {
width: 200px;
height: 200px;
background-color: red;
position: relative;
}
#box {
width: 50px;
height: 50px;
background-color: blue;
position: absolute;
animation: move 2s linear alternate infinite;
}
<div id="container">
<div id="box"></div>
</div>
<p id="demo"></p>
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
I have some code which acts as a toggle to open/close an element. I am trying to figure out how to manipulate this so that when one element is clicked - the active one closes.
I have used animation to make the content appear from the right hand side of the page.
Please take a look at the code, I need to access the open callback but not sure how.
(function($) {
$.fn.clickToggle = function(func1, func2) {
var funcs = [func1, func2];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 2;
});
return this;
};
}(jQuery));
// cache sliding obj in a var
var tab1 = $('.tab1');
var tab1content = $('.tab1_results');
var tab2 = $('.tab2');
var tab2content = $('.tab2_results');
tab1.clickToggle(function() {
tab1.animate({
'right': '450px'
});
tab1content.animate({
'right': '0'
});
}, function() {
tab1.animate({
'right': '0'
});
tab1content.animate({
'right': '-450px'
});
});
tab2.clickToggle(function() {
tab2.animate({
'right': '450px'
});
tab2content.animate({
'right': '0'
});
}, function() {
tab2.animate({
'right': '0'
});
tab2content.animate({
'right': '-450px'
});
});
.filter {
position: fixed;
right: 0;
z-index: 99;
top: 0;
height: 100%;
}
.tab1_results {
background: #1cb2e7
}
.tab2_results {
background: #1cb2e1;
}
.tab1_results,
.tab2_results {
position: fixed;
width: 450px;
right: -450px;
z-index: 99;
top: 0;
height: 100%;
}
a.tab1 {
background-image: url('http://placehold.it/100x100?text=TAB1');
top: -1px;
z-index: 100;
height: 100px;
width: 100px;
position: absolute;
right: 0;
background-repeat: no-repeat;
margin-top: 0px;
}
a.tab2 {
background-image: url('http://placehold.it/100x100?text=TAB2');
top: 50%;
z-index: 100;
height: 100px;
width: 100px;
position: absolute;
right: 0;
background-repeat: no-repeat;
margin-top: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filter">
<a class="tab1" href="#"></a>
<div class="tab1_results">
tab 1 content
</div>
<a class="tab2" href="#"></a>
<div class="tab2_results">
tab 2 content
</div>
</div>
Don't use jQuery to animate things. Instead, use jQuery to toggle an "active" class, and use CSS transitions to make the active element slide in and the others out.
CSS3 transitions are hardware-accelerated, and overall, that's way less code.
See in Codepen
$(".header").click(function() {
$(this)
.parent()
.toggleClass("active")
.siblings()
.removeClass("active")
})
.filter {
position: absolute;
right: 0;
height: 100%;
}
.filter .tab {
height: 100%;
width: 200px;
background: #add8e6;
border: #808080 solid 1px;
transition: all 0.3s ease-out;
z-index: 1;
position: absolute;
top: 0;
left: 0;
}
.filter .tab:nth-child(2) .header {
top: 110px;
}
.filter .tab:nth-child(3) .header {
top: 220px;
}
.filter .tab.active {
transform: translateX(-100%);
z-index: 2;
}
.filter .tab .header {
cursor: pointer;
position: absolute;
left: 0;
top: 0;
background: #d3d3d3;
color: #a9a9a9;
width: 100px;
height: 100px;
transform: translateX(-100%);
}
.filter .tab .header:hover {
outline: #a9a9a9 solid 2px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filter">
<div class="tab">
<div class="header">Tab 1</div>
<div class="contnet">
tab 1 content
</div>
</div>
<div class="tab">
<div class="header">Tab 2</div>
<div class="contnet">
tab 2 content
</div>
</div>
<div class="tab">
<div class="header">Tab 3</div>
<div class="contnet">
tab 3 content
</div>
</div>
</div>
You could do something like this:
if (tab2.css("right").replace("px","") > 0) {
tab2.trigger("click");
}
demo
(function($) {
$.fn.clickToggle = function(func1, func2) {
var funcs = [func1, func2];
this.data('toggleclicked', 0);
this.click(function() {
var data = $(this).data();
var tc = data.toggleclicked;
$.proxy(funcs[tc], this)();
data.toggleclicked = (tc + 1) % 2;
});
return this;
};
}(jQuery));
// cache sliding obj in a var
var tab1 = $('.tab1');
var tab1content = $('.tab1_results');
var tab2 = $('.tab2');
var tab2content = $('.tab2_results');
tab1.clickToggle(function() {
if (tab2.css("right").replace("px","") > 0) {
tab2.trigger("click");
}
tab1.animate({
'right': '450px'
});
tab1content.animate({
'right': '0'
});
}, function() {
tab1.animate({
'right': '0'
});
tab1content.animate({
'right': '-450px'
});
});
tab2.clickToggle(function() {
if (tab1.css("right").replace("px","") > 0) {
tab1.trigger("click");
}
tab2.animate({
'right': '450px'
});
tab2content.animate({
'right': '0'
});
}, function() {
tab2.animate({
'right': '0'
});
tab2content.animate({
'right': '-450px'
});
});
.filter {
position: fixed;
right: 0;
z-index: 99;
top: 0;
height: 100%;
}
.tab1_results {
background: #1cb2e7
}
.tab2_results {
background: #1cb2e1;
}
.tab1_results,
.tab2_results {
position: fixed;
width: 450px;
right: -450px;
z-index: 99;
top: 0;
height: 100%;
}
a.tab1 {
background-image: url('http://placehold.it/100x100?text=TAB1');
top: -1px;
z-index: 100;
height: 100px;
width: 100px;
position: absolute;
right: 0;
background-repeat: no-repeat;
margin-top: 0px;
}
a.tab2 {
background-image: url('http://placehold.it/100x100?text=TAB2');
top: 50%;
z-index: 100;
height: 100px;
width: 100px;
position: absolute;
right: 0;
background-repeat: no-repeat;
margin-top: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="filter">
<a class="tab1" href="#"></a>
<div class="tab1_results">
tab 1 content
</div>
<a class="tab2" href="#"></a>
<div class="tab2_results">
tab 2 content
</div>
</div>