Rotating images in canvases - javascript

I'm trying to create some of rotating images. So I create an array of canvases and put in each picture. But for some reason they are not displayed. Help me please.
var canvas = [], ctx = [], particles = [];
for (var i = 0; i < 10; i++){
sym.$( sym.$("Rectangle") ).append('<canvas id="partical' + i + '"></canvas>');
canvas.push(document.getElementById("partical" + i));
canvas[i].width = 550;
canvas[i].height = 400;
ctx[i] = canvas[i].getContext("2d");
}
for(var i = 0; i < 10; i++){
particles.push({
x: Math.random()*canvas[i].width, //x-coordinate
y: Math.random()*canvas[i].height, //y-coordinate
img: new Image()
})
particles[i].img.src = "images/Flake" + Math.floor(Math.random()*4+1) + ".png";
}
function draw(){
for(var i = 1; i < 10; i++){
ctx[i].clearRect(0, 0, canvas[i].width, canvas[i].height);
var p = particles[i];
ctx[i].drawImage(p.img,p.x,p.y,50,50);
ctx[i].fill();
}
}
draw();

jsFiddle : https://jsfiddle.net/CanvasCode/u0p9wtut/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var Particle = function(xSet, ySet)
{
this.XPos = xSet;
this.YPos = ySet;
this.Sprite = new Image();
this.Sprite.src = "http://s.cdn.gaiaonline.com/images/thumbnails/85449184bbb9.png";
this.Rotation = 0;
}
var particles = new Array();
for(var i = 0; i < 10; i++){
particles.push(new Particle(Math.random()*c.width, Math.random()*c.height));
}
function draw()
{
ctx.fillStyle = "#000";
ctx.fillRect(0,0,c.width,c.height);
for(var i = 0; i < particles.length; i++)
{
var particle = particles[i];
particle.YPos += 1;
// Draw image rotated
ctx.save();
ctx.save();
ctx.translate(particle.XPos + particle.Sprite.width / 2, particle.YPos + particle.Sprite.height / 2);
ctx.rotate( particle.Rotation );
ctx.translate(-(particle.XPos + (particle.Sprite.width / 2)), -(particle.YPos));
ctx.drawImage(particle.Sprite, particle.XPos, particle.YPos);
ctx.restore();
ctx.restore();
if(particle.YPos > c.height)
{
particle.YPos = 0;
particle.XPos = Math.random()*c.width;
}
particle.Rotation += 0.01;
}
}
setInterval(draw, 3);
What you can do is use the ctx.save, ctx.restore and ctx.translate, you simply first save your canvas context so we can reload it later, we then translate the canvas, basically a translate is like setting an offset on where the image is drawn, we set the translate position to the center of the sprite, then we rotate the image around (the translate means we will rotate the image around its centre point). We then once again update the translate, draw the image rotated and then restore the canvas context because we may want to draw something else. If we don't restore the context then the next image that was draw would take into account the translate and rotate.

Related

Canvas not drawing after using

I have a function that, when called, clears the canvas.
function ClearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
The problem I'm having is that when I try to draw something onto the canvas again using fillRect() the items I want to draw appear on the bottom of the canvas, only a few of them showing up. The second time I try, nothing shows up.
To see my full code and a test run, go here
var width = 50;
var height = 50;
var interpolate = d3.interpolate('white', 'black');
var elevation = [];
var colormap = [];
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
var rectY = 0;
Generate2DArray(elevation, 0, width, height);
Generate2DArray(colormap, 0, width, height);
var gen = new SimplexNoise();
function Generate2DArray(EmptyArray, fill, width, height) {
for(var i = 0; i < height; i++) {
EmptyArray.push([]);
for(var j = 0; j < width; j++) {
EmptyArray[i][j] = fill;
}
}
}
function noise(nx, ny) {
// Rescale from -1.0:+1.0 to 0.0:1.0
return gen.noise2D(nx, ny) / 2 + 0.5;
}
function ClearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function GenTerrain() {
for(var y = 0; y < height; y++) {
for(var x = 0; x < width; x++) {
var nx = x/width - 0.5, ny = y/height - 0.5;
elevation[y][x] = noise(nx * 2.57, ny * 2.57);
colormap[y][x] = interpolate(elevation[y][x]);
ctx.fillStyle = colormap[y][x];
ctx.fillRect(x*10, y+rectY, 10, 10);
}
rectY += 9
}
}
Your rectY is being declared at the top of your code, at the global level:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
var rectY = 0;
So, every time GenTerrain runs, it references that variable and adds to it:
rectY += 9
Fix it by encapsulating rectY inside GenTerrain so it starts at 0 each time the function is called.
function GenTerrain() {
var rectY = 0;
for(var y = 0; y < height; y++) {
for(var x = 0; x < width; x++) {
var nx = x/width - 0.5, ny = y/height - 0.5;
elevation[y][x] = noise(nx * 2.57, ny * 2.57);
colormap[y][x] = interpolate(elevation[y][x]);
ctx.fillStyle = colormap[y][x];
ctx.fillRect(x*10, y+rectY, 10, 10);
}
rectY += 9
}
}

Canvas rotation - fixed background, moving foreground

Goal
The stripes in the background remain fixed while the cones rotate about the center.
Current State
live demo:
https://codepen.io/WallyNally/pen/yamGYB
/*
The loop function is around line 79.
Uncomment it to start the animation.
*/
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(-Math.PI/(180));
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
objects[i].update();
objects[i].draw();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
}
//loop();
What I have tried
The translate(W/2, H/2) should place the context at the center of the page, then this.ctx.rotate(-Math.PI/(180)) should rotate it one degree at a time. This is the part that is not working.
Using save()and restore() is the proper way to keep some parts of an animation static while others move. I placed the save and restore in different parts of the code to no avail. There are one of two types of result : Either a new entirely static image is produced, or some erratic animation happens (in the same vein of where it is now).
Here is the changed pen: http://codepen.io/samcarlinone/pen/LRwqNg
You needed a couple of changes:
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var angle = 0;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(angle);
this.ctx.translate(-W/2, -H/2);
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
ctx.save();
objects[i].update();
objects[i].draw();
ctx.restore();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
angle += Math.PI/360;
}
loop();
First I added a variable to keep track of rotation and increment it in the loop
Second I save and restore for each individual line, alternatively if all lines were going to perform the same transformation you could move that code before and after the drawing loop
Third to get the desired affect I translate so the center point is in the middle of the screen, then I rotate so that the lines are rotated, then I translate back because all the lines have coordinates on the interval [0, H]. Instead of translating back before drawing another option would be to use coordinates on the interval [-(H/2), (H/2)] etc.

HTML5 Canvas: Bouncing Balls with Image Overlay

I'm really struggling with a couple problems in the HTML5 canvas.
I've posted the project to GitHub pages (https://swedy13.github.io/) and added an image (the circles are in motion) so you can see the issue. Basically, if you scroll down you'll find several green circles bouncing around on the page. I'd like to replace those with my client logos.
I'm calling requestAnimation from three files based on different actions, all of which can be found in https://github.com/swedy13/swedy13.github.io/tree/master/assets/js
Filenames:
- filters.js (calls requestAnimation when you use the filters)
- main.js (on load and resize)
- portfolio.js (this is where the canvas code is)
Update: I've added the "portfolio.js" code below so the answer can be self-contained.
function runAnimation(width, height, type){
var canvas = document.getElementsByTagName('canvas')[0];
var c = canvas.getContext('2d');
// ---- DIMENSIONS ---- //
// Container
var x = width;
var y = height - 65;
canvas.width = x;
canvas.height = y;
var container = {x: 0 ,y: 0 ,width: x, height: y};
// Portrait Variables
var cPos = 200;
var cMargin = 70;
var cSpeed = 3;
var r = x*.075;
if (y > x && x >= 500) {
cPos = x * (x / y) - 150;
cMargin = 150;
}
// Landscape Variables
if (x > y) {
cPos = y * (y / x) - 50;
cMargin = 150;
cSpeed = 3;
r = x*.05;
}
// ---- CIRCLES ---- //
// Circles
var circles = [];
var img = new Image();
// Gets active post ids and count
var activeName = [];
var activeLogo = [];
var activePosts = $('.active').map(function() {
activeName.push($(this).text().replace(/\s+/g, '-').toLowerCase());
// Returns the image source
/*activeLogo.push($(this).find('img').prop('src'));*/
// Returns an image node
var elem = document.getElementsByClassName($(this).text().replace(/\s+/g, '-').toLowerCase())
activeLogo.push(elem[0].childNodes[0]);
});
// Populates circle data
for (var i = 0; i < $('.active').length; i++) {
circles.push({
id:activeName[i],
r:r,
color: 100,
/*image: activeLogo[i],*/
x:Math.random() * cPos + cMargin,
y:Math.random() * cPos + cMargin,
vx:Math.random() * cSpeed + .25,
vy:Math.random() * cSpeed + .25
});
}
// ---- DRAW ---- //
requestAnimationFrame(draw);
function draw(){
c.fillStyle = 'white';
c.fillRect(container.x, container.y, container.width, container.height);
for (var i = 0; i < circles.length; i++){
/*var img = new Image();
var path = circles[i].image;*/
/*var size = circles[i].r * 2;*/
/*img.src = circles[4].image;*/
var img = activeLogo[i];
img.onload = function (circles) {
/*c.drawImage(img, 0, 0, size, size);*/
var pattern = c.createPattern(this, "repeat");
c.fillStyle = pattern;
c.fill();
};
c.fillStyle = 'hsl(' + circles[i].color + ', 100%, 50%)';
c.beginPath();
c.arc(circles[i].x, circles[i].y, circles[i].r, 0, 2*Math.PI, false);
c.fill();
// If the circle size/position is greater than the canvas width, bounce x
if ((circles[i].x + circles[i].vx + circles[i].r > container.width) || (circles[i].x - circles[i].r + circles[i].vx < container.x)) {
circles[i].vx = -circles[i].vx;
}
// If the circle size/position is greater than the canvas width, bounce y
if ((circles[i].y + circles[i].vy + circles[i].r > container.height) || (circles[i].y - circles[i].r + circles[i].vy < container.y)){
circles[i].vy = -circles[i].vy;
}
// Generates circle motion by adding position and velocity each frame
circles[i].x += circles[i].vx;
circles[i].y += circles[i].vy;
}
requestAnimationFrame(draw);
}
}
The way it works right now is:
1. I have my portfolio content set to "display: none" (eventually it will be a pop-up when they click on one of the circles).
2. The canvas is getting the portfolio objects from the DOM, including the image that I can't get to work.
3. If I use the "onload()" function, I can get the images to show up and repeat in the background. But it's just a static background - the circles are moving above it and revealing the background. That isn't what I want.
So basically, I'm trying to figure out how to attach the background image to the circle (based on the circle ID).
----------------- UPDATE -----------------
I can now clip the image to a circle and get the circle to move in the background. But it isn't visible on the page (I can tell it's moving by console logging it's position). The only time I see anything is when the circle lines up with the images position, then it shows.
function runAnimation(width, height, type){
var canvas = document.getElementsByTagName('canvas')[0];
var c = canvas.getContext("2d");
canvas.width = width;
canvas.height = height;
// Collects portfolio information from the DOM
var activeName = [];
var activeLogo = [];
$('.active').map(function() {
var text = $(this).text().replace(/\s+/g, '-').toLowerCase();
var elem = document.getElementsByClassName(text);
activeName.push(text);
activeLogo.push(elem[0].childNodes[0]);
});
var img = new Image();
img.onload = start;
var circles = [];
var cPos = 200;
var cMargin = 70;
var cSpeed = 3;
for (var i = 0; i < 1; i++) {
circles.push({
id: activeName[i],
img: activeLogo[i],
size: 50,
xPos: Math.random() * cPos + cMargin,
yPos: Math.random() * cPos + cMargin,
xVel: Math.random() * cSpeed + .25,
yVel: Math.random() * cSpeed + .25,
});
img.src = circles[i].img;
}
requestAnimationFrame(start);
function start(){
for (var i = 0; i < circles.length; i++) {
var circle = createImageInCircle(circles[i].img, circles[i].size, circles[i].xPos, circles[i].yPos);
c.drawImage(circle, circles[i].size, circles[i].size);
animateCircle(circles[i]);
}
requestAnimationFrame(start);
}
function createImageInCircle(img, radius, x, y){
var canvas2 = document.createElement('canvas');
var c2 = canvas2.getContext('2d');
canvas2.width = canvas2.height = radius*2;
c2.fillStyle = 'white';
c2.beginPath();
c2.arc(x, y, radius, 0, Math.PI*2);
c2.fill();
c2.globalCompositeOperation = 'source-atop';
c2.drawImage(img, 0, 0, 100, 100);
return(canvas2);
}
function animateCircle(circle) {
// If the circle size/position is greater than the canvas width, bounce x
if ((circle.xPos + circle.xVel + circle.size > canvas.width) || (circle.xPos - circle.size + circle.xVel < 0)) {
console.log('Bounce X');
circle.xVel = -circle.xVel;
}
// If the circle size/position is greater than the canvas width, bounce y
if ((circle.yPos + circle.yVel + circle.size > canvas.height) || (circle.yPos + circle.yVel - circle.size < 0)) {
console.log('Bounce Y');
circle.yVel = -circle.yVel;
}
// Generates circle motion by adding position and velocity each frame
circle.xPos += circle.xVel;
circle.yPos += circle.yVel;
}
}
I'm not sure if I'm animating the correct thing. I've tried animating canvas2, but that didn't make sense to me.
PS - Sorry for the GitHub formatting, not sure why it looks like that.
PPS - Apologies for any junk code I didn't clean up. I've tried a lot of stuff and probably lost track of some of the changes.
PPPS - And forgive me for not making the answer self-contained. I thought linking to GitHub would be more useful, but I've updated the question to contain all the necessary info. Thanks for the feedback.
To get you started...
Here's how to clip an image into a circle using compositing.
The example code creates a single canvas logo-ball that you can reuse for each of your bouncing balls.
var logoball1=dreateImageInCircle(logoImg1,50);
var logoball2=dreateImageInCircle(logoImg2,50);
Then you can draw each logo-ball onto your main canvas like this:
ctx.drawImage(logoball1,35,40);
ctx.drawImage(logoball2,100,75);
There are many examples here on Stackoverflow of how to animate the balls around the canvas so I leave that part to you.
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var img=new Image();
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/m%26m600x455.jpg";
function start(){
var copy=createImageInCircle(img,50);
ctx.drawImage(copy,20,75);
ctx.drawImage(copy,150,120);
ctx.drawImage(copy,280,75);
}
function createImageInCircle(img,radius){
var c=document.createElement('canvas');
var cctx=c.getContext('2d');
c.width=c.height=radius*2;
cctx.beginPath();
cctx.arc(radius,radius,radius,0,Math.PI*2);
cctx.fill();
cctx.globalCompositeOperation='source-atop';
cctx.drawImage(img,radius-img.width/2,radius-img.height/2);
return(c);
}
body{ background-color:white; }
#canvas{border:1px solid red; }
<canvas id="canvas" width=512 height=512></canvas>

How to optimize canvas rendering for dynamic loading HTML5 game world?

I've been working on an isometric game engine for my own game. Currently, it's a big, open world with the map data being retrieved dynamically from the Node.js server. 
To understand what I'm doing... for the most part it's a tile based world. So each map has a max number of cols,rows (19) and each world has a max number of maps by col,row (6). So it's a 6x6 world map consisting of 19x19 tiles per map. Whenever the players move onto a new map/region, the client requests a 3x3 matrix of the surrounding maps with the center map being the map the player is currently on. This part is pretty well optimized.
My problem, however, is finding a great way to optimize the drawing onto the canvas. Currently, I don't have a lot of lag doing so, but I also have a fast computer, but I worry that at times it could cause others to lag / mess with the rendering of other graphics.
Basically, how I have it working right now is when the data is sent back from the server, it adds each map and all the tile images for each col/row it has to render into a buffer. Each loop of the game loop, it will basically render a small section of the 25 tiles onto the specific map's hidden canvas. When all of the requested maps are done rendering (after a few game loops), the camera will go ahead and merge these hidden maps into 1 big map canvas of the 3x3 matrix (by slicing parts from the hidden canvases and merging them onto the new canvas).
Ideally I would love this whole process to be async. but I've been looking into web workers and apparently they do not support canvas well. Has anyone come up with a process to do something similar and keep it well optimized?
Thanks!
Here's an example of rendering a 19x19 grid in each frame. A new random tile is added from right to left top to bottom in each frame. The grid is rendered in the same order and you can see that this works for overlapping tiles.
I think it's best to save each tile and make a function that renders the entire grid. So if the player gets updates in the 3x3 surrounding area then download and keep those tiles and re-render the entire grid.
update
I provided a function to eliminate overdraw and a toggle. This may increase performance for some people. It draws from bottom to top left to right. This draws the overlaying items first and with globalCompositeOperation "distination-over" tells the canvas to leave existing pixels alone when adding new content. This should mean less work to do in putting pixels on the canvas as it's not drawing over unused pixels.
var cols = 19;
var tile_width = 32;
var rows = 19;
var tile_height = 16;
var y_offset = 64;
var h_tw = tile_width / 2;
var h_th = tile_height / 2;
var frames = 0;
var fps = "- fps";
setInterval(function(){
fps = frames + " fps";
frames = 0;
}, 1000);
var can = document.getElementById('tile');
var ctx = can.getContext('2d');
var wcan = document.getElementById('world');
var wctx = wcan.getContext('2d');
wcan.width = cols * tile_width;
wcan.height = rows * tile_height + y_offset;
var tiles = initTiles();
document.getElementById('toggle').addEventListener('click', function() {
if (this.innerHTML == 'renderWorld') {
renderFn = renderWorldNoOverdraw;
this.innerHTML = "renderWorldNoOverdraw";
} else {
renderFn = renderWorld;
this.innerHTML = "renderWorld";
}
});
//renderWorld();
var ani_x = cols;
var ani_y = 0;
var renderFn = renderWorld;
ani();
function initTiles () {
var tiles = [];
for (var y = 0; y < rows; y++) {
var row = [];
for (var x = 0; x < cols; x++) {
var can = document.createElement('canvas');
can.width=tile_width;
can.height=tile_height+y_offset;
row[x]=can;
}
tiles[y] = row;
}
return tiles;
}
function ani() {
var can = tiles[ani_y][--ani_x]
if (ani_x == 0) ani_x = cols, ani_y++;
ani_y %= rows;
var ctx = can.getContext('2d');
randTile(can, ctx);
renderFn();
requestAnimationFrame(ani);
}
// renders from bottom left to right and skips
// drawing over pixels already present.
function renderWorldNoOverdraw() {
frames++;
wctx.clearRect(0,0,wcan.width,wcan.height);
wctx.save();
wctx.globalCompositeOperation = "destination-over";
wctx.translate(0, y_offset);
var x_off = 0;
var y_off = 0;
var y_off2 = 0;
for (var y = rows; y--;) {
x_off = (cols * h_tw)- ((rows-y) * h_tw);
y_off = y * h_th + tile_height;
y_off2 = y_off;
for (var x = 0; x < cols; x++) {
var can = tiles[y][x];
wctx.drawImage(can, x_off, y_off2 + y_offset);
y_off2 -= h_th;
x_off += h_tw;
}
}
wctx.translate(0,-y_offset);
wctx.fillStyle = "#ddaadd";
wctx.fillRect(0,0,wcan.width, wcan.height);
wctx.restore();
wctx.fillStyle= "black";
wctx.fillText(fps, 10, 10);
}
function renderWorld() {
frames++;
wctx.fillStyle = "#CCEEFF";
wctx.fillRect(0, 0, wcan.width, wcan.height);
wctx.save();
wctx.translate(0, y_offset);
var x_off = 0;
var y_off = 0;
var y_off2 = 0;
for (var y = 0; y < rows; y++) {
x_off = (cols * h_tw) + (y * h_tw) - h_tw;
y_off = y * h_th;
y_off2 = y_off;
for (var x = cols; x--;) {
var can = tiles[y][x];
wctx.drawImage(can, x_off, y_off2 - 64);
y_off2 += h_th;
x_off -= h_tw;
}
y_off += h_th;
x_off -= h_tw;
}
wctx.restore();
wctx.fillStyle= "black";
wctx.fillText(fps, 10, 10);
}
function randTile(can, ctx) {
var maxH = can.height - 24;
var ranH = Math.floor(Math.random() * maxH);
var h = Math.max(ranH, 1);
ctx.clearRect(0, 0, can.width, can.height);
ctx.beginPath();
ctx.save();
ctx.translate(0, can.height - 16);
ctx.moveTo(0, 8);
ctx.lineTo(16, 0);
ctx.lineTo(32, 8);
ctx.lineTo(16, 16);
ctx.lineTo(0, 8);
ctx.strokeStyle = "#333333";
ctx.stroke();
// random floor color
var colors = ["#dd9933", "#22aa00", "#66cccc", "#996600"];
ctx.fillStyle = colors[Math.floor(Math.random() * 4)];
ctx.fill();
// random building
if (Math.floor(Math.random() * 8) == 0) {
ctx.beginPath();
ctx.moveTo(8, 8);
ctx.lineTo(8, -h - 4);
ctx.lineTo(16, -h);
ctx.lineTo(16, 12);
ctx.lineTo(8, 8);
ctx.stroke();
ctx.fillStyle = "#333333";
ctx.fill();
ctx.beginPath();
ctx.moveTo(16, 12);
ctx.lineTo(16, -h);
ctx.lineTo(24, -h - 4);
ctx.lineTo(24, 8);
ctx.lineTo(16, 12);
ctx.stroke();
ctx.fillStyle = "#999999";
ctx.fill()
ctx.beginPath();
ctx.moveTo(16, -h);
ctx.lineTo(24, -h - 4);
ctx.lineTo(16, -h - 8);
ctx.lineTo(8, -h - 4);
ctx.moveTo(16, -h);
ctx.stroke();
ctx.fillStyle = "#CCCCCC";
ctx.fill()
}
ctx.restore();
}
body {
background-color: #444444;
}
<button id="toggle">renderWorld</button><br/>
<canvas id='tile' width="32" height="32" style="display:none"></canvas>
<canvas id="world" width="608" height="368">
</canvas>

img src doesn't work when I use local files

I've had problems with getting a rain effekt on my canvas. After some searching on google I found this
<script type="text/javascript">
var ctx;
var imgBg;
var imgDrops;
var x = 0;
var y = 0;
var noOfDrops = 50;
var fallingDrops = [];
function setup() {
var canvas = document.getElementById('canvasRegn');
if (canvas.getContext) {
ctx = canvas.getContext('2d');
imgBg = new Image();
imgBg.src = "http://lorempixel.com/600/600/sports/";
setInterval(draw, 36);
for (var i = 0; i < noOfDrops; i++) {
var fallingDr = new Object();
fallingDr["image"] = new Image();
fallingDr.image.src = "http://lorempixel.com/10/10/sports/";
fallingDr["x"] = Math.random() * 600;
fallingDr["y"] = Math.random() * 5;
fallingDr["speed"] = 3 + Math.random() * 5;
fallingDrops.push(fallingDr);
}
}
}
function draw() {
drawBackground();
for (var i=0; i< noOfDrops; i++)
{
ctx.drawImage (fallingDrops[i].image, fallingDrops[i].x, fallingDrops[i].y); //The rain drop
fallingDrops[i].y += fallingDrops[i].speed; //Set the falling speed
if (fallingDrops[i].y > 450) { //Repeat the raindrop when it falls out of view
fallingDrops[i].y = -25 //Account for the image size
fallingDrops[i].x = Math.random() * 600; //Make it appear randomly along the width
}
}
}
function drawBackground(){
ctx.drawImage(imgBg, 0, 0); //Background
}
</script>
The strange thing is that the code works as long as I don't change the image source from the link to my png-files. All I get is copies of my file drawn over and over again til the canvas's is full of lines.
Help please!
It seems that for some reason your background is not rendered.
If you don't want to have any background, you have to clear the canvas before drawing drops at their new positions, or else your canvas will flood :)
Replace: ctx.drawImage(imgBg, 0, 0);
with: clearRect(0, 0, width, height)
See, also, this short demo.

Categories

Resources