I am trying to create a 3D ribbon using CSS and JavaScript.
Main features needed are:
- Ribbon should use sticky scroll method. i.e. moves from bottom to top on page scroll and then get fixed at the top.
- 3D effect in ribbon, it changes it's perspective on scroll
I have created the effect, here's the demo page: http://staging.xhtml-lab.com/ribbon/
You can check the code by using view source, JS is at the bottom of page.
But it have some bugs, which i am not being able to fix and looking for help:
- Corner (triangles) are not moving properly on scroll
- It works fine if i scroll slowly, but everything is messed up on scrolling fast
- If i scroll down and refresh the page, ribbon is moved down and calculations are messed up.
I am looking for help to fix these issues.
Following is the JS code:
$(document).ready(function() {
var docHeight = $(window).height();
var ribbonOffsetTop = 200;
var ribbonOffsetBottom = 50;
var initialPosition = parseInt($('#ribbon').css('top'));
var lastScrollTop = 0;
var ribbonHeight = 74;
var availableScroll = docHeight-ribbonOffsetTop-ribbonOffsetBottom;
var step = availableScroll/34;
var remainingScroll = availableScroll-step;
var stepsMoved = 0;
console.log(availableScroll);
$(window).scroll(function() {
var st = $(this).scrollTop();
if (st > lastScrollTop){
// downscroll code - Ribbon moving up
if (parseInt($('#ribbon').css('top')) > ribbonOffsetTop) {
$('#ribbon').css('top', initialPosition - parseInt(st));
var scrollingPosition = docHeight-st-ribbonOffsetTop-ribbonOffsetBottom;
if(remainingScroll > scrollingPosition) {
remainingScroll -= step;
$('.ribbon-front').css("top", $('.ribbon-front').position().top - 1);
if(stepsMoved < 17) {
$('.ribbon-edge-innerleft, .ribbon-edge-outerleft').css("border-width", (17 - stepsMoved)+"px 26px 0 0");
$('.ribbon-edge-innerright, .ribbon-edge-outerright').css("border-width", (17 - stepsMoved)+"px 0 0 26px");
$('.ribbon-edge-outerleft, .ribbon-edge-outerright').css("top", stepsMoved-34);
} else {
$('.ribbon-edge-innerleft, .ribbon-edge-innerright').css("top", stepsMoved -17);
$('.ribbon-edge-outerleft, .ribbon-edge-outerright').css("top", "23px");
$('.ribbon-edge-innerleft, .ribbon-edge-outerleft').css("border-width", "0px 26px "+(stepsMoved - 17)+"px 0");
$('.ribbon-edge-innerright, .ribbon-edge-outerright').css("border-width", "0px 0 "+(stepsMoved - 17)+"px 26px");
}
stepsMoved ++;
}
}
} else if (st < lastScrollTop ) {
// upscroll code - Ribbon moving down
if (parseInt($(this).scrollTop()) <= docHeight-ribbonOffsetTop-ribbonOffsetBottom) {
$('#ribbon').css('top', (docHeight-parseInt(st))-ribbonHeight);
var scrollingPosition = docHeight-st-ribbonOffsetTop-ribbonOffsetBottom;
if(remainingScroll < scrollingPosition) {
remainingScroll += step;
$('.ribbon-front').css("top", $('.ribbon-front').position().top + 1);
if(stepsMoved > 17) {
$('.ribbon-edge-innerleft, .ribbon-edge-outerleft').css("border-width", "0px 26px "+(stepsMoved - 17)+"px 0");
$('.ribbon-edge-innerright, .ribbon-edge-outerright').css("border-width", "0px 0 "+(stepsMoved - 17)+"px 26px");
} else {
$('.ribbon-edge-innerleft, .ribbon-edge-innerright').css("top", stepsMoved -17);
$('.ribbon-edge-outerleft, .ribbon-edge-outerright').css("top", "23px");
$('.ribbon-edge-innerleft, .ribbon-edge-outerleft').css("border-width", (17 - stepsMoved)+"px 26px 0 0");
$('.ribbon-edge-innerright, .ribbon-edge-outerright').css("border-width", (17 - stepsMoved)+"px 0 0 26px");
$('.ribbon-edge-outerleft, .ribbon-edge-outerright').css("top", stepsMoved-34);
}
stepsMoved --;
}
}
}
lastScrollTop = st;
});
});