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.
Related
I have a test page to better explain my problem. I have several items on a list (they're images on the test page); when I click on one of them, a corresponding slideshow, using flexslider, sldes down.
The problem is that, on page load, the slideshow shows all slides at once, at a much smaller size than intended. But then, if I switch the focus from the window (i.e. switch between browser tabs or move to another program and come back), the slideshow is now working and the slides are the proper size. This happens in mobile devices too.
When I check with firebug, there's an element.style rule applying to ul.slides:
transform: translate3d(-89px, 0px, 0px);
Which hides one of the slides. Additionally, there's another rule for the list items inside ul.slides that gives them their initial width, which is not even the same for all sliders so I don't understand where it is coming from.
Can someone take a look and suggest a fix? I've tried overriding the element.style rule but so far unsuccessfully.
I think I've figured it out, in principal at least...
.flexslider{display:none;} seems throw off the re-size function of Flexslider.
You could just remove it, but that makes for some ugly loading.
To avoid said ugly loading I put together a quick, work-around- jsFiddle
$(document).ready(function(){
$(".flexslider").css('display','block').slideUp();
});
There's a still a quick glitch while loading, but hopefully it will at least steer you in the right direction.
Another method I played with a bit was to try and force the re-size function like so-
$(".client").click(function () {
$('.flexslider').resize(); // Problematic but promising
var project = this.id;
var project_id = '#' + project + '-project';
var elem = $(".flexslider:visible").length ? $(".flexslider:visible"): $(".flexslider:first");
elem.slideUp('slow', function () {
$(project_id).slideDown('slow');
});
});
This sort of solved the mini-picture issue, but was spotty at best.
I want to slide an image (of a boomerang) off screen and then 5 seconds later slide it back into place. I want the image to right next to some text to begin with and end.
Ideally I'd like the animation to be smooth. I can find many examples doing things like this, but none that seem to do this very simple thing. Any pointers in the right direction would be greatly appreciated.
$(document).ready(function()
{
var my_div = $("#target");
var div_top = my_div.offset().top;
$(document).scroll(function()
{
if (div_top <= $(document).scrollTop()+($(window).height() /2))
{
// EVENT TO SEND IMAGE OFF SCREEN TO THE RIGHT
// EVENT TO WAIT 5 SECONDS
// EVENT TO SEND THE IMAGE BACK
}
});
});
<div id="target;">
<p style="font-size:32px; display: inline;">TEXT</p>
<img id="foo" style="height:35px;" src="https://upload.wikimedia.org/wikipedia/commons/4/46/Ic_account_box_48px.svgg">
You've tagged the question with javascript and provide code that's an incomplete javascript solution, but you also mention you want it to be smooth.
Perhaps declaring a CSS animation using transforms would be better?
Check out https://daneden.github.io/animate.css/ for some examples of what a CSS animation can do. And they can be quite complex, as you can define as many steps as needed.
Now if in some of your animation steps you need to perform calculations, you're stuck with JS, but you can still use a library that uses CSS transitions under the hood get get a smooth frame-rate.
I've used move.js for such a task in the past, and worked pretty well.
https://visionmedia.github.io/move.js/
I am trying to achieve a "crt-like" scrolling glitch effect using Javascript and CSS. I have come up with the following code which clones the content and applies clip to make it look like it scrolls while adding random horizontal offset.
function scanglitch() {
var e = $('#wrapper').clone().appendTo('#glitchcontainer');
var i = 0;
e.css({"clip": "rect(" + i + "px,3830px," + (i + 15) + "px,0px)"});
e.css("z-index",200);
var interval = setInterval(function () {
e.css({"clip": "rect(" + i + "px,3830px," + (i + 15) + "px,0px)"});
e.css({"left": Math.round(Math.random() * 10) + "px"});
i+=4;
if (i > window.innerHeight) {
e.remove();
window.clearInterval(interval);
}
}, 40);
}
Fiddle (Click on the text to see the effect)
I am actually quite pleased with the effect, but the implementation is obviously a hack. As a result the performance is unacceptably low (chrome cpu usage spikes from 5% to 50% when the effect is triggered).
Could someone help me figure out a way to achieve this effect in a more elegant and less performance-heavy way?
UPDATE:
I have implemented your suggestions: Using translate instead of left, scrolling with translate instead of a js loop, calculations outside of the css tag and using requestAnimationFrame(). The code is nicer and more predictable now, but the animations are still very taxing.
New fiddle
You can try using requestAnimationFrame (it is available in almost all browsers). Seems to make a big difference in Chrome.
JSFiddle
EDIT
Here's a transition-only version, and while it doesn't even implement the jitter, it's useful for comparison. Surprisingly(?) it shows about the same, if not more, CPU usage. (You can check the Profile and Timeline tabs in Chrome)
CSS3 Transition-Only JSFiddle
Here's some information about why that should be expected. Essentially, CSS transitions and requestAnimationFrame work very similarly under the hood.
I would delegate as much as possible to css transitions. So instead of moving the clip with js in the interval callback, transition it from top to bottom (example of transitioning).
You could try something similar with the left property, there's no random easing function but maybe you could achieve something similar with one of the bounce functions. Maybe change the easing function with an interval that's less frequent than your current one.
Also, just by slowing the interval of your current solution you'd get visually ok results with less CPU usage.
Side-note: for a completely different route you can replicate your html in a canvas and apply some effects to that. Google has plenty of results for "canvas glitch".
Update: here's my version of your latest fiddle
I get about 10 % less cpu usage with it when comparing to yours. Key differences are:
uses a timeout instead of requestAnimationFrame. requestAnimationFrame is meant to keep framerate high and the animation smooth but we don't need that for the random offsetting. Timeout is also better than an interval since the loop function is quaranteed to finish before next iteration starts.
removed the transparent background, since transparency has a rendering cost
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.
See the following fiddle:
[edit: updated fiddle => http://jsfiddle.net/NYZf8/5/ ]
http://jsfiddle.net/NYZf8/1/ (view in different screen sizes, so that ideally the image fits inside the %-width layouted div)
The image should start the animation from the position where it correctly appears after the animation is done.
I don't understand why the first call to setMargin() sets a negative margin even though the logged height for container div and img are the very same ones, that after the jqueryui show() call set the image where I would want it (from the start on). My guess is that somehow the image height is 0/undefined after all, even though it logs fine :?
js:
console.log('img: ' + $('img').height());
console.log('div: ' + $('div').height());
$('img').show('blind', 1500, setMargin);
function setMargin() {
var marginTop =
( $('img').closest('div').height() - $('img').height() ) / 2;
console.log('marginTop: ' + marginTop);
$('img').css('marginTop', marginTop + 'px');
}
setMargin();
Interesting problem...after playing around with your code for a while (latest update), I saw that the blind animation was not actually firing in my browser (I'm testing on Chrome, and maybe it was firing but I wasn't seeing it as the image was never hidden in the first place), so I tried moving it inside the binded load function:
$('img').bind('load', function() {
...
$(this).show('blind', 500);
});
Now that it was animating, it seemed to 'snap' or 'jump' after the animation was complete, and also seemed to appear with an incorrect margin. This smacks of jQuery not being able to correctly calculate the dimensions of something that hadn't been displayed on the screen yet. On top of that, blind seems to need more explicit dimensions to operate correctly. So therein lies the problem: how to calculate elements' rendered dimensions before they've actually appeared on the screen?
One way to do this is to fade in the element whose dimensions you're trying to calculate very slightly - not enough to see yet - do some calculations, then hide it again and prep it for the appearance animation. You can achieve this with jQuery using the fadeTo function:
$('img').bind('load', function() {
$(this).fadeTo(0, 0.01, function() {
// do calculations...
}
}
You would need to work out dimensions, apply them with the css() function, blind the image in and then reset the image styles back to their original states, all thanks to a blind animation that needs these dimensions explicitly. I would also recommend using classes in the css to help you manage things a little better. Here's a detailed working example: jsfiddle working example
Not the most elegant way of doing things, but it's a start. There are a lot more easier ways to achieve seemingly better results, and I guess I just want to know why you're looking to do image blinds and explicit alignment this way? It's just a lot more challenging achieving it with the code you used...anyways, hope this helps! :)