I am using the smooth scrollbar plugin and am having issues with elements with position fixed.
I have a div ID 'scroll', the nav, footer and content are inside this
Since transform creates a new local coordinate system(W3C Spec), position: fixed is fixed to the origin of scrollbar content container, i.e. the left: 0, top: 0 point.
Therefore, you may need to register a scroll listener and apply offsets to the fixed element.
I am having issues with the getting the footer (#footer) to work, the nav (#fixed) is working correctly
Any suggestions?
var fixedElem = document.getElementById('fixed');
var footerElem = document.getElementById('footer');
var scrollbar = Scrollbar.init(
document.getElementById('scroll'),
);
scrollbar.addListener(function(status) {
var offset = status.offset;
fixed.style.top = offset.y + 'px';
fixed.style.left = offset.x + 'px';
footer.style.bottom = offset.y + 'px';
footer.style.left = offset.x + 'px';
});
CSS
#fixed {
position: fixed;
top: 0
left: 0;
}
#footer {
position: fixed;
bottom: 0
left: 0;
}
Related
I trying to create a map framework for some games and i have a problem with recalc position of marker. Look url to test, with wheel you can resize div with image but the dot red not come back to own position. Sorry but im new on this y trying to learn more about js and css. Thanks
$('.map-live').css('width', "928px");
$('.map-live').css('height', "928px");
$('.map-live').css('background-size', "100%");
$('.map-live').bind('mousewheel DOMMouseScroll', function(event) {
var divSize = $('.map-live').css('width');
console.log(divSize);
divSize = divSize.replace('px', '')
divSize = parseInt(divSize);
console.log("oldSize: " + divSize);
var delta_px = event.originalEvent.wheelDelta > 0 ? (divSize + (divSize * 0.15)) : (divSize - (divSize * 0.15));
console.log("NewSize: " + delta_px);
$(this).css('width', delta_px + "px");
$(this).css('height', delta_px + "px");
$(this).css('background-size', "100%");
UpdatePoints();
});
$(function() {
$("#map-live").draggable();
});
document.getElementById('map-live').addEventListener('click', printPosition)
function getPosition(e) {
var rect = e.target.getBoundingClientRect();
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
return {
x,
y
}
}
function printPosition(e) {
var position = getPosition(e);
console.log('X: ' + position.x + ' Y: ' + position.y);
var divX = parseInt($('.map-live').css('width').replace('px', ''));
var divY = parseInt($('.map-live').css('height').replace('px', ''));
var vhX = (position.x / divX) * 100;
var vhY = (position.y / divY) * 100;
console.log('vhX: ' + vhX + ' vhY: ' + vhY);
}
function UpdatePoints() {
$('.point').css('top', '2.477565353101834vh');
$('.point').css('left', '2.477565353101834vh');
$('.point').css('position', 'absolute');
}
body {
margin: 0;
overflow: hidden;
}
.map-live {
position: absolute;
left: 10px;
z-index: 9;
background-image: url(https://i.ibb.co/d2y5G1y/map.jpg);
width: 222px;
height: 222px;
transition: all 0.2s linear;
}
.point {
position: absolute;
left: 2.477565353101834vh;
top: 2.477565353101834vh;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div class="map-live ui-widget-content" id="map-live">
<div class="point"></div>
</div>
jsfiddle.net/f84mto52
Someone can correct me, but I believe your use of position: absolute is what is making the <div class="point"></div> stay in place.
Your UpdatePoints is setting always the same position in the div. With 'vh' you are calculating and absolute position proportional to viewport, no to parent container.
So, you are zooming the background image but the position (x, y) will be always be (x, y), positions are not zoomed. You need to recalculate which is the new position.
So you need to calculate new position.
function UpdatePoints(){
var divW = parseInt($('.map-live').css('width').replace('px',''));
var divH = parseInt($('.map-live').css('height').replace('px',''));
var topPosition = (2.477565353101834 / 928) * divH;
var leftPosition = (2.477565353101834 / 928) * divW;
$('.point').css('top', topPosition+'vh');
$('.point').css('left', leftPosition+'vh');
$('.point').css('position', 'absolute');
}
Also, instead using 'vh' I recommend to calculate the px position instead. I have added the already calculated delta_px parameter to UpdatePoints function:
<style>
.point {
position: absolute;
left: 22.99180647678502px;
top: 22.99180647678502px;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
}
</style>
<script>
function UpdatePoints(delta_px){
var position = (delta_px/100)*2.477565353101834;
$('.point').css('top', position+'px');
$('.point').css('left', position+'px');
$('.point').css('position', 'absolute');
}
</script>
Also, here we are calculating the top-left position of the .point element, not the position for the center. As it is a circle, it work fine, but if you use any other shape the position translation should be calculated from its center.
I recommend to do some research about how to translate elements. You can start here:
Calculating relative position of points when zoomed in and enlarged by a rectangle!
Zoom in on a point (using scale and translate)!
How do I effectively calculate zoom scale?!
I am trying to detect when a user scrolls up or down on an fixed height element and update the element's transform: translateX CSS value accordingly to scroll the contents either to the left or two the right. However, I can't figure out how to get the proper value from the delta.
document.getElementById("list").addEventListener("wheel", myFunction);
function myFunction(event) {
var matrix = $('.gallery-list').css('transform').split(/[()]/)[1];
var y = parseInt(event.deltaY);
var posX = parseInt(matrix.split(',')[4]);
console.log(y);
console.log(posX);
console.log(y + posX);
//$('.gallery-list').css('transform', 'translateX('+posX + y+'px)');
}
Here is a Codepen here: https://codepen.io/kylehagler/pen/OKxMGr
Add this to your css:
.outside {
width: 100vw;
height: 100vh;
top: 0;
left: 0;
position: absolute;
}
Surround the gallery-list div with:
<div id="outside" class="outside">
Finally, here is the JS:
document.getElementById("outside").addEventListener("wheel", myFunction);
var total = 0;
function myFunction(event) {
var y = parseInt(event.deltaY);
total += y;
$(".gallery-list").css('transform', 'translateX(' + total + 'px)');
}
I have a container and and image inside that container. When the container is not in view - the image must be at translate y 0%. When the container is halfway into the viewport and past halfway - the image must be translate y 50%. The % value must be bound to the position of the container into the viewport (controlled by scrolling). The position of the container also determines the speed the image is being translated at. The problem I'm getting is that when the speed value changes, the image jerks up or down instead of changing the speed from that point onward.
Here is my script:
if (wScroll > $(".largeWindow").offset().top - ($(window).height())) {
var cont = $(".largeWindow");
var img = $(".coffee2");
var top = cont.offset().top - cont.height();
var speed;
// translate the image within the container
var moveImage = function() {
setSpeed();
var scroll = Math.floor((wScroll - top)) * speed;
return img.css("transform", "translate(-50%, " + scroll + "%)");
}
// get the position of the image within the container
var getImagePos = function() {
return img.position().top - img.height()/2;
}
var getContainerPos = function() {
var windowHeight = $(window).height();
var contPos = Math.floor(cont.offset().top + cont.height()/2) - wScroll;
return Math.floor(contPos/windowHeight * 100);
}
// set the speed the image will be translated at
var setSpeed = function() {
if (getContainerPos() < 50) {
speed = 0;
}
else if (getContainerPos() < 60 ) {
speed = 0.5
}
else if (getContainerPos() < 70 ) {
speed = 0.5
}
else {
speed = 0.8
}
}
getContainerPos();
moveImage();
getImagePos();
}
Here is the sass for the container and image:
.largeWindow
position: relative
margin: 0 auto
height: 400px
width: 400px
border-radius: 50%
overflow: hidden
background:
image: url(../images/bgTable.jpg)
size: cover
repeat: no-repeat
position: center
attachment: fixed
.coffee2
position: absolute
height: 200px
width: 200px
left: 50%
transform: translateX(-50%)
top: - 200px
background:
image: url(../images/bgCup.png)
size: contain
repeat: no-repeat
position: center
My website at the moment has three sections in a single scroll layout. With a Heading for two sections: About & Contact (these are div boxes) that animate when you scroll to the bottom of the page. What I'm trying to achieve is having the animation take place when the user scrolls down and hits the bottom of each (div box) section as opposed to the bottom of the website.
I believe I need to implement the .offset() function but unsure if that is correct?
Any help would be greatly appreciated.
CSS
.header {
display: none;
position: relative;
left: 0px;
right: 0px;
top: 500px;
height: 80px;
width: 100%;
background:red;
color: #fff;
text-align: center;
}
JS
var header = $('.header'),
extra = 10; // In case you want to trigger it a bit sooner than exactly at the bottom.
header.css({ opacity: '0', display: 'block' });
$(window).scroll(function() {
var scrolledLength = ( $(window).height() +extra) + $(window).scrollTop(),
documentHeight = $(document).height();
console.log( 'Scroll length: ' + scrolledLength + ' Document height: ' + documentHeight )
if( scrolledLength >= documentHeight ) {
header
.addClass('top')
.stop().animate({ top: '20', opacity: '1' }, 800);
}
else if ( scrolledLength <= documentHeight && header.hasClass('top') ) {
header
.removeClass('top')
.stop().animate({ top: '500', opacity: '0' }, 800);
}
});
Fiddle - http://jsfiddle.net/SFPpf/480/
Looks like position() would be better in this case. The position method is relative to the document whereas offset is relative to the parent element. It returns an object with the properties "top" and "left". It can only return the position of one element at a time, so for the first div, you would need to use first() and eq() to get a specific one.
The bottom of a .fillWindow will be its vertical position + its height.
var $fillWindow = $(".fillWindow").first(), // or eq() for others
position = $fillWindow.position(),
height = $fillWindow.height();
//bottom = position.top + height;
scrollTop() can now be used to check when the user scrolls past the .fillWindow.
if ( $(window).scrollTop() >= position.top ) {
// do the animation here
} else {
// do something else
}
Edit: I just caught my mistake. It should be $(window).scrollTop(). You should also just test for scrollTop being at the top of the .fillWindow.
I have implemented a parallax scrolling effect based on a tutorial I found. The effect works great. However, when I specify the background images, I am unable to control the y (vertical) axis. This is causing problems because I'm trying to set locations on multiple layered images.
Any thoughts on what's causing the problem?
Here is one external script:
$(document).ready(function(){
$('#nav').localScroll(800);
//.parallax(xPosition, speedFactor, outerHeight) options:
//xPosition - Horizontal position of the element
//inertia - speed to move relative to vertical scroll. Example: 0.1 is one tenth the speed of scrolling, 2 is twice the speed of scrolling
//outerHeight (true/false) - Whether or not jQuery should use it's outerHeight option to determine when a section is in the viewport
$('#mainimagewrapper').parallax("50%", 1.3);
$('#secondaryimagewrapper').parallax("50%", 0.5);
$('.image2').parallax("50%", -0.1);
$('#aboutwrapper').parallax("50%", 1.7);
$('.image4').parallax("50%", 1.5);
})
This is another external script:
(function( $ ){
var $window = $(window);
var windowHeight = $window.height();
$window.resize(function () {
windowHeight = $window.height();
});
$.fn.parallax = function(xpos, speedFactor, outerHeight) {
var $this = $(this);
var getHeight;
var firstTop;
var paddingTop = 0;
//get the starting position of each element to have parallax applied to it
$this.each(function(){
firstTop = $this.offset().top;
});
if (outerHeight) {
getHeight = function(jqo) {
return jqo.outerHeight(true);
};
} else {
getHeight = function(jqo) {
return jqo.height();
};
}
// setup defaults if arguments aren't specified
if (arguments.length < 1 || xpos === null) xpos = "50%";
if (arguments.length < 2 || speedFactor === null) speedFactor = 0.1;
if (arguments.length < 3 || outerHeight === null) outerHeight = true;
// function to be called whenever the window is scrolled or resized
function update(){
var pos = $window.scrollTop();
$this.each(function(){
var $element = $(this);
var top = $element.offset().top;
var height = getHeight($element);
// Check if totally above or totally below viewport
if (top + height < pos || top > pos + windowHeight) {
return;
}
$this.css('backgroundPosition', xpos + " " + Math.round((firstTop - pos) * speedFactor) + "px");
});
}
$window.bind('scroll', update).resize(update);
update();
};
})(jQuery);
Here is the CSS for one section:
#aboutwrapper {
background-image: url(../images/polaroid.png);
background-position: 50% 0;
background-repeat: no-repeat;
background-attachment: fixed;
color: white;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
#aboutwrapper .image4 {
background: url(../images/polaroid2.png) 50% 0 no-repeat fixed;
height: 500px;
width: 100%;
margin: 0 auto;
padding: 0;
}
.image3{
margin: 0 auto;
min-width: 970px;
overflow: auto;
width: 970px;
}
Both of these are being called to achieve the parallax scrolling. I really just want to more specifically control the background image locations. I've tried messing with the CSS background position and I've messed with the first javascript snippet as well. No luck.
just a quick shot, have you tried actually placing the images, either in a div or just using the img src tag to actually move the element rather than manipulating the y axis of a background image?