I realise this used to be the default behaviour of getBoundingClientRect() but it seems that I'm in the rare position of needing this feature!
I have a CSS animation that moves a div across the Y axis using translate. However, I want the finishing position of the div ...but before the animation has even begun.
Is there any (neat) way of doing this assuming I have no knowledge of the animation parameters?
You can use getBoundingClientRect just as is.
Here is an example:
var element = document.getElementById("move");
window.setInterval(function() {
var structure = element.getBoundingClientRect();
element.innerHTML = "left: " + Math.floor(structure.left) + "px<br/> top: " + Math.floor(structure.top) + "px";
}, 100);
body {
background-color: #222;
height: 450px;
}
#move {
position: absolute;
width: 200px;
height: 200px;
background-color: white;
animation: move 5s infinite alternate;
}
#keyframes move {
from {
left: 0;
top: 0;
}
to {
left: calc(100% - 200px);
top: calc(100% - 200px);
}
}
<div id="move">HELLO!</div>
Related
Currently, I have layered 4 images on top of a background image. When your mouse hovers over each image, it disappears until the user refreshes. I would like to create 26 clones of an image. Ideally, I could position each image copy and the jquery would autogenerate id names like so (#myid(n)) a.k.a #myid1, #myid2. As I am unable to pull this image cloning off so far, I have to copy and paste each block of code over and over again. However, once I added my sixth image, I encountered performance problems, and my code stopped working.
I have included two codepens. This codepen works with 4 image copies : https://codepen.io/narutofan389/collab/NWGpQWo
This codepen doesn't work with 6 copies: https://codepen.io/narutofan389/collab/MWapQyO
I have heard too many mouseover events can create performance issues. I am not sure if this is what the source of my issues. I am also trying on a separate codepen to test image cloning with separate ids. This is the code so far taken from another stack overflow answer:
html
<body>
<div id="sand"></div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
javascript
$(document).ready(function(){
for (var i = 0; i < 2; i++) {
var img = "<img src ='https://s3-us-west-2.amazonaws.com/s.cdpn.io/4405662/sandsmaller.png'
id='myid"+i+"'/>";
$("body #sand").append(img);
}
})
Again I am trying to generate different ids that I can position individually?
Since your cloning snippet is in jQuery, I hope a solution using it is acceptable.
First I had to add a #sand container missing from your markup, as it's where the code is appending the images. Also added a div wrapper to each image to mirror your codepen (although you might not need it), and added a sand class to the images.
Then, instead of adding an event for each element, I used Event delegation so I can attach just one handler to the wrapping element. I'm targeting all images inside the #sand container that are not already hidden.
And then simplified the css a bit removing redundant rules and moving common properties to the new classes.
for (let i = 1; i <= 6; i++) {
// Create the wrapping div
var $container = $("<div class='sand" + i + "'>");
// Create the img
var $img = $("<img src ='https://s3-us-west-2.amazonaws.com/s.cdpn.io/4405662/sandsmaller.png' class='sand' id='sand" + i + "'/>");
// Add image to container
$container.append($img);
// Add container to the document
$("body #sand").append($container);
}
// Listen when the mouse hovers an image
$('#sand').on('mouseenter', 'img.sand:not(.hide)', function() {
$(this).addClass('hide');
});
$('#sand').on('animationend', 'img.sand.hide', function() {
$(this).hide();
});
html {
background: url(https://i.postimg.cc/HWJvtDGx/lockcorrect.jpg) no-repeat center center fixed;
background-size: cover;
height: 100%;
overflow: hidden;
}
#bg {
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
}
#-webkit-keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-moz-keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-o-keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#keyframes fade {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.sand {
position: absolute;
height: 90vh;
}
#sand6 {
top: 0px;
right: 200px;
}
#sand5 {
top: 300px;
left: 500px;
}
#sand4 {
top: 300px;
right: 200px;
}
.hide {
animation: fade 3s;
animation-fill-mode: forwards;
}
#sand3 {
height: 100vh;
top: 0px;
left: 700px;
}
#sand2 {
height: 100vh;
top: 0px;
left: 300px;
}
#sand1 {
position: relative;
height: 100vh;
right: 30px;
}
<div id="bg">
<img src="https://i.postimg.cc/HWJvtDGx/lockcorrect.jpg
" alt="lock">
</div>
<div id="sand">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I found a piece of code that almost does what I want except I want it to be horizontal / based on mouse Y instead of X. Now I understand that in the js X will be changed to Y, but I struggle with rotating the divs.
Also, if I want to put some text over it, how would I do so that the background change affects the text colour (so if the text is black and half of the background is black, to make sure once when the black background overlays the text, text colour changes to another or gets inverted for example?
Also also, I tried to figure out in js which part dictates the responsiveness of the mouse movement, i.e., how would you do so that the colour shifting is not lagging after the mouse but I couldn't figure out?
https://codepen.io/erutuf/pen/NJLwqV
haml
#banner-wrapper.banner-wrapper
.banner.design
.banner-content
.banner.dev
.banner-content
scss
body {
margin: 0;
padding: 0;
.banner-wrapper {
position: relative;
width: 100%;
height: 400px;
overflow: hidden; background:red;
}
.banner {
position: absolute;
overflow: hidden;
&.dev {
margin-left: -500px;
width: calc(50vw + 500px);
.banner-content {
margin-left: 500px; background:black;
}
}
.banner-content {
height: 400px;
}
img {
width: 100vw;
}
}
}
js
document.addEventListener('DOMContentLoaded', function(){
let banner = document.getElementById('banner-wrapper');
let devLayer = banner.querySelector('.dev');
let delta = 0;
banner.addEventListener('mousemove', function(e){
delta = (e.clientX - window.innerWidth / 2) * 0.5;
devLayer.style.width = e.clientX + 500 + delta + 'px';
});
})
you can play with JS + CSS. The following code can be your starting point :).
btw i'm adapting code from your link https://codepen.io/erutuf/pen/NJLwqV
document.addEventListener("DOMContentLoaded", function(){
let banner = document.getElementById("banner-wrapper");
let devLayer = banner.querySelector(".dev");
let delta = 0;
// play with div's height
banner.addEventListener("mousemove", function(e){
delta = (e.clientY - window.innerHeight / 2) * 0.5;
devLayer.style.height = e.clientY + delta + "px";
});
})
<div class="banner-wrapper" id="banner-wrapper">
<div class="banner design">
<div class="banner-content">BANNER TEXT</div>
</div>
<div class="banner dev">
<div class="banner-content"></div>
</div>
</div>
<style type="text/css">
body {
margin: 0;
padding: 0;
}
body .banner-wrapper {
position: relative;
width: 100%;
height: 200px;
overflow: hidden;
background: red;
}
body .banner {
position: absolute;
overflow: hidden;
}
body .banner.dev {
width: 100%;
/* play with responsiveness here. note that 0.1 is more responsive than 0.5. more info : https://www.w3schools.com/css/css3_transitions.asp */
-webkit-transition: height 0.2s linear;
transition: height 0.2s ease;
}
body .banner.dev .banner-content {
background: black;
}
body .banner .banner-content {
height: 400px;
}
body .banner img {
width: 100%;
}
.banner.design {
margin-top: -25px;
height: 50px;
top: 50%;
font-size: 50px;
/* set color & mix-blend-mode for text color vs background color effect. more info : https://css-tricks.com/methods-contrasting-text-backgrounds/ */
mix-blend-mode: difference;
color: #fff;
z-index: 1;
margin-left: -175px;
left: 50%;
width: 350px;
}
</style>
I'm trying to recreate the parallax effect that can be seen on Apple's iPhone 6s webpage: click
The iPhone objects have a slight, floaty, parallax animation when you scroll up or down. I'd like to find an easy way to recreate this for multiple objects on my webpage. I've found ScrollMagic and Skrollr but they seem overly complex for what I am trying to accomplish.
So for example, how would I animate these black boxes to animate the same way as the iPhones?
Does anyone know of a quick way to implement this with HTML/CSS/JS?
Thanks for the help!
<div class="box1">
</div>
<div class="box2">
</div>
<div class="box3">
</div>
<div class="box4">
</div>
html{
height: 1500px;
width: 800px;
}
.box1{
position: relative;
background-color: black;
height: 150px;
width: 150px;
top: 260px;
left: 56%;
}
.box2{
position: relative;
background-color: black;
height: 150px;
width: 150px;
top: 360px;
left: 56%;
}
.box3{
position: relative;
background-color: black;
height: 150px;
width: 150px;
top: 260px;
left: 16%;
}
.box4{
position: relative;
background-color: black;
height: 150px;
width: 150px;
top: 320px;
left: 86%;
}
My comment was moderated so I will try once more.
The following code might help you.
$( window ).scroll(e=>{
// get scroll direction
let direction = 'down';
if ( this.oldScroll > this.scrollY ) direction = 'up';
this.oldScroll = this.scrollY;
animate('.box1', direction);
animate('.box2', direction, 3);
});
function animate( element, direction, speed, smooth ){
element = $( element )
speed = speed || 2;
smooth = smooth || 2;
// get element offset
let Y = parseInt( element.attr('data-y') || 0 );
// Calculate movement
if ( direction == 'down' ) Y = Y - (1*speed)
else Y = Y + (1*speed)
// Apply values
element.css({
'transition': smooth + 's transform',
'transform' : 'translateY(' + Y.toFixed(2) + 'px)',
})
// store new element offset
element.attr('data-y', Y)
}
You execute the function for each element on windows scroll. You can pass values for the speed and smoothness of the movement.
The function calculates the movement and applies transform: translateY() and transition: 2s transform; attributes to the element.
I have a more complete version of the code on code.actus.works/act-parallax
How can I correct my code to keep the div in the center of the window when it is resized:
window.addEventListener("resize",handleResize,false);
function handleResize(){
var newwidth = window.innerWidth.value;
var newheight = window.innerHeight.value;
window.resizeTo(newwidth , newheight);
}
There is definitely no need for javascript coding for that: e.g. use auto margins with a parent container that has absolute or relative positioning instead.
You actually do not need to use JavaScript to achieve this. It can be done with pure CSS.
If you still want to use JS, you basically just have to get the window.innerWidth and window.innerHeight and divide them by 2. This will give you a point in the exact center of the window. Then just subtract half of the width from your element and half of the height to offset the left and top position of the element you want to center. This is necessary, because the positioning is relative to the upper left corner of the document.
When your using a CSS solution with an absolute positioned element make sure that the parent elements position is set to relative.
Here is an example with both, JS and CSS centering.
var centerDiv = document.querySelector('.center-js'),
showHideBtn = document.querySelector('.show-hide'),
winW = 0,
winH = 0;
// this is just the button click handler.
showHideBtn.addEventListener('click', function() {
if (centerDiv.style.opacity != 0) {
centerDiv.style.opacity = 0;
this.textContent = "Hide CSS centering";
} else {
centerDiv.style.opacity = 1;
this.textContent = "Show CSS centering";
}
}, false);
// here is the win resize handler;
function windowResize () {
winW = window.innerWidth;
winH = window.innerHeight;
centerDiv.style.top = (winH/2) - (centerDiv.clientHeight/2) + 'px';
centerDiv.style.left = (winW/2) - (centerDiv.clientWidth/2) + 'px';
}
window.addEventListener("resize", windowResize, false);
windowResize();
centerDiv.style.opacity = 1;
html {
position: relative;
min-height: 100%;
font-family: sans-serif;
color: white;
}
div {
text-align: center;
line-height: 200px;
vertical-align: middle;
}
.center-js {
position: absolute;
top: 0;
left: 0;
width: 200px;
height: 200px;
background: black;
opacity: 1;
transition: opacity .5s linear 0s;
z-index: 1020;
}
.center-css {
position: absolute;
top: 50%;
left: 50%;
margin-left: -100px;
margin-top: -100px;
width: 200px;
height: 200px;
background: red;
z-index: 1010;
}
<button class="show-hide">Show CSS centering</button>
<div class="center-js">JS centering</div>
<div class="center-css">CSS centering</div>
I am using this script to create a parallax scroll effect on my page:
$(window).scroll(function (e) {
parallax();
});
function parallax() {
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', - (scrolled * 0.1) + '%');
$('.cloud2').css('top', - (scrolled * 0.3) + '%');
$('.cloud3').css('top', - (scrolled * 0.2) + '%');
}
HTML:
<div class="cloud1"></div>
<div class="cloud2"></div>
<div class="cloud3"></div>
CSS (same for .cloud2 and .cloud3 but with different background image, opacity and 'top' 'left'):
.cloud1 {
background: url(../images/cloud1.png) no-repeat;
opacity: 0.9;
position: fixed;
width: 100%;
height: 100%;
top: 50%;
left: 20%;
z-index: 1;
}
When the script begins (on scroll) the HTML changes to this:
<div class="cloud1" style="top: 0%; "></div>
which makes the 'cloud' jump to the top of the page, and then the parallax starts (which you can see for a very short period of time as it's already jumped to the top of the page)
Is there a way to set the style="top: 0%;" to start at say 20% when the parallax begins, and then begin to multiply by 0.1?
Here is a codepen of the problem : http://codepen.io/anon/pen/tkfDH
Hopefully this is clear,
Any help is appreciated
Jon
Okay so I think i've fixed the problem.
$(window).scroll(function(e){
parallax();
});
function parallax(){
var scrolled = $(window).scrollTop();
$('.cloud1').css('top', -(scrolled*0.1)+70+'%');
// the 70 corresponds to the 'cloud1' value for 'top'.
$('.cloud2').css('top', -(scrolled*0.3)+50+'%');
// the 50 corresponds to the 'cloud2' value for 'top'.
}
http://cdpn.io/naIjf
#hero {
background:black;
color: white;
}
.cloud1, .cloud2 {
opacity: 0.8;
position: fixed;
width: 100%;
height: 100%;
z-index: 1;
}
.cloud1 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 70%;
left: 0;
}
.cloud2 {
background: url('http://www.jrk-design.co.uk/v2/images/big-cloud.png') no-repeat;
top: 50%;
left: 65%;
}
Fixed the jump.
Hope this helps.