The Process of Clearing and Redrawing a Square on a HTML Canvas - javascript

I have been working on some HTML/Javascript Code and the main thing I want to have happen is when you press any of the arrow keys, the square that I drew moves that direction.
My general train of thought on what I have to do, is when I click on the key, it first clears the canvas, then redraws it with a different x and y value based on the function.
I tried that, but what happens is that the square just vanishes and I have no clue why.
I have been attempting to debug this for a while, and if anyone has any pointers I would love to here them!
<!DOCTYPE html>
<html>
<head>
<title> HTML </title>
<style>
canvas {
border: 1px solid #000000;
}
</style>
</head>
<body>
<center>
<canvas width = "620" height = "620" id = "myCanvas" ></canvas>
</center>
<script src = "script.js" > </script>
</body>
</html>
This is the Javascript Code (Sorry for not well formatting, still getting the hang of formatting code in StackOverflow)
document.addEventListener('keydown', function(event) {
if(event.keyCode == 37)
moveLeft();
if(event.keyCode == 39 )
moveRight();
if(event.keyCode == 38)
moveUp();
if(event.keyCode == 40)
moveDown();
});
function moveLeft() {
context.clearRect(0, 0, canvas.width, canvas.height);
//Edit X and Y Values
var newX, newY;
newX = squareX + 1;
newY = squareY;
context.rect(newX, newY, squareSizeX, squareSizeY);
context.fill(newX, newY, squareSizeX, squareSizeY);
}
function moveRight() {/* Needs to be Finished */}
function moveUp() {/* Needs to be Finished */}
function moveDown() {/* Needs to be Finished */}
var canvas;
var context;
var squareX, squareY;
var squareSizeX = 75;
var squareSizeY = 75;
function renderToCanvas() {
var didRender = false;
try {
canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
/* INPUT DRAWING HERE */
//Drawing Square
squareX = canvas.width / 2;
squareY = canvas.height / 2;
context.rect(squareX, squareY, squareSizeX, squareSizeY);
context.fillRect(squareX, squareY, squareSizeX, squareSizeY);
context.stroke();
/* END DRAWING HERE */
didRender = true;
console.log("Rendered Drawing: " + didRender);
}
catch(err) {
console.log("Rendered Drawing: " + didRender);
console.log(err.message);
}
}
renderToCanvas();

In your moveLeft instead of this
context.rect(newX, newY, squareSizeX, squareSizeY);
context.fill(newX, newY, squareSizeX, squareSizeY);
Do this
context.fillRect(newX, newY, squareSizeX, squareSizeY);
Check out the docs for Canvas Context
You only use context.rect() or context.fill() when you are working on a path using context.beginPath()

Related

Javascript how to make object appear over a background image

Hello I am trying to create a guitar hero sort of program with red circles appearing over a violin image when the corresponding key presses are pressed but I can't seem to be able to make them appear over the image even if I write the code after the canvas code. Can someone help me with this? I would also like to make the circles disappear after a while but timeout won't do the trick here because the image is not one color only for example changing the red circles to the background color after a while. How would i do this?
<html>
<head>
<title>Violin Hero</title>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<style>
body {
background-image: url("violin.jpg");
background-size: 2500px 1300px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="1024" height="768"></canvas>
<img id="bow" src="bow.jpg" style="display:none;" />
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
window.addEventListener("keydown", soundPlay);
function fillRed() {
ctx.fillStyle = "red";
ctx.fill();
}
function keyQ(){
ctx.beginPath();
ctx.arc(1200, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyW(){
ctx.beginPath();
ctx.arc(300, 300, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyE(){
ctx.beginPath();
ctx.arc(900, 500, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
function keyR(){
ctx.beginPath();
ctx.arc(950, 100, 15, 0, Math.PI*2);
ctx.fillStyle = "red";
ctx.fill();
}
//var x = event.keyCode;
//<input type="text" onkeydown="pressedKey(event)">
function soundPlay(event) {
var x = event.keyCode;
if (x == 27) { // 27 is the ESC key
alert ("You pressed the Escape key!");
}
else if (x == 81) {
keyQ();
var sound = new Audio('1.mp3');
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 87) {
keyW();
var sound = new Audio("2.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 69) {
keyE();
var sound = new Audio("3.mp3");
sound.play();
setTimeout(fillRed, 200);
}
else if (event.keyCode == 82) {
keyR();
var sound = new Audio("4.mp3");
sound.play();
setTimeout(fillRed, 200);
}
}
</script>
</body>
</html>
To bring something in front of images/To bring something always behind elements, one should use z-index.
Make a css for background image like this:
#backgroundImg{
position: absolute;
left: 0px;
top: 0px;
z-index: -1;
}
In this way, the background image will always be behind. Please check this or this for more details.
For your second question, I suggest you should make another post and keep this question focused on one issue only.
I've created a simple Plunkr example for you on how to achieve this kind of functionality in JS.
Click s, a or any other to show a red dot.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body id='mybody'>
<img id='violin' src='http://cdn.shopify.com/s/files/1/0704/3831/products/Antoni_Debut_Violin_Outfit_3677b25a-7618-46f7-9313-6080c2a51e27_grande.jpg?v=1444483336'>
<script>
document.addEventListener('keydown', (event) => {
console.log(event);
if (event.key.toLowerCase() === 's') {
showRedDot(110, 420);
} else if (event.key.toLowerCase() === 'a') {
showRedDot(150, 350);
} else {
showRedDot(200, 300);
}
});
var showRedDot = (top, left) => {
var oldDot = document.getElementById('redDot');
if (oldDot) {
oldDot.remove();
}
var dot = document.createElement('DIV');
dot.id = 'redDot';
dot.style.width = '10px';
dot.style.height = '10px';
dot.style.position = 'absolute';
dot.style.borderRadius = '100%';
dot.style.background = 'red';
dot.style.top = top + 'px';
dot.style.left = left + 'px';
document.getElementById('mybody').appendChild(dot);
};
</script>
</body>
</html>
Here's a working Plunkr

Canvas moves using keyboard input but image does not

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.

How to write a loop so that I will draw to user canvas?

I have a canvas element. I have a few troubles, how to draw to user canvas in "realtime",.. So, that my drawing is not already there when they open the site, but rather to draw to the canvas like somebody is actually drawing... So looping through the coordinates.
That's what I tried so far but it's BAAD! It's drawing slowly and it takes a lot of CPU.
// Pencil Points
var ppts = [];
/* Drawing on Paint App */
tmp_ctx.lineWidth = 4;
tmp_ctx.lineJoin = 'round';
tmp_ctx.lineCap = 'round';
tmp_ctx.strokeStyle = '#4684F6';
tmp_ctx.fillStyle = '#4684F6';
// Tmp canvas is always cleared up before drawing.
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
tmp_ctx.beginPath();
var timer = 0;
$.timer(500, function() {
ppts.push({x: 10*timer, y: 5*timer});
timer++;
})
$.timer(10, function() {
if (timer > 250) {
timer = 0;
clearTempCanvas();
} else {
for (var i = 1; i < ppts.length - 2; i++) {
var c = (ppts[i].x + ppts[i + 1].x) / 2;
var d = (ppts[i].y + ppts[i + 1].y) / 2;
tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d);
}
console.log(i);
tmp_ctx.stroke();
}
})
function clearTempCanvas() {
// Writing down to real canvas now
ctx.drawImage(tmp_canvas, 0, 0);
// Clearing tmp canvas
tmp_ctx.clearRect(0, 0, tmp_canvas.width, tmp_canvas.height);
// Emptying up Pencil Points
ppts = [];
}
Here's an example for you to learn from: http://jsfiddle.net/m1erickson/j4HWS/
It works like this:
define some points to animate along and put those points in an array points.push({x:25,y:50})
use requestAnimationFrame to create an animation loop
break each line segment into 100 sub-segments and animate along those sub-segments
Example code:
<!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");
ctx.lineWidth=2;
ctx.strokeStyle="blue";
var points=[];
points.push({x:125,y:125});
points.push({x:250,y:200});
points.push({x:125,y:200});
points.push({x:125,y:125});
var pointIndex=1;
var linePct=0;
var continueAnimating=true;
var img=new Image();img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/pen.png";
function start(){
animate();
}
function draw(pointIndex,linePct){
// clear the canvas
ctx.clearRect(0,0,canvas.width,canvas.height);
// draw fully completed lines
ctx.beginPath();
ctx.moveTo(points[0].x,points[0].y);
for(var i=1;i<pointIndex;i++){
ctx.lineTo(points[i].x,points[i].y);
}
// draw current line-in-process
var pos=getLineXYatPercent(points[pointIndex-1],points[pointIndex],linePct/100);
ctx.lineTo(pos.x,pos.y);
ctx.stroke();
// draw the pen
ctx.drawImage(img,pos.x-93,pos.y-92);
}
function animate() {
if(!continueAnimating){return;}
requestAnimationFrame(animate);
// Drawing code goes here
draw(pointIndex,linePct);
if(++linePct>100){
linePct=1;
if(++pointIndex>points.length-1){
continueAnimating=false;
}
}
}
function getLineXYatPercent(startPt,endPt,percent) {
var dx = endPt.x-startPt.x;
var dy = endPt.y-startPt.y;
var X = startPt.x + dx*percent;
var Y = startPt.y + dy*percent;
return( {x:X,y:Y} );
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=350 height=350></canvas>
</body>
</html>

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>

Drawing line in Canvas having issue

I'm currently working on an iOS app which uses HTML 5 and JavaScript for drawing Graphs.
I just did a sample App.
My Code:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var a = 0;
var b = 0;
function init()
{
var can = document.getElementById('can');
can.addEventListener("click",click, false);
}
function click(event)
{
var can = document.getElementById('can');
var c = can.getContext('2d');
var parentPosition = getPosition(event.currentTarget);
c.lineWidth = 1;
c.strokeStyle = '#FFFFFF';
c.beginPath();
c.moveTo(a, b);
a = event.clientX - parentPosition.x;
b = event.clientY - parentPosition.y;
c.lineTo(a, b);
c.stroke();
}
function getPosition(element)
{
var xPosition = 0;
var yPosition = 0;
while (element)
{
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
</script>
</head>
<body oncopy='copy();' onpaste='paste();'onload ='init();'>
<canvas id="can" style="height:300px;width:300px;background-color:black;">Oops!</canvas>
</body>
</html>
My Issue:
When a user Taps on the screen, I'm drawing a line to that particular point from previous point.
But in my case when I tap on the screen the line is drawn to some other point. Say if I tapped on point (100,100) the line will be drawn to (100, some arbitrary value). Always the Y position is wrong.
What I did:
Tested it on simulator
Tested it on device
Tested it on Firefox
Tested it on Chrome
All results are same. I couldn't find the issue. I alerted the clicked x and y co-ordinate. It's coming correctly. Only problem is with the draw functionality.
Screenshots:
As you can see the X-coordinate is correct. But Y-coordinate is always coming wrong.
Please help me, Thanks in advance.
Can you please make these changes.
In html line#47,
<canvas id="can" height=300 width=300 style="background-color:red;">Oops!</canvas>
In script line#23,
c.beginPath();
c.moveTo(a, b);
a = event.clientX - parentPosition.x;
b = event.clientY - parentPosition.y;
console.log('a:'+a+'--b:'+b);
c.lineTo(a, b);
c.stroke();
TO CLEAR
This is the code that you have to change to have a reusable code:
c.moveTo(a/(can.clientWidth/can.width), b/(can.clientHeight/can.height));
a = event.clientX - parentPosition.x;
b = event.clientY - parentPosition.y;
console.log('a:'+a+'--b:'+b);
c.lineTo(a/(can.clientWidth/can.width), b/(can.clientHeight/can.height));
If you don't use this, the code below works only for 300x300 canvas size.
LAST EDIT:
By analyzing the 2d context (var c = can.getContext('2d');console.log(c);) you can easily understand this error: there is a relation (not explicit) from the canvas and it's 2d context.
As you can see from the image:
the height and the width of the canvas(this is 500*500) are differents from its offset,scroll and client size. So, before to draw, you need to calculate the ratio: 500/150 will be the height coefficient and 500/300 the width one, so a will be multiplied by 1.66667 and b will be multiplied by 3.33333.
Same for the old example (canvas 300*300) the coefficent are 300/300=1 (a:width) 300/150=2 (b:height)
OLD REPLY:
But now, you have to guess why..cause actually I have no time
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript">
var a = 0;
var b = 0;
function init()
{
var can = document.getElementById('can');
can.addEventListener("click",click, false);
}
function click(event)
{
var can = document.getElementById('can');
var c = can.getContext('2d');
var parentPosition = getPosition(event.currentTarget);
console.log(parentPosition);
console.log(event);
c.lineWidth = 1;
c.strokeStyle = '#FFFFFF';
c.beginPath();
c.moveTo(a, b/2);
a = event.clientX - parentPosition.x;
b = event.clientY - parentPosition.y;
console.log('a:'+a+'--b:'+b);
c.lineTo(a, b/2);
c.stroke();
}
function getPosition(element)
{
var xPosition = 0;
var yPosition = 0;
while (element)
{
xPosition += (element.offsetLeft - element.scrollLeft + element.clientLeft);
yPosition += (element.offsetTop - element.scrollTop + element.clientTop);
element = element.offsetParent;
}
return { x: xPosition, y: yPosition };
}
</script>
</head>
<body oncopy='copy();' onpaste='paste();'onload ='init();'>
<canvas id="can" style="height:300px;width:300px;background-color:black;">Oops!</canvas>
<br>
pagex<input type="text" id="ics">pagey<input type="text" id="ips"><br>
screenx<input type="text" id="ics2">screeny<input type="text" id="ips2">
<script>
$("#can").mousemove(function(event) {
var msg = "Handler for .mousemove() called at ";
document.getElementById('ics').value= event.pageX
document.getElementById('ips').value= event.pageY;
document.getElementById('ics2').value= event.screenX;
document.getElementById('ips2').value= event.screenY;
});
</script>
</body>
</html>

Categories