So I am building a website that requires web animations, and in my initial development, I used jQuery to build the animations, however I have been told that jQuery is becoming old practice, and have decided to switch over to vanilla JavaScript, however I am not sure if I am using the best practice to do so. As such, here is my code:
window.onscroll=function top(){
var totalDuration=250;//total desired duration of animation
var img=document.getElementById("image");
var objective=document.getElementById("objective");
var header=document.getElementsByTagName("header");
var newHeaderHeight=.25*window.innerHeight;
var newImageMargLeft=.15*window.innerHeight;
var newImageMargTop=.01*window.innerHeight;
var origHeaderHeight=window.getComputedStyle(header[0],null).getPropertyValue("height");
var origImageMargLeft=window.getComputedStyle(img,null).getPropertyValue("margin-left");
var origImageMargTop=window.getComputedStyle(img,null).getPropertyValue("margin-top");
origHeaderHeight=origHeaderHeight.substring(0,origHeaderHeight.length-2);
origImageMargLeft=origImageMargLeft.substring(0,origImageMargLeft.length-2);
origImageMargTop=origImageMargTop.substring(0,origImageMargTop.length-2);
var headerFactor=((newHeaderHeight-origHeaderHeight)/totalDuration);
var imgMargLeftFactor=((newImageMargLeft-origImageMargLeft)/totalDuration)*5;
var imgMargTopFactor=((newImageMargTop-origImageMargTop)/totalDuration)*5;
var id=setInterval(func,250);
function func(){
if (window.scrollY>window.innerHeight*.1){
if (header[0].style.height===newHeaderHeight){
id=clearInterval();
}
else{
header[0].style.height=window.getComputedStyle(header[0],null).getPropertyValue("height").substring(0,window.getComputedStyle(header[0],null).getPropertyValue("height").length-2)-headerFactor;
img.style.marginTop=window.getComputedStyle(img,null).getPropertyValue("margin-Top")-imgMargTopFactor;
img.style.marginLeft=window.getComputedStyle(img,null).getPropertyValue("margin-Left")-imgMargLeftFactor;
console.log("Header: "+(parseFloat(window.getComputedStyle(header[0],null).getPropertyValue("height").substring(0,window.getComputedStyle(header[0],null).getPropertyValue("height").length-2)))-4);
console.log("Margin Top: "+typeof(4));
console.log("Margin Left: "+img.style.marginLeft);
}
}
I know it looks very chaotic, and that was what I was afraid of.
I am essentially trying to animate a header bar that collapses after the scroll bar scrolls past a certain point. However I have multiple elements inside of it that I want to collapse and manipulate, and not just keep it to scale (i.e. change margins when collapsing, and set back to original when expanding, all of which is to be done simultaneously and, from the user's perspective, evenly.
A follow up question I have is, is it worth doing it in vanilla JavaScript? Or should I learn a framework? If so, which one, and why use a framework over vanilla JavaScript, even after all of my research, I am struggling to see why it is so important to learn these frameworks for web development, if they are built off of JavaScript in the first place (in reference to vue or react, etc.)
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'm working on a highly responsive website at the moment and I hit 2 areas where certain blocks of content need to move to others areas of the site. It would not be possible to do so purely with CSS. I suppose I could relatively reposition the blocks but as the dimensions change this isn;t really possible.
The option I am thinking of is, when a media query gets triggered, to then pull a block out of the page and append it in elsewhere where I need it.
I realise this is not ideal bit what I am wanting to ask is if this is a reasonable thing to so.
I know some of you may say reorder some of the markup but that is not possible. As stated above, I know falling back to javascript is not ideal but it would suit this and I don't particularly wish to duplicate content just so I can avoid the use of javascript.
Flexbox would be perfect but support is not where I want it to be currently for me to use that.
What do people here think? Any other solutions?
The right way is to listen to media queries using MediaQueryList:
var mql = window.matchMedia("(max-width: 320px)");
mql.addListener(function(event) {
if(event.matches) {
// Window width is less than or equal to 320, do something cool.
} else {
// Window width is more than 320, do something else.
}
});
The events will trigger when the query is either met or 'unmet'.
Alternatively, you can listen to a resize event, but note your function will get triggered for every new dimension. (Assuming jQuery in the code below.)
$(window).resize(function() {
if($(window).width() <= 320) {
// Window width is less than or equal to 320, do something cool.
} else {
// Window width is more than 320, do something else.
}
});
Like you said yourself though, using JS to make your layout responsive is generally NOT advisable. You can never assume all your users have JS enabled and all goes well.
I would rather see you solve this by restructuring your HTML and CSS. If the content layout has to change a lot, try outputting a block of content in two different places in your HTML and toggling visibility with CSS media queries (setting one to display:none; and the other to display:block;). You should be able to solve most responsive layout issues by rethinking your website structure.
Others looking for a solution may be interested in the Bootstrap Toolkit JS library available here: https://github.com/maciej-gurban/responsive-bootstrap-toolkit
Responsive Bootstrap Toolkit provides an easy way of breakpoint
detection in JavaScript, detecting changes in currently active
breakpoint, as well as executing any breakpoint-specific JavaScript
code.
The SASS module enables quick and simple styling for elements needing
different property values for each screen resolution.
Then you can do things like:
(function($, document, window, viewport){
// Listen to resize event
$(window).bind('resize', function() {
// Default 300ms poll delay
viewport.changed(function() {
// Debug
console.log( 'Current breakpoint: '+ viewport.current() );
// Trigger custom event
$('body').trigger('viewportChanged', [viewport.current()]);
}, 300)
});
// Register event listener
$(document).on('viewportChanged', 'body', function(event, current) {
console.log('Current breakpoint: '+ current);
}
})(jQuery, document, window, ResponsiveBootstrapToolkit);
You could check out some of the already available responsive design HTML boilerplates like Twitter Bootstrap or Zurb Foundation. Maybe their existing configurations satisfy your need.
I have a similar problem on two websites and i do:
JavaScript/jQuery with the window re size event and have breakpoints in JavaScript to. I then remove the item and append/prepend it where i want it to be.
On my other website i use Twitter Bootstrap which is very responsive and looks nice.
I would personally go with Twitter Bootstrap as its a nice grid system. If your site is very complex and cant be done using Twitter Bootstrap them capturing the window re size event is the best way.
$(window).resize(function() {
//Use $(window).width() and maybe some ifs/a switch to handle break points
if($(window).width()<700){
//Move it here
}
});
With CSS and JS it can be done :) You can clone the content to another section with jquery (append), then using media queries you can control what shows.
Here is what I do:
I do the appendTo:
$( $('.goto').html() ).appendTo('.mobile')
Here's an example I did:
http://jsfiddle.net/Riskbreaker/vkfWd/
This might not be what you are looking for (since its really not moving it but cloning the content )but this is the way I do it.
On Codepen I found a neat little interactive graphic use of Javascript, jQuery, and the canvas element.
http://codepen.io/altescape/pen/tbdao
Note: After reading the comments below, I removed the demo I had
uploaded, and even the author of the pen acknowledges he 'just wanted
to play' with it and didn't create it. Hence, I am linking to it just
because it's neat but using it without permission is a no-no. Thanks
for bringing it to my attention.
What I want is to insert it on that (my) site's homepage, in the place of the "under construction message" that is front and center. I'm pretty new to JS but I am good with HTML & CSS, and aware of the basics of DOM...I thought I'd be able to figure out how to adjust it appropriately but no luck, when I inserted the code as if it were HTML going in a div it just floated in the middle of the screen like it is now.
About 90% to the bottom of the JS file there are a few lines of code:
$(function () {
function n(d) {
var b = "";
for (jj = 0; jj < d.length; jj++) b += d.charCodeAt(jj).toString(16);
return b
}
function p() {
j.attr({
height: $(window).height(),
width: $(window).width()
});
k = j.width();
l = j.height();
q()
}
The whole height and width seemed promising but making and adjustment broke it entirely. Can anybody explain to me how to make sense of or successfully manipulate this code so I can position it...perhaps even in a way that will allow it to display appropriately in different size browser windows (I am using CSS media queries)?
I read every post on here that seemed to be related, but to be honest, I might not even be using relevant query phrases as I am not sure if I am using the right terminology. I am completely lost on this one and a bit out of my league, thanks for your patience.
The issue I am having is fairly complicated to explain. I have written up a javascript that displays an image slideshow, and it works fairly well, despite using up more resources than I would like
// imgArr[] is populated before
var i = 0;
var pageLoaded = 0;
window.onload = function() {pageLoaded = 1;}
function loaded(i,f) {
if (document.getElementById(i) != null) f();
else if (!pageLoaded) setTimeout('loaded(\''+i+'\','+f+')',100);
}
}
function displaySlideshow() {
document.getElementById(destinationId).innerHTML = '<div id="slideWindow"><img src="'+imgArr[i]+'" />' + '<img src="'+imgArr[i + 1]+'" /></div>';
setTimeout('displaySlideshow()',1000*3);
i++;
if (i >= imgArr.length - 1)
i = 0;
}
loaded(destinationId,displaySlideshow);
So, this script dynamically adds two images to a HTML element, and it is wrapped in a div.
The div is styled with the height and width of the image, with the overflow (the second image) hidden.
The second image is below the first, and the slideshow is meant to go from RIGHT to LEFT.
My inquiry is twofold:
1) Is there a more efficient way of doing this?
2) How would I animate the images? Would I need to put the second image on the right of the first with CSS somehow, and then set a timer to pull the images (via a style) leftward?
I really don't recommend rolling your own animation library. The Facebook Animation Library written by the wonderful Marcel Laverdet is simple to use and comes with a lot of tutorials to get what you want out of your slideshow. (Note: ignore the FBJS stuff, it's exactly the same even if you're using it on your own site.)
If you're not using a framework, I think you'll find a lot of pain ahead of you. If you still don't want to use a framework, at least find one that is liberally licensed, and take a look at the source code. Here's one, for example.
The basic theory is, yes, you set a timer that moves the image on some sort of interval, either fixed or based on some sort of mathematical equation (eg, sin, cos, etc). By setting these intervals close together, and making lots of them, you get an "animation" in javascript. Typically, you'd use some sort of absolute positioning, moving one element off the screen as the other moves on.
I have a swf with loads text into a Sprite that resizes based on the content put into - I'd like though for the ones that are longer than the page to have the browser use its native scroll bars rather than handle it in actionscript (very much like http://www.nike.com/nikeskateboarding/v3/...)
I did have a look at the stuff nike did but just wasn't able to pull it off. Any idea's?
The trick is to use some simple JavaScript to resize the Flash DOM node:
function resizeFlash( h ) {
// "flash-node-id" is the ID of the embedded Flash movie
document.getElementById("flash-node-id").style.height = h + "px";
}
Which you call from within the Flash movie like this:
ExternalInterface.call("resizeFlash", 400);
You don't actually need to have the JavaScript code externally, you can do it all from Flash if you want to:
ExternalInterface.call(
"function( id, h ) { document.getElementById(id).style.height = h + 'px'; }",
ExternalInterface.objectID,
400
);
The anonymous function is just to be able to pass in the ID and height as parameters instead of concatenating them into the JavaScript string.
I think that the JavaScript is fairly cross-platform. If you want to see a live example look at this site: talkoftheweather.com. It may not look as though it does anything, but it automatically resizes the Flash movie size to accommodate all the news items (it does this just after loading the news, which is done so quickly that you don't notice it happening). The resize forces the browser to show a vertical scroll bar.
I've never done it that way around but I think swffit might be able to pull it off.
I halfway looked at swffit but the height (and width sometimes but mainly height) would be dynamic - swffit let's you declare a maxHeight but that number would be constantly changing...maybe I could figure out how to set it dynamically. A great place for me to start though - thanks!
What I've mostly been using if for is to limit how small you can make a "fullbrowser" flash, and for that it works great.
Happy hacking!
(and don't forget to post your findings here, I might need that too soon ;))
SWFSize
See here for more details.
Intuitsolutions.ca