I refer to http://dygraphs.com/tests/synchronize.html.
Right now my own implementation is also giving me fits, which isn't surprising since I developed it as an edited version of the official example.
Try this: upon page load go to any of the four graphs and in the middle at a skinny section do a zoom in (click-drag from left to right); then double-click.
What happened? You zoomed in and the traces filled the graph vertically, but for a little bit of padding--- automatic scaling. And then upon zooming out with the double-click everything appeared to be as before. Ahh... but it wasn't and still isn't unless you've reloaded the page.
Now move to any OTHER of the four graphs and repeat the first step... zoom in at a the same skinny spot (the data happen to be the same for each of these graphs). Notice that the automatic vertical scaling is missing. And that's a permanent condition in all four charts until you reload the page.
This is with the latest version of Firefox on Ubuntu 12.04 LTS. You can see the Javascript by just looking at the web page source. I have been thinking that it has to do with the causal use of the blockRedraw boolean, but my more complicated efforts with that have yet to pan out.
I do believe that it's most appropriate for me to answer my own question, though it is a bit awkward. I burned a number of hours on this simple thing since posting the question. Here's the code and the answer:
` <script type="text/javascript">
gs = [];
var blockRedraw = false;
var initialized = false;
for (var i = 1; i <= 4; i++) {
gs.push(
new Dygraph(
document.getElementById("div" + i),
NoisyData, {
rollPeriod: 7,
errorBars: true,
drawCallback: function(me, initial) {
if (blockRedraw || initial) return;
blockRedraw = true;
var range = me.xAxisRange();
//var yrange = me.yAxisRange();
for (var j = 0; j < 4; j++) {
if (gs[j] == me) continue;
gs[j].updateOptions( {
dateWindow: range/*,
valueRange: yrange*/
} );
}
blockRedraw = false;
}
}
)
);
}
</script>`
The code there is copied directly off of the dygraphs.com synchronize.html page except that I've commented out var yrange = me.yAxisRange() and also the valueRange part of the updateOptions() argument.
Apparently if you put those range values in there you are forestalling the auto scaling from happening. I don't really know what's happening under the hood but that seems to be the deal. It solves the problem for my own analogous implementation. (That is, I found that the jsfiddle version that dygraphs.com has provided doesn't actually draw the graphs, making it useless for testing. So I have only tested this on my version which is really almost the same.)
Related
I am trying to replicate Conway's Game of Life and though my code seems to be kosher it appears not to behave like it should.
This is the basic meat of it:
if (pressingSpace) {
running = true;
} else {
running = false;
};
if (running) {
for (var i=0; i<tiles.length; i++) {
var tile = tiles[i];
if (tile.alive && (tile.neighborsAlive() < 2 || tile.neighborsAlive() > 3)) {
tile.die();
};
if (!tile.alive && tile.neighborsAlive() == 3) {
tile.comeToLife();
};
};
};
for (var i=0; i<tiles.length; i++) {
var key = tiles[i];
if (!key.alive && mouseDown && key.sprite.contains([cursorX,cursorY]) && cursorX != null) {
key.comeToLife();
}
};
All the functions in play have been thoroughly tested and seem to work as expected. But when this is run, the "alive" squares seem to overrun the screen much more easily than they should. In particular when a column is made three tiles high, it vanishes on the next frame when it should, per the rules, produce two "alive" tiles on either side at the same time.
I suspect this has something to do with the order of operations. Do I need to "mark" appropriate tiles for a state change, instead of change them on the spot? I know there are a lot of implementations of Conway out there but I'm trying to develop this on my own-ish. That said, any nudges in the right direction would be greatly appreciated. Thanks!
You can see it in action here: http://www.eggborne.com/tiles
As far as I can see, it's because of you change tilemap while iterating over it.
E.g. I assume .comeToLife() method changes .alive field to true, and if .neighborsAlive() return non-cached value, but calculates .alive tiles around, you are essentially changing your playfield while iterating, and newly changed cells ruin the whole picture.
Easiest solution will be to create 'old' and 'new' tilemaps, and iterate over 'old' one, while bringing changes to 'new' only. Caching 'neighborsAlive' is essentially creating two arrays, just in different way — that way you're also creating a tilemap, with each tile holding a value of how many neighbors are alive at this moment — and you have to determine this value before everything else changes. If you don't, you will have the same issue, as you currently have.
For demonstration of your problem, make your playfield update with each tile change — you will see your problem animated :)
Hope this helps your issue.
some time ago I started to write some code in JavaScript to learn it a little bit. I picked a rollin/rollout animation as 'project'. (I know about JQuery's slideDown/slideUp, but I wanted to work with pure JavaScript.)
I finished my effect, and the result looks pretty good in all major browsers except Firefox (tested versions 22.x to the latest (25.0.1)). In Firefox, the rolling (in and out) stutters while it rolls smoothly in Chrome, Opera, and Internet Explorer.
The general approach is (unsurprisingly) to have an element's style.height (or width) attribute increased/decreased several times by some pixels over a given time. To avoid calculating sizes every time the effect takes place, I calculate them one time and place them in an array (first item (0 + stepSize), last item wanted height/width). The decrease of the element's height is done by this function:
var verticalRollInWorker = function(step) {
if (step > 0) {
$(btt).style.height = stepSizes[step - 1];
setTimeout(function() { verticalRollInWorker(step - 1); }, delay);
} else {
$(btt).style.display = "none";
$(btt).style.height = 0;
// Enable roll out effect:
stateChange(false);
if (afterFullRollIn != null) {
afterFullRollIn();
}
}
}
In the particular example, I'm using 20 steps over 400ms. The step sizes in the array are rounded to integers, that's why the last step just sets 0 - to handle rounding differences.
(For convenience, I wrote my own $(element) helper, there's no JQuery involved here.)
I tested Firefox without Add-Ons, no difference.
I highly appreciate any help you can provide :)
One problem that I noticed in the above code is that you used $(btt). So, every 20s when the function is iterated, the browser needs to obtain the jQuery object. You could rather store it into a variable say 'var BTT=$(btt);' and use this BTT. Fetching jQuery object is a time consuming task.
Since you are using setTimeout(), the function will be executed every 20ms regardless of the completion of the current execution, this may also cause a drag. As Dagg Nabbit said, you could use setInterval() instad of setTimeout.
Another possible reason might be browser-reflow. I made a personalised scrollbar, and found browser reflow was noticeably greater in my FF than Chrome or IE. This depends on the size of the element, DOM tree depth, overflow property, and more...
And again use this code and see if it is fixed. reduces the subtraction into 1 code.
var BTT=$(btt).get(0);
var verticalRollInWorker = function(step) {
if (step > 0) {
step--;
BTT.style.height = stepSizes[step];
setTimeout(function() { verticalRollInWorker(step); }, delay);
}
else {
BTT.style.display = "none";
BTT.style.height = 0;
// Enable roll out effect:
stateChange(false);
if (afterFullRollIn != null) {
afterFullRollIn();
}
}
}
Further Comments can be made only after seeing a live example.
Regards.
Im trying to do code in javascript a ruzzle solver. For now it just dig through the maze and find every possible path ( in the future I will match them against a dictionary to find the real valid words in it)
You can see it here : http://178.239.177.105/ruzzle/
I wanted to do it with an animation that show how the algorithm works on it, but im issuing a problem.
If you load it, the page just dont show anything, and my browser crash after a while.
BUT...
if you set an alert("") function, somewhere in the middle of the recursion function, you would be able to go through any step in the algorithm.
Especially if you set the browser to prevent to show any further alert messages, you'll finally see the animation working on the maze.
I was actually trying to do this via setInterval(), but is not working.
So I have two questions:
- Why do the script cause the page to crash, or not if there's an alert?
- How can I properly show the animation using some kind on wait() mechanism?
Thanks
You can see all the code by going on the page and look at the source code, however for the sake of clarity I'll paste the relevant code here:
You can also play with the code here : http://jsfiddle.net/Gcw2U/
(you will have to uncomment the last line in the to make it run)
//this matrix of chars rapresent the 4x4 puzzle
var ruzle_model = [["w","a","l","k"],["m","o","o","n"],["h","a","t","e"],["r","o","p","e"]];
// ""offsets" rapresent the four motion vector(up,down,left,right)
// used to visit the matrix
var offsets = [[1,0],[0,1],[-1,0],[0,-1]];
//recursive function to dig the maze
function path(m,i,j,paths,checkeds){
alert("SET BROWSER TO AVOID NEXT ALERTS MSGs!");
//base case, if not hitting a wall or already checked cell
if ( ! (i<=3 && i>=0 && j>=0 && j<=3) || isChecked(checkeds,i,j)){
terminal.innerHTML = terminal.innerHTML + "-"+ paths;
uncheckAllCells();
return paths;
}
//call path for every direction (up,down,left,right) stored in offsets
var tmp = [];
for (var c=0; c<offsets.length;++c){
var offset = offsets[c];
checkCells(i,j);
checkeds.push(new Array(i,j));
tmp.push(path(m,i+offset[0],j+offset[1],paths + m[i][j],copy(checkeds)));
}
return tmp;
}
//call path on every cell in the maze
function ruzzle(r){
var sol = []
for(var i=0; i<4; ++i){
for(var j=0; j<4; ++j){
var checkeds = new Array();
sol.push(path(r,i,j,'',checkeds));
}
}
terminal.innerHTML = sol;
return sol;
}
Javascript loops and recursions inhibit rendering of the page, so any changes made will stay invisible until the script stops executing, like when you spawn an alert. When a user sets "do not show alert messages", the alert still yields execution time to the underlying eventloop, which will update the page.
For as-fast-as-possible (high fps) animations, use requestAnimationFrame().
In your case, setTimeout() is the best way to go. Set a timeout on the recursive call to path.
function recursive(args) {
// do stuff to args
setTimeout(function () {
recursive(args);
}, 5);
}
Example
I am using KineticJS to perform HTML Canvas animations. Animations work perfectly on all desktop browsers, and non retina iDevices (including iPad mini). However, from a retina device (browser or in-app webview using appcelerator) these animations are very sluggish. I have seen similar issues with canvas animations on retina display, but have not found any true solution.
My Stage constructor is 1024w x 768h.
All images are preloaded. And animations are constructed using the preloader's callback function.
If I reduce my stage size by half (and scale inner contents accordingly), the animation will play almost normally (still a little choppier than other ipads). My only justification for trying this was my very poor understanding that a retina display is two 'points'/pixel.
Any insight or ideas are welcome. My next attempt is to start changing image resolutions, rather than scaling dynamically.
This is due to a feature added four months ago. KineticJS will recognize if the pixelratio of the device is over 1 and try to make it as sharp as with pixelratio 1. The problem is, like you have found out, that it kills the performance to the point that it's useless. We have found this to be the case for our use cases.
Our solution: We commented out the pixel ratio part in KineticJS and hard coded it to always be one.
Pros:
The performance goes back up to normal
Cons:
Image is not as sharp
This is the part where we have made the change:
Kinetic.Canvas = function(width, height, pixelRatio) {
// eduplus change to fix pixel ratio performance problems
this.pixelRatio = 1; //pixelRatio || _pixelRatio;
When discussing this with Eric, he made comments to investigate pixel ratio performance, but I don't think he has had the time to do that yet. Hope this helps!
Using KineticJS 5 or above (I am not sure when exactly this global setting was introduced), the simplest and least intrusive way to do this is to set Kinetic.pixelRatio to your desired value before instantiating your stage:
Kinetic.pixelRatio = 1;
var stage = new Kinetic.Stage({
...
});
I use this before instantiating my Stage to overload pixelRatio without modifying KineticJS's source file. (Saves you from having to update the source file after any updates.)
https://gist.github.com/echong/6107722
CoffeeScript:
# Adjust device pixel ratio
for className in ["HitCanvas", "SceneCanvas", "Canvas"]
Kinetic[className].prototype.init = ((p_method) -> (p_config={}) ->
p_config.pixelRatio = 1
p_method.call #, p_config
) Kinetic[className].prototype.init
JavaScript:
_ref = ["HitCanvas", "SceneCanvas", "Canvas"];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
className = _ref[_i];
Kinetic[className].prototype.init = (function(p_method) {
return function(p_config) {
if (p_config == null) {
p_config = {};
}
p_config.pixelRatio = 1;
return p_method.call(this, p_config);
};
})(Kinetic[className].prototype.init);
}
I regularly have two sets of pictures named the same way and I would like to script the process of checking for differences. I'm looking for a basic check, if there is no differences between the two images, discard one of them, if there is a single pixel difference, keep both. For those who question the wisdom of doing this in photoshop, this is an addition to another script that is already running and this optional check will help reduce the number of files I have to upload. I would appreciate the help.
If you really have to do this in Photoshop, this is how I'd propose it:
var doc1 = app.open(new File("~/Desktop/test1.bmp"));
var doc2 = app.open(new File("~/Desktop/test2.bmp"));
doc2.selection.selectAll();
doc2.selection.copy();
app.activeDocument = doc1;
var newLayer = doc1.paste();
newLayer.blendMode = BlendMode.DIFFERENCE;
var histogram = doc1.histogram;
for (var i = 1; i < histogram.length; ++i) {
if (histogram[i] > 0) {
alert('Different!');
break;
}
}
I paste the second picture into the first one and set the resulting layer's blend mode to difference. If the two pictures are identical, the resulting picture should be all black. I therefore check if any color values apart from 0 have any pixels in the histogram.
I assumed the two images have the same size.