I'm doing some pretty processor heavy processing on a few audio files. Before I go in to this function called startProcessing I want to show a div which overlays the entire page and says calculating...Problem is the div is only shown after the function has terminated. When I click the button which activates tis code the button freezes and only when the process function has terminated does it unfreeze and show the loader. Anyone seen similar behaviour and was able to solve it?
document.getElementById('loader').innerHTML = "<p>Calculating...</p><p>Please Wait</p><img src='../img/loader.gif' />";
document.getElementById('loader').style.visibility = "visible";
document.getElementById('notification').style.visibility = "visible";
var speed = document.getElementById("playbackSpeed").value/100;
console.log("Changing speed");
if (speed > 1.5){
startProcessing(1.5);
backend.playbackSpeed = 1.5;
} else if (speed < 0.75){
startProcessing(0.75);
backend.playbackSpeed = 0.75;
} else {
startProcessing(speed);
backend.playbackSpeed = speed;
}
You could throw the heavy processing into a Web Worker. That would free up your UI.
Note: Its not IE friendly... only IE10 (I think)
Try to run heavy calculations with some delay:
setTimeout(function(){
var speed = document.getElementById("playbackSpeed").value/100;
console.log("Changing speed");
speed = Math.min(Math.max(speed, 0.75), 1.5);
startProcessing(speed);
backend.playbackSpeed = speed;
}, 13);
One approach could be to use setTimeout or setInterval for your div showing the progress bar. Another way to get around it is doing some (pseudo) multithreading.
Related
I have searched extensively to find a solution to this but have not succeeded.
I have created a 4 second video clip that loops seamlessly in an editor.
However when the clip runs in a page via Safari, Chrome or Firefox there is a small but noticeable pause in the playback from end back to beginning.
I have tried using the loop and preload attributes both together and independently.
I have also tried the following javascript:
loopVid.play();
loopVid.addEventListener("timeupdate", function() {
if (loopVid.currentTime >= 4) {
loopVid.currentTime = 0;
loopVid.play();
}
}
But in all cases the momentary pause remains and spoils the effect.
I'm open to any ideas?
Since this question is a top search result in Google, but doesn't "technically" have an answer yet, I'd like to contribute my solution, which works, but has a drawback. Also, fair warning: my answer uses jQuery.
It seems the slight pause in the video loop is because it takes time for html5 video to seek from one position to another. So it won't help anything to try to tell the video to jump to the beginning when it ends, because the seek will still happen. So here's my idea:
Use javascript to clone the tag, and have the clone sit hidden, paused, and at the beginning. Something like this:
var $video = $("video");
var $clone = $video.clone();
$video.after($clone);
var video = $video[0];
var clone = $clone[0];
clone.hidden = true;
clone.pause();
clone.currentTime = 0;
Yes, I used clone.hidden = true instead of $clone.hide(). Sorry.
Anyway, after this the idea is to detect when the original video ends, and then switch to the clone and play it. That way there is only a change in the DOM as to which video is being shown, but there is actually no seeking that has to happen until after the clone starts playing. So after you hide the original video and play the clone, you seek the original back to the beginning and pause it. And then you add the same functionality to the clone so that it switches to the original video when it's done, etc. Just flip flopping back and forth.
Example:
video.ontimeupdate = function() {
if (video.currentTime >= video.duration - .5) {
clone.play();
video.hidden = true;
clone.hidden = false;
video.pause();
video.currentTime = 0;
}
}
clone.ontimeupdate = function() {
if (clone.currentTime >= clone.duration - .5) {
video.play();
clone.hidden = true;
video.hidden = false;
clone.pause();
clone.currentTime = 0;
}
}
The reason I add the - .5 is because in my experience, currentTime never actually reaches the same value as duration for a video object. It gets pretty close, but never quite there. In my case I can afford to chop half a second off the end, but in your case you might want to tailor that .5 value to be as small as possible while still working.
So here's my entire code that I have on my page:
!function($){
$(document).ready(function() {
$("video").each(function($index) {
var $video = $(this);
var $clone = $video.clone();
$video.after($clone);
var video = $video[0];
var clone = $clone[0];
clone.hidden = true;
clone.pause();
clone.currentTime = 0;
video.ontimeupdate = function() {
if (video.currentTime >= video.duration - .5) {
clone.play();
video.hidden = true;
clone.hidden = false;
video.pause();
video.currentTime = 0;
}
}
clone.ontimeupdate = function() {
if (clone.currentTime >= clone.duration - .5) {
video.play();
clone.hidden = true;
video.hidden = false;
clone.pause();
clone.currentTime = 0;
}
}
});
});
}(jQuery);
I hope this will be useful for somebody. It works really well for my application. The drawback is that .5, so if someone comes up with a better way to detect exactly when the video ends, please comment and I will edit this answer.
I've found that Firefox will stutter while looping if I'm using mp4 or ogv files. I changed the code in my page to try using a webm file first instead, and suddenly the stutter was gone and the video looped seamlessly, or at least close enough that I didn't see an issue. If you haven't given that a shot, it could be worth it to try converting the file to a webm format and loading that instead.
I'm trying to make pacman move without using jquery.animation because I want more control. so I'm using setInterval, but it only works sometimes. if you refresh enough, it will eventually "click on" and work fine, but if you refresh again, it won't work, it's here http://pacman.townsendwebdd.com if you want to look at it, thank you
//earlier in the code
this.moveInterval = setInterval(_this.move, 40, _this);
move: function(_this)
{
if(_this.pause)//set to true for now
return false;
var horz = 0;
var vert = 0;
var dir = _this.dir;
//set horizontal and vertical directions
if(dir % 2 == 0)
horz = dir - 1;
else
vert = dir - 2;
_this.top += vert;
_this.left += horz;
$('#pacman').css('top', _this.top);
$('#pacman').css('left', _this.left);
},
I'm not sure if this will fix the problem, but I would recommend using request animation frame instead of setInterval.
The other thing I think would be the problem (and I've been stung by this too) is that you're possibly trying to start the animation before the page has fully loaded. Try putting your code into a function and calling it with the onload attribute of the body tag.
Good luck!
Griffork.
I have several flash movies on a site. They all loop through an animation which lasts for approximately 15 seconds (but this is not set in stone). They all begin to play at the same time and are in sync.
However, when I resize the browser window, or scroll the page, if a flash player instance is not in the viewport, it stops playing. When it returns to the viewport, it resumes and subsequently is out of sync with the other flash player instances.
I am under the impression this is a flash player optimisation. Is there anyway of disabling this behaviour, possibly through JS / AS3? It appears to happen in Firefox and Chrome on Windows.
UPDATE
Just to clarify. I have methodologies in place using local connection and ExternalInterface to sync the ads. What I am looking for is a method to disable the "optimisation" of FlashPlayer which results in the frame rate being drastically reduced.
You can't disable this feature. It's put in place to lower the memory and CPU use when the flash application isn't visible.
What is available for you though is something called the Throttle API. This is a dedicated API created to allow creators of Flash applications the ability to be notified exactly when their application is going to be slowed down/throttled.
Here's an example.
addEventListener(ThrottleEvent.THROTTLE, onThrottleEventHandler);
function onThrottleEventHandler(e:ThrottleEvent):void
{
if(e.state == ThrottleType.THROTTLE)
{
/**
* the player is about to be slowed down to a frame rate
* set in e.targetFrameRate
*/
}
else if(e.state == ThrottleType.PAUSE)
{
/**
* the player is going to be paused completely, AKA 0 fps
*/
}
else if(e.state == ThrottleType.RESUME)
{
/**
* the player is now back to normal as it has resumed
* from the paused or throttled state
*/
}
}
Now you can figure out a way that works best for you but my suggestion is to store the current time that has passed whenever being throttled or paused via:
currentTime = getTimer();
Then calculate how much time has passed once your application has resumed using:
passedTime = getTimer() - currentTime;
Then do what you like with this information.
Hopefully this has helped, should offer you a greater degree of control now that you're familiar with the Throttle API. For more information on it, check it out in the documentation here: ThrottleEvent
I belive this kind of behavior its normal, its kind of a bug of flash that has never been fixed.
I belive inha may got u a solution, but not on an enter_frame event. that just to brutal.
what I would do is:
create a timer event.. each X seconds.. so it will call a checkFunction,
in my checkFunction(). I would check if all my movieClips are syncronized.
and if I found 1 that is not.. ill put a simple gotoAndPlay(xFrame);
var aMovieClips:Array; //get all ur movieclips into this array.
var timeToCheck = 1000; //time to check for a unsincronized movieclip
var time:Timer=new Timer(timeToCheck,0);//do inifinite call each 1000 seconds
time.start();
time.addEventListener(TimerEvent.TIMER, checkFunction);
public function checkFunction(e:TimerEvent):void
{
var aCurrentFrames:Array;
for (var n:int = 0;n<aMovieClips.length();n++)
aCurrentFrames.push(aMovieClips[n].currentFrame);
//so now u have all current frames of all movie clips.. so u can add a
//gotoAndPlay(x); to any unsyncronized movieclip
}
If it is very important that each SWF progresses simultaneously, I would control it by JavaScript.
Assuming each SWF file is a simple MovieClip, something like this is how I would go about it:
Set the Document Class of each FLA file to this:
package {
import flash.display.MovieClip;
import flash.external.ExternalInterface;
public class ExternalInterfaceControlledMC extends MovieClip {
public function ExternalInterfaceControlledMC() {
this.stop();
if (ExternalInterface.available) {
try {
ExternalInterface.addCallback("setFrame", jsSetFrame);
} catch (error:Error) {
trace("An Error occurred:", error.message);
}
} else {
trace("ExternalInterface is not available");
}
}
private function jsSetFrame(value:String):void {
var frameNumber = int(value) % this.totalFrames;
this.gotoAndStop(frameNumber);
}
}
}
In the JavaScript, you would add a reference of each instance of the SWFs into an array, then use a timer to tell each SWF to progress to a frame number.
var swfElements; //Array
var currFrame = 1;
function onPageLoad() {
//Init timer
setInterval("progressFrame", 1000 / 30); //30 fps
}
function progressFrame() {
for (var i = 0; i < swfElements.length; i++) {
swfElements[i].setFrame(currFrame);
}
currFrame++;
}
Please beware that nothing about this code is tested and is only meant to be used to illustrate my train of thought.
I've got some JavaScript to center images and <object>s on a page if they're over a threshold width. It also checks that certain classes haven't already been manually applied.
$('img,object').bind('load', function() {
w = $(this).width();
if (w > 400 && !( $(this).hasClass('inlineimage') | $(this).parent().hasClass('inlineimage') ))
$(this).css('margin', '10px ' + (parseInt((800-w)/2)-30) +'px');
});
It's horrific but the meaning behind this was all originally quite sane. The CMS doesn't make it easy to specify alignment and developing it to allow this would have taken significant time away from other jobs. A client-side hack works.
The only problem with it is that the JS waits until the whole image has loaded. Obviously this means that on slower networks, the page loads, the images start loading and some time later the images snap into position. Ugly.
But the browser seems to know the width of an image as soon as it starts to download it. I would really love to hook into this event and splat this visual bug.
Of course, if there's a CSS way of approaching this, I'm open to that too.
In browsers that support it, you can poll for natural dimensions:
var interval = setInterval( function() {
if( img.naturalWidth ) {
clearInterval(interval);
console.log( "Natural available: "+ (new Date - now );
console.log( img.naturalWidth, img.naturalHeight );
}
}, 0 );
In the demo here on uncached image I get:
Natural available: 782
62 71
Loaded: 827
So the real dimensions were available 50 milliseconds before load event. Unfortunately in IE, the readystate "loading" doesn't guarantee real dimensions.
Change the query string for the image before each test to ensure uncached.
Here's whatwg link on natural dimensions: http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#dom-img-naturalwidth
var span = document.getElementById('span'); // The parent span
var check = function (){
if(span.offsetWidth > 0){
console.log('Width while loading', span.offsetWidth);
}
else{
setTimeout(check, 100);
}
};
check();
Demo. This should show the width in the console while it's loading first, and then the width after it's loaded. That is as long as the image isn't cached. (If the demo doesn't work for someone, try changing the hoo part of the image URL to anything else)
In the interest of this still working on more than the latest browsers, I've cobbled together a best effort brute force. It waits 500ms between attempts and checks images to see if the current run through is the same width as the last time it tried.
As soon as the width for an image is the same in two consecutive passes, we run the centring code.
This uses arrays to keep track of things so we're not constantly raping the DOM nor are we querying items that aren't applicable (because they've already been dealt with or ruled out).
attempts = 0;
arr = [];
$.each($('img,object').not('inlineimage'), function(){
arr.push([this, -2, $(this).width()]);
});
checkImgs = function() {
attempts++;
newarr = []
$.each(arr, function(){
if ($(this[0]).parent().hasClass('inlineimage'))
return;
w = $(this[0]).width();
this[1] = this[2];
this[2] = w;
if (this[1] != this[2])
return newarr.push(this);
// We know this image is loaded enough now - we can do things!
if (w >= 400)
$(this[0]).css('margin', '10px ' + (parseInt((800-w)/2)-30) +'px');
});
arr = newarr;
if (arr.length && attempts < 6)
setTimeout(checkImgs, 500);
}
setTimeout(checkImgs, 500);
It's not beautiful but it seems to work both efficiently (CPU was getting hammered by some of my earlier attempts) and quickly (cached images spring into place within 500ms).
Use Firefox 10.0.2 to open Framework.html from this project: http://code.google.com/p/unitspeeds-vhh/ (EDIT: I'm now preloading the icons. Use this revision if you'd like to try to debug the original problem.)
Hit F5 to refresh.
Hit F5 a few more times very quickly.
Expected: The unit icons (unitIconObj in the code) should always render.Actual: They never render on the first page load. First F5 usually shows all icons. Some very fast repetitions of F5 cause most most -- but not all -- icons to show.
The basic problem I'm trying to solve is icons not rendering properly the first time, and I assume this means I need to be preloading the images. I've been trying a few different methods to do this, but the behavior is not strictly reproducible, and I think I just don't know enough about refreshes and caching to figure this out myself. The icons themselves are very small image files, so I'm surprised to see that this is an issue at all.
Very sorry for the messy code and question -- I'm a noob! Any advice would be welcome.
Edit: Here's the part where I load the image file and render it:
for (var x = 0; x < sortedOutput.length; x++)
{
// Draw the unit icon
var unitIconObj = new Image();
if (sortedOutput[x].Filename == "--") // I don't have real icons for a few units
{
unitIconObj.src = "Icons/Creep.jpg";
} else
{
unitIconObj.src = "Icons/" + sortedOutput[x].Filename + ".jpg";
}
speedContext.drawImage(unitIconObj, ChartBuffer+textBlock+2+4*iconSpace, 50+(x*iconSpace), BarHeight, BarHeight);
}
Have you tried changing this so it waits to call drawImage function until the onload event on the image fires. This will ensure that the image is loaded before any of the other magic happens.
for (var x = 0; x < sortedOutput.length; x++)
{
var unitIconObj= new Image();
unitIconObj.onload = function(){
speedContext.drawImage(unitIconObj, ChartBuffer+textBlock+2+4*iconSpace, 50+(x*iconSpace), BarHeight, BarHeight);
};
if (sortedOutput[x].Filename == "--") // I don't have real icons for a few units
{
unitIconObj.src = "Icons/Creep.jpg";
} else
{
unitIconObj.src = "Icons/" + sortedOutput[x].Filename + ".jpg";
}
}
found this here: https://developer.mozilla.org/en/Canvas_tutorial/Using_images