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);
}
Related
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
I have some problems with including an PDF on an JSF site. I'm using pdfobject (http://pdfobject.com/) but it does not work out the way I want. I can't adjust my settings for my desired outcome, where there is a unscrollable, scaled document (so that it fits the frame) shown in a frame with width = 595px & height = 842px. I tried until now:
<script type="text/javascript" src="pdfobject.js"></script>
<script type="text/javascript">
window.onload = function() {
var myPDF = new PDFObject({
url : "ls_v7.pdf",
width: "595px",
height: "842px",
pdfOpenParams : {
page: 1,
view : 'FitB'
}
}).embed("pdf");
};
</script>
[...]
<div id="pdf">
It appears you don't have Adobe Reader or PDF support in this web
browser. Click here to download the PDF
</div>
or also
<object data="ls_v7.pdf#page=1&view=fitH"
type="application/pdf" width="595" height="842"> </object>
I think I tried most of the cases mentioned in this document, but where not able to come up with the right solution. (The oucome is always a frame with scroll-bars & the PDF gets always shown in full size)
Some background information:
I first included an PDF with iFrame on a JSF page, what went very well. But the Problem is, that on IE8 (some of the client machines) does not show them. So I went to this approach, if you would suggest to try another framework/etc. I would be also very greatful.
it's best to use CSS to specify exact size of the wrapper element.
PDFObject expands the PDF to 100% width/height of the parent container, so wrap your PDF in a div then size the div using CSS.
See this example: http://pdfobject.com/examples/simplest-styled.html
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.
I have a simple html5/canvas and js-setup:
HTML
<canvas id="canvas" width="500" height="500" ></canvas>
JS
var canvas = $("#canvas"),
c = canvas[0].getContext("2d");
c.fillStyle = "gray";
c.fillRect(0, 0, 500, 500);
$(document).mousedown(function() {
console.log('down');
});
$(document).mouseup(function() {
console.log('up');
});
What buffles me is that I am able to log events with google chrome like so
down
up
down
up
down
down
down
down
up
down
down
down
meaning, I get consecutive down events. I think it is caused by the canvas element, because I am not able to reproduce this behavior without it.
Here is a fiddle: http://jsfiddle.net/SunnyRed/zcmaT/
Update
I think it only happens, when the user clicks and drags, which might be the case in my scenario. Here is a simple clicking demo. I can't reproduce it in Firefox and Opera.
The only way that I could replicate this is in your demo was that I either:
started a click outside the page (in another iframe from JS fiddle) and then did the mouse up over the canvas. Or
start the click on the canvas and then release it outside the bounds of the page (such as over the page padding).
I believe this is the correct behaviour.
Here is a link: http://www.avineon.com/
Open this link see on the top. Four images are rotating.
I need something similiar using Javascript.
Is it possible by using Javascript.
I don't think you'll have much luck if you try to do that in pure javascript. It might be possible using the emerging canvas and SVG libraries such as Raphael, but you'll still have cross-browser issues. That site used Flash, and I'd recommend using that if you wanted such an effect.
...why you'd want that on your website is another story though...
You could so something similar, but not exact.
Transparency = Supported in FF, Safari, IE7+
Changing image width = Place image in div with this Css
.class img {
display: block;
width: 100%;
height: 100%
}
This will make the image stretch to fill the .class div. You can then use JS to make this div narrower like the carousel does, and the image contained will animate within the div.
You would then need to track the mouse locations to determine how fast it spins.
You can use an equation using cosine for smooth acceleration from the far ends (IIRC)
You will not however be able to get the images in reverse, unless you create a copy in a server side language or use canvas.
Your best bet would not be to attempt to render something in actual 3D, but rather to use visual tricks to approximate a 3D effect. That is, use perspective / image deformation to make it look like a cube is rotating, similar to what is implemented at this page, which has a better explanation of the math involved.
Really, though, you're probably better off just using Flash.
That effect is possible in JavaScript simply by modifying each of the images width, height, and left styles over time. It's an involved script, but only needs to interpolate those three styles on the each of the image elements.
To get the rotation effect, decrement the width style of the image in a setInterval function while moving the left style property. There is a slight decrement on the height also.
You'll need two images for each side, a front and reverse. When the width decrements to zero, swap the image with it's flipped version and start incrementing the width.
Alternatively use Webkit's, and Firefox's transform css properties.
Or try one of these coverflow components that look similar:
Protoflow,
ImageFlow
<html>
<head>
<title></title>
</head>
<body>
<script type="text/javascript">
if (document.all || document.getElementById){ //if IE4 or NS6+
document.write('<style type="text/css">\n');
document.write('.dyncontent{display: none; width: 728px; height: 90px;}\n');
document.write('</style>');
}
var curcontentindex=0;
var messages=new Array();
function getElementByClass(classname){
var inc=0;
var alltags=document.all? document.all : document.getElementsByTagName("*");
for (i=0; i<alltags.length; i++){
if (alltags[i].className==classname)
messages[inc++]=alltags[i];
}
}
function rotatecontent(){
//get current message index (to show it):
curcontentindex=(curcontentindex<messages.length-1)? curcontentindex+1 : 0;
//get previous message index (to hide it):
prevcontentindex=(curcontentindex==0)? messages.length-1 : curcontentindex-1;
messages[prevcontentindex].style.display="none"; //hide previous message
messages[curcontentindex].style.display="block"; //show current message
}
window.onload=function(){
if (document.all || document.getElementById){
getElementByClass("dyncontent");
setInterval("rotatecontent()", 5000);
}
}
</script>
<table width="100%">
<tr align="center">
<td>
<div class="dyncontent" style="display: block">
first
</div>
<div class="dyncontent">
second
</div>
<div class="dyncontent">
Third
</div>
</td>
</tr>
</table>
</body>
</html>