Canvas moves using keyboard input but image does not - javascript

so I started with the basics adding canavs, css, javascript. should the image be in the html or javascript?
next i added a background color to the canvas. then i add canvas properties in javascript along with keyCodes. i got the image in with window.onload. after that i notice the canvas was moving but not the image.
var canvas = document.getElementById("app");
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
var keys = [];
window.addEventListener("keydown", function(e){
keys[e.keyCode] = true;
}, false);
window.addEventListener("keyup", function(e){
delete keys[e.keyCode];
}, false);
function game(){
window.onload;
update();
render();
}
function update(){
if(keys[38]) img.y--;
if(keys[40]) img.y++;
if(keys[37]) img.x--;
if(keys[39]) img.x++;
}
function render(){
ctx.fillRect(img.x, img.y);
}
window.onload = function() {
var c=document.getElementById("app");
var ctx=c.getContext("2d");
var img=document.getElementById("chio");
ctx.drawImage(img,10,10);
};
setInterval(function(){
game();
}, 1000/30)
// > note: window.onload shows the images
#app{
background-color:#33ff00
}
<html>
<head>
<link href="app.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<canvas id="app" width=300 height=640></canvas>
<img id="chio" src="chio.png"/>
<script src="app.js"></script>
</body>
</html>
I'm lost at this point, please help me

I made some correction in "app.js" but I don't know what do you want exactly. If you wanted to move the image then this is a way.
var canvas = document.getElementById("app");
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
var keys = [];
var ctx;
var img;
var position = {x:0,y:0};
window.addEventListener("keydown", function(e){
keys[e.keyCode] = true;
}, false);
window.addEventListener("keyup", function(e){
keys[e.keyCode] = false;
}, false);
function game(){
update();
render();
}
function update(){
if(keys[38]) position.y--;
if(keys[40]) position.y++;
if(keys[37]) position.x--;
if(keys[39]) position.x++;
}
function render(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img,position.x,position.y);
}
window.onload = function() {
var c=document.getElementById("app");
ctx=c.getContext("2d");
img=document.getElementById("chio");
};
setInterval(function(){
game();
}, 1000/30);
// > note: window.onload shows the images

There are a number of problems with the code you've given, the most problematic being that you're trying to access DOM elements in various places potentially before the document has loaded. This should all be done attached to the window.onload event you're already using.
Another issue is that you're declaring variables locally and initializing them, but elsewhere in your code you treat them as global variables and try to access them - generating more errors. These variables should be moved to the global scope.
You're also trying to modify some x/y attribute on the original <img> element to track its position on the canvas - this won't work. I'd move the position tracking into a JavaScript object with x/y properties.
Lastly, you're not calling the correct code to draw the image to the canvas in your render() function. I'd suggest clearing the canvas and redrawing the image with drawImage().
Putting all these suggestions to practice, your JavaScript becomes:
// Global variables for later use
var keys = [];
var canvas;
var ctx;
var img;
// Object to track image position on canvas
var imgPos = {
x: 0,
y: 0
}
window.addEventListener("keydown", function(e){
keys[e.keyCode] = true;
}, false);
window.addEventListener("keyup", function(e){
delete keys[e.keyCode];
}, false);
function game(){
window.onload;
update();
render();
}
function update(){
if(keys[38]) imgPos.y--;
if(keys[40]) imgPos.y++;
if(keys[37]) imgPos.x--;
if(keys[39]) imgPos.x++;
}
function render(){
// Clear canvas and redraw image at new location
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img,imgPos.x,imgPos.y);
}
window.onload = function() {
// Initialize canvas
canvas = document.getElementById("app");
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
// Draw image to canvas
ctx=canvas.getContext("2d");
img=document.getElementById("chio");
ctx.drawImage(img,imgPos.x,imgPos.y);
// Start game loop
setInterval(function(){
game();
}, 1000/30);
};
Here's a JSFiddle to demonstrate. I've commented the code wherever I made significant changes to help you follow it better. Hope this helps! Let me know if you have any questions.

Related

How can I create a canvas, then set its color, and then append it to a div using Javascript/ Jquery?

I am trying to build a basic game and somehow got really hung up on the first few steps. I am trying to create a canvas, the the color of the canvas, and then append to a div element. Every time I load this I either get an error, or nothing. Even if the 2 console.logs load properly. Please help!
My HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Dodge</title>
<script src="//code.jquery.com/jquery.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/journal/bootstrap.min.css" rel="stylesheet" integrity="sha256-fHWoqb8bPKjLiC7AuV6qy/lt0hrzfwM0ciyAu7Haf5w= sha512-3t2GeiCRNeKhZnUaUMygGiLKZzb/vPhvfw3y1Rt2FCwKuRaLVrOCTpavIYsZ4xqM52mbO7M93NaXbm/9dOA2Og==" crossorigin="anonymous">
<script src="../../../game.js">
</script>
</head>
<body>
<center>
<h1 id="h1">Dodge the enemy by pressing the left and right arrow keys!</h1>
<button
id="play"
class="btn btn-primary">Play game!</button>
</br>
</br>
<button
id="again"
class="btn btn-primary">Play Again!</button>
<div id="play-area">
</div>
</center>
</body>
</html>`
And heres the JS:
$(function () {
function createCanvas(width, height, id) {
var canvas = document.createElement("canvas");
var id2 = "#" + id;
canvas.width = width;
canvas.height = height;
canvas.id = id;
$(id2).css("color", "lawngreen");
$("#game-area").append(canvas);
}
$("#play").click(function () {
console.log("hello");
createCanvas(900, 900, "game-canvas");
console.log("hi!");
});
});
First you create the canvas object correctly, but you should also append it to the body. This is done after basic parameters are set.
After that you can manipulate the css with jQuery.
It works in my fiddle.
Check it out here: https://jsfiddle.net/xu15q5h8/
I changed your code to point out how it correctly works:
$(function () {
function createCanvas(width, height, id) {
var canvas = document.createElement('canvas');
var body = document.getElementsByTagName("body")[0];
canvas.id = id;
canvas.width = width;
canvas.height = height;
body.appendChild(canvas);
$('canvas').css('background-color', 'rgba(158, 167, 184, 0.2)');
cursorLayer = document.getElementById("CursorLayer");
console.log(cursorLayer);
}
$("#play").click(function () {
console.log("hello");
createCanvas(900, 900, "game-canvas");
alert("hi!");
});
});
Why not just draw the color onto the canvas instead of using CSS.
function createCanvas(width, height, id) {
var canvas = document.createElement("canvas");
var id2 = "#" + id;
canvas.width = width;
canvas.height = height;
canvas.id = id;
var ctx = canvas.getContext("2d");
ctx.fillStyle = "lawngreen";
ctx.fillRect (0, 0, width, height);
$("#play-area").append(canvas);
}
Here is the modified code demo.

Adding more images to the canvas to drag and drop

I want to be able to spawn a new image to the canvas at the click of a button, rather than having to manually edit the code.
I have the following HTML5/JavaScript code that allows images to be dragged and dropped between multiple canvases and it works perfectly for what I require.
What I am doing:
<canvas style="float: left" height="125" width="400" id="cvs1">[No canvas support]</canvas>
<canvas style="float: left; margin-left: 100px" height="125" width="400" id="cvs2">[No canvas support]</canvas>
<script src="http://www.rgraph.net/libraries/RGraph.common.core.js" ></script>
<script>
window.onload = function ()
{
var canvas1 = document.getElementById("cvs1");
var canvas2 = document.getElementById("cvs2");
var context1 = canvas1.getContext('2d');
var context2 = canvas2.getContext('2d');
var imageXY = {x: 5, y: 5};
/**
* This draws the image to the canvas
*/
function Draw ()
{
//Clear both canvas first
canvas1.width = canvas1.width
canvas2.width = canvas2.width
//Draw a red rectangle around the image
if (state && state.dragging) {
state.canvas.getContext('2d').strokeStyle = 'red';
state.canvas.getContext('2d').strokeRect(imageXY.x - 2.5,
imageXY.y - 2.5,
state.image.width + 5,
state.image.height + 5);
}
// Now draw the image
state.canvas.getContext('2d').drawImage(state.image, imageXY.x, imageXY.y);
}
canvas2.onclick =
canvas1.onclick = function (e)
{
if (state && state.dragging) {
state.dragging = false;
Draw();
return;
}
var mouseXY = RGraph.getMouseXY(e);
state.canvas = e.target;
if ( mouseXY[0] > imageXY.x
&& mouseXY[0] < (imageXY.x + state.image.width)
&& mouseXY[1] > imageXY.y
&& mouseXY[1] < (imageXY.y + state.image.height)) {
state.dragging = true;
state.originalMouseX = mouseXY[0];
state.originalMouseY = mouseXY[1];
state.offsetX = mouseXY[0] - imageXY.x;
state.offsetY = mouseXY[1] - imageXY.y;
}
}
canvas1.onmousemove =
canvas2.onmousemove = function (e)
{
if (state.dragging) {
state.canvas = e.target;
var mouseXY = RGraph.getMouseXY(e);
// Work how far the mouse has moved since the mousedon event was triggered
var diffX = mouseXY[0] - state.originalMouseX;
var diffY = mouseXY[1] - state.originalMouseY;
imageXY.x = state.originalMouseX + diffX - state.offsetX;
imageXY.y = state.originalMouseY + diffY - state.offsetY;
Draw();
e.stopPropagation();
}
}
/**
* Load the image on canvas1 initially and set the state up with some defaults
*/
state = {}
state.dragging = false;
state.canvas = document.getElementById("cvs1");
state.image = new Image();
state.image.src = 'http://www.rgraph.net/images/logo.png';
state.offsetX = 0;
state.offsetY = 0;
state.image.onload = function ()
{
Draw();
}
}
</script>
This can also be seen on this JS Fiddle (Note: you have to click the image before you can drag it)
The problem I am having:
I would like to add more images to the canvases so that any of the images can then be dragged and dropped between however many canvases I choose to create.
I can quite easily add more canvases to the page to drag and drop between, however when it comes to adding/spawning more images to the canvases I cannot get it to work.
The only way I can think of being able to do this is by repeating the Draw() function for every single image that gets added. That would mean if I wanted 30 images to be able to drag and drop between 10 different canvases for example, I would need to repeat the Draw() function 30 times. Surely that cannot be the best way to do this?
Unless I am missing something very obvious I cannot see another way of doing this?
Here’s how to configure your code to create multiple objects and click-drag between canvases.
Demo: http://jsfiddle.net/m1erickson/Bnb6A/
Code an object factory function that creates new draggable objects and put all new objects in an array.
Keep this information about each draggable object:
dragging (true/false) indicating if this object is currently being dragged
image: the image for this object
x,y: the current top,left position of this object
width,height: the size of this object
offsetX,offsetY: indicates where the mouse clicked relative to top,left of this object
draw: (a function) that allows this object to draw itself (surrounded by a red rect if it’s being dragged)
On click:
Get the mouse position
Clear both canvases
Iterate through the object array
If an object is being dragged, unset the dragging flag
If an object is now selected, set the dragging flag and set the offsetX,offsetY for the starting mouse position relative to this object.
Redraw all objects
On mousemove:
Get the mouse position
Clear both canvases
Iterate through the object array
If an object is being dragged, move it to the mouse position (setting x,y adjusted for the offset)
Redraw all objects
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{ border: 1px solid #808080; }
</style>
<script>
$(function(){
var canvas1 = document.getElementById("cvs1");
var canvas2 = document.getElementById("cvs2");
var contexts=[];
contexts.push(canvas1.getContext('2d'));
contexts.push(canvas2.getContext('2d'));
function clearAll(){
//Clear both canvas first
canvas1.width = canvas1.width
canvas2.width = canvas2.width
}
canvas1.onclick=function(e){ handleClick(e,1); };
canvas2.onclick=function(e){ handleClick(e,2); };
//
function handleClick(e,contextIndex){
e.stopPropagation();
var mouseX=parseInt(e.clientX-e.target.offsetLeft);
var mouseY=parseInt(e.clientY-e.target.offsetTop);
clearAll();
for(var i=0;i<states.length;i++){
var state=states[i];
if(state.dragging){
state.dragging=false;
state.draw();
continue;
}
if ( state.contextIndex==contextIndex
&& mouseX>state.x && mouseX<state.x+state.width
&& mouseY>state.y && mouseY<state.y+state.height)
{
state.dragging=true;
state.offsetX=mouseX-state.x;
state.offsetY=mouseY-state.y;
state.contextIndex=contextIndex;
}
state.draw();
}
}
canvas1.onmousemove = function(e){ handleMousemove(e,1); }
canvas2.onmousemove = function(e){ handleMousemove(e,2); }
//
function handleMousemove(e,contextIndex){
e.stopPropagation();
var mouseX=parseInt(e.clientX-e.target.offsetLeft);
var mouseY=parseInt(e.clientY-e.target.offsetTop);
clearAll();
for(var i=0;i<states.length;i++){
var state=states[i];
if (state.dragging) {
state.x = mouseX-state.offsetX;
state.y = mouseY-state.offsetY;
state.contextIndex=contextIndex;
}
state.draw();
}
}
var states=[];
var img=new Image();
img.onload=function(){
states.push(addState(0,0,img));
}
img.src="http://www.rgraph.net/images/logo.png";
function addState(x,y,image){
state = {}
state.dragging=false;
state.contextIndex=1;
state.image=image;
state.x=x;
state.y=y;
state.width=image.width;
state.height=image.height;
state.offsetX=0;
state.offsetY=0;
state.draw=function(){
var context=contexts[this.contextIndex-1];
if (this.dragging) {
context.strokeStyle = 'red';
context.strokeRect(this.x,this.y,this.width+5,this.height+5)
}
context.drawImage(this.image,this.x,this.y);
}
state.draw();
return(state);
}
$("#more").click(function(){
states.push(addState(states.length*100,0,img));
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="more">Add Image</button><br>
<canvas height="125" width="300" id="cvs1">[No canvas support]</canvas><br>
<canvas height="125" width="300" id="cvs2">[No canvas support]</canvas>
</body>
</html>

HTML5 Canvas 100% height and width

I'm trying to make this raindrop canvas script take up 100% width and height, but nothing I seem to do works. I tried changing the CSS, and height/width in the Canvas area, but it either doesn't change anything, or it makes it not work at all. The one time I tried something that actually made it full size, it seemed to have a weird effect on the raindrops, they became all blurry and much larger, so it must have actually stretched the canvas instead of making it larger. Here's the code for the default 800x800 pixel canvas.
Style
<style>
article, aside, figure, footer, header, hgroup,
menu, nav, section { display: block; }
</style>
Script for canvas
<script type="text/javascript">
var canvas = null;
var context = null;
var bufferCanvas = null;
var bufferCanvasCtx = null;
var flakeArray = [];
var flakeTimer = null;
var maxFlakes = 200; // Here you may set max flackes to be created
function init() {
canvas = document.getElementById('canvasRain');
context = canvas.getContext("2d");
bufferCanvas = document.createElement("canvas");
bufferCanvasCtx = bufferCanvas.getContext("2d");
bufferCanvasCtx.canvas.width = context.canvas.width;
bufferCanvasCtx.canvas.height = context.canvas.height;
flakeTimer = setInterval(addFlake, 200);
Draw();
setInterval(animate, 30);
}
function animate() {
Update();
Draw();
}
function addFlake() {
flakeArray[flakeArray.length] = new Flake();
if (flakeArray.length == maxFlakes)
clearInterval(flakeTimer);
}
function blank() {
bufferCanvasCtx.fillStyle = "rgba(0,0,0,0.8)";
bufferCanvasCtx.fillRect(0, 0, bufferCanvasCtx.canvas.width, bufferCanvasCtx.canvas.height);
}
function Update() {
for (var i = 0; i < flakeArray.length; i++) {
if (flakeArray[i].y < context.canvas.height) {
flakeArray[i].y += flakeArray[i].speed;
if (flakeArray[i].y > context.canvas.height)
flakeArray[i].y = -5;
flakeArray[i].x += flakeArray[i].drift;
if (flakeArray[i].x > context.canvas.width)
flakeArray[i].x = 0;
}
}
}
function Flake() {
this.x = Math.round(Math.random() * context.canvas.width);
this.y = -10;
this.drift = Math.random();
this.speed = Math.round(Math.random() * 5) + 1;
this.width = (Math.random() * 3) + 2;
this.height = this.width;
}
function Draw() {
context.save();
blank();
for (var i = 0; i < flakeArray.length; i++) {
bufferCanvasCtx.fillStyle = "white";
bufferCanvasCtx.fillRect(flakeArray[i].x, flakeArray[i].y, flakeArray[i].width, flakeArray[i].height);
}
context.drawImage(bufferCanvas, 0, 0, bufferCanvas.width, bufferCanvas.height);
context.restore();
}
</script>
And finally here's the body
<body onload="init()">
<canvas id="canvasRain" width="800px" height="800px">Canvas Not Supported</canvas>
</body>
body, #canvasRain {width:100%; height:100%; margin:0px;} will set your size properly but your problem is that your canvas height/width you're using to do your drawing doesn't pick up the proper px values when setting them with %'s. And that's where the scaling comes in with the fuzzy flakes. It takes some default canvas size and stretches to 100% of the view. Adding something like
bufferCanvas.width = canvas.width = window.innerWidth;
bufferCanvas.height = canvas.height = window.innerHeight;
seems to do the trick. And you might want/need to handle resize events to recalculate it. Here is a sample. I couldn't get jsFiddle to work for me, so it's just the whole thing.
I've set up a fiddle that shows how to resize the canvas using some simple CSS.
http://jsfiddle.net/C7LfU/1/
$('#canvasRain').css({
"height": window.innerHeight,
"width": window.innerWidth
});
I've also went ahead and updated your animation to use requestAnimationFrame. This probably what caused your Flakes to be fuzzy: The animation lagged since setTimeout doesn't scale to when the browser is actually ready to draw another frame.
window.requestAnimFrame = (function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
function animate() {
requestAnimFrame(animate);
Update();
Draw();
}
Read a little more about why you should use requestAnimationFrame at: http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

javascript alert when canvas is clicked

I have a canvas on which I am making a menu screen for my game:
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
ctx.font="30px monospace";
ctx.fillStyle = "black";
ctx.strokeText("click to begin",140,260);
When the user clicks "click to begin", I want it to progress to my game, but considering that I can't get the onclick working I just want it to alert that it has worked. So far (based off of tutorials and examples I have found) I have the following code:
mouse = (function (target) {
var isButtonDown = false;
c.addEventListener('mousedown', function () {
isButtonDown = true;
});
return {
isButtonDown: function () {
return isButtonDown;
}
};
}(document));
var isButtonDown = input.isButtonDown();
if (isbuttondown == true) {
alert("Mouse clicked");
}
This code does nothing when I run it. Could someone please explain to me how to get this working, or at least what I need to change?
Thanks in advance,
Riley
Here is a Solution.
Solution
I have removed the alert and instead used console.log. Check the console.
JS
canvas.addEventListener('click', function (evt) {
var mousePos = getMousePos(canvas, evt);
var message = 'Mouse Clicked at ' + mousePos.x + ',' + mousePos.y;
console.log(message);
}, false);
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
EDIT: Here is the same fiddle with Alert option. FIDDLE

Add Mouse Events for Canvas Drawing

I need to add mouse event via Javascript to below code... I have already added touch events in order to test in desktop browsers I need to add mouse events .. I tried adding mouse event to addEventListener but seems to not work I'm not pretty sure what was wrong...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=768px, maximum-scale=1.0" />
<title>rsaCanvas</title>
<script type="text/javascript" charset="utf-8">
window.addEventListener('load',function(){
// get the canvas element and its context
var canvas = document.getElementById('rsaCanvas');
var insertImage = document.getElementById('insert');
var context = canvas.getContext('2d');
//load image and annotation method
var loadData = {
imageLoad: function(){
var img = new Image();
img.src = 'the_scream.jpg';
context.drawImage(img,0,0);
}
};
// create a drawer which tracks touch movements
var drawer = {
isDrawing: false,
touchstart: function(coors){
context.beginPath();
context.moveTo(coors.x, coors.y);
this.isDrawing = true;
},
touchmove: function(coors){
if (this.isDrawing) {
context.lineTo(coors.x, coors.y);
context.stroke();
}
},
touchend: function(coors){
if (this.isDrawing) {
this.touchmove(coors);
this.isDrawing = false;
}
}
};
// create a function to pass touch events and coordinates to drawer
function draw(event){
// get the touch coordinates
var coors = {
x: event.targetTouches[0].pageX,
y: event.targetTouches[0].pageY
};
// pass the coordinates to the appropriate handler
drawer[event.type](coors);
}
// attach the touchstart, touchmove, touchend event listeners.
canvas.addEventListener('touchstart',draw, false);
canvas.addEventListener('touchmove',draw, false);
canvas.addEventListener('touchend',draw, false);
insertImage.addEventListener('click',loadData.imageLoad, false);
// prevent elastic scrolling
document.body.addEventListener('touchmove',function(event){
event.preventDefault();
},false); // end body.onTouchMove
},false); // end window.onLoad
</script>
<style>
#rsaCanvas{border:5px solid #000;}
</style>
</head>
<body>
<div id="container">
<canvas id="rsaCanvas" width="400" height="500">
Sorry, your browser is not supported.
</canvas>
<button id="insert">Insert Image</button>
</div>
</body>
</html>
try this one.
function init () {
// ...
// Attach the mousemove event handler.
canvas.addEventListener('mousemove', ev_mousemove, false);
}
// The mousemove event handler.
var started = false;
function ev_mousemove (ev) {
var x, y;
// Get the mouse position relative to the canvas element.
if (ev.layerX || ev.layerX == 0) { // Firefox
x = ev.layerX;
y = ev.layerY;
} else if (ev.offsetX || ev.offsetX == 0) { // Opera
x = ev.offsetX;
y = ev.offsetY;
}
// The event handler works like a drawing pencil which tracks the mouse
// movements. We start drawing a path made up of lines.
if (!started) {
context.beginPath();
context.moveTo(x, y);
started = true;
} else {
context.lineTo(x, y);
context.stroke();
}
}
source http://dev.opera.com/articles/view/html5-canvas-painting/
if your problem is with insertImage.addEventListener('click',loadData.imageLoad, false); not showing image when u click, it is because
imageLoad: function(){
var img = new Image();
img.src = 'the_scream.jpg';
context.drawImage(img,0,0);
}
Note img.src is async, to draw the image do
img.onload = (function() {
var image = img;
return function() {context.drawImage(image, 0, 0);};
})();

Categories