Ok - here is what I am trying to do. I was looking online for a cool timeline that I can purchase - allowing zoom in zoom out, posting of events on it, and so on. However, all the examples I found are either too expensive or just downright useless.
So, I have decided to create my own, but there are two elements that I am having trouble with.
1) Converting the wheel scroll to left-right scrolling (so not up-down). I can't seem to find an easy and quick way to do this.
But, more importantly..
2) I need the area I will be showing the timeline on to automatically expand as I go about my scrolling. So, if I scroll down, it will add an "equivalent" area on the right, and down, on the left. So I was thinking like making an iFrame (already use these) and when you scroll it just adds more "timeline" on the left or the right, loads what ever it needs to load from the DB/list of events, and so on, ad infinitum, thus creating an ever-expanding list of blocks that are time-sized.
If I can do the two things above, then I am set - the rest (loading/positioning) I can figure out - just these two things are eluding my imagination and ability to find an answer.
Basically you need a horizontal infinite scroll script.
Take this plugin I wrote:
$.fn.hScroll = function( options )
{
function scroll( obj, e )
{
var evt = e.originalEvent;
var direction = evt.detail ? evt.detail * (-120) : evt.wheelDelta;
if( direction > 0)
{
direction = $(obj).scrollLeft() - 120;
}
else
{
direction = $(obj).scrollLeft() + 120;
}
$(obj).scrollLeft( direction );
e.preventDefault();
}
$(this).width( $(this).find('div').width() );
$(this).bind('DOMMouseScroll mousewheel', function( e )
{
scroll( this, e );
});
}
Initialize it with:
$('body').hScroll();
Makes your website a horizontally scrollable website.
Your content div must be wider than your body (ex. 3000px).
As for the infinite scrolling effect you pretty much gotta do that your self because I can't know what kind of data you'll input. But I'll explain.
Your children elements in the content div must be floated to left. (every new appended div will not go to new line).
Set an interval to check if the user's scrollLeft position is near the end of the content (just like pinterest and similar site).
function loadNewData(){ /* Your search for data and update here. */ }
setInterval('loadNewData', 500);
search for new data according to your last one with AJAX. When you get new data, append it into your content div (in a div that's floated left, as I wrote previously), and mark it as your last item.
Maybe you could use your ID to mark the last item on it's div.
<div data-id="467" class="item"> // your data here </div>
You can fetch it with
$('.item:last').attr('data-id');
with jQuery.
Related
I am trying to make an Alarm clock UI using react and I am stuck at this component where users can scroll or swipe through hours, minutes etc.. I tried some methods but failed.
I tried on scroll, on wheel, but my problem is I just can't get the accurate value which user sees(like the 03:30 PM).
I don't want you to help me with code, just need to know how to approach this.
I would approach this problem like this
let's address the challenges here
Scrolling to the desired points only
Looped scrolling
Auto pick the Value - without clicking basically.
Scrolling to the desired points only
This concept is called snap scrolling, you can use some library for that avoid writing its logic by yourself because then you will end up handling a lots of edge cases.
Looped scrolling
You need to handle this using basic JS logic you can provide some extra buffer elements at the end and at the starting refer to this example
https://codepen.io/lemmin/pen/bqNBpK
window.onscroll = function () {
// Horizontal Scroll.
var y = document.body.getBoundingClientRect().top;
page.scrollLeft = -y;
// Looping Scroll.
var diff = window.scrollY - dummy_x;
if (diff > 0) {
window.scrollTo(0, diff);
}
else if (window.scrollY == 0) {
window.scrollTo(0, dummy_x);
}
}
Auto pick the Value
one very basic approach could be, you can get the scroll offset on change of scroll, and as you have the height of every entity you can get the element that is in focus(or highlighted to the user).
Below is one more approach, you can create a selector div then you can check for the overlap on-scroll-stop whichever element is within this div, you can get its value.
personally, I think the first approach will be simpler and more stable. I have seen people using both types of approaches.
let me know if could help with anything else.
I have built a WordPress theme. I came across a website that created a div to follow the user's cursor. The div was enlarged smoothly when the user hovers over a button or a link.
I want to add this nice functionality as an optional feature.
I added a div to the web page, #ambition_cursor and added some basic styling. The div now shows like a blue circle. The circle has position fixed to the top left corner of the site. The position can be changed by adding a CSS translate property.
I managed to make it work with the following code:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
var ambition_cursor_x = e.clientX; // Get the horizontal coordinate
var ambition_cursor_y = e.clientY; // Get the vertical coordinate
var ambition_cursor_pos = `translate(${ambition_cursor_x}px, ${ambition_cursor_y}px)`;
ambition_cursor.style.transform = ambition_cursor_pos;
}
window.addEventListener('mousemove', ambition_mouse);
The big downside here is the lag (?). There's quite a big delay, especially when moving the mouse around very fast. You can try it out on this site. I also put the situation in a JSFiddle; although the delay doesn't really happen there.
I didn't apply yet much styling (the default cursor is visible, so you can get a better idea of the real position). I first want this to work better, before I spent much time on that.
How can I increase the speed of this, so that the div position follows the mouse more accurately? I'm a beginner, so I don't really know which JavaScript optimisations I should make.
Current code is JavaScript, but jQuery is also an option.
Many thanks in advance!
Update: example how it looks on my computer.
All elements on the page have a transition applied. Remove/override this style and the delay goes away (tested).
As an alternative to the great answer of Joseph Atkinson:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
ambition_cursor.style.left = e.clientX + 'px'; // Get the horizontal coordinate
ambition_cursor.style.top = e.clientY + 'px' ; // Get the vertical coordinate
}
window.addEventListener('mousemove', ambition_mouse);
See: https://levelup.gitconnected.com/use-javascript-to-make-an-element-follow-the-cursor-3872307778b4
I visited the site example, cracked open the dev console, and found throttled(20, ambition_mouse) It is not a performance issue, and the solution is to not throttle the events. It was too smooth to be a performance issue, which gave me the first clue it had to be an accidental/deliberate effect.
I am looking to create a scrolling effect similar to that shown here: http://www.seaham-hall.co.uk/
However I am unable to achieve the desired effect, and inspecting the sites code gives me no hints. Quite difficult to google for as it is also quite difficult to describe. The closest I can get to finding a solution is this JSFiddle:
http://jsfiddle.net/xtyus/1/
(function($){
/* Store the original positions */
var d1 = $('.one');
var d1orgtop = d1.position().top;
var d2 = $('.two');
var d2orgtop = d2.position().top;
var d3 = $('.three');
var d3orgtop = d3.position().top;
var d4 = $('.four');
var d4orgtop = d4.position().top;
/* respond to the scroll event */
$(window).scroll(function(){
/* get the current scroll position */
var st = $(window).scrollTop();
/* change classes based on section positions */
if (st >= d1orgtop) {
d1.addClass('latched');
} else {
d1.removeClass('latched');
}
if (st >= d2orgtop) {
d2.addClass('latched');
} else {
d2.removeClass('latched');
}
if (st >= d3orgtop) {
d3.addClass('latched');
} else {
d3.removeClass('latched');
}
if (st >= d4orgtop) {
d4.addClass('latched');
} else {
d4.removeClass('latched');
}
});
})(window.jQuery);
However I am not sure that is going in the right direction, this pulls images up and covers the previous image, but notice on the Seaham Hall site the images don't appear to move up at all, they are stationary and become revealed as you scroll.
How do I recreate this effect? My initial thought was to have the first image shrink as you scroll from 1000px down to 0px, and the second image grow to 1000px, and as you continue to scroll this image then shrinks and the third grows, and so on. However this means that after the first image all the other images have a starting size of 0px and there would technically be no scrolling on the page to begin with, so that is an issue.
My second thought is that perhaps the second image is fixed to the page, the first image slides up revealing the second as you scroll, the second image would not appear to move. Once the first image has gone off the top of the page the second image is detached from the page and allowed to move up with scrolling, while the third image is attached and revealed as the second moves up, this would give the exact effect seen in the Seaham website but I have no clue of it is the correct answer.
If anyone can point me to tutorials or a JSFiddle with a basic concept I can probably figure it out from there. Just stumped what direction to approach this from.
That's a nice effect. Here's one way to do it.
Put each image in a fixed position div, which takes up the entire viewport (initially) and has overflow:hidden.
Set each div's z-index to be higher than the next div's.
As the window scrolls, adjust the height of the divs as a function of the window height times the div's position (index) in the DOM, minus the window's scrollTop:
$(window).scroll(function() {
$('.D').each(function(index) {
$(this).css({
height: $(window).height()*(index+1) - $(window).scrollTop()
});
});
});
Additional content will need a higher z-index than the image divs. And note that z-index works with positioned elements only.
Fiddle
Your desired effect isn't technically a parallax background, but it's close enough that parallax jQuery frameworks should work for you.
I would suggest you research jQuery Parallax plugins as they'll likely provide the functionality you'd like without much custom work. Of course since you're dealing with large images it's also best to keep an eye on the resource management; a good plugin should be fairly efficient but others may be slow or resource intensive.
Check this jquery plugin:ScrollMagic
usage: taken from github
The basic ScrollMagic design pattern is one controller, which has several scenes attached.
Each scene has a definite start and end position and defines what happens when the container is scrolled to the specific offset.
/*
Basic workflow example
*/
// init controller
var controller = new ScrollMagic();
// assign handler "scene" and add it to controller
var scene = new ScrollScene({duration: 100})
.setPin("#my-sticky-element") // pins the element for a scroll distance of 100px
.addTo(controller); // add scene to controller
// adding multiple scenes at once
var scene2 = new ScrollScene();
var scene3;
controller.addScene([
scene2,
scene3 = new ScrollScene({duration: 200}), // add scene and assign handler "scene2"
new ScrollScene({offset: 20}) // add anonymous scene
]);
An example, http://www.laravel.com
I want to mimic this effect. I've seen it used a lot across the web lately, but I've never seen a tutorial covering how to create it.
Anyone happen to have some instructions or perhaps a tutorial on recreating this effect?
It's called parallax scrolling. You can do such things with skrollr.js.
And a great tutorial
There are plenty of examples and tutorials for sticky headers,
First link on google search for sticky header http://codepen.io/senff/pen/ayGvD
// Create a clone of the menu, right next to original.
$('.menu').addClass('original').clone().insertAfter('.menu').addClass('cloned').css('position','fixed').css('top','0').css('margin-top','0').css('z-index','500').removeClass('original').hide();
scrollIntervalID = setInterval(stickIt, 10);
function stickIt() {
var orgElementPos = $('.original').offset();
orgElementTop = orgElementPos.top;
if ($(window).scrollTop() >= (orgElementTop)) {
// scrolled past the original position; now only show the cloned, sticky element.
// Cloned element should always have same left position and width as original element.
orgElement = $('.original');
coordsOrgElement = orgElement.offset();
leftOrgElement = coordsOrgElement.left;
widthOrgElement = orgElement.width();
$('.cloned').css('left',leftOrgElement+'px').css('top',0).css('width',widthOrgElement+'px').show();
$('.original').css('visibility','hidden');
} else {
// not scrolled past the menu; only show the original menu.
$('.cloned').hide();
$('.original').css('visibility','visible');
}
}
I'm trying to add in previous and next buttons to my content slider but seem to be having problems, what I would really like to do is move the $slideCtn left or right by the width slideWidth each time the previous or next button is clicked but i'm unsure how to increment each click by the value of slideWidth. I've tried ++ and -- etc but with no results, would anyone be able to show me the best way to do something like this? Also any other advice very welcome!
Or should I create a global index variable that gets set at 0, then as the pagination x's are clicked or the prev/next arrows are clicked update this global variable?
JS Snippet
//Add previous + next arrows
$dirArrows.on('click', function(e){
var arrDir = $(this).data('dir');
$slideCtn.css('left', ( arrDir === 'prev' ) ? -(slideWidth) : +(slideWidth));
e.preventDefault();
});
JS Fiddle
http://jsfiddle.net/SG5ad/10/
At the moment, you're telling it to move to an absolute position - either -200px or +200px (never 0px, 400px, 600px, etc).
You'll need to take into account its current position as well as how much you want to adjust it: http://jsfiddle.net/SG5ad/12/
var arrDir = $(this).data('dir')
iLeft = parseInt( $slideCtn.css('left') );
$slideCtn.css('left', ( arrDir === 'prev' ) ? iLeft - slideWidth : iLeft + slideWidth);
A bug you'll want to fix as well is that the Next/Prev buttons do nothing until you've already jumped to a specific slide with the "x" navigation.
As an entirely separate issue, about 6 months ago I wrote something like this as part of a project at work (it had a few more bells and whistles, but nothing drastically different), and there's one important thing I'd say is worth changing.
In order to go from slide a to slide d at the moment, you animate slides a,b,c and d, which means that
a) 4 slides are animating instead of 1 (plus all their child elements)
b) you have to pass through slides b and c even though they're not relevant
I'd have a look at changing the base position of all your slides to be stacked on top of each other using z-index, then simply animating the top slide off to one side to reveal the one underneath it. It requires a bit of code to track which slides are where ($.data() may help there) but gives you a much more performant slider at the end of it.
You've gotta do it with .animate()
$dirArrows.on('click', function(e){
var arrDir = $(this).data('dir');
if (arrdir == left){
$slideCtn.animate({
left: "+=250"
});
}
});