I've run into this problem on a few occasions but I can't seem to find a solid answer or solution to the problem.
I created a site that uses two canvases layered on top of each other which display properly in Chrome, but in Firefox only one of the canvases will display. Here's my code:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
var interval;
var width, height;
// ------------- SETUP ----------------------
window.onload = function() {
width = document.width;
height = document.height;
setupC1();
setupC2();
}
function setupC1(){
canvas1 = document.createElement("canvas");
canvas1.width = document.width;
canvas1.height = document.height;
canvas1.style.position = "absolute";
canvas1.style.top = "0px";
canvas1.style.left = "0px";
canvas1.style.zIndex = "-2";
document.body.appendChild(canvas1);
ctx = canvas1.getContext("2d");
interval = setInterval(draw, 50);
}
function setupC2(){
canvas2 = document.createElement("canvas");
canvas2.width = "399";
canvas2.height = "274";
canvas2.style.position = "absolute";
canvas2.style.top = (window.innerHeight/2)-100 +"px";
canvas2.style.left = (window.innerWidth/2)-200 +"px";
canvas2.style.zIndex = "-1";
document.body.appendChild(canvas2);
ctx2 = canvas2.getContext("2d");
interval = setInterval(gun, 50);
}
// ------------- DRAW ----------------------
function draw() {
var x = Math.round(Math.random()*window.innerWidth);
var y = Math.round(Math.random()*window.innerHeight);
function rndColor() {
return '#' + ('00000' + (Math.random() * 16777216 << 0).toString(16)).substr(-6);
}
//draw here
ctx.strokeStyle=rndColor();
ctx.beginPath();
ctx.moveTo(window.innerWidth/2, window.innerHeight/2);
ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke();
}
function gun(){
ctx2.fillStyle="#000000";
ctx2.strokeStyle="#000000";
ctx2.beginPath();
ctx2.moveTo(51, 28);
ctx2.lineTo(66, 28);
ctx2.lineTo(71, 19);
ctx2.lineTo(75, 19);
ctx2.lineTo(77, 28);
ctx2.lineTo(191, 28);
ctx2.lineTo(191, 30);
ctx2.lineTo(238, 30);
ctx2.lineTo(238, 28);
ctx2.lineTo(350, 28);
ctx2.lineTo(355, 23);
ctx2.lineTo(358, 28);
ctx2.lineTo(368, 28);
ctx2.lineTo(368, 36);
ctx2.lineTo(373, 36);
ctx2.lineTo(374, 59);
ctx2.lineTo(368, 59);
ctx2.lineTo(368, 69);
ctx2.lineTo(371, 69);
ctx2.lineTo(371, 77);
ctx2.lineTo(368, 80);
ctx2.lineTo(368, 95);
ctx2.lineTo(265, 102);
ctx2.lineTo(265, 153);
ctx2.lineTo(164, 153);
ctx2.lineTo(169, 141);
ctx2.lineTo(249, 141);
ctx2.lineTo(249, 103);
ctx2.lineTo(198, 106);
ctx2.bezierCurveTo(192, 106, 195, 135, 200, 137);
ctx2.lineTo(194, 139);
ctx2.bezierCurveTo(190, 136, 178, 108, 180, 106);
ctx2.lineTo(169, 143);
ctx2.lineTo(156, 156);
ctx2.lineTo(157, 176);
ctx2.lineTo(143, 190);
ctx2.lineTo(144, 208);
ctx2.lineTo(129, 222);
ctx2.lineTo(129, 242);
ctx2.lineTo(120, 242);
ctx2.lineTo(120, 255);
ctx2.lineTo(42, 246);
ctx2.lineTo(48, 233);
ctx2.lineTo(37, 231);
ctx2.lineTo(25, 220);
ctx2.lineTo(75, 113);
ctx2.bezierCurveTo(75, 90, 55, 85, 46, 83);
ctx2.closePath();
ctx2.fill();
ctx2.stroke();
}
</script>
</head>
<body>
</body>
</html>
I feel like I may have heard about potential firefox issues with using negative z-indexes, could that really be the problem?
There are no width or height properties on the document object in the specs, so document.width ends up as undefined, and so does document.height. So you're setting your canvas1 to have a width and height of 0, which is the number undefined converts to.
You may want to use one of the things listed at https://developer.mozilla.org/en-US/docs/DOM/document.width#Alternatives and https://developer.mozilla.org/en-US/docs/DOM/document.height#Alternatives
Related
I created a canvas with a circle inside and filled it with a gradient.
I am not sure how to make the canvas as well as the circle inside the canvas responsive to the screen size.
I tried using vh and vw for the width and height of the canvas. But when I change the height or width of the window, the circle looks either too long or too wide.
Question:
I want the entire circle to decrease in size when the window size is reduced. I am not sure how to do this.
Code:
var c = document.getElementById('canvassun');
var ctx = c.getContext('2d');
var grd = ctx.createRadialGradient(85, 85, 20, 85, 85, 70);
grd.addColorStop(0, 'red');
grd.addColorStop(0.5, 'orange');
grd.addColorStop(0.8, 'yellow');
grd.addColorStop(1, 'white');
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(90, 90, 70, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath;
#canvassun {
height: 30vh;
width: 14vw;
border: 1px solid black;
margin: 0 auto;
display: block;
margin-top: 18%;
}
<canvas id="canvassun" width=170 height=170></canvas>
Listen to window resize event and redraw the canvas
function draw() {
var c = document.getElementById('canvassun');
var ctx = c.getContext('2d');
var grd = ctx.createRadialGradient(85, 85, 20, 85, 85, 70);
grd.addColorStop(0, 'red');
grd.addColorStop(0.5, 'orange');
grd.addColorStop(0.8, 'yellow');
grd.addColorStop(1, 'white');
ctx.beginPath();
ctx.fillStyle = grd;
ctx.arc(90, 90, 70, 0, 2 * Math.PI);
ctx.fill();
ctx.closePath;
}
window.addEventListener("resize", draw);
Note Probably you need to debounce the draw function for performance
Hi I have following script, but when I run it in Chrome I dont see the result.
What did I miss? What do I have to add to html to see my results.
<script>
noStroke();
var leftX = 145;
var rightX = 274;
var sunRadius = 100;
var draw = function() {
background(184, 236, 255);
fill(255, 170, 0);
ellipse(200, 100, sunRadius, sunRadius);
// clouds
fill(255, 255, 255);
// left cloud
ellipse(leftX, 150, 126, 97);
ellipse(leftX+62, 150, 70, 60);
ellipse(leftX-62, 150, 70, 60);
// right cloud
ellipse(rightX, 100, 126, 97);
ellipse(rightX+62, 100, 70, 60);
ellipse(rightX-62, 100, 70, 60);
leftX--;
rightX++;
sunRadius+=2;
};
</script>
Whatever noStroke (and other functions like fill and `background) are, make sure they're defined in your code, or else the rest of the function won't execute.
The reason that your function isn't being callled... Is because you're not calling it.
Add a call to draw after the function is declared. The end of the code should look like:
leftX--;
rightX++;
sunRadius+=2;
};
draw(); //Actually run the function
I think ellipse is new for canvas. I found a function for backwards compatibility on github.
var can = document.getElementById('can');
var ctx = can.getContext('2d');
var leftX = 145;
var rightX = 274;
var sunRadius = 100;
draw();
function draw() {
ctx.fillStyle = "rgb(184, 236, 255)";
ctx.fillRect(0, 0, can.width, can.height);
ctx.beginPath();
ellipse(200, 100, sunRadius, sunRadius);
ctx.fillStyle = "rgb(255, 170, 0)";
ctx.fill();
// clouds
ctx.fillStyle = "rgb(255, 255, 255)";
// left cloud
ctx.beginPath();
ellipse(leftX, 150, 126, 97);
ellipse(leftX + 62, 150, 70, 60);
ellipse(leftX - 62, 150, 70, 60);
ctx.fill();
// right cloud
ctx.beginPath();
ellipse(rightX, 100, 126, 97);
ellipse(rightX + 62, 100, 70, 60);
ellipse(rightX - 62, 100, 70, 60);
ctx.fill();
leftX--;
rightX++;
sunRadius += 2;
};
function ellipse(cx, cy, w, h) {
var rx = w / 2;
var ry = h / 2;
var rot = 0;
var aStart = 0;
var aEnd = Math.PI * 2;
florianEllipse(ctx, cx, cy, rx, ry, rot, aStart, aEnd);
}
function florianEllipse(context, cx, cy, rx, ry, rot, aStart, aEnd){
context.save();
context.translate(cx, cy);
context.rotate(rot);
context.translate(-rx, -ry);
context.scale(rx, ry);
context.arc(1, 1, 1, aStart, aEnd, false);
context.restore();
}
<canvas id="can" width="400" height="300"></canvas>
I'm trying to change fillstyle on focus in and focus out event. When the event call multiple time it's overlapping. Here my code:
function FillColorToFields(id, isOnFocus) {
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var coordinates = $('#hidCoord_' + id).val().split(',');
if (isOnFocus) {
context.fillStyle = "rgba(0,255,0,0.1)";
context.fillRect(coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
} else {
context.fillStyle = "rgba(255, 255, 255, 0.5)";
context.fillRect(coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
}
}
Simply use context.clearRect(x, y, width, height). Its purpose is to erase any previously drawn content of the rectangle (check out the documentation). See this forked fiddle for an example.
I set the image as canvas background image instead of drawing it to canvas. It's working fine now.
http://jsfiddle.net/vm47p2sk/8/
<canvas id="myCanvas"></canvas>
<a id = "green" href="#">On focus</a>
<a id = "transparent" href="#">On focus out</a>
$('#myCanvas').css("background-image", "url(https://www.webkit.org/blog-files/acid3-100.png)");
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
context.strokeStyle = "#009900";
context.lineWidth = 3;
context.strokeRect (5, 5, 100, 100);
$('#green').click(function (){
context.clearRect (8, 8, 94, 94);
context.fillStyle = "rgba(0,255,0,0.1)";
context.fillRect (8, 8, 94, 94);
});
$('#transparent').click(function (){
context.clearRect (8, 8, 94, 94);
context.fillStyle = "rgba(255, 255, 255, 0.1)";
context.fillRect (8, 8, 94, 94);
});
i have a Canvas:
function drawWindRose(){
var canvas = document.getElementById('windrose');
var bild = canvas.getContext('2d');
var frame = canvas.getContext('2d');
frame.fillStyle = "rgb(200,0,0)";
frame.fillRect (0, 0, 200, 200);
bild.save();
bild.translate(100,100);
bild.rotate((360-Compass)*Math.PI/180);
bild.fillStyle = "rgb(0,0,0)";
bild.font = '8pt Arial';
bild.fillText('N', 102, 30);
bild.fillText('E', 170, 110);
bild.fillText('S', 92, 170);
bild.fillText('W', 30, 96);
bild.closePath()
bild.strokeStyle= "rgb(0,0,0)"; // schwarz
bild.beginPath();
bild.lineWidth = 2;
bild.arc(100,100,95,0,Math.PI*2,true);
bild.moveTo(105,100);
bild.lineTo(195,100);
bild.moveTo(100,105);
bild.lineTo(100,195);
bild.moveTo(95,100);
bild.lineTo(5,100);
bild.moveTo(100,95);
bild.lineTo(100,5);
bild.moveTo(105,100);
bild.arc(100,100,5,0,Math.PI*2,true);
bild.closePath()
bild.stroke();
bild.beginPath();
bild.lineWidth = 5;
if(Azimuth>=0&&Distance>=1)
{
bild.arc(100,100,85,0,Math.PI*2,true);
bild.arc(100,100,85,0,(Azimuth-90)*(Math.PI/180),true);
bild.lineTo(100,100);
}
if(Distance<=1)
{
bild.arc(100,100,2,0,Math.PI*2,true);
}
bild.strokeStyle= "#00FF00";//green
bild.stroke();
bild.translate(-100,-100);
bild.restore();
};
<canvas style="padding-left: 0; padding-right: 0; margin-left: auto; margin-right: auto; display: block;"id="windrose" width="200" height="200"> Ihr Browser kann kein Canvas! </canvas>
Like u can see, i want to rotate the canvas. Its a kind of Compass for a FXOS-App.
I know how to rotate an image, but i dont get it to work with this drawing.
The "Compass" Variable is the Deviceorientation un Degrees.
So if you point the device to east, the Compass must be rotated 90degrees to the left...
Maybe some of you has got an idea.
regards
goerdy
I would use offscreen canvas to draw to the compass and then rotate that as an image onto my main canvas like (Example hardcoded values(azimuth and distance) and get deg from html):
window.onload = setupRose;
var TO_RADIANS = Math.PI / 180;
function drawRotatedImage(context, image, x, y, angle) {
var canvas = document.getElementById('myCanvas');
context.save();
context.translate(x, y);
context.rotate(angle * TO_RADIANS);
context.drawImage(image, -(image.width / 2), -(image.height / 2), image.width, image.height);
context.restore();
}
var myCompass = {};
function setupRose() {
myCompass.g_canvas = document.createElement('canvas');
myCompass.g_canvas.width = 200;
myCompass.g_canvas.height = 200;
m_context = myCompass.g_canvas.getContext('2d');
m_context.fillStyle = "rgb(0,0,0)";
m_context.font = '8pt Arial';
m_context.fillText('N', 102, 30);
m_context.fillText('E', 170, 110);
m_context.fillText('S', 92, 170);
m_context.fillText('W', 30, 96);
m_context.strokeStyle = "rgb(0,0,0)"; // schwarz
m_context.beginPath();
m_context.lineWidth = 2;
m_context.arc(100, 100, 95, 0, Math.PI * 2, true);
m_context.moveTo(105, 100);
m_context.lineTo(195, 100);
m_context.moveTo(100, 105);
m_context.lineTo(100, 195);
m_context.moveTo(95, 100);
m_context.lineTo(5, 100);
m_context.moveTo(100, 95);
m_context.lineTo(100, 5);
m_context.moveTo(105, 100);
m_context.arc(100, 100, 5, 0, Math.PI * 2, true);
m_context.closePath()
m_context.stroke();
m_context.beginPath();
m_context.lineWidth = 5;
if (32 >= 0 && 13 >= 1) {
m_context.arc(100, 100, 85, 0, Math.PI * 2, true);
m_context.arc(100, 100, 85, 0, (32 - 90) * (Math.PI / 180), true);
m_context.lineTo(100, 100);
}
if (13 <= 1) {
m_context.arc(100, 100, 2, 0, Math.PI * 2, true);
}
m_context.strokeStyle = "#00FF00"; //green
m_context.stroke();
}
function drawWindRose() {
var canvas = document.getElementById('windrose');
var bild = canvas.getContext('2d');
var frame = canvas.getContext('2d');
frame.fillStyle = "rgb(200,0,0)";
frame.fillRect(0, 0, 200, 200);
var deg = parseFloat(document.getElementById("degrees").value);
if (!deg) deg = 0;
drawRotatedImage(bild, myCompass.g_canvas, 100, 100, deg);
};
I'm trying to get up to speed on the canvas tag and I'm getting stuck when it comes to basic animations. I've searched around and I can get most of the tutorials I've found working, but I've had some trouble translating that into what I'm trying to do.
I have a bar graph that I'm building for my portfolio, and I would like to have the ability to animate the bars on the graph. Basically when the page loads, the bars start from the bottom of the graph, and grow upwards to where they need to be. I have a version I built in jquery found here to give an idea of what I'm after: http://jokedesigns.com/portfoliov6/
Could someone point me in the right direction on how to achieve the animations I'm looking for? Even if its a simple function I should be able to rework it into what I need. Most of the tutorials I've found mainly deal with rotation, I did find one that was a linear animation, but I still wasn't able to quite rework that into what I need.
Here is the code I have so far for the graph:
<html>
<head>
<script type="application/javascript">
function loadImages(sources, callback) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
function draw() {
var canvas = document.getElementById("canvas");
var canvasbg = document.getElementById("canvasbg");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
var ctx2 = canvasbg.getContext("2d");
var img = new Image();
img.onload = function(){
ctx2.drawImage(img,0,0);
};
img.src = 'skills_bg.jpg';
ctx.fillStyle = "#0a4888";
ctx.fillRect (0, 82, 34, 50);
ctx.fillStyle = "#ed9323";
ctx.fillRect (60, 82, 34, 50);
ctx.fillStyle = "#87982d";
ctx.fillRect (120, 82, 34, 50);
ctx.fillStyle = "#902e63";
ctx.fillRect (180, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (360, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (420, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (480, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (540, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (600, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (660, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (720, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (780, 82, 34, 50);
ctx.fillStyle = "#262627";
ctx.fillRect (840, 82, 34, 50);
var sources = {
ps: 'icn_ps.png',
ai: 'icn_ai.png',
dw: 'icn_dw.png',
id: 'icn_id.png',
ht: 'icn_html.png',
cs: 'icn_css.png',
js: 'icn_js.png',
sql: 'icn_mysql.png',
php: 'icn_php.png',
perl: 'icn_perl.png',
ruby: 'icn_ruby.png',
cplus: 'icn_cplusplus.png',
asp: 'icn_asp.png'
};
loadImages(sources, function(images) {
ctx.drawImage(images.ps, 0, 132, 36, 37);
ctx.drawImage(images.ai, 60, 132, 36, 37);
ctx.drawImage(images.dw, 120, 132, 36, 37);
ctx.drawImage(images.id, 180, 132, 36, 37);
ctx.drawImage(images.ht, 360, 132, 36, 37);
ctx.drawImage(images.cs, 420, 132, 36, 37);
ctx.drawImage(images.js, 480, 132, 36, 37);
ctx.drawImage(images.sql, 540, 132, 36, 37);
ctx.drawImage(images.php, 600, 132, 36, 37);
ctx.drawImage(images.perl, 660, 132, 36, 37);
ctx.drawImage(images.ruby, 720, 132, 36, 37);
ctx.drawImage(images.cplus, 780, 132, 36, 37);
ctx.drawImage(images.asp, 840, 132, 36, 37);
});
}
}
</script>
</head>
<body onload="draw();">
<canvas id="canvasbg" width="960" height="200" style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="canvas" width="960" height="200" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</body>
</html>
You can use requestAnimationFrame to create animation loops to allow your bars to grow
To create uniform growth for bars that are uneven height you can apply a percentage
// this will grow all bars at an even rate
bar1Height = bar1.maxHeight * percentComplete/100;
bar2Height = bar2.maxHeight * percentComplete/100;
percentComplete++;
Here's example code and a Demo: http://jsfiddle.net/m1erickson/YR4D7/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var skillBars=[];
skillBars.push({max:200,color:"red"});
skillBars.push({max:75,color:"green"});
skillBars.push({max:275,color:"blue"});
var chartBottomY=325;
var chartBarWidth=30;
var chartBarPadding=20;
var percent=0;
animate();
function animate() {
// if not 100% done, request another frame
if(percent++<100){
requestAnimationFrame(animate);
}
// Drawing code goes here
ctx.clearRect(0,0,canvas.width,canvas.height);
var x=chartBarPadding;
for(var i=0;i<skillBars.length;i++){
var height=skillBars[i].max*percent/100;
ctx.fillStyle=skillBars[i].color;
ctx.fillRect(x,chartBottomY,chartBarWidth,-height);
x+=chartBarWidth+chartBarPadding;
}
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>
I see a couple issues.
First, you draw everything at one time, whereas you should draw after each image is loaded, but yiu will want to use setTimeout or something similar to allow the canvas element to be drawn.
You should also have a method for the bar, and have it remember the current step value and it will just draw the next block.
I would put onload on the image tag, image.onload function with return, and when it loaded draw the next bar and load the next one.
But remember to use setTimeout to allow the drawing to take place.
Here are some links that may help
JavaScript animation with multiple setTimeout
https://developer.apple.com/library/safari/documentation/AudioVideo/Conceptual/HTML-canvas-guide/AnimatingtheCanvas/AnimatingtheCanvas.html