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.
Related
I'm trying to create a wobbly circle with multiple ellipses in the background, however I can't add the for loop to the draw function otherwise it will be running in every frame, and if I add it to setup then the wobbly circle leaves a trace. And if I use clear() then it removes my background. How can I solve this, please?
function setup() {
createCanvas(600, 600);
for (var i = 0; i < 1000; i++){
fill(255);
ellipse(random(0, width), random(0, width), random(5, 5), random(5, 5));
}
x = width/2; // Circle center x
y = height/2; // Circle center y
r = 100; // Circle radius
verts = 200; // Number of vertices for drawing the circle
wobbleSlider = createSlider(0, 200, 100, 1); // How much the circle radius can vary
smthSlider = createSlider(1, 500, 70, 1); // How smooth the noise function is (higher is smoother)
t = 1;
}
function draw() {
let wobble = wobbleSlider.value()
let smth = smthSlider.value();
//clear();
t += 0.01
beginShape()
for(let i = 0; i < verts; i++){
let f = noise(50*cos(i/verts*2*PI)/smth + t, 50*sin(i/verts*2*PI)/smth + t)
vertex(x + (r+wobble*f) * cos( (i/verts) * 2 * PI ), y + (r+wobble*f) * sin( (i/verts) * 2 * PI ) )
}
endShape(CLOSE)
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
enter image description here
What you want is some sort of layering system that allows you to have a fixed background and draw over it things that chage. You can achieve this with graphics. It basically allows you to create an independent "canvas" and draw over it, then you can render it like an image in your animation.
First you use createGraphics which is similar to createCanvas with the difference that you can store the result in a variable like: let myGraphics = createGraphics(600,600). Then you draw over it like in your canvas. For example ellipse(...) becomes myGraphics.ellipse(...). Then you can render it using image like image(myGraphics, 0, 0).
See the working code below
If this answers your question dont forget to mark it as the answer using the green check at the left of the answer so others can reference from it in the future :)
let background;
function setup() {
createCanvas(600, 600);
background = createGraphics(600, 400);
for (var i = 0; i < 1000; i++){
background.fill(255);
background.ellipse(random(0, width), random(0, width), random(5, 5), random(5, 5));
}
x = width/2; // Circle center x
y = height/2; // Circle center y
r = 100; // Circle radius
verts = 200; // Number of vertices for drawing the circle
wobbleSlider = createSlider(0, 200, 100, 1); // How much the circle radius can vary
smthSlider = createSlider(1, 500, 70, 1); // How smooth the noise function is (higher is smoother)
t = 1;
}
function draw() {
clear();
image(background,0,0);
let wobble = wobbleSlider.value()
let smth = smthSlider.value();
//clear();
t += 0.01
beginShape()
for(let i = 0; i < verts; i++){
let f = noise(50*cos(i/verts*2*PI)/smth + t, 50*sin(i/verts*2*PI)/smth + t)
vertex(x + (r+wobble*f) * cos( (i/verts) * 2 * PI ), y + (r+wobble*f) * sin( (i/verts) * 2 * PI ) )
}
endShape(CLOSE)
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<!DOCTYPE html>
<html lang="en">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
I have an image (well data) that is m = 3600 n = 512. It has to stay like this. The data really starts as an array but is then broken down into m,n chunks. I would like to change the aspect ratio in canvas. If I change canvas.width, it gives me more available space that I don't use. If I change canvas.style.width, it increases both height and width.
I want the image to be wider while keeping its same length.
<!doctype html>
<html class="no-js" lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Font Awesome -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.css"
rel="stylesheet"
/>
<!-- Google Fonts -->
<link
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
rel="stylesheet"
/>
<!-- MDB -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.11.0/mdb.min.css"
rel="stylesheet"
/>
<!-- MDB -->
<script
type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/mdb-ui-kit/3.11.0/mdb.min.js"
></script>
<style>
body {
max-width: 910px;
margin: 0 auto;
background-color:#FFFFFF;
text-align:center;
}
</style>
</head>
<body>
<label class="form-label" for="customRange1">X frequency</label>
<div class="range">
<input type="range" class="form-range" id="customRange1" />
</div>
<label class="form-label" for="customRange2">Y frequency</label>
<div class="range">
<input type="range" class="form-range" id="customRange2" />
</div>
<canvas style="outline: black 2px solid;" id="leftcanvas" ></canvas>
<script>
function pixel(array){
var inc = 0;
var buffer = new Uint8ClampedArray(width * height * 4); // have enough bytes
for(var y = 0; y < height; y++) {
for(var x = 0; x < width; x++) {
var pos = (y * width + x) * 4; // position in buffer based on x and y
buffer[pos ] = 0; // some R value [0, 255]
buffer[pos+1] = 0; // some G value
buffer[pos+2] = 0; // some B value
buffer[pos+3] = array[inc]; // set alpha channel
inc++
}
}
return buffer;
};
function makecanvas(idtag,height,imgdata){
var canvas = document.getElementById(idtag),
ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
canvas.height = height;
canvas.width = width;
/* THIS PART I CANT FIGURE OUT */
/* increases canvas but not image */
canvas.width = width*1.25;
/* increases width and length */
//canvas.style.width = 1.25* Math.round(512) + "px";
var idata = ctx.createImageData(width, height);
idata.data.set(imgdata);
ctx.putImageData(idata, 0, 0);
return [idata,ctx];
};
function freq(hzx,hzy){
data = [];
for (var y = 0; y < 3600; y+= 1){
for (var x = 0; x < 512; x+= 1){
data.push(Math.round((255/4*(Math.sin(hzy*2*Math.PI*y/3600) + Math.sin(hzx*2*Math.PI*x/511)+2))))
}
}
return data;
}
trace = freq(1,1)
var width = 512,
height = trace.length/512;
imgmatrix = pixel(trace);
CI = makecanvas("leftcanvas",height,imgmatrix);
var idata = CI[0];
const ictx = CI[1];
var slideX = document.getElementById('customRange1');
var slideY = document.getElementById('customRange2');
slideX.onchange = function() {
hzx = slideX.value;
hzy = slideY.value;
trace = freq(hzx,hzy)
imgmatrix = pixel(trace);
idata.data.set(imgmatrix);
ictx.putImageData(idata, 0, 0);
}
slideY.onchange = function() {
hzx = slideX.value;
hzy = slideY.value;
trace = freq(hzx,hzy)
imgmatrix = pixel(trace);
idata.data.set(imgmatrix);
ictx.putImageData(idata, 0, 0);
}
</script>
</body>
</html>
I'm almost afraid to answer - but what about the most obvious solution:
Instead of just changing the width of the canvas via CSS - change both width & height.
canvas.style.width = 1.2 * Math.round(512) + "px";
canvas.style.height = "3600px";
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 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';
I want to make a loading bar for my web application and I want to use a html canvas for this. This is the script that I use to fill up the canvas:
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
var xPos = 0;
draw = function() {
if(xPos < 300){
c.rect(0, 0, xPos, 30);
c.fill(255,0,0);
xPos += 0.5;
}
};
</script>
I tested this code on a online code converter (khan academy) and it worked (of course without the first 2 lines and c. in front of most things), and that is also my trouble I don't know where I have to put c. in front of?
I simplified the page a little bit:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000"
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
</script>
</body>
</html>
Whatever you are trying to draw... this:
draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
}
};
... it is a definition of variable in global context (context of window object), then assigning a function to it. That's all - it only defines the behavior.
What you need also needs to execute that (a sidenote: to execute it after the canvas is actually created - when you put code in a script tag after canvas tag - it's sufficient and you did it already).
To execute the function use:
draw();
Or don't wrap code in function at all (unless it's to be called multiple times).
Or use a syntax construct to execute the function created in place like this:
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15); // use this to achieve animation effect
}
})();
var xPos = 0;
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#FF0000";
var draw;
(draw = function(){
if(xPos < 300) {
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
setTimeout(draw,15);
}
})();
#bar {
width: 300px;
height: 50px;
}
<canvas id="bar"></canvas>
Edit: I've been thinking of what you might need, as it's not entirely abvious what you want. I have created this jsfiddle. Maybe it'll be of any help.
Hmmm...
You got some things mixed up. Try this:
<html>
<canvas id = "cvs1" width = "300" height = "30"></canvas>
</html>
And for the script:
var c = document.getElementById("cvs1").getContext("2d");
c.fillStyle = "#ff0000" //Set Fill Color(Set to red)
if(xPos < 300){
c.fillRect(xPos, 0, 30, 30);
xPos += 0.5;
}
If not:
What you did was use fill and rect seperately. You need to set the color, and then use the fillRect() function to draw the rectangle.
EDIT: You got the x,y,width,height as width,height,x,y. Fixed answer.
Good luck!
You need to call draw for every animation step. You could do this using setTimeout, setInterval or requestAnimationFrame :
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.css">
</head>
<body>
<canvas id="bar"></canvas>
<script>
var canvas = document.getElementById("bar");
var c = canvas.getContext("2d");
c.fillStyle = "#ff0000";
xPos=0;
draw = function(){
if(xPos < 300){
c.fillRect(0, 0, xPos, 30);
xPos += 0.5;
requestAnimationFrame(draw);
}
};
requestAnimationFrame(draw);
</script>
</body>
</html>