How can I refresh the data without breaking the canvas - javascript

I have a basic weather application that gets data from forecast.io and displays icons using the related skycons which draw and animates icons using the html5 canvas
Everything seems to works fine, but i have to update the weather regularly without refresh the whole page and the jquery Ajax load method seemed like an answer to my problem. The text data refresh fine and gets the new information but the canvas seems to break.
I managed to isolate the problem. It seems I don't understand how the html canvas works.
Here is a simpler problem
This code draws a red rectangle and refreshes part of the page with the jquery load method
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div id="container">
<div id="weather">
<canvas id="icon"></canvas>
</div>
</div>
<script>
var i = document.getElementById('icon');
var c = i.getContext('2d');
c.fillStyle = "red";
c.fillRect(0, 0, 300, 300);
</script>
<script>
var container = $("#container");
setInterval(function () {
container.load("index.php #weather");
console.log("refresh")
}, 1000);
</script>
Unfortunately, the red rectangle disappear on the reload. gif
My question is, what should I do to make it stay/reappear?
I tried putting the canvas code inside the interval function after the load, but the rectangle appears for a fraction of a second to only vanish again?
Please try this on your own machines to confirm my problems
Can someone explain me how the canvas works and please guide me to a solution
The problem is the same for my icons they blink for a second after the reload to disappear
recordit.co/Ta6u5oVkie

Fixed my problem. It was a common beginner's mistake, I didn't redraw in the canvas in the callback of the ajax function.
thanks

Related

Image resize within the div on manual browser width change

thanks to some external resources and help of some great people the following codepen.io image(post) grid with zoom in effect on hoover was created. There is only one small feature that actually I can't figure out is if for example the user will decide to resize his browser width the images will behaive very very badly, this JS code in some kind destroy responsive behavior of images, but if you refresh the page everything will look nice again.
JS CODE
$(function(){
$('.item-inner').each(function(){
var img = $(this).find('img');
$(this).css({height:img.height(), width:img.width()});
})
})
This code should be put inside a resize() event and also on ready()
function updateImageSize(){
$('.item-inner').each(function(){
var img = $(this).find('img');
$(this).css({height:img.height(), width:img.width()});
})
}
$(window).on('resize',updateImageSize);

Slideshow Script Centering Issue on Images of Varying Width

I'm trying to build a slideshow script will work with images of any width. Not too surprisingly, I'm having some centering issues that cause the portrait mode images to start off on the left when they initially display and then immediately move to the center after a short delay (giving it a bit of a "shooting ducks at a carnival" feel) .
I think that the solution is to get the image width right before it displays and then use that to center it, but I've been having some trouble finding reliable code that does that correctly. I've seen some examples that get the dimensions on load, but since the page (obviously) only loads once before the slideshow starts, that doesn't help much. I put it into CodePen for anyone to view that is kind enough to try and assist me:
http://codepen.io/Realto619/pen/fhdwK
I'm also having a problem with the getPrev() and getNext() functions not working on the first click, They work fine after that, and they seem to be firing on those first clicks, but they don't do what they're designed to until the second click.
Thanks in advance...
As I suspected, the problem was due to the image dimensions / image container not changing for each slide, so the css couldn't center it without having an accurate width for margin:0 auto; to work properly.
I created the following function and then called it in each of the other functions:
function getDim() {
iW = $(window).innerWidth();
iH = $(window).innerHeight();
natW = $(".fadein img").get(0).naturalWidth;
natH = $(".fadein img").get(0).naturalHeight;
natR = natW/natH;
adjH = iH*0.98;
adjW = adjH * natR;
$(".fadein").css('width',adjW);
$(".fadein img").css('width',adjW);
$(".fadein img").css('height',adjH);
}
Hopefully this will help someone else with a similar issue that comes here.

Invisible/hidden canvas does not show up in Chrome

A canvas styled with visibility: hidden; is supposed to appear window-sized after one second with this code, right?
var canvas = document.getElementById("myCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// draw on canvas.getContext("2d") ...
window.setTimeout(function() {
canvas.style.visibility = "visible";
}, 1000);
It works with IE11, but not with Chrome32 (running on Windows7).
(Phew, I never though I would find something that works with IE but not with Chrome!)
I tried using display: none; and canvas.style.display= "block"; to hide and show the canvas and got the same behavior.
Here is a test: http://jsfiddle.net/CX49R/
Oddly, in jsfiddle with Chrome, the canvas (and its drawn content) appears after you move the mouse over the document area (after the function triggered by setTimeout is called, of course). But it never appears if the same HTML+CSS+JS code runs in a single Chrome tab/window (unless you open "Development tools" through "Inspect element", or click on the document area).
What am I missing here? I tried to reduce the code to the minimum of my original scenario.
It seems like it's somehow related to the canvas element. Creating a hidden parent div and showing that instead of the canvas element seems to solve the issue:
http://jsfiddle.net/CX49R/2/
<div id="wrapper">
<canvas id="myCanvas">Your browser does not support canvas.</canvas>
</div>
I don't have enough reputation to comment, so I'll give you an answer instead. The issue is not the setTimeout, the issue is with canvas.style.visibility = "visible";. I set up an alert in your timeout and it fired after a second, no problem. My only guess is that canvas.style.visibility is waiting on a mouse event to trigger itself.

Javascript load background-image asynchrously

Is it possible to load a background-image asynchronously?
I've seen many jQuery plugins to load normal image in an asynchronous way, but I can't find if it's possible to preload / asynchronously load a background-image.
EDIT
I clarify my problem. I've been working on this test site http://mentalfaps.com/
The background image is loaded randomly from a set of images refreshed each hour by a chron job (which takes random images on a flickr catalog).
The host is free and slow at the moment, so the background image takes some time to load.
The positioning of the first overlay (the one with the PNG transparent mentalfaps logo) and width are regulated by a function created in the jQuery(document).ready construct.
If you try to refresh the page many times, the width of the right overlay div is 0 (and so you see a "hole" in the layout)
Here is the method to set my positions:
function setPositions(){
var oH = $('#overlay-header');
var overlayHeaderOffset = oH.offset();
var overlayRightWidth = $(window).width() - (overlayHeaderOffset.left + oH.width());
if (overlayRightWidth >= 0) {
$('#overlay-right').width(overlayRightWidth);
} else {
$('#overlay-right').width(0);
}
var lW = $('#loader-wrapper');
lW.offset({
left: (overlayHeaderOffset.left + oH.width() - lW.width())
});
}
The problem is that the $(window).width() is lower then the effective window width! so the check fails and the script goes for $('#overlay-right').width(0);
any ideas?
Not sure whether I really understand your question, but background images (and all other images) are already loaded asynchronously - the browser will start separate requests for them as soon as it encounters the URL while parsing the HTML.
See this excellent answer for background on loading order: Load and execution sequence of a web page?
If you meant something else, please clarify.
The trick to loading something in the background is to load it once, so the next time when it is loaded it already is in the cache.
Put the following at the end of your html:
<script>
var img = new Image();
img.onload = function () {
document.getElementsByTagName('body')[0].style.backgroundImage = 'background.png';
};
img.src = 'background.png';
</script>
You could use a prefetch link in the head.
<link rel="prefetch" href="/images/background.jpg">
You should be able to add these links to the head via JavaScript.
I like to use CSS to fill the background with a color for page load.
After DOM ready event, I use jQuery to modify the CSS and add a background image. That way, the image isn't loaded until after page loads. Not sure about async, but this method gives the user a decent experience.
Example: http://it.highpoint.edu/
The right side navigation links have a background image. The page initializes with a background color. It is replaced with a background image after page load, via jQuery.
changes in this file jquery.ImageOverlay.js
set your height and width and enjoy this...
imageContainer.css({
width : "299px",
height : "138px",
borderColor : hrefOpts.border_color
});
As it is already mentioned, the background image is loaded asynchronously. If you need to load the background image from JQuery code you may also set the addClass() method to set a CSS class or attr("style=\"background-image:url('myimage.png')\"")
Ive found the answer myself, it was a problem due to the .offset() method that gived sometimes the wrong values.
I had the write values using the .position() :
var overlayHeaderOffset = oH.position();

Why aren't these Canvases rendering?

I'm creating a web app that allows users to enter a number of colors, by specifying RGB values. Upon submission, the user will see a canvas with a solid rectangle drawn in the color chosen.
On this page, I have 7 canvases. The first one draws just fine, but none of the rest show up. The browser is Safari. Here's the relevant code:
First, the script element in the header, which defines the function I use to draw to the canvas.
<script language="JavaScript" TYPE="text/javascript"><!--
function drawCanvas(canvasId, red, green, blue) {
var theCanvas = document.getElementById("canvas" + canvasId);
var context = theCanvas.getContext("2d");
context.clearRect(0,0,100,100);
context.setFillColor(red,green,blue,1.0);
context.fillRect(0,0,100,100);
}
// -->
</script>
Next, the HTML source, where I have my canvas tags and some embedded Javascript to call my drawCanvas function
<canvas id="canvas0" width="100" height="100">
</canvas>
<script language="JavaScript" TYPE="text/javascript"><!--
drawCanvas(0,250,0,0);
// -->
</script>
.
. //more source
.
<canvas id="canvas1" width="100" height="100">
</canvas>
<script language="JavaScript" TYPE="text/javascript"><!--
drawCanvas(1,4,250,6);
// -->
</script>
Also provided is a screenshot. As you can see, the "red" canvas comes up just fine, but the second one, which should be green, doesn't show up at all. Any ideas?
There is some strangeness with the way setFillColor is interpreting the color values -- change the second call to drawCanvas(1,0,250,0) (instead of 4, 250, 6 for the last three args) and the green canvas shows just fine (on showing a local HTML file -- #Chetan's suggestion is worthwhile for pages that don't load that fast, but it doesn't solve your problem;-). This occurs in both Safari and Chrome. Unfortunately I cannot find a documentation for setFillColor (the coming HTML5 standard uses a different approach and does not appear to define such a method) so I can't check whether that's a webkit bug (webkit being what both Safari and Chrome are using for rendering) or a difference in what args setFillColor wants!
Edit: I experimented a bit and it seems it wants the RGB component in the range 0.0 to 1.0, not 0 to 255. Changing the call to setFillColor to:
context.setFillColor(red/256,green/256,blue/256,1.0);
therefore appears to work just fine.
You need to wait until the page has loaded until you can reliably do document.getElementById. You'd usually do DOM manipulation in window onload or DOMContentLoaded event.
This should work:
window.onload = function() {
drawCanvas(0,250,0,0);
drawCanvas(1,4,250,6);
}

Categories