Parallax Issue in Javascript - javascript

I was creating a parallax effect in which the image and the text move in opposite direction to the movement of the mouse. That is happening inside an element called parallax-wrapper. But when I move out of the element I want the image and the text to return back to their original positions. I have tried to detect the mouse position outside the element but for some reason it not firing properly.
The codepen link is - https://codepen.io/rohitgd/pen/gRLNad?editors=1010
HTML
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>
CSS
body {
background-color:#fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color:#0c0c0c;
position: relative;
overflow: hidden;
.layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color:#FFF;
transition: all 200ms ease-out;
}
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
Javascript
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
$(document).mouseleave(function(e) {
var target = $(e.target);
if( !target.is("div.layer")) {
alert('out of the element');
e.stopPropagation();
}
});
What I want is when the mouse is outside the parallax-wrapper the Image and the text return back to their original positions.

You're not resetting the transformations when your mouse leaves. You need to add this where you have the alert...
$(".parallax-wrapper").mouseleave(function(e) {
$("*[data-mouse-parallax]").each(function() {
$(this).css({ transform: "translate3d( 0, 0, 0 )" });
});
});
Note that the mouseleave event is triggered when the mouse leaves .parallax-wrapper, not document as you previously had it.
Here's a modified codepen...
https://codepen.io/anon/pen/ZyBgYJ

I think a selector was wrong. Here's a correct version or see code below.
To show better when you are inside/outside I change the background color, that's better than an alert. When you leave the wrapper (the black background) it flips correctly now.
Where RED is set you can reset the transform to the origin.
// Trying to replicate the effect here - https://tympanus.net/Development/MorphingBackgroundShapes/
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$(".parallax-wrapper").css("background-color", "#00ff00"); // <-- EXIT
// reset transform here
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
// this is the selector I changed from "document" to ".parallax-wrapper"
$(".parallax-wrapper").mouseleave(function(e) {
var target = $(e.target);
if( !target.is("div.layer")) {
$(".parallax-wrapper").css("background-color", "#ff0000"); // <-- ENTER
e.stopPropagation();
}
});
body {
background-color:#fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color:#0c0c0c;
position: relative;
overflow: hidden;
.layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color:#FFF;
transition: all 200ms ease-out;
}
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>

Replace $(document).mouseleave with $(".parallax-wrapper").mouseleave.
$(".parallax-wrapper").mousemove(function(e) {
var x = e.pageX - $(this).offset().left - $(this).width() / 2;
var y = e.pageY - $(this).offset().top - $(this).height() / 2;
$("*[data-mouse-parallax]").each(function() {
var factor = parseFloat($(this).data("mouse-parallax"));
x = -x * factor;
y = -y * factor;
$(this).css({ transform: "translate3d( " + x + "px, " + y + "px, 0 )" });
});
});
$(".parallax-wrapper").mouseleave(function(e) {
alert('out of the element');
});
body {
background-color: #fff;
padding: 100px;
display: flex;
justify-content: center;
align-items: center;
}
.parallax-wrapper {
width: 500px;
height: 300px;
background-color: #0c0c0c;
position: relative;
overflow: hidden;
}
.parallax-wrapper .layer {
width: 80%;
height: 80%;
position: absolute;
left: 30px;
text-align: center;
line-height: 300px;
font-size: 38px;
color: #FFF;
transition: all 200ms ease-out;
}
img {
width: 200px;
height: 200px;
position: relative;
top: 50px;
right: 70px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parallax-wrapper">
<div class="layer" data-mouse-parallax="0.1">
<img src="https://tympanus.net/Development/MorphingBackgroundShapes/img/1.jpg"/>
</div>
<div class="layer" data-mouse-parallax="0.3">REVERT</div>
</div>

Related

Background reveal javascript not working properly

By following this tutorial :https://codepen.io/xaviDDB/pen/ExaKeeN I made a section in my website with this background reveal. here is the link:http://example.com/abra/
The code works fine if I do not have any other section in this page. But if I do, then it gets very strange. The reveal circle move away from the Mouse. See the page, I have added a horse image & the code gets messy. How do I solve this?
This is my current code:
(function() {
let magic = document.querySelector('.magic');
let magicWHalf = magic.offsetWidth / 2;
document.body.addEventListener('mousemove', function(e) {
magic.style.left = e.pageX - magicWHalf + 'px';
magic.style.top = e.pageY - magicWHalf + 'px';
});
document.body.addEventListener('mouseout', function(e) {
//magic.style.left = 'calc(50% - 10rem)';
//magic.style.top = 'calc(50% - 10rem)';
});
})();
.containers {
position: relative;
height: 100vh;
width: 100%;
background-color: #ffffff;
text-align: center;
overflow: hidden;
z-index: 1;
}
.containers:hover {
cursor: crosshair;
}
.text {
position: absolute;
font-size: 72px;
font-family: Arial, Helvetica, sans-serif;
color: #000000;
bottom: 20%;
left: 0;
right: 0;
z-index: 3;
}
.magic {
position: absolute;
top: calc(50% - 10rem);
left: calc(50% - 10rem);
width: 500px;
height: 500px;
background: center center no-repeat fixed;
background-size: cover;
border-radius: 50%;
z-index: 2;
}
<div class="containers">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
You have to update your mouse-move function in javascript. It has to calculate the relative mouse position to its parent (.container)
and one more improvement: set the eventListener on the element you want to hover. Not the entire body.
(function() {
const container = document.querySelector('.container');
const magic = document.querySelector('.magic');
const magicWHalf = magic.offsetWidth / 2;
container.addEventListener('mousemove',function(e){
const rect = container.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
magic.style.left = (e.pageX - (rect.left + scrollLeft)) - magicWHalf+'px';
magic.style.top = (e.pageY - (rect.top + scrollTop)) - magicWHalf+'px';
});
container.addEventListener('mouseout',function(e){
//magic.style.left = 'calc(50% - 10rem)';
//magic.style.top = 'calc(50% - 10rem)';
});
})();
.container {
position: relative;
height: 100vh;
width: 100%;
background-color: #ffffff;
text-align: center;
overflow: hidden;
z-index: 1;
}
.container:hover {
cursor: crosshair;
}
.text {
position: absolute;
font-size: 72px;
font-family: Arial, Helvetica, sans-serif;
color: #000000;
bottom: 20%;
left: 0;
right: 0;
z-index: 3;
}
.magic {
--size: 20rem;
position: absolute;
top: calc(50% - var(--size));
left: calc(50% - var(--size));
width: var(--size);
height: var(--size);
background: center no-repeat fixed;
background-size: cover;
border-radius: 50%;
z-index: 2;
}
<h1>add</h1>
<h1>extra</h1>
<h1>space</h1>
<h1>at top</h1>
<div class="container">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
You need to add the height of the previous element of your div.container
html
<div class="other">Other div </div>
<div class="container">
<div class="text">Lorem Ipsum</div>
<div class="magic" style="background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/142996/hover-reveal.jpg')"></div>
</div>
js
let magic = document.querySelector('.magic');
let magicWHalf = magic.offsetWidth / 2;
let heightPrevELm=document.querySelector('.other').offsetHeight;
document.body.addEventListener('mousemove',function(e){
magic.style.left = e.pageX - magicWHalf+'px';
magic.style.top = e.pageY - (magicWHalf+heightPrevELm)+'px';
});
You can see the result here :
https://codepen.io/bertyn99/pen/YzEwOpO
But i think if they are multiple element before we need to optimize the code

Cursor changer effect

I am having trouble changing my custom cursor width and height when I hover on the img element.
I tried using both css and javascript for the effect to work but it won't. When I change my function from "onmouseover" to "onclick" it works perfectly fine.
const cursor = document.querySelector('#cursor');
document.addEventListener('mousemove', e => {
cursor.setAttribute("style", "top: " + (e.clientY - 10) + "px; left: " + (e.clientX - 10) + "px;")
})
/*
/////Second way with javascript/////
var cursor = document.getElementById('cursor');
document.addEventListener('mousemove', function(e){
var x = e.clientX;
var y = e.clientY;
cursor.style.left= x + "px";
cursor.style.top= y + "px";
});
*/
function myFunction() {
document.getElementById("cursor").style.width = "100px";
document.getElementById("cursor").style.height = "100px";
}
body {
margin: 0;
height: 100vh;
background: rgb(27, 27, 27);
}
#cursor {
width: 30px;
height: 30px;
border: 2px solid gray;
border-radius: 50%;
position: fixed;
transition-duration: 100ms;
transition-timing-function: ease-out;
}
img {
position: absolute;
top: 50%;
left: 50%;
}
img:hover #cursor {
width: 100px;
height: 100px;
}
<div id="cursor"></div>
<img onmouseover="myFunction()" src="navbar.svg" alt="navbar">
How about this class toggle. Works.
Always preferable to use addEventListener everywhere
const cursor = document.querySelector('#cursor');
document.addEventListener('mousemove', e => {
cursor.setAttribute("style", "top: " + (e.clientY - 10) + "px; left: " + (e.clientX - 10) + "px;")
})
const hoverIt = e => cursor.classList.toggle("hover");
document.getElementById("navbarimg").addEventListener("mouseover",hoverIt);
document.getElementById("navbarimg").addEventListener("mouseover",hoverIt);
#cursor {
width: 30px;
height: 30px;
border: 2px solid gray;
border-radius: 50%;
position: fixed;
transition-duration: 100ms;
transition-timing-function: ease-out;
}
#cursor.hover {
width: 100px;
height: 100px;
}
img {
position: absolute;
top: 50%;
left: 50%;
}
img:hover #cursor {
width: 100px;
height: 100px;
}
<div id="cursor"></div>
<img id="navbarimg" src="navbar.svg" alt="navbar">
So the css solution here will not work as the #cursor is not a child of the img. You could have it a child of the anchor but that is probably the wrong approach anyway as it is not extendable.
You should probably change the logic to use an eventListener for simplicity...
document.getElementById("testImg").addEventListener("mouseover", function( event ) {
alert("over"); // Do your resizing here and ensure the image has the matching id
})

Keep parallax moving for one second on mouseout and stop smoothly

I would like to make a website with mouse parallax effect like in this page http://brightmedia.pl background mouse parallax is so smooth..
I have two questions:
When you mouseover on a container from, let's say, the top left corner, the image jumps. How can I make a smooth animation?
When you mouseout of a container, how can I make the image move a little bit and stop with a smooth animation?
What would code to solve these problems be?
Here is basic code:
$('.container').mousemove( function(e){
var xPos = e.pageX;
var yPos = e.pageY;
$('#par1').css({marginLeft: -xPos/20});
});
.container {
position: relative;
width: 100%;
height: 800px;
background: grey;
overflow: hidden;
margin: 0 auto;
}
.container img {
width: 110%;
height: 100vh;
position: absolute;
}
body{
height: 1000px;
}
h1{
font-size: 60px;
z-index: 10;
position: absolute;
left: 50%;
top: 30%;
transform: translate(-50%, -50%);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="css.css">
</head>
<body>
<div class="container" id="container">
<img id="par1" src="https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg" alt="">
<h1>TEXT</h1>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="script.js"></script>
</body>
</html>
As I had solved the problem long time ago and I forgot about this post so I decided to update with the answer. Maybe it will be helpful for anyone else.
Problem solved by using GSAP. Below You can see the code that works exactly as I wanted
let wrap = document.getElementById('container');
let request = null;
let mouse = { x: 0, y: 0 };
let cx = window.innerWidth / 2;
let cy = window.innerHeight / 2;
document.querySelector('.container').addEventListener('mousemove', function(event) {
mouse.x = event.pageX;
mouse.y = event.pageY;
cancelAnimationFrame(request);
request = requestAnimationFrame(update);
});
function update() {
dx = mouse.x - cx;
dy = mouse.y - cy;
let tiltx = (dy / cy );
let tilty = - (dx / cx);
TweenMax.to("#container img", 1, {x:-tilty*20, y:-tiltx*20, rotation:0.01, ease:Power2.easeOut});
}
window.addEventListener('resize', function(event){
window.innerWidth / 2;
window.innerHeight / 2;
});
* {
margin:0;
padding:0;
box-sizing:border-box;
}
.container {
position: relative;
width: 100%;
height: 100vh;
overflow: hidden;
display:flex;
flex-direction:column;
justify-content:center;
align-items:center;
}
.container img {
width: 110%;
height: 120vh;
position: absolute;
}
h1 {
z-index:100;
font-size: 6rem;
z-index: 10;
color:#333;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/latest/TweenMax.min.js"></script>
<div class="container" id="container">
<img id="par1" src="https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg" alt="">
<h1>GSAP Mouse Parallax</h1>
</div>
You can rely one mouseenter / mouseleave to add animation:
$('.container').mousemove(function(e) {
var xPos = e.pageX;
var yPos = e.pageY;
$('#par1').css({
marginLeft: -xPos / 10
});
});
$('.container').mouseenter(function(e) {
var xPos = e.pageX;
var yPos = e.pageY;
$('#par1').animate({
"marginLeft": -xPos / 10
}, "slow");
});
$('.container').mouseleave(function(e) {
$('#par1').animate({
"marginLeft": "0"
}, "slow");
});
.container {
position: relative;
width: 100%;
height: 800px;
background: grey;
overflow: hidden;
margin: 0 auto;
}
.container img {
width: 110%;
height: 100vh;
position: absolute;
}
body {
height: 1000px;
}
h1 {
font-size: 60px;
z-index: 10;
position: absolute;
left: 50%;
top: 30%;
transform: translate(-50%, -50%);
}
<div class="container" id="container">
<img id="par1" src="https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg" alt="">
<h1>TEXT</h1>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
As Temani said, playing with transition and eventually delay should do the job.
For 1st question: transition seems appropriate, associated with a mousein listener. Or even better, use the $(element).animate() function that allows to set the animation duration. That way, you don't set any value for transition duration.
For 2nd question: listener on mouseout > same process, but shorter animation (for the img shifting as well as the animation duration).
This should also give you some ideas:
https://codepen.io/Aldlevine/pen/Jowke
Based on Teemani below code example:
$('.container').mousemove(function(e) {
var xPos = e.pageX;
var yPos = e.pageY;
$('#par1').css("margin-left", -xPos / 10);
});
$('.container').mouseenter(function(e) {
var xPos = e.pageX;
var yPos = e.pageY;
$('#par1').css("margin-left", -xPos / 10);
});
$('.container').mouseleave(function(e) {
$('#par1').css({"transition": "margin-left 1s ease-in-out", "margin-left": "0"});
setTimeout( function() {
$('#par1').css("transition", "initial");
}, 500);
});
.container {
position: relative;
width: 100%;
height: 800px;
background: grey;
overflow: hidden;
margin: 0 auto;
}
.container img {
width: 110%;
height: 100vh;
position: absolute;
transition: margin-left 0.2s;
/* transition: margin-left 0.2s ease-in-out 0.2s;*/
}
body {
height: 1000px;
}
h1 {
font-size: 60px;
z-index: 10;
position: absolute;
left: 50%;
top: 30%;
transform: translate(-50%, -50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container" id="container">
<img id="par1" src="https://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg" alt="">
<h1>TEXT</h1>
</div>

Why does device orientation javascript mess up my element positioning?

So I've got my site more or less responsive. Everything stays centered and nice sizes when full screen desktop or mobile. But when I try to incorporate some device orientation javascript everything goes haywire. I'm sure it's something obvious that I'm missing since I'm a newbie but any insights would be appreciated :) Sorry in advance for the mess (been trying many different things without success and still getting my bearings with everything).
CSS:
body {
display: flex;
min-height: 100vh;
flex-direction: column;
width: 100%;
height: 100%;
min-width: 375px;
min-height: 375px;
}
.barbox {
position: relative;
flex: 1;
}
.colorbars {
margin:auto;
position: absolute;
top: 50%;
left: 50%;
width: 60vw;
height: 60vw;
max-width: 700px;
max-height: 700px;
transform: translate(-50%, -50%);
border: 4px solid black;
}
.coverart {
flex: 1;
position: absolute;
width: 80%;
top: 10%;
left: 10%;
display: block;
border: 2px solid black;
box-shadow: 11px 9px 41px 0px rgba(0,0,0,0.75);
margin: auto;
}
.bgimg {
background-size:cover;
background-repeat: repeat;
width: 100vw;
height: 100vh;
overflow: hidden;
}
HTML:
<body class="bgimg">
<div class="barbox">
<div class="colorbars">
<a href=""> <img class="coverart" src="css/images/RET001.jpg"/>
</a>
</div>
</div>
</body>
JS:
<script type="text/javascript">
var colorbars = document.querySelector('.colorbars');
var barbox = document.querySelector('.barbox');
var output = document.querySelector('.output');
var maxX = barbox.clientWidth - colorbars.clientWidth;
var maxY = barbox.clientHeight - colorbars.clientHeight;
function handleOrientation(event) {
var x = event.beta; // In degree in the range [-180,180]
var y = event.gamma; // In degree in the range [-90,90]
output.innerHTML = "beta : " + x + "\n";
output.innerHTML += "gamma: " + y + "\n";
if (x > 90) { x = 90};
if (x < -90) { x = -90};
x += 90;
y += 90;
colorbars.style.top = (maxX*x/180 - 10) + "px";
colorbars.style.left = (maxY*y/180 - 10) + "px";
}
window.addEventListener('deviceorientation', handleOrientation);
</script>
JS Commented Out:
JS Added Back In:

How do I get my Javascript to show just one spotlight centred on the mouse?

At the top of my website you can see that I have an animation at the top, I'm having trouble getting it to show just one spotlight that is centred on the mouse along with having the text shadow effect being centred on the mouse also.
I have found that by zooming in on the browser the centring issue is fixed but if possible I would rather not set a fixed zoom level for visitors.
Below I have attached the CSS followed by the JavaScript that I have used:
The CSS:
#text-shadow-box {
position: relative;
width: 100%;
height: 350px;
background: #666;
overflow: hidden;
cursor: none;
border: 1px solid Black;
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
}
#text-shadow-box div.wall {
position: absolute;
top: 175px;
left: 0;
width: 100%;
}
#tsb-text {
margin: 0;
color: #999;
font-family: Helvetica, Arial, sans-serif;
font-size: 80px;
line-height: 1em;
height: 1px;
font-weight: bold;
text-align: center;
}
div.wall div {
position: absolute;
background: #999;
overflow: hidden;
top: 150px;
left: 0;
height: 300px;
width: 100%;
}
#tsb-spot {
position: absolute;
overflow: hidden;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url(/spotlight.png) top center;
}
The JavaScript:
<script type="text/javascript" language="javascript" charset="utf-8">
var text;
var spot;
///window.onload = init;
init();
function init() {
text = document.getElementById('tsb-text');
spot = document.getElementById('tsb-spot');
document.getElementById('text-shadow-box').onmousemove = onMouseMove;
document.getElementById('text-shadow-box').ontouchmove = function (e) {e.preventDefault(); e.stopPropagation(); onMouseMove({clientX: e.touches[0].clientX, clientY: e.touches[0].clientY});};
onMouseMove({clientX: 300, clientY: 200});
}
function onMouseMove(e) {
var xm = e.clientX - 300;
var ym = e.clientY - 175;
var d = Math.sqrt(xm*xm + ym*ym);
text.style.textShadow = -xm + 'px ' + -ym + 'px ' + (d / 5 + 10) + 'px black';
xm = e.clientX - 600;
ym = e.clientY - 450;
spot.style.backgroundPosition = xm + 'px ' + ym + 'px';
}
</script>
With your current implementation, you are using an image for the spotlight, found on this line:
background: url(http://www.zachstronaut.com/lab/text-shadow-box/spotlight.png) top center;
A much better implementation would be to add a <canvas> element instead where your title is currently on your website. You can use CanvasRenderingContext2D.createRadialGradient() to create a spotlight effect: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createRadialGradient.
You can also see some similar implementations of what I am recommending here:
https://jsfiddle.net/4Ezkg/
http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

Categories

Resources