I want to create a custom scrollbar using just pure JavaScript and I'm having problem with making the pointer to reach the end of the scrollbar when I reach the bottom of the page. Is there any way to do that without using jQuery?
Demo on Fiddle
HTML:
<div id="scroll-bar"></div>
<div id="pointer"></div>
<div class="test">first</div>
<div class="test"></div>
<div class="test"></div>
<div class="test">middle</div>
<div class="test"></div>
<div class="test"></div>
<div class="test">final</div>
JavaScript:
var body = document.getElementsByTagName('body')[0];
var allDivs = document.getElementsByTagName('div');
var scrollBar = document.getElementById("scroll-bar");
var pointer = document.getElementById("pointer");
for (var i = 0; allDivs[i] != undefined; i++) {
var last = i;
}
var pageHeight = allDivs[last].offsetHeight + allDivs[last].offsetTop;
pointer.style.top = "7%";
function setPosition(e) {
var pos = e.screenY * 86;
var move = pos / scrollBar.offsetHeight - 10;
if (move > 7 && move < 89) {
pointer.style.top = move + "%";
}
var scrollValue = move * pageHeight / 100;
window.scrollTo(0, scrollValue);
}
function resetPosition() {
scrollBar.removeEventListener('mousemove', setPosition);
pointer.removeEventListener('mousemove', setPosition);
}
scrollBar.addEventListener('mousedown', function (event) {
pointer.addEventListener('mousemove', setPosition);
pointer.addEventListener('mouseup', resetPosition);
scrollBar.addEventListener('mousemove', setPosition);
scrollBar.addEventListener('mouseup', resetPosition);
});
scrollBar.addEventListener('click', function (event) {
setPosition(event);
});
pointer.addEventListener('mousedown', function (event) {
pointer.addEventListener('mousemove', setPosition);
pointer.addEventListener('mouseup', resetPosition);
scrollBar.addEventListener('mousemove', setPosition);
scrollBar.addEventListener('mouseup', resetPosition);
});
body.addEventListener("mousewheel", function () {
scrollBy(0, -window.event.wheelDelta);
});
body.addEventListener("DOMMouseScroll", function (e) {
scrollBy(0, e.detail * 50);
});
CSS:
html {
overflow: hidden;
}
.test {
height: 100px;
border-style: groove;
border-width: 10px;
border-color: red;
}
#scroll-bar {
position: fixed;
right: 0%;
top: 7%;
width: 3%;
height: 86%;
background-color: red;
}
#pointer {
position: fixed;
right: 0.5%;
top: 7%;
width: 2%;
height: 4%;
background-color: blue;
z-index: 3;
}
Related
<style>
#container {
width: 400px;
height: 400px;
position: relative;
background: rgb(240, 240, 231);
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
#animate1 {
width: 50px;
height: 50px;
left: 350px;
top: 2px;
position: absolute;
background-color: rgb(43, 1, 1);
}
</style>
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
<div id="animate1"></div>
</div>
<script>
function myMove() {
var elem = document.getElementById("animate");
var elem1 = document.getElementById("animate1");
var pos = 0;
var pos1 = 0;
var id = setInterval(frame, 5);
var id1 = setInterval(frame1, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + "px";
elem.style.left = pos + "px";
}
}
function frame1() {
if (pos1 == 350) {
clearInterval(id1);
} else {
pos1++;
elem1.style.top = pos1 + "px";
elem1.style.right = pos1 + "px";
}
}
}
</script>
In the above code I have 2 cubes(div). On click of button, the left cube should move from left to right till the end of the container diagonally and right cube should move from right to left diagonally till the end of the container. But only left cube is moving from left to right and right cube is moving from top to bottom. I want right cube to be moved from right to left diagonally till the end of the container. And this is my sandbox link. https://codesandbox.io/s/autumn-sun-uz961?file=/index.html
.animate1 class has left:350px make it to right:0 it will work.
function myMove() {
var elem = document.getElementById("animate");
var elem1 = document.getElementById("animate1");
var pos = 0;
var pos1 = 0;
var id = setInterval(frame, 5);
var id1 = setInterval(frame1, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + "px";
elem.style.left = pos + "px";
}
}
function frame1() {
if (pos1 == 350) {
clearInterval(id1);
} else {
pos1++;
elem1.style.top = pos1 + "px";
elem1.style.right = pos1 + "px";
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: rgb(240, 240, 231);
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
#animate1 {
width: 50px;
height: 50px;
right:0px;
position: absolute;
background-color: rgb(43, 1, 1);
}
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
<div id="animate1"></div>
</div>
Update your css and change left: 350px; to right: 0px; for #animate1 :
function myMove() {
var elem = document.getElementById("animate");
var elem1 = document.getElementById("animate1");
var pos = 0;
var pos1 = 0;
var id = setInterval(frame, 5);
var id1 = setInterval(frame1, 5);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + "px";
elem.style.left = pos + "px";
}
}
function frame1() {
if (pos1 == 350) {
clearInterval(id1);
} else {
pos1++;
elem1.style.top = pos1 + "px";
elem1.style.right = pos1 + "px";
}
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: rgb(240, 240, 231);
}
#animate {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
#animate1 {
width: 50px;
height: 50px;
right: 0px; /* instead of right : 350px; */
top: 2px;
position: absolute;
background-color: rgb(43, 1, 1);
}
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
<div id="animate1"></div>
</div>
Off Topic, but are you aware of CSS transitions?
function myMove() {
document.getElementById("animate").classList.toggle("move");
document.getElementById("animate1").classList.toggle("move");
}
// try clicking the boxes themselves
for (let item of document.querySelectorAll("#animate, #animate1")) {
item.onclick = function() {
item.classList.toggle("move");
}
}
#container {
width: 400px;
height: 400px;
position: relative;
background: rgb(240, 240, 231);
}
#animate {
width: 50px;
height: 50px;
top: 0;
left: 0;
position: absolute;
background-color: red;
transition: 3s linear;
}
#animate.move {
top: 350px;
left: 350px;
}
#animate1 {
width: 50px;
height: 50px;
right: 0px;
top: 2px;
position: absolute;
background-color: rgb(43, 1, 1);
transition: 3s linear;
}
#animate1.move {
top: 350px;
right: 350px;
}
<p>
<button onclick="myMove()">Click Me</button>
</p>
<div id="container">
<div id="animate"></div>
<div id="animate1"></div>
</div>
Actually I am trying to make this type of effect using javascript, need some help how to implement it.
View Images from here:-
https://ibb.co/2c9y9jV
https://ibb.co/Jpqk3xr
My code:
function move(e) {
console.log("mouse location:", e.clientX, e.clientY);
let x = e.clientX - 520;
let y = e.clientY - 210;
let ele = document.getElementsByClassName('after')[0];
ele.style.transform = "translate3d(" + x + "px," + y + "px,0px)"
}
var temp = false;
function toggle() {
temp = !temp;
if (temp) {
let ele = document.getElementsByClassName('after')[0];
ele.style.display = 'block';
} else {
let ele = document.getElementsByClassName('after')[0];
ele.style.display = 'none';
}
}
img {
z-index: 100;
}
.after {
position: absolute;
left: 0;
bottom: 0;
border-radius: 50%;
width: 20%;
height: 20%;
display: block;
background: white
}
.image-container {
margin: 0 auto;
position: relative;
overflow: hidden;
width: max-content;
height: max-content;
}
<button onclick="toggle()">Toggle</button>
<div class="image-container">
<img onmousemove="move(event)" src="http://lorempixel.com/300/200" />
<div class="after">
</div>
</div>
I couldn't be able to make effect like image
I have an animation with several span, I want them all to be separated and can be read completely.
window.horizontalScroller = function($elem) {
var left = parseInt($elem.css("left"));
var temp = -1 * $('#horizontalScroller > div').height();
if (left < temp) {
left = $('#horizontalScroller').height()
$elem.css("left", left);
}
$elem.animate({
left: (parseInt(left) - 60)
}, 11000, function() {
window.horizontalScroller($(this))
});
}
$(document).ready(function() {
var i = 0;
$("#horizontalScroller > span").each(function() {
$(this).css("left", i);
i += 60;
window.horizontalScroller($(this));
});
});
#horizontalScroller {
position: absolute;
width: 300px;
height: 300px;
border: 1px solid red;
overflow: hidden;
}
#horizontalScroller>span {
position: absolute;
border: 1px solid blue;
display: inline-block;
background: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="horizontalScroller">
<span>100 characteres</span>
<span>110 characteres</span>
<span>120 characteres</span>
<span>130 characteres</span>
<span>140 characteres</span>
<span>150 characteres</span>
</div>
Try updating your $(document).ready to be like below:
$(document).ready(function() {
var i = 0;
$("#horizontalScroller > span").each(function () {
$(this).css("left", i);
i += 100;
window.horizontalScroller($(this));
});
});
If you only want to separate them then you can just increse the i:
$(document).ready(function() {
var i = 0;
$("#horizontalScroller > span").each(function () {
$(this).css("left", i);
i += 110;
window.horizontalScroller($(this));
});
});
But the whole animation breaks after some time, so I recommend a different approach or some heavy optimization.
Fiddle link
I am trying to make this circle in perspective(check fiddle link). I tried the css property but it shows unusual behaviour.
/*
using:
circular positioning code:
http://stackoverflow.com/a/10152437/1644202
point at:
http://pointat.idenations.com/api
depends on:
jquery
https://github.com/thomas-dotworx/jqrotate (pointat)
*/
function createFields() {
$('.field').remove();
var container = $('#container');
for(var i = 0; i < +$('input:text').val(); i++) {
$('<div/>', {
'class': 'field',
'text': i + 1,
}).appendTo(container);
}
}
function distributeFields(deg) {
deg = deg || 0;
var radius = 200;
var fields = $('.field:not([deleting])'), container = $('#container'),
width = container.width(), height = container.height(),
angle = deg || Math.PI*3.5, step = (2*Math.PI) / fields.length;
fields.each(function() {
var x = Math.round(width/2 + radius * Math.cos(angle) - $(this).width()/2);
var y = Math.round(height/2 + radius * Math.sin(angle) - $(this).height()/2);
if(window.console) {
console.log($(this).text(), x, y);
}
$(this).css({
left: x + 'px',
top: y + 'px'
});
angle += step;
});
}
$('input').change(function() {
createFields();
distributeFields();
initPointAt();
});
var timer = null,
timer2 = null;
$('#addone').click(function() {
// do not append to current, otherwise you see it moving through the container
$('.field').addClass('moveAni');
$('<div/>', {
'class': 'field',
'text': $('.field').length +1
})
.css({
left: $('#container').width()/2-25 + 'px',
top: $('#container').height()/2-25 + 'px'})
.addClass('moveAni')
.appendTo('#container')
.pointat({
target: "#center",
defaultDirection: "down"
});
distributeFields();
// without css:
//$('.field').pointat("updateRotation");
// with css: for css move animation
clearInterval(timer); clearTimeout(timer2);
timer = setInterval(function() {
$('.field').pointat({
target: "#center",
defaultDirection: "down"
}); // does not seem to update correctly: .pointat("updateRotation")
}, 20);
timer2 = setTimeout(function() {
clearInterval(timer);
}, 420); // css animation timeout, interval +1 extra to update after the ani
// update input field
$('input:text').val($('.field').length);
});
$('#delone').click(function() {
$('#container .field:not([deleting]):last')
.attr('deleting', 'true')
.css({
left: $('#container').width()/2-25 + 'px',
top: $('#container').height()/2-25 + 'px'
})
.fadeOut(400, function() {
$(this).remove();
});
// do distribiution as if the currently out-animating fields are gone allready
distributeFields();
clearInterval(timer); clearTimeout(timer2);
timer = setInterval(function() {
$('.field').pointat({
target: "#center",
defaultDirection: "down"
}); // does not seem to update correctly: .pointat("updateRotation")
}, 20);
timer2 = setTimeout(function() {
clearInterval(timer);
}, 420); // css animation timeout, interval +1 extra to update after the ani
// update input field
$('input:text').val($('.field:not([deleting])').length); // update yet
});
createFields();
distributeFields();
initPointAt();
function initPointAt() {
$('.field').pointat({
target: "#center",
defaultDirection: "down",
xCorrection: -20,
yCorrection: -20
});
}
body { padding: 2em; }
#container { width: 600px; height: 600px; border: 1px solid #000; position: relative; border-radius: 50%;}
#center { width: 10px; height: 10px; position: absolute; left: 295px; top: 295px; background: #000; border-radius: 50%; }
.field { position: absolute; background: #f00; }
#crosshair-x { width: 600px; height: 1px; background: #000; position: absolute; left: 0; top: 300px; }
#crosshair-y { width: 1px; height: 600px; background: #000; position: absolute; left: 300px; top: 0; }
.field {
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
}
.moveAni {
transition: left 400ms ease-out, top 400ms ease-out;
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//pointat.idenations.com/jquery.pointat.min.js"></script>
<script src="//pointat.idenations.com/jquery.rotate-1.0.1.min.js"></script>
Number of fields: <input type="text" value="4" />
<button id="addone">++</button>
<button id="delone">--</button>
<div id="container">
<div id="center"></div>
<div id="crosshair-x"></div>
<div id="crosshair-y"></div>
</div>
Then i inserted an image tad inside container and tried to add field inside image tag.
I achieved this using three.js but don't want to do this in it because it takes too much time to load.
Wrap your container in another div you apply perspective to. The perspective must be applied to the parent, not to the element itself.
Updated Fiddle link : http://jsfiddle.net/w840vkbL/1/
#perspective {
perspective: 500px;
width: 150px;
}
#container {
transform: rotateY(40deg);
background: lightblue;
height: 150px;
}
<div id="perspective">
<div id="container">
<h3>SOME PERSPECTIVE CONTENT</h3>
</div>
</div>
I tried to build a website similar to this. To do this I wrote the following code:
var $window = $(window);
var lastScrollTop = 0;
var shown_elements = 0;
var next_element = 0;
$window.on('scroll', scroll_to_next);
$window.trigger('scroll');
var window_height = $window.height();
var window_top_position = $window.scrollTop();
var window_bottom_position = (window_top_position + window_height);
var scroll = $(window).scrollTop();
function scroll_to_next() {
shown_elements = Math.ceil($(window).scrollTop() / window_height);
next_element = shown_elements * window_height;
if (lastScrollTop < $(window).scrollTop() && lastScrollTop != 0) {
//$window.scrollTop(next_element);
$('html, body').animate({
scrollTop: next_element
}, 'slow');
//alert(next_element);
}
lastScrollTop = $(window).scrollTop();
}
This is the HTML:
<div class="showroom1">
<div class="showroom_left">
<img class="fixed" src="mokups/frame.png">
<img class="screen" src="mokups/screen2.png">
</div>
<div class="showroom_right">
<h3>Hello</h3>
<h4>description</h4>
</div>
</div>
<div class="showroom2">
<div class="showroom_left">
<img class="screen" src="mokups/screen1.png">
</div>
<div class="showroom_right">
<h3>Hello</h3>
<h4>description</h4>
</div>
</div>
<div class="showroom1">
<div class="showroom_left">
<img class="fixed" src="mokups/frame.png">
<img class="screen" src="mokups/screen2.png">
</div>
<div class="showroom_right">
<h3>Hello</h3>
<h4>description</h4>
</div>
</div>
This code runs the first time. And scroll automatically to the second "showroom". But when I try to scroll a second time the page will not scroll.
What is wrong with my code?
I created a JSFiddle a while a go for another question with the same issue. https://jsfiddle.net/8zgsdzy0/
Here is the code:
var lastScrollPos = 0;
var scrollFired = false;
var textConainersElement = jQuery('.text-container p');
var mainElem = jQuery("[data-main='true']");
var firstElem = jQuery("section:first-child");
var lastElem = jQuery("section:last-child");
var wrapper = jQuery(".wrapper");
jQuery(document).on('DOMMouseScroll mousewheel', function(e) {
// if the scroll has occrued already then dont fire it again until transition ended
if (scrollFired == true) {
jQuery(window).scrollTop(lastScrollPos);
return false;
}
var inviewElem = jQuery("[data-inview='true']");
var nextElem = inviewElem.next();
var prevElem = inviewElem.prev();
var currentTop = parseInt(firstElem.attr('data-top'));
if (e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) {
// Scrolling down
// if viewed element is last element do nothing
if (inviewElem.index() >= lastElem.index())
return false;
// if main section is inview then scroll through its elements
if (inviewElem.index() == mainElem.index()) {
// if the active child is not the last element then process
var active = jQuery('.text-container .active');
if (active.index() != textConainersElement.length - 1) {
jQuery('.text-container .active').removeClass('active').next().addClass('active');
// Dont scroll further
return false;
}
}
var top = currentTop + 100;
firstElem.css("margin-top", "-" + top + "vh").attr("data-top", top);
nextElem.attr("data-inview", 'true');
inviewElem.attr("data-inview", 'false');
} else {
// Scrolling up
// if viewed element is first element do nothing
if (inviewElem.index() <= firstElem.index())
return false;
// if main section is inview then scroll through its elements
if (inviewElem.index() == mainElem.index()) {
// if the active child is not the last element then process
var active = jQuery('.text-container .active');
if (active.index() != 0) {
jQuery('.text-container .active').removeClass('active').prev().addClass('active');
// Dont scroll further
return false;
}
}
var top = currentTop - 100;
firstElem.css("margin-top", "-" + top + "vh").attr("data-top", top);
prevElem.attr("data-inview", 'true');
inviewElem.attr("data-inview", 'false');
}
// Set values to use for next scrolling event
lastScrollPos = jQuery(window).scrollTop();
scrollFired = true;
// reset scrollFired var after transition ended
firstElem.one('transitionend', function() {
scrollFired = false;
});
//prevent page fom scrolling
return false;
});
body {
margin: 0;
}
.wrapper {
display: block;
width: 100%;
height: 100vh;
overflow: hidden;
}
section {
display: block;
width: 100%;
height: 100vh;
border-bottom: 2px dashed black;
position: relative;
transition: all 0.5s;
background-color: #c4c4c4;
}
section[data-inview="true"] {
background-color: #929292;
}
.phone-container {
align-items: center;
background: #dedede none repeat scroll 0 0;
border-left: 5px solid black;
display: flex;
float: right;
height: 100vh;
justify-content: center;
width: 500px;
}
.phone {
width: 200px;
height: 500px;
background: #A6A6A6 none repeat scroll 0 0;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
border-radius: 5px;
}
section.long-scroll {
height: auto;
}
p {
margin-top: 80px;
}
p:first-child {
margin-top: 0px;
}
.text-container {
float: left;
width: 200px;
}
.spacer {
display: block;
width: 100%;
}
p.active {
color: #C1E7FF;
}
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.clearfix {
display: inline-block;
}
/* start commented backslash hack \*/
* html .clearfix {
height: 1%;
}
.clearfix {
display: block;
}
/* close commented backslash hack */
.stuck {
position: fixed;
top: 0;
}
.fixed {
position: fixed;
top: 0;
}
.sticky-wrapper {
height: auto !important;
}
.text-container {
padding-left: 40px;
padding-top: 40px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='wrapper'>
<section data-inview='true' data-top='0'>
Scroll-down
</section>
<section class="long-scroll clearfix" id="pin" data-main='true'>
<div class="text-container">
<p class="active">Text - 1</p>
<p>Text - 2</p>
<p>Text - 3</p>
<p>Text - 4</p>
</div>
<div class="phone-container">
<div class="phone">Slide-1</div>
</div>
</section>
<section id="unhook"></section>
</div>
Please add your function scroll_to_next() to $(window).scroll();
Since you are not capturing the scroll event provided by $(window). So it happens for the first time.
Example
I think the problem is with this line of code:
if (lastScrollTop < $(window).scrollTop() && lastScrollTop != 0)
Specifically
lastScrollTop != 0
The first time the code runs through the variable "lastScrollTop" is set to 0, so the if statement evaluates false and doesn't scroll, but the variables "shown_elements" and "next_element" are changed. The second time you run the code through "lastScrollTop" has been changed but it doesn't work as you would expect as the other variables have been changed.
The solution is probably to change the if statement and change "lastScrollTop != 0".