I need a little help: here is the piece of code incriminated:
html:
<div class="contain">
<div class="background-image background-cover"></div>
<div class="circle">
<div class="inside blur-big background-cover"></div>
<div class="inside blur-small background-cover"></div>
<div class="inside clear background-cover"></div>
</div>
</div>
CSS:
.contain {
position: relative;
height: 200px;
margin-left: -98px;
width: 150%;
}
.background-cover {
width: 100%;
height: 100%;
background: no-repeat center center fixed;
background-size: cover;
-webkit-background-size: cover;
}
.background-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgb(36, 36, 36);
background-attachment: scroll;
background-image: url(https://dummyimage.com/600x400/000/fff);
}
.circle {
position: absolute;
border-radius: 100%;
width: 115px;
height: 115px;
box-sizing: border-box;
}
.circle .inside {
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
background-image: url(https://dummyimage.com/600x400/000/fff);
}
.blur-big {
height: 100%;
width: 100%;
-webkit-filter: blur(3px);
filter: blur(3px);
}
/* positioned slightly 'inside' the big blur */
.blur-small {
margin: 5px;
height: 105px;
width: 105px;
-webkit-filter: blur(1px);
filter: blur(1px);
}
.clear {
margin: 10px;
height: 95px;
width: 95px;
}
JavaScript:
if ('ontouchstart' in window) {
} else
addContainMouseMoveFunctionality(); //just add this functionality when it'll be used
function addContainMouseMoveFunctionality() {
//do as little as possible in the mousemove-event, so initiate variables here
let circle = document.getElementsByClassName('circle')[0];
let contain = document.getElementsByClassName('contain')[0];
//add event listener for the mouse enters the image, show circle
contain.addEventListener("mousemove", moveCircle);
//add event listener for when the mouse leaves the image, hide circle
contain.addEventListener("mouseout", function(e) {
//give the circle a position outside the viewport
circle.style.top = '-999px';
circle.style.left = '-999px';
});
function moveCircle(e) {
//get the offset from the top to avoid the circle going all over the place when scrolling down or horizontally
let doc = document.documentElement;
let left = window.pageXOffset - doc.scrollLeft + doc.clientLeft;
let top = window.pageYOffset - doc.scrollTop + doc.clientTop;
//give the circle a position near the mouse, position minus half of its width/height to center it
circle.style.top = top + e.pageY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.pageX - circle.offsetWidth / 2 + 98 + 'px'; // 98 is for the margin of contain
}
}
I think the problem is with these formulas but maybe not:
circle.style.top = top + e.clientY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.clientX - circle.offsetWidth / 2 + 98 + 'px';
Here is a fiddle which shows how it works: https://jsfiddle.net/hw615quf/7/https://jsfiddle.net/hw615quf/7/
When you scroll a little to the right, you will see what the problem is: the circle which was centred around the cursor is now no more centred...
It is not that problematic in this fiddle but when I incorporate my code on the Wordpress site with Salient, the circle is pretty much down and left from the cursor's position. When I scroll down, the circle is a little bit closer to the image but still not centred... And anyway, I don't want my circle to be centred only when the image is barely visible.
Maybe it is my formula which is problematic? Can anyone help me with this scroll?
Thanks for your help and for reading, have a nice day/evening/night :)
Benjamin
clientX and clientY does not change as page scroll changes they remain fixed. You should use pageX and pageY in this scenario. Like this
circle.style.top = top + e.pageY - circle.offsetHeight / 2 + 'px';
circle.style.left = left + e.pageX - circle.offsetWidth / 2 + 98 + 'px';
Here is a working example https://jsfiddle.net/681Lakn0/
Related
I want to set a scale and a margin of an element to make it centered in a fluid way by using wheel event.
I want to use margins for centering as at some point I would like to set scroll position on wrapping element in fluid way as well.
As you can see in jsfiddle example I'm using css transition attribute to make it fluid.
At the same time I'm changing a scale and a margin but it looks like margin animation kicks in faster leading to moving the div side ways first. You can try it with greater zoom and do mousewheel up and down.
How to fix it so it starts and ends simultanously so the cross located in the middle of the picture doesn't move sideways during zooming in and out?
jsfiddle
<html>
<div id="wrap">
<div id="el">
+
</div>
</div>
</html>
var scale = 1;
var $wrap = $('#wrap');
var $el = $('#el');
$(function() {
$el.on('wheel', function (e) {
scale = e.originalEvent.wheelDelta > 0 ? scale * 1.5: scale / 1.5;
e.preventDefault();
var l = ($wrap.width() - $el.width() * scale) / 2;
var t = ($wrap.height() - $el.height() * scale) / 2;
$el.css({
'transform': "scale(" + scale + ")",
'margin-top': t + "px",
'margin-left': l + "px",
});
});
});
#wrap {
position: fixed;
width: 400px;
height: 300px;
background: pink;
}
#el {
position: relative;
width: 200px;
height: 200px;
text-align: center;
line-height: 200px;
transition: 1s;
transform-origin: 0 0;
background-image: radial-gradient(circle at 0px 0px, #666 1px, transparent 0);
background-size: 4px 4px;
}
Edit: The best way to see the issue is to use mouse scroll once (one tick) and at the end of animation scroll it once again.
Edit2: So I've used Gabriele Petrioli answer and it looks good, however I still needs this info about position of the element. I came up with solution where I 'move'd margins to css transform attribute as 'translate' option and it looks working ok
I've replaced:
$el.css({
'transform': "scale(" + scale + ")",
'margin-top': t + "px",
'margin-left': l + "px",
});
with:
$el.css({
'transform': "translate(" + t + "px, " + l + "px) scale(" + scale + ")",
});
jsfiddle
I would use absolute positioning and position it at the center from the start.
Some changes
use position:absolute and left/right to position it in the center
use transform: translate(-50%, -50%) to match the grid center with the wrapper center
set the origin to 50% 50% as well so you do not have to account for movement
now that you do not need the margins, you can just adjust the scale
added a Math.max/Math.min in there just to keep the example sane for testing.
var scale = 1;
var $wrap = $('#wrap');
var $el = $('#el');
$(function() {
$el.on('wheel', function(e) {
e.preventDefault();
scale = e.originalEvent.wheelDelta > 0 ? scale * 1.5 : scale / 1.5;
scale = Math.min(Math.max(scale, 0.2) ,20);
$el.css({
'transform': `translate(-50%,-50%) scale(${Math.max(scale,0.1)})`,
});
});
});
#wrap {
position: fixed;
width: 400px;
height: 300px;
background: pink;
}
#el {
position: absolute;
width: 200px;
height: 200px;
text-align: center;
line-height: 200px;
transition: transform 1s;
transform-origin: 50% 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-image: radial-gradient(circle at 0px 0px, #666 1px, transparent 0);
background-size: 4px 4px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<div id="wrap">
<div id="el">
+
</div>
</div>
</html>
I am trying to do something like when the mouse will moves left to right or right to left the middle will move according to the mouse pointer inside the circle. but I can't. here is my code
circle size 180deg
more reference here is the image
$(document).on("click mousemove", ".circle", function (e) {
var x = e.clientX;
var y = e.clientY;
var angel = Math.round(Math.atan2(x, y) * (180 / Math.PI))
$(".needle").css("transform", "rotate(" + angel + "deg)");
});
#needle {
width: 6px;
height: 83px;
background: red;
transform-origin: bottom;
transition: transform 0.3s;
transform: rotate(345deg);
box-sizing: border-box;
margin-left: -3px;
position: absolute;
left: 116px;
top: 44px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="circle">
<div id="needle" class="needle"></div>
</div>
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.