I am trying to make my image follow my mouse. I have used a lecture guide from university to create this code, and it seems identical to all the code I've seen, but I get the error in Chrome developer tools:
Uncaught TypeError: thisCanvas.addEventListener is not a function
Any ideas? I've stared at this for hours now.
<!DOCTYPE html>
<html>
<head>
<title> Gravity Game </title>
<meta charset = "UTF-8">
<link type = "text/css" rel = "stylesheet" href = "style.css">
</head>
<body onLoad="start_game()">
<header>
<h1 id = "title1"> Gravity </h1> <h1 id = "title2"> Game </h1>
</header>
<ul id = "nav">
<li class = "inactive"> About </li>
<li id = "active"> Play Game </li>
</ul>
<canvas id = "myCanvas" width = "1500" height = "500"></canvas>
<script>
var thisCanvas = document.getElementById("myCanvas").style.background = 'white';
var context = myCanvas.getContext("2d");
var worldX = 100;
var worldY = 100;
//Draw a circle
/*context.beginPath();
context.arc(95, 50, 40, 0, 2 * Math.PI);
context.closePath();
context.fill();*/
thisCanvas.addEventListener("mousemove",seen_move,false);
function seen_move(e)
{
var bounding_box = thisCanvas.getBoundingClientRect();
worldX = (e.clientX-bounding_box.left) * (thisCanvas.width/bounding_box.width);
worldY = (e.clientY-bounding_box.top) * (thisCanvas.height/bounding_box.height);
}
function start_game()
{
setInterval(loop_game, 50);
}
function loop_game()
{
thisCanvas.width = thisCanvas.width;
update_world(worldX, worldY);
}
function update_world(x, y)
{
var world_img = new Image();
world_img.src = "images/world.png";
context.drawImage(world_img, x, y);
}
</script>
</body>
</html>
var thisCanvas = document.getElementById("myCanvas").style.background = 'white';
thisCanvas now has the string value white.
thisCanvas.addEventListener() is basically like saying 'white'.addEventListener(). Because there’s no String.prototype.addEventListener this won’t work.
You need to assign document.getElementById("myCanvas") to thisCanvas and then set its background color.
var thisCanvas = document.getElementById("myCanvas").style.background = 'white';
should be
var thisCanvas = document.getElementById("myCanvas")
You are trying to assign your canvas style-changing methods as variable thisCanvas, instead of assigning the canvas element itself
The problem is with:
var thisCanvas = document.getElementById("myCanvas").style.background = 'white';
thisCanvas does not hold a reference to the <canvas> element. Instead, it's bound to 'white' because of a chained assignment.
You probably want something like:
var thisCanvas = document.getElementById("myCanvas");
thisCanvas.style.background = 'white';
Related
I am trying to build a webpage that will allow a user to display a dungeon map from images stored in an array (directly or by reference) to a block. Suffice to say I am not having a lot of luck and I have researched until I am blue in the face. Can someone please let me know what I'm doing wrong...
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dungeons and Dragons 3.5 Map Generator</title>
<script src="GenerateMaps.js"></script>
<link rel='stylesheet'>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body onload="runExperiments();">
<div id="row">
<div class="page_items" id="map">
<script>
window.onload=function() {
let c = document.getElementById("map");
let ctx = c.getContext("2d");
let x;
let y;
c.width = (window.innerWidth / 2)-(window.innerWidth % 30);
c.height = (window.innerHeight)-(window.innerHeight % 30);
ctx.width = c.width - 30;
ctx.height = c.width - 30;
let elem = document.createElement("image");
elem.setAttribute("src", "floor.png");
elem.setAttribute("height", "30");
elem.setAttribute("width", "30");
elem.setAttribute("src", "floor.png");
for (x = 30; x < ctx.height; x += 30) {
for (y = 30; y < ctx.width; y += 30) {
c.appendChild(elem);
}
}
}
</script>
</div>
</div>
</body>
You might have other problems, but the immediate one is highlighted if you look at the Console of the developer tools in your browser.
Uncaught TypeError: c.getContext is not a function
at window.onload
getContext is a function found on canvas elements but you are trying to call it on a div.
I've been knocking my head against the keyboard trying to figure out why the animation from this tutorial is not showing up on the canvas correctly, if at all. In chrome it draws the leftmost part of the image on the canvas, but in safari it draws nothing at all.
I've tried different methods of delaying until the image loads, putting the script tag in various places in the html, no luck. Debugging in chrome shows no errors.
The source code for the animation is not quite the same as what he presents in the tutorial, I've tried to make sense of it. I've been at it for two days and you'll pinpoint it 30 seconds, I want to see this damn coin spin.
spriteSheet.jpg:
animation.html:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<link href='http://fonts.googleapis.com/css?family=Ubuntu' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="style.css" type="text/css" />
<title>Test Profile Page</title>
</head>
<body>
<header>
<h1>Hello</h1>
</header>
<nav>
<ul>
<li>Pictures</li>
<li>Animation?</li>
<li>Cartoon</li>
</ul>
</nav>
<section>
<img src="spriteSheet.jpg" />
<canvas id="coinAnimation"></canvas>
</section>
<footer>
</footer>
<script src="animation.js"></script>
</body>
</html>
animation.js:
window.onload = function () {
var spriteSheet = new Image();
spriteSheet.src = "spriteSheet.jpg";
//define sprite class
function sprite (options) {
var that = {},
frameIndex = 0,
tickCount = 0,
ticksPerFrame = options.ticksPerFrame || 0,
numberOfFrames = options.numberOfFrames || 1;
that.context = options.context;
that.width = options.width;
that.height = options.height;
that.image = options.image;
that.loop = options.loop;
that.update = function () {
tickCount += 1;
if (tickCount > ticksPerFrame) {
tickCount = 0;
// If the current frame index is in range
if (frameIndex < numberOfFrames - 1) {
// Go to the next frame
frameIndex += 1;
} else if (that.loop) {
frameIndex = 0;
}
}
};
that.render = function () {
// Clear the canvas
that.context.clearRect(0, 0, that.width, that.height);
// Draw the animation
that.context.drawImage(
that.image,
frameIndex * that.width / numberOfFrames,
0,
that.width / numberOfFrames,
that.height,
0,
0,
that.width / numberOfFrames,
that.height);
};
return that;
}
var canvas = document.getElementById("coinAnimation");
canvas.width = 100;
canvas.height = 100;
var coin = new sprite({
context: canvas.getContext("2d"),
width: 100,
height: 100,
image: spriteSheet
});
function gameLoop () {
window.requestAnimationFrame(gameLoop);
coin.update();
coin.render();
}
spriteSheet.addEventListener("load", gameLoop);
}
When you enter the width on your coin you need to enter the width of your entire image (which seems to be 440), not the width of a single frame. Along with that you need to set the numberOfFrames to 10:
var coin = new sprite({
context: canvas.getContext("2d"),
width: 440,
height: 100,
image: spriteSheet,
numberOfFrames: 10
});
Note when it find the width of a single frame it does width/numberOfFrames to find that, this is why it will not work if you just enter 100. Now your coin should be spinning.
Fiddle Example.
If you want the slow the coin down you can add ticksPerFrame: 5 for example, the higher that is the slower it will go.
I am having trouble adding boxes dynamically to an HTML canvas. There should be a random amount of boxes, in random positions, of random colors.
The goal of what I am doing with the boxes is to be able to move them.
Essentially I am really lost.
Here is the html code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Ramdom Boxes</title>
<script src="A2Q1.js"></script>
</head>
<body>
</body>
</html>
Here is the Javascript code:
window.onload = init;
function init() {
//when page is loaded create a bunch of boxes randomly throughout the page
//get the body element of the document
var body = document.getElementsByTagName("body")[0];
//create the canvas tag
var canvas = document.createElement("canvas");
canvas.height = 666;
canvas.width = 1346;
var context = canvas.getContext("2d");
//create the random boxes and append onto the canvas
var randNum = Math.floor(Math.random() * 1000 + 1);
var boxes = [];
for(var i=0;i<randNum;i++){
boxes[i].height = 50;
boxes[i].width = 50;
boxes[i].x = Math.floor(Math.random() * (1346 - boxes[i].width));
boxes[i].y = Math.floor(Math.random() * (666 - boxes[i].height));
boxes[i].colour = '#'+ Math.round(0xffffff * Math.random()).toString(16);
}
for(var i=0;i<boxes.length;i++){
context.fillStyle = colour;
context.fillRect(boxes[i].x, boxes[i].y, , boxes[i].height);
}
//append the canvas onto the body
body.appendChild(canvas);
}
Nothing is showing up on the page, through debugging it seems it is having issues with the properties. I am not sure where to go from here.
You can use masonry jquery plugin to sort boxes.
context.fillStyle = colour;
Did you mean
context.fillStyle = boxes[i].colour;
I want to get the color of a pixel from image with using pure JavaScript.
I wrote this script, but it did not work:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);}
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
How to change the code, what would he worked correctly?
For example for the picture "http://i.imgur.com/hvGAPwJ.png", the result should be RGB = 255, 255, 255.
Your code is almost (see below) correct in its self BUT unfortunately when you use images from other origins than the page itself certain criteria must be there for it to work due to CORS (security feature).
You cannot use images from other origins out of the box. The server they are on need to have accept-* header set to allow this.
If not your getImageData and toDataURL will be blank (throws a security error that you can see in the console).
If you don't have access to modify the server the only way to get around this is to use your own server as a image proxy (http://myServer/getImage.cgi|php|aspx...?http/otherServer/img)
As pointed on in comments always set src after onload so you are sure onload gets initialized.
var pic = new Image();
pic.onload = function() { /* funky stuff here */ };
pic.src = 'http://i.imgur.com/hvGAPwJ.png'; //Last
If you indent your script properly, the error becomes more apparent:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);
}
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
You are setting a function on the image's load event, but not waiting for it to happen before you update the contents of the div.
You should move everything inside the pic.onload function, apart from setting the pic.src:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Get Pixel</title>
<script type='text/javascript'>
window.onload = function() {
var canvas = document.createElement("canvas");
var pic = new Image();
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(pic, 0, 0);
var c = canvas.getContext('2d');
var p = c.getImageData(7, 7, 1, 1).data;
var hex = "RGB = " + p[0]+", "+p[1]+", "+p[2];
document.getElementById("output").innerHTML = hex;
}
pic.src = 'http://i.imgur.com/hvGAPwJ.png';
}
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
Now the problem is just cross origin restrictions.
To solve cross origins restrictions, you may add this line:
pic.crossOrigin = "Anonymous";
Right after defining pic var.
May not work in some cases though.
I'm trying to work with a texture atlas and the canvas tag to do some animation. I don't get any errors but all I am seeing is the last frame. Is there something I should be doing so I see all the "frames"?
I have tested this with hard coding the x/y coordinates on the texture atlas so I know I can cruise around it.
Here's my code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en">
<head>
<meta charset="utf-8">
<title>Canvas Animation</title>
<!-- meta tags -->
<meta name="keywords" content="">
<meta name="description" content="">
<!-- javascript -->
<script language="javascript">
var textureAtlas = new Image();
var moeImg = new Image();
function init() {
animateProps = new Array;
textureAtlas.src = "images/textureatlast1.png";
moeImg.src = "images/moe.jpg";
var textureAtlasCoords = new Array("0,0", "100,0", "200,0", "300,0", "400,0", "500,0", "600,0");
for(var c=0; c<textureAtlasCoords.length; c++) {
animateObj = new Object();
var thisCoord = textureAtlasCoords[c];
var thisCoordSplit = thisCoord.split(",");
var thisX = thisCoordSplit[0];
var thisY = thisCoordSplit[1];
//var a = setTimeout(Function(){animate(ctx, textureAtlas, thisX, thisY)},1000);
animateObj['canvasId'] = "princessAnimation";
animateObj['imgsrc'] = textureAtlas;
animateObj['x'] = thisX;
animateObj['y'] = thisY;
animateProps.push(animateObj);
var a = setInterval(function(){animate(animateProps);},1000);
}
clearInterval(a);
}
function imgDraw(ctx, thisImg) {
console.log(thisImg);
//(image, x(
ctx.drawImage(thisImg,0,0, 1024, 451, 0, 0, 1024, 451);
}
function animate() {
//get animation properties
for(thisProp in animateProps) {
var canvasId = animateProps[thisProp]['canvasId'];
var thisImg = animateProps[thisProp]['imgsrc'];
var thisX = animateProps[thisProp]['x'];
var thisY = animateProps[thisProp]['y'];
}
var canvas = document.getElementById(canvasId);
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,1024,451);
ctx.drawImage(thisImg,thisX,thisY, 1024, 451, 0, 0, 1024, 451);
}
}
</script>
<!-- stylesheets -->
<!--conditional comments -->
</head>
<body onload="init();">
<div id="animationWrapper">
<canvas width="100" height="150" id="princessAnimation"></canvas>
</div>
</body>
</html>
Here's the image I am working with (Note: I know my coordinates are off per the file, right now I am just trying to get the transition to work, I'll then fine tune the x/y coordinates (of course unless you want to do that for me. : D )
It's the interval. You're setting them all before animate is ever fired, overwriting the previous interval. So you just keep printing out the 0,600 coordinate. It's not the only thing wrong from what I can see, but it's the reason you're only getting the last image.
Push each coordinate, then use the interval to loop through the animations. Don't set the interval until all of them are pushed, then use a global to count the steps, increment on animation (upon redrawing to the canvas).
For example (simplified, and this may need some work to get working the way you want):
var textureAtlas = new Image(),
steps = 0, maxsteps = 0;
//var moeImg = new Image();
var a;
function init() {
animateProps = new Array;
textureAtlas.src = "textureatlas1.png";
//moeImg.src = "images/moe.jpg";
var textureAtlasCoords = new Array("0,0", "100,0", "200,0", "300,0", "400,0", "500,0", "600,0");
maxsteps = textureAtlasCoords.length;
for(var c=0; c<textureAtlasCoords.length; c++) {
animateObj = new Object();
var thisCoord = textureAtlasCoords[c];
var thisCoordSplit = thisCoord.split(",");
var thisX = thisCoordSplit[0];
var thisY = thisCoordSplit[1];
//var a = setTimeout(Function(){animate(ctx, textureAtlas, thisX, thisY)},1000);
animateObj['canvasId'] = "princessAnimation";
animateObj['imgsrc'] = textureAtlas;
animateObj['x'] = thisX;
animateObj['y'] = thisY;
animateProps.push(animateObj);
}
a = setInterval(function(){animate(animateProps);},1000);
}
function animate() {
if(steps>=maxsteps) steps =0;
//get animation properties
var canvasId = animateProps[steps]['canvasId'];
var thisImg = animateProps[setps]['imgsrc'];
var thisX = animateProps[steps]['x'];
var thisY = animateProps[steps]['y'];
var canvas = document.getElementById(canvasId);
if (canvas.getContext){
var ctx = canvas.getContext('2d');
ctx.clearRect(0,0,1024,451);
console.log(thisX+" "+thisY);
ctx.drawImage(thisImg,thisX,thisY, 1024, 451, 0, 0, 1024, 451);
}
steps++;
}
I'm also not so sure on ctx.drawImage(thisImg,thisX,thisY, 1024, 451, 0, 0, 1024, 451);... I feel like you're not binding the image to the right parameters. Remember that ctx.drawImage is
img, sx, sy, sw, sh, dx, dy, dw, dh for the args.
img - the image.
sx, sy, sw, sh - clip to the rectangle defined by this.
dw, dh - scale to these dimensions
dx, dy - position here.
Hope that helps some.