Using jquery to toggle a CSS property and also animate it - javascript

I have the below code:
$('#button').click(function () {
$('#divName').animate({
top: 90%,
}, 1000, function(){
});
});
When the button is clicked, it sets the top property for the DIV to 90%.
When I click the button again, I went to revert the CSS back to its original (50%).
How can I do this?
My attempt which seems to work but seems messy:
var state = false;
$('#button').click(function () {
if (state) {
state = false;
$('#divName').animate({
top: '50%',
}, 1000, function(){
});
} else if (state == false){
state = false;
$('#divName').animate({
top: '90%',
}, 1000, function(){
});
}
});

You could do it with CSS transitions. With jQuery just toggle a class.
$('#button').click(function () {
$('#divName').toggleClass('animate');
});
.container {
position: relative;
height: 80vh;
border: 2px solid red;
}
#divName {
position: absolute;
top: 50%;
width: 100%;
height: 50px;
border: 2px solid blue;
transition: top 1s linear;
}
.animate {
top: 90% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="button">Press</button>
<div class="container">
<div id="divName"></div>
</div>

You could improve this with some minor changes:
var state = false;
$('#button').click(function() {
percent = state ? 50 : 90
$('#divName').animate({
top: percent + '%',
}, 1000, function() {});
state = !state;
});
div {
background-color: green;
position: absolute;
top: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="button">clickme</p>
<div id="divName">
<p>hello</p>
</div>

here is one way to do it by removing the style added by jQuery
var div = $('#divName');
$('#button').click(function () {
var style = div.attr("style");
if(style && style.includes("top")){
div.attr("style", style.replace(/top:[^;]+;/,""));
}else{
div.css("top", "90%");
}
});
#divName{
width: 20px;
height: 20px;
border: black solid 1px;
position: absolute;
top:50%; /*you need to give an init value to top*/
transition: top 1s linear;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<button id="button">click me</button>
<div id="divName"></div>

Related

CSS: How to don't reset onhover animation on every hover

I have a simple on-hover CSS animation which makes slide transition between images.
When the user makes the hover on SECTION ONE and before the animation ends make hover on SECTION two, animation restart and make lagging move.
MY CODE:
var $circle = $('#circle');
function moveCircle(e) {
TweenLite.to($circle, 0.8, {
css: {
left: e.pageX,
top: e.pageY
}
});
}
$(window).on('mousemove', moveCircle);
#import "compass/css3";
#keyframes in {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
#keyframes out {
from {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
html {
background: #0E3741;
}
#circle {
position: absolute;
pointer-events : none;
width: 400px;
height: 200px;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
}
#circle .circle-wrapper {
overflow: hidden;
width: 400px;
height: 200px;
position: relative;
}
#circle img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 400px;
height: 200px;
object-fit: cover;
overflow: hidden;
}
#wrapper {
display: flex;
flex-direction: column;
}
.special-element {
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
#one {
background: blue;
}
#two {
background: red;
}
#one:hover ~ #circle .circle-wrapper #imgOne {
animation: in 1s ease-in-out;
z-index: 2;
}
#one:hover ~ #circle .circle-wrapper #imgTwo {
animation: out 1s ease-in-out;
}
#two:hover ~ #circle .circle-wrapper #imgTwo {
animation: in 1s ease-in-out;
z-index: 2;
}
#two:hover ~ #circle .circle-wrapper #imgOne {
animation: out 1s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script>
<section id="wrapper">
<section class="special-element" id="one">
section one
</section>
<section class="special-element" id="two">
section two
</section>
<div id="circle">
<div class="circle-wrapper">
<img id="imgOne" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg">
<img id="imgTwo" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg">
</div>
</div>
</section>
Is there any solution how I can prevent this lagging issue?
Maybe is there any solution to how I can solve it and make this animation smooth?
I'm looking for something like animation on this website.
Updated version
You can do a simplified version of it with gsap. It is probably best not to mix plain css too much with the gsap, unless you use css inside the gsap library. Because gsap will manipulate some of the props. E.g. the transformation. And it is better to use transform than just left/top because it is hardware accelerated.
I've done some improvements to the code I've posted before. It looks smoother now. In addition, I have added a little zoom and horizontal-shift effect - similar to the animation on the referenced website. Also, the animation now starts from the bottom.
The animation is really well done on the referenced page. It is done with WebGL. This is not your every-day animation and requires quite a bit of effort to make it work - at least for someone who is not a designer. It uses a 3d transformation matrix and some other effects together.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css#5.0.1/reset.min.css" />
<script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
<script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<style type="text/css">
.section {
display: block;
width: 100%;
height: 300px;
border-bottom: 1px solid red;
}
.overlay {
position: absolute;
top: 0;
left: 0;
display: none;
background: transparent;
z-index: -1;
}
.stack {
position: relative;
min-width: 300px;
min-height: 300px;
width: 480px;
height: 320px;
max-width: 480px;
max-height: 320px;
overflow: hidden;
z-index: 1;
}
.img {
position: absolute;
top: 0;
left: 0;
width: auto;
height: auto;
max-width: 100%;
object-fit: contain;
z-index: -1;
}
</style>
</head>
<body>
<main class="main">
<section class="section section-1" data-img="img-1">section 1</section>
<section class="section section-2" data-img="img-2">section 2</section>
<div class="overlay">
<div class="stack">
<img id="img-1" class="img" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg">
<img id="img-2" class="img" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg">
</div>
</div>
</main>
<script type="application/javascript">
window.onload = () => {
const overlay = document.querySelector(".overlay");
const stack = document.querySelector(".stack");
const s1 = document.querySelector(".section-1");
const s2 = document.querySelector(".section-2");
const main = document.querySelector(".main");
const overlaySize = {
width: 480,
height: 320
};
const easeFunc = "sine.inOut";
const easeDuration = 0.5;
let animation;
let activeSection;
let currentTarget;
function createAnimation() {
//console.log('create animation');
t1 = gsap.timeline({
paused: true
});
t1.to(currentTarget, {
zIndex: 2,
display: "block"
}, 0);
t1.fromTo(currentTarget, {
y: "100%"
}, {
y: 0,
duration: easeDuration,
ease: easeFunc
}, 0);
t1.to(currentTarget, {
scale: 1.25,
transformOrigin: "center",
duration: easeDuration,
ease: easeFunc
}, 0);
stack.querySelectorAll(".img").forEach((it) => {
if (it !== currentTarget) {
t1.to(it, {
zIndex: -1
}, 0);
t1.to(it, {
scale: 1,
transformOrigin: "center"
}, 0);
t1.to(it, {
display: "none"
}, easeDuration);
}
});
return t1;
}
function onMouseLeave(e) {
const target = e.target;
//console.log("leave", e.target);
if (target === activeSection) {
gsap.set(overlay, {
display: "none"
});
currentTarget = null;
}
}
function onMouseEnter(e) {
currentTarget = stack.querySelector(`#${e.target.dataset.img}`);
gsap.set(overlay, {
display: "block"
});
if (!animation) {
//console.log("undefined animation")
animation = createAnimation();
animation.play();
} else if (animation.isActive()) {
//console.log("still active");
animation.timeScale(10); // fast forward the rest of the animation
animation = createAnimation();
animation.timeScale(1).play();
} else {
//console.log("no longer active");
animation = createAnimation();
animation.play();
}
}
function onMouseMove(e) {
const hoveredEl = document.elementFromPoint(e.pageX, e.pageY);
if (hoveredEl.classList.contains("section")) {
if (activeSection !== hoveredEl) {
activeSection = hoveredEl;
}
} else if (hoveredEl.classList.contains("overlay") || hoveredEl.classList.contains("stack") || hoveredEl.classList.contains("pointer")) {
// do nothing
} else {
if (activeSection) {
activeSection = null;
}
}
if (currentTarget) {
// update overlay
gsap.set(overlay, {
x: e.pageX - overlaySize.width / 2,
y: e.pageY - overlaySize.height / 2
});
// add a little horizontal-shift effect
const dx = window.innerWidth / 2 - e.pageX;
const offsetX = dx / window.innerWidth / 2 * 100;
gsap.to(currentTarget, {
x: offsetX * 2,
duration: 2
}, 0);
}
}
gsap.set(overlay, {
x: 0,
y: 0
});
stack.querySelectorAll('.img').forEach((it) => gsap.set(it, {
x: 0,
y: "100%"
}));
window.addEventListener("mousemove", onMouseMove);
s1.addEventListener("mouseleave", onMouseLeave);
s2.addEventListener("mouseleave", onMouseLeave);
s1.addEventListener("mouseenter", onMouseEnter);
s2.addEventListener("mouseenter", onMouseEnter);
}
</script>
</body>
</html>
Old answer
I have been playing around a little bit with the gsap library today. I've honestly never done anything with or like it. Tried to do it with the x and y params that you may pass to gsap. It will take care of the transformations - also the TimeLine stuff
is quite handy. The result is not that great, also the animations look like it could be done better, but maybe it might still help you out. You could also improve some of the logic and animation probably. At least it runs quite stable - performance wise.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset-css#5.0.1/reset.min.css" />
<script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.9.1/gsap.min.js"></script>
<script type="application/javascript" defer src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/plugins/CSSPlugin.min.js"></script>
<style type="text/css">
.section {
display: block;
width: 100%;
height: 200px;
border-bottom: 1px solid red;
}
.overlay {
position: absolute;
top: 0;
left: 0;
display: none;
border: none; // 1px dashed black;
background: transparent; // lavender;
overflow: hidden;
}
.stack {
position: relative;
left: 0;
right: 0;
top: 0;
bottom: 0;
min-width: 300px;
min-height: 300px;
width: 480px;
height: 320px;
z-index: 0;
}
.anim-img {
position: absolute;
top: 0;
left: 0;
width: auto;
height: auto;
max-width: 100%;
object-fit: contain;
z-index: 1;
}
</style>
</head>
<body>
<main class="main">
<section class="section section-1">section 1</section>
<section class="section section-2">section 2</section>
<div class="overlay">
<div class="stack">
<img id="img-1" class="anim-img" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg">
<img id="img-2" class="anim-img" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg">
</div>
</div>
</main>
<script type="application/javascript">
window.onload = () => {
const overlay = document.querySelector(".overlay");
const img1 = document.getElementById("img-1");
const img2 = document.getElementById("img-2");
const s1 = document.querySelector(".section-1");
const s2 = document.querySelector(".section-2");
const main = document.querySelector(".main");
let anim;
let isS1active = false;
let isS2active = false;
let showEl;
let hideEl;
let leaveTimeout;
function reverseFadeInOut(showEl, hideEl) {
console.log("create reverse timeline anim -> ", {
showEl,
hideEl
});
const tl = gsap.timeline({
paused: true
});
tl
.to(showEl, {
zIndex: 1
}, 0)
.to(hideEl, {
zIndex: 10
}, 0)
.to(hideEl, {
y: "-100%",
duration: 0.375
}, 0)
.to(hideEl, {
display: "none"
}, 0.375)
.to(hideEl, {
zIndex: 1
}, 0.375)
.to(showEl, {
display: "block",
zIndex: 10
}, 0.375)
.fromTo(showEl, {
y: "-100%"
}, {
y: 0,
duration: .375
}, 0.375)
.to(hideEl, {
display: "none"
});
return tl;
}
function fadeInOut(showEl, hideEl) {
console.log("create timeline anim -> ", {
showEl,
hideEl
});
const tl = gsap.timeline({
paused: true
});
tl
.to(hideEl, {
zIndex: 1
}, 0)
.to(showEl, {
display: "block",
zIndex: 10
}, 0)
.fromTo(showEl, {
y: "-100%"
}, {
y: 0,
duration: .75
}, 0)
.fromTo(hideEl, {
y: 0
}, {
y: "-100%",
duration: .75
}, 0)
.to(hideEl, {
display: "none"
}, 0.75);
return tl;
}
function animateImage() {
if (isS1active || isS2active) {
if (isS1active) {
showEl = img1;
hideEl = img2;
} else if (isS2active) {
showEl = img2;
hideEl = img1;
}
if (!anim) {
console.log("create new animation");
anim = fadeInOut(showEl, hideEl);
anim.play();
} else {
console.log("anim active:", anim.isActive());
if (anim.isActive()) {
console.log("reverse");
anim.kill();
anim = reverseFadeInOut(showEl, hideEl);
anim.play();
} else {
anim = fadeInOut(showEl, hideEl);
anim.play();
}
}
}
}
function moveOverlay(e) {
e.preventDefault();
e.stopPropagation();
gsap.set(overlay, {
x: e.pageX + 15,
y: e.pageY + 15,
display: isS1active || isS2active ? "block" : "none"
});
}
function mouseOver(e, el, isEntering) {
e.preventDefault();
e.stopPropagation();
el.classList.toggle("active");
isS1active = s1.classList.contains("active");
isS2active = s2.classList.contains("active");
if (isEntering) {
clearTimeout(leaveTimeout);
animateImage();
} else {
leaveTimeout = setTimeout(() => {
if (anim) {
console.log("kill anim");
anim.kill();
anim = null;
}
gsap.timeline({
onComplete: () => {
console.log("clear props");
gsap.set(".anim-img", {
clearProps: true
});
}
});
}, 500);
}
}
gsap.set(overlay, {
x: "0",
y: "0"
});
gsap.set(img1, {
x: "0",
y: "-100%"
});
gsap.set(img2, {
x: "0",
y: "-100%"
});
window.addEventListener("mousemove", moveOverlay);
s1.addEventListener("mouseenter", (e) => {
mouseOver(e, s1, true);
});
s1.addEventListener("mouseleave", (e) => {
mouseOver(e, s1, false);
});
s2.addEventListener("mouseenter", (e) => {
mouseOver(e, s2, true);
});
s2.addEventListener("mouseleave", (e) => {
mouseOver(e, s2, false);
});
}
</script>
</body>
</html>
I think that problem is because "moving circle function". Moving dom element with Left and right is not good for performance. You should move the circle with "transform". transform runs with GPU acceleration and it performs better and make move smooth.
Try this code.
function moveCircle(e) {
TweenLite.to($circle, 0.8, {
css: {
transform: `translate(${e.pageX}px, ${e.pageY}px)`
}
});
}
Yes, there is, by modifying the value of the second parameter of TweenLite.to, because that's the duration, see more here: http://www.tud.ttu.ee/im/Jaak.Henno/FlashDevelop/greensock-as3/greensock-as3/docs/com/greensock/TweenLite.html#to()
var $circle = $('#circle');
function moveCircle(e) {
TweenLite.to($circle, 0.1, {
css: {
left: e.pageX,
top: e.pageY
}
});
}
$(window).on('mousemove', moveCircle);
#import "compass/css3";
#keyframes in {
from {
transform: translateY(-100%);
}
to {
transform: translateY(0);
}
}
#keyframes out {
from {
transform: translateY(0);
}
to {
transform: translateY(100%);
}
}
html {
background: #0E3741;
}
#circle {
position: absolute;
pointer-events : none;
width: 400px;
height: 200px;
top: 50%;
left: 50%;
margin: -50px 0 0 -50px;
}
#circle .circle-wrapper {
overflow: hidden;
width: 400px;
height: 200px;
position: relative;
}
#circle img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 400px;
height: 200px;
object-fit: cover;
overflow: hidden;
}
#wrapper {
display: flex;
flex-direction: column;
}
.special-element {
width: 100%;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
}
#one {
background: blue;
}
#two {
background: red;
}
#one:hover ~ #circle .circle-wrapper #imgOne {
animation: in 1s ease-in-out;
z-index: 2;
}
#one:hover ~ #circle .circle-wrapper #imgTwo {
animation: out 1s ease-in-out;
}
#two:hover ~ #circle .circle-wrapper #imgTwo {
animation: in 1s ease-in-out;
z-index: 2;
}
#two:hover ~ #circle .circle-wrapper #imgOne {
animation: out 1s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script>
<section id="wrapper">
<section class="special-element" id="one">
section one
</section>
<section class="special-element" id="two">
section two
</section>
<div id="circle">
<div class="circle-wrapper">
<img id="imgOne" src="https://upload.wikimedia.org/wikipedia/commons/3/3b/Coca-cat.jpg">
<img id="imgTwo" src="https://staticcdn.sk/images/photoarchive/sized/700/2020/07/29/ohrozeny-vtak-krakla-belasa.jpg">
</div>
</div>
</section>
The website is using canvas for the moving slideshow and they've used webgl for the smooth kind of reveal effects.
<div class="site-footer">
<div class="js-scroll-height"></div>
<canvas width="780" height="624" class="js-webgl" style="width: 1041px;height: 833px;opacity: 1;border: 1px solid brown;"></canvas>
</div>
We can create similar reveal effect using simple animation and z-index manipulation:
var $cursor = $('#cursor');
function movecursor(e) {
TweenLite.to($cursor, 0.8, {
css: {
left: e.pageX,
top: e.pageY
}
});
}
$(window).on('mousemove', movecursor);
let topImg = null;
$('.special-element').mouseenter((e) => {
//make all images at same level
$('.img-wrapper').css({ zIndex: '1' });
//make last focused image at second highest level
if (topImg) topImg.css({ zIndex: '2' });
//make current image as topImage
let atr = $(e.target).attr('data-img');
topImg = $('.img-wrapper[data-img="' + atr + '"]');
//make it topmost
topImg.css({ zIndex: '3' });
});
:root {
--cursor-img-height: 30vh;
--cursor-img-width: 30vw;
}
html,
body {
background: #0E3741;
}
#wrapper {
display: flex;
flex-direction: column;
}
.special-element {
width: 100%;
height: 33vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
}
.special-element:nth-child(1) {
background: lightblue;
}
.special-element:nth-child(2) {
background: lightcoral;
}
.special-element:nth-child(3) {
background: lightgreen;
}
#cursor {
position: absolute;
pointer-events: none;
margin: 0;
margin-top: calc(var(--cursor-img-height) * -0.5);
margin-left: calc(var(--cursor-img-width) * -0.5);
overflow: hidden;
width: var(--cursor-img-width);
height: var(--cursor-img-height);
}
.img-wrapper {
position: absolute;
bottom: 0;
left: 0;
width: var(--cursor-img-width);
height: var(--cursor-img-height);
overflow: hidden;
}
.img-wrapper>img {
position: absolute;
bottom: 0;
left: 0;
width: var(--cursor-img-width);
height: var(--cursor-img-height);
object-fit: fill;
z-index: 1;
}
.special-element[data-img="one"]:hover~#cursor [data-img="one"],
.special-element[data-img="two"]:hover~#cursor [data-img="two"],
.special-element[data-img="three"]:hover~#cursor [data-img="three"] {
animation: slide .8s ease-in-out;
}
#keyframes slide {
from {
height: 0px;
transform: scale(1.2);
}
to {
height: (--cursor-img-height);
transform: scale(1);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.11.4/TweenMax.min.js"></script>
<section id="wrapper">
<section class="special-element" data-img="one">food</section>
<section class="special-element" data-img="two">animal</section>
<section class="special-element" data-img="three">night</section>
<div id="cursor">
<div class="img-wrapper" data-img='one'>
<img src="https://picsum.photos/id/674/400/200">
</div>
<div class="img-wrapper" data-img='two'>
<img src="https://picsum.photos/id/433/400/200">
</div>
<div class="img-wrapper" data-img='three'>
<img src="https://picsum.photos/id/901/400/200">
</div>
</div>
</section>
View in full page mode.

Keep div visible when the mouse is over it

I have a div2 that fades away after 3 seconds and appears again on div1 or itself hover.
The problem is that it fades away again after 3 seconds and I want it to remain active while the mouse is over it.
Here's my code:
$(document).ready(function(){
// div2 fades away after 3s
setInterval(function(){
$(".div2").addClass("fade-away");
}, 3000);
// div2 pops up on hover
$(".div1, .div2").hover(function(){
$(".div2").removeClass("fade-away")
});
});
.div1 {
width: 300px;
height: 200px;
background: pink;
}
.div2 {
position: absolute;
width: 300px;
height: 50px;
margin-top: -70px;
background: lightblue;
opacity: 1;
}
.fade-away {
opacity: 0;
}
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<div class="div1"></div>
<div class="div2"></div>
Is there a way to make the div2 remain active while the mouse is over it with javascrit and css only? Sorry for my english.
You can use a boolean flag to do it.
Set the boolean to true when mouseenter and set it to false on mouseleave event.
https://jsfiddle.net/ramseyfeng/0nc2bw8f/
$(document).ready(function() {
let mouseIn = false;
// div2 fades away after 3s
setInterval(function() {
if (!mouseIn) {
$(".div2").addClass("fade-away");
}
}, 3000);
$('.div1').on('mouseenter', () => {
mouseIn = true;
});
$('.div1').on('mouseleave', () => {
mouseIn = false;
});
// div2 pops up on hover
$(".div1, .div2").hover(function() {
$(".div2").removeClass("fade-away")
});
});
.div1 {
width: 300px;
height: 200px;
background: pink;
}
.div2 {
position: absolute;
width: 300px;
height: 50px;
margin-top: -70px;
background: lightblue;
opacity: 1;
}
.fade-away {
opacity: 0;
}
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<div class="div1"></div>
<div class="div2"></div>
Here is a quick and easy way to do it.
You can do it by hovering over any class, I just did it in text for the example.
.hide {
display: none;
}
.myDIV:hover + .hide {
display: block;
color: red;
}
<body>
<h2>Display an Element on Hover</h2>
<div class="myDIV">Hover over me.</div>
<div class="hide">I am shown when someone hovers over the div above.</div>
</body>

Animate div from right to left and then from left to right again

I try to animate a div from its original position to left of the screen, if a button was clicked. If another button is clicked then i want it to animate back to it's origin position. I was able to figure out on how to animate it from right to left, but i cant animate it back to its original position.
var left = $('#coolDiv').offset().left;
$("#b1").click(
function() {
$("#coolDiv").css({
left: left
}).animate({
"left": "0px"
}, "slow");
}
);
$("#b2").click(
function() {
$("#coolDiv").css({
right: right
}).animate({
"right": "0px"
}, "slow");
}
);
#coolDiv {
width: 50px;
height: 50px;
position: absolute;
right: 0;
background: yellow;
}
#b1 {
margin-top: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="coolDiv">cool</div>
<button id="b1">left</button>
<button id="b2">right</button>
http://jsfiddle.net/XqqtN/5385/
Set the left CSS to the window width minus the width of the box.
$("#b1").click(function() {
// Get the current left of the div
var left = $('#coolDiv').offset().left;
$("#coolDiv").css({
left: left
}).animate({
left: 0
}, "slow");
});
$("#b2").click(function() {
var left = $(window).width() - $('#coolDiv').width();
$("#coolDiv").css({
left: 0
}).animate({
left: left
}, "slow");
});
#coolDiv {
width: 50px;
height: 50px;
position: absolute;
right: 0;
background: yellow;
}
#b1 {
margin-top: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="coolDiv">cool</div>
<button id="b1">Left</button>
<button id="b2">Right</button>
Optimized Code:
// Common function to animate Div on both button clicks
function animateDiv(left, right) {
$('#coolDiv').css({
left: left
}).stop(true, true).animate({
left: right
}, 'slow');
}
$('#b1').click(function() {
animateDiv($('#coolDiv').offset().left, 0);
});
$('#b2').click(function() {
animateDiv(0, $(window).width() - $('#coolDiv').width());
});
#coolDiv {
width: 50px;
height: 50px;
position: absolute;
right: 0;
background: yellow;
}
#b1 {
margin-top: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="coolDiv">cool</div>
<button id="b1">Left</button>
<button id="b2">Right</button>
Can you try something simple like this?
$(function () {
$(".animateable").animate({
left: $(window).innerWidth() - 50
}, 1000, function () {
$(".animateable").animate({
left: 0
}, 1000);
});
});
* {font-family: Segoe UI; line-height: 1;}
.animateable {position: absolute; width: 50px; text-align: center; background-color: #ccf; line-height: 2em;}
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<div class="animateable">
Hi
</div>
You can use setInterval to make it work a lot of times.
$(function () {
setInterval(function () {
$(".animateable").animate({
left: $(window).innerWidth() - 50
}, 1000, function () {
$(".animateable").animate({
left: 0
}, 1000);
});
}, 2000);
});
* {font-family: Segoe UI; line-height: 1;}
.animateable {position: absolute; width: 50px; text-align: center; background-color: #ccf; line-height: 2em;}
<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<div class="animateable">
Hi
</div>
This is your updated code. Make changes like following:
$("#b1").click(
function() {
$("#coolDiv").animate({
"left": "0px"
},
"slow"
);
$("#coolDiv").css('right', '');
}
);
$("#b2").click(
function() {
$("#coolDiv").animate({
"right": "0px"
},
"slow"
);
$("#coolDiv").css('left', '');
}
);
#coolDiv {
width: 50px;
height: 50px;
position: absolute;
right: 0;
background: yellow;
}
#b1 {
margin-top: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<div id="coolDiv">cool</div>
<button id="b1">B1</button>
<button id="b2">B2</button>
Hope it helps.

How can i check if multiple divs have been clicked in JS?

I'm trying to "track" if all divs have been clicked. If all divs have been clicked something should happen. This can only happen when all divs have been clicked.
http://jsbin.com/cawukapumi/1/
This is what i've gathered so far.
Any help is more then appreciated.
$(document).ready(function(){
$(".masterobject").click(function() {
$(this).data('clicked, true');
});
if ($('#obj1').data('clicked') && $('#obj2').data('clicked') && $('#obj3').data('clicked') && $('#obj4').data('clicked') && $('#obj5').data('clicked') ) {
console.log( "all has been clicked" );
}
});
.masterobject {
position: absolute;
background-color: red;
z-index: 2;
}
#obj1 {
width: 50px;
height: 60px;
top: 25%;
left: 19%;
}
#obj2 {
width: 150px;
height: 100px;
top: 12%;
left: 84%;
}
#obj3 {
width: 80px;
height: 80px;
top : 66%;
left : 73%;
}
#obj4 {
top: 54%;
left: 28%;
width: 60px;
height: 70px;
}
#obj5 {
width: 100px;
height: 100px;
top: 45%;
right: 13%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="masterobject" id="obj1"></div>
<div class="masterobject" id="obj2"></div>
<div class="masterobject" id="obj3"></div>
<div class="masterobject" id="obj4"></div>
<div class="masterobject" id="obj5"></div>
Add a class, see if its count matches the count of items:
$(document).ready(function(){
$(".masterobject").click(function() {
$(this).addClass("clicked");
if ($(".masterobject").length == $(".clicked").length)
alert("all clicked");
});
});
In general, you could do something like this:
var clickers = $(".clicker");
clickers.on("click", function() {
$(this).data("clicked", true);
$(this).addClass("clicked");
var all = true;
clickers.each(function() {
all &= $(this).data("clicked");
return all;
});
if (all) {
alert("all clicked!");
}
});
.clicker {
background-color: red;
width: 100px;
height: 100px;
position: absolute;
}
.clicked {
background-color: blue;
}
#div1 {
left: 10px;
top: 10px;
}
#div2 {
left: 10px;
top: 130px;
}
#div3 {
left: 130px;
top: 10px;
}
#div4 {
left: 130px;
top: 130px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="clicker" id="div1"></div>
<div class="clicker" id="div2"></div>
<div class="clicker" id="div3"></div>
<div class="clicker" id="div4"></div>
What we are doing is for every div with the class clicker we bind a click handler that will get the clicked property of this div. Then we check to see if all divs with this class have been clicked and pop an alert if they have.
Note: I added a class so you can tell when you've clicked a div (in my example, they now turn blue). You could actually use that instead of a data property by using .hasClass.
1 approach: You'll need to check if all the divs are clicked each time one is clicked. So, I'd loop through each of your div's, see if the attribute is set... and if not, set a standard boolean var to false.
Something like the following...
var allClicked = true;
$('.masterobject').each(function(){
if(!$(this).data('clicked')){
allClicked=false;
return false;
}
});
if(allClicked){
alert('yay!');
}
http://jsbin.com/kokumohohe/2/edit?output
It is a bit ugly, but you can do something like:
div1 = "1";
div2 = "1";
div3 = "1";
divSum = div1 + div2 + div3;
console.log(divSum);
$("#div1").click(function() {
div1 = "2";
check();
});
$("#div2").click(function() {
div2 = "2";
check();
});
$("#div3").click(function() {
div3 = "2";
check();
});
function check () {
divSum = div1 + div2 + div3;
if (divSum = 222) {
alert("TAdaaahh!");
};
}
Here is a fiddle: http://jsfiddle.net/xdpyx3rx/1/
What about this approach using combination of jQuery and getElementsByClassName method, which allows you not to requery DOM on each click taking advantage of live NodeList:
$(document).ready(function() {
var clicked = document.getElementsByClassName('clicked');
var $masterObjects = $(".masterobject").click(function() {
$(this).addClass("clicked");
if ($masterObjects.length === clicked.length) {
alert("all clicked");
}
});
});
Demo: http://jsbin.com/wepoqumita/1/

Detect Hover for two intersecting Circular elements

i did an example on jsFiddle ( http://jsfiddle.net/aRWhm/ ) , the idea is to know when i'm over lets say the intersection between the red and the blue circle.
but the problem is that every time i reach the intersection, the class "is-over" of the red circle is removed.
Html:
<div>
<span id="Div1"></span>
<span id="Div2"></span>
<span id="Div3"></span>
<span id="Div4"></span>
</div>
CSS:
div {
display: block;
margin: 0 auto;
overflow: hidden;
width: 950px;
}
span {
display: block;
position: absolute;
opacity: 0.5;
border-radius: 999px;
z-index: 1;
}
#Div1 {
background-color: #FF0000;
height: 200px;
left: 50px;
top: 80px;
width: 200px;
}
#Div2 {
background-color: #0000FF;
height: 150px;
left: 40px;
top: 230px;
width: 150px;
}
#Div3 {
background-color: #008000;
height: 250px;
left: 100px;
top: 190px;
width: 250px;
}
#Div4 {
background-color: #FFFF00;
height: 100px;
left: 200px;
top: 130px;
width: 100px;
}
JavaScript:
$(document).ready(function () {
$("#Div1").hover(
function () {
$(this).addClass("is-over");
},
function () {
$(this).removeClass("is-over");
}
);
$("#Div2").hover(
function () {
$(this).addClass("is-over");
},
function () {
$(this).removeClass("is-over");
}
);
$("#Div3").hover(
function () {
$(this).addClass("is-over");
},
function () {
$(this).removeClass("is-over");
}
);
$("#Div4").hover(
function () {
$(this).addClass("is-over");
},
function () {
$(this).removeClass("is-over");
}
);
});
Here you go.
First, the Code:
(function($){
$.mlp = {x:0,y:0}; // Mouse Last Position
function documentHandler(){
var $current = this === document ? $(this) : $(this).contents();
$current.mousemove(function(e){jQuery.mlp = {x:e.pageX,y:e.pageY}});
$current.find("iframe").load(documentHandler);
}
$(documentHandler);
$.fn.ismouseover = function(overThis) {
var result = false;
this.eq(0).each(function() {
var $current = $(this).is("iframe") ? $(this).contents().find("body") : $(this);
var offset = $current.offset();
result = offset.left<=$.mlp.x && offset.left + $current.outerWidth() > $.mlp.x &&
offset.top<=$.mlp.y && offset.top + $current.outerHeight() > $.mlp.y;
});
return result;
};
})(jQuery);
$(document).ready(function () {
$("#myDiv").mousemove(
function() {
$("#myDiv").children("span").each(function(){
if($(this).ismouseover())
$(this).addClass("is-over");
else
$(this).removeClass("is-over");
});
});
});
Now an explanation:
I stole the .ismouseover() code shamelessly from this answer by Ivan Castellanos and repurposed it to your needs. Form there I used a .mousemove() event to fire every time you're in the parent container, which you can see in this fiddle needed to be given height and width parameters to ensure that it had a bounding box.
Lastly I simply check to see which circles you're over, and add the is-over class to them. The Fiddle is based off Anton's work, although it provides intersection support instead of moving one to the top.
Hope this helps.

Categories