I'm trying some draw techniques I found in this URL:
http://perfectionkills.com/exploring-canvas-drawing-techniques/
I just noticed that the higher level css properties are not applied to the canvas element mouse events. Is there a easy way to fix this?
<head>
<meta charset="utf-8">
<title>Spray Can</title>
<style>
body {
margin: 0;
padding: 0;
}
#container {
border: 1px solid #ccc;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#canvas {
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var isDrawing;
canvas.onmousedown = function(e) {
isDrawing = true;
context.moveTo(e.clientX, e.clientY);
};
canvas.onmousemove = function(e) {
if (isDrawing) {
var k = 4;
var radgrad = context.createRadialGradient(e.clientX, e.clientY, k, e.clientX, e.clientY, k * 2);
radgrad.addColorStop(0, 'rgba(0,0,0,1)');
radgrad.addColorStop(0.5, 'rgba(0,0,0,0.5)');
radgrad.addColorStop(1, 'rgba(0,0,0,0)');
context.fillStyle = radgrad;
context.fillRect(e.clientX - k * 2, e.clientY - k * 2, k * 2 * 2, k * 2 * 2);
}
};
canvas.onmouseup = function() {
isDrawing = false;
};
});
</script>
</head>
<body>
<div id="container">
<canvas id="canvas" width="400" height="400"></canvas>
</div>
</body>
https://jsfiddle.net/crpq8t5q/1/
What you need is to convert your mouse event's coordinates to be relative to the canvas ones.
Since here you don't touch the scale nor rotation this is just a simple canvasX = mouseX - canvas.offsetLeft and canvasY = mouseY - canvas.offsetTop.
These offsetXXX properties are available on the canvas, but you can also use getBoundingClientRect()which will return better results if your css is more complicated (e.g nested elements with different scrollable areas).
But since this offset will change each time you scroll or resize the page, you need to update these values.
Also, it is a very bad idea to create a readialGradient in a mouse event. This event can fire at really high rate, and creating gradients eats memory.
It is then better to create a single gradient, and modify your whole context's matrix so that the gradient be placed at the mouse coordinates :
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var isDrawing;
var k = 4;
// create the gradient only once
var radgrad = context.createRadialGradient(0, 0, k, 0, 0, k * 2);
radgrad.addColorStop(0, 'rgba(0,0,0,1)');
radgrad.addColorStop(0.5, 'rgba(0,0,0,0.5)');
radgrad.addColorStop(1, 'rgba(0,0,0,0)');
// get our canvas margins;
var rect;
function getRect() {
rect = canvas.getBoundingClientRect();
}
canvas.onmousedown = function(e) {
isDrawing = true;
context.moveTo(e.clientX, e.clientY);
};
canvas.onmousemove = function(e) {
if (isDrawing) {
// normalize our mouse event's coordinates
var x = e.clientX - rect.left;
var y = e.clientY - rect.top;
// change the canvas matrix coordinates so we draw at mouse positions
context.setTransform(1, 0, 0, 1, x, y)
context.fillStyle = radgrad;
context.fillRect(-k * 2, -k * 2, k * 2 * 2, k * 2 * 2);
}
};
canvas.onmouseup = function() {
isDrawing = false;
};
var debouncing = false;
function resizeHandler() {
debouncing = false;
getRect();
}
window.onscroll = window.onresize = function() {
// debounce the events
if (!debouncing) {
requestAnimationFrame(resizeHandler);
}
debouncing = true;
}
getRect();
body {
margin: 0;
padding: 0;
}
#container {
border: 1px solid #ccc;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
#canvas {}
<div id="container">
<canvas id="canvas" width="400" height="400"></canvas>
</div>
Related
I have a canvas with some styling applied. There is a single letter centered in the canvas. Please take a look at the code below.
As the title suggest, I am trying to change the letter by pressing a key.
For example:
Letter A centered in canvas: I press the g - key, it changes to the letter g (Uppercase included)
As to my knowledge, I might have to use the method "keyup" with a "document.addEventListener".
Currently I am going through a course on learning JS, but I have noticed a strong reliance on certain libraries in the course, which I frankly dislike. I am not trashing the benefits, but I would prefer building a base with pure JS before using certain libraries I hardly understand. Some guidance would be appreciated.
body {
background-color: #000000;
}
canvas {
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #111416;
border: 10px solid #a60000;
border-style: double;
box-shadow: 0 0 20px 5px #a60000;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<link rel="stylesheet" href="canvas.css">
<canvas id="myCanvas" width="800" height="800"></canvas>
<script>
// Get id from the canvas element
var canvas = document.getElementById("myCanvas");
// Provide 2D rendering context for the drawing surface of canvas
var context = canvas.getContext("2d");
// Get width and height of the canvas element
var canvW = document.getElementById("myCanvas").width;
var canvH = document.getElementById("myCanvas").height;
let text = "f";
context.fillStyle = "#a60000";
context.font = "700px serif";
// Measure the size of the letter and the specific font
// Always centers the letter regardless of size
// Display size of letter
const metrics = context.measureText(text);
const mx = metrics.actualBoundingBoxLeft * -1;
const my = metrics.actualBoundingBoxAscent * -1;
const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
const x = (canvW -mw) *0.5 - mx;
const y = (canvH - mh) *0.5 - my;
context.save();
context.translate(x, y);
context.beginPath();
context.rect(mx, my, mw, mh);
context.stroke();
context.fillText(text, 0, 0);
context.restore();
const onKeyUp = (e) => {
text = e.key.toUpperCase();
manager.render();
};
document.addEventListener("keyup", onKeyUp);
</script>
</body>
</html>
Your function call manager.render() results in an error as it's not present in the provided code snippet. I created one and moved your drawing stuff into it. The render function takes the input as an argument. Besides that I just had to add clearRect() to prevent overlapping letters.
// Get id from the canvas element
var canvas = document.getElementById("myCanvas");
// Provide 2D rendering context for the drawing surface of canvas
var context = canvas.getContext("2d");
// Get width and height of the canvas element
var canvW = document.getElementById("myCanvas").width;
var canvH = document.getElementById("myCanvas").height;
context.fillStyle = "#a60000";
context.font = "700px serif";
render("t");
function render(text) {
// Measure the size of the letter and the specific font
// Always centers the letter regardless of size
// Display size of letter
const metrics = context.measureText(text);
const mx = metrics.actualBoundingBoxLeft * -1;
const my = metrics.actualBoundingBoxAscent * -1;
const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
const x = (canvW -mw) *0.5 - mx;
const y = (canvH - mh) *0.5 - my;
context.clearRect(0,0,canvas.width,canvas.height)
context.save();
context.translate(x, y);
context.beginPath();
context.rect(mx, my, mw, mh);
context.stroke();
context.fillText(text, 0, 0);
context.restore();
}
const onKeyUp = (e) => {
const text = e.key.toUpperCase();
render(text);
};
document.addEventListener("keyup", onKeyUp);
body {
background-color: #000000;
}
canvas {
padding: 0;
margin: auto;
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: #111416;
border: 10px solid #a60000;
border-style: double;
box-shadow: 0 0 20px 5px #a60000;
}
<canvas id="myCanvas" width="800" height="800"></canvas>
The problem is that you dont redraw the canvas again after the hitting the button. For that you have to call the method context.clearRect(0, 0, canvas.width, canvas.height);In the eventlistener you have to call a function to redraw by wrapping your logic into a function. Now you can pass to the function the text as parameter you want to have rendered. Working Example:
code:
const redraw = function (text) {
var canvas = document.getElementById('myCanvas');
// Provide 2D rendering context for the drawing surface of canvas
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
// Get width and height of the canvas element
var canvW = document.getElementById('myCanvas').width;
var canvH = document.getElementById('myCanvas').height;
context.fillStyle = '#a60000';
context.font = '700px serif';
// Measure the size of the letter and the specific font
// Always centers the letter regardless of size
// Display size of letter
const metrics = context.measureText(text);
const mx = metrics.actualBoundingBoxLeft * -1;
const my = metrics.actualBoundingBoxAscent * -1;
const mw = metrics.actualBoundingBoxLeft + metrics.actualBoundingBoxRight;
const mh = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent;
const x = (canvW - mw) * 0.5 - mx;
const y = (canvH - mh) * 0.5 - my;
context.save();
context.translate(x, y);
context.beginPath();
context.rect(mx, my, mw, mh);
context.stroke();
context.fillText(text, 0, 0);
context.restore();
};
redraw('I');
const onKeyUp = (e) => {
text = e.key.toUpperCase();
redraw(text);
};
document.addEventListener('keyup', onKeyUp);
I am making a magnifying glass for a canvas application but ive run into an issue with scrolling.
Essentially the goal is to take a canvas and when an image is added (in this case a cgm image) and make a snapshot of it, scale it up and draw it on to a second smaller canvas that overlays it and follow the mouse (preferably a drag/mousedown and up, but i am using mousemove for testing purposes). I believe the issue is in the zoom.style.top & zoom.style.left NOTE on my main aplication I have a top margin of 70px so keep that in mind.
here is a quick example I wrote up
<!-- language: lang-js -->
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var ox = canvas.width / 2;
var oy = canvas.height / 2;
ctx.font = "42px serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "blue";
ctx.fillRect(ox / 2, oy / 2, ox, oy);
function magnify() {
var main = document.getElementById("canvas1");
var ctx = main.getContext('2d')
var base64 = main.toDataURL('image/png', 0);
drawing = new Image();
drawing.onload = () => {
var zoom = document.getElementById("tCanvas");
var zoomCtx = zoom.getContext('2d');
zoomCtx.drawImage(drawing, 0, 0);
}
main.addEventListener("mousemove", function(e) {
var zoom = document.getElementById("tCanvas");
var zoomCtx = zoom.getContext('2d');
zoomCtx.clearRect(0, 0, zoom.width, zoom.height);
zoomCtx.drawImage(main, e.x, e.y, 200, 200, 0, 0, 300, 300);
zoom.style.top = e.pageY - 70 + "px"
zoom.style.left = e.pageX - 10 + "px"
e.pageY = -150
e.pageX = -150
zoom.style.display = "block";
});
main.addEventListener("mouseleave", function() {
var zoom = document.getElementById("tCanvas");
zoom.style.display = "none";
});
drawing.src = base64;
};
<canvas id="tCanvas" class="cgm" height="100" width="100" style="background-color:white; position: absolute; display: none; z-
index:1;border:1px solid red;"> </canvas>
<canvas tabindex=1 class="cgm" id="canvas1" style="position:relative; background:white;
left:0;right:0;margin:auto;z-index:1;margin-top:70px; "></canvas>
<p></p>
<button id="zoom" onclick="magnify();">Zoom</button>
Here's a fiddle for reference (I fixed the height to display the scroll issue).
JSFiddle
I simplified a lot of the code on your JSFiddle.
See if this is the behavior you are looking for:
const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext("2d");
const zoom = document.getElementById("tCanvas");
const zoomCtx = zoom.getContext('2d');
for (let i = 10; i < 20; i++)
for (let j = -60; j < 800; j += 60)
ctx.fillText(j + i, i * 20 - 180, i * 9 + j);
function getMousePos(evt) {
var rect = canvas.getBoundingClientRect()
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
}
}
canvas.addEventListener("mousemove", function(e) {
zoomCtx.clearRect(0, 0, zoom.width, zoom.height);
let pos = getMousePos(e)
zoomCtx.drawImage(canvas, pos.x, pos.y, 200, 200, 0, 0, 300, 300);
zoom.style.top = e.pageY - 10 + "px"
zoom.style.left = e.pageX - 10 + "px"
zoom.style.display = "block";
});
canvas.addEventListener("mouseleave", function() {
zoom.style.display = "none";
});
#tCanvas {
border: 1px solid red;
display: none;
position: absolute;
background-color: #808080;
pointer-events: none;
}
#canvas1 {
background-color: #808080;
}
<canvas id="tCanvas" width=100 height=100></canvas>
<canvas id="canvas1" width=240 height=800></canvas>
I think that your issue was with pointer-events: none; the top canvas was preventing the events from reaching the bottom canvas.
Also you don't have to declare your document.getElementById(".. on every function, those should be global constants
For the issue with a long canvas we need to use canvas.getBoundingClientRect in the calculation to get the real position of the mouse in the canvas
I'm writing a drawing app in HTML5 Canvas, which includes a freehand draw with the mouse.
I have a problem whereby the mouse move to draw the stroke is not under the crosshair cursor. The X co-ordinate is fine, but the Y coordinate is offset by a varying amount as the mouse pointer is moved (closer at the top of the page, drifts further away as we closer to the bottom).
It has something to do with the 'header bar' div at the top.
Here is the code.
<style>
#divContainer {
width: 100%;
height: 100%;
}
#divHeader {
position: absolute;
left: 0px;
top: 0px;
right: 0px;
height: 28px;
background-color: #333;
}
#divContentArea {
position: absolute;
left: 0px;
top: 29px;
right: 0px;
bottom: 5px;
}
#divContentCenter {
position: absolute;
top: 0px;
left: 0px;
bottom: 0px;
right:0px;
}
.canvascontainer {
position: relative;
overflow: auto;
width:100%;
height:100%;
}
.canvas {
cursor: crosshair;
width: 100%;
height: 100%;
position:absolute;
left:0px;
top:0px;
z-index: 2;
}
.maincanvas {
cursor: crosshair;
width: 100%;
height: 100%;
position:absolute;
left:0px;
top:0px;
z-index: 1;
}
</style>
<div id="divContainer">
<div id="divHeader">
The Header
</div>
<div id="divContentArea">
<div id="divContentCenter">
<div id='canvascontainer' class='canvascontainer' >
<canvas id="canvas" class='canvas'>
Sorry, your browser does not support a canvas object.
</canvas>
<canvas id="maincanvas" class='maincanvas'>
Sorry, your browser does not support a canvas object.
</canvas>
</div>
</div>
</div>
</div>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
const canrect = canvas.getBoundingClientRect();
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var maincanvas = document.getElementById('maincanvas');
var maincontext = maincanvas.getContext('2d');
maincanvas.width = window.innerWidth;
maincanvas.height = window.innerHeight;
var lastPoint;
var startPoint;
var isDrawing = false;
context.lineWidth = 3;
context.lineJoin = context.lineCap = 'round';
context.setLineDash([0, 0]);
context.globalAlpha = 1.0;
function drawGuideLines() {
for ( i = 0; i < canvas.height; i += 20 ) {
context.beginPath();
context.setLineDash([2, 2]);
context.lineWidth = 1;
if ( i % 60 == 0 ) {
context.lineWidth = 2;
}
context.strokeStyle = '#ccc';
context.moveTo(0,i);
context.lineTo(canvas.width,i);
context.stroke();
}
for ( i = 0; i < canvas.width; i += 20 ) {
context.beginPath();
context.setLineDash([2, 2]);
context.lineWidth = 1;
if ( i % 60 == 0 ) {
context.lineWidth = 2;
}
context.strokeStyle = '#ccc';
context.moveTo(i,0);
context.lineTo(i, canvas.height);
context.stroke();
}
}
function getMousePos(e) {
return {
x: e.offsetX - canrect.left,
y: e.offsetY + canrect.top
};
}
function clearPage() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
function copyToMain () {
maincontext.drawImage(canvas, 0, 0);
clearPage();
}
canvas.onmousedown = function(e) {
isDrawing = true;
canvas.addEventListener("mousemove", drawDirectPath, false);
lastPoint = { x: e.clientX, y: e.clientY };
lastPoint = { x: e.offsetX, y: e.offsetY };
// lastPoint = { x: e.offsetX, y: e.PageY };
lastPoint = getMousePos(e);
};
function drawDirectPath(e) {
if (!isDrawing) return;
context.beginPath();
context.setLineDash([0, 0]);
context.lineWidth = 3;
context.strokeStyle = 'red';
context.fillStyle = 'red';
//show_mouse_info(e, 'GetMousePos:' + getMousePos(e).x + ', ' + getMousePos(e).y);
//show_mouse_info(e, 'boundrect:' + canrect.x + ', ' + canrect.y);
//mx = e.clientX;
//my = e.clientY;
mx = e.offsetX;
my = e.offsetY;
context.moveTo(lastPoint.x, lastPoint.y);
context.lineTo(mx, my);
context.stroke();
lastPoint = { x: mx, y: my };
}
canvas.onmouseup = function() {
isDrawing = false;
copyToMain ();
};
canvas.onmouseleave = function() {
isDrawing = false;
copyToMain ();
};
drawGuideLines();
</script>
I have tried using OffsetX/Y, PageX/Y, clinetX/Y to see if these make a difference but I cannot solve the problem.
The test, click the mouse in the top right or top left and drag/draw down diagonally to the opposite bottom corner to see the effect.
Don't give the canvas a width and height of 100% using CSS.
.canvas {
cursor: crosshair;
position:absolute;
left:0px;
top:0px;
z-index: 2;
}
Couple other things you may want to consider
Always declare variables for (let i =...
Don't make getBoundingClientRect() a const. The reason for this is if you needed to add a resize function you wouldn't be able to change the bounds because the variable holds the original bounds.
You are assigning lastPoint over and over. Not really sure what this is about.
lastPoint = { x: e.clientX, y: e.clientY };
lastPoint = { x: e.offsetX, y: e.offsetY };
// lastPoint = { x: e.offsetX, y: e.PageY };
lastPoint = getMousePos(e);
I'm working on a pixel art project. What I was expecting to do here is be able to click any box inside the grid and render it with the the color from a color input.
I managed to understand how the loop works to create a grid using canvas and javascript. Next, I created a function called colorPicker() which allows me to click on any of the grid cells and take the value from the color input and render it that color. I used canvas.addEventListener("click", function(event) { ... })
and passed variables xCoord and yCoord with the value of event.x and event.y. This allows me to return the position of the mouse on click inside the grid.
The problem I'm running into right now is that it is only rendering 1 square out of all 400 I have drawn on the grid. The rendering works, it's just I can only click one box and render its color from the input.
Can anyone provide me with some help to solve this function just using the javascript logic I currently have right now?
var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");
// The function that draws the grid
function drawGrid() {
ctx.fillStyle = "#009EFF";
ctx.fillRect(0, 0, 400, 400);
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
// The for loop that draws the x-axis
for (x = 0; x <= 400; x += 20) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 400);
ctx.stroke();
}
// The for loop that draws the y-axis
for (y = 0; y <= 400; y += 20) {
ctx.moveTo(0, y);
ctx.lineTo(400, y);
ctx.stroke();
}
}
drawGrid();
// Function that clicks and fill grid boxes w / color
function colorPicker() {
canvas.addEventListener("click", function(event) {
var newColor = color.value;
ctx.fillStyle = newColor;
xCoord = event.x;
yCoord = event.y;
ctx.fillRect(0, 0, 20, 20);
console.log(xCoord, yCoord);
console.log(newColor);
});
}
colorPicker();
#canvas {
border: 1px solid black;
background-size: 100%;
display: block;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
padding-left: 0;
padding-right: 0;
}
<div class="color-wheel">
Color: <input type="color" id="color" />
</div>
<canvas id="canvas" width="400" height="400"></canvas>
Your problem is this line:
ctx.fillRect(0, 0, 20, 20);
Instead of filling the clicked cell, you’re filling only the upper left cell on every click.
Currently you’re just using (0, 0) here, when you should be calculating this position from the cursor. The coordinates used by the canvas and the cursor are different though, so you’ll need to write a conversion function:
function mousePosToCanvasPos(mouseX, mouseY) {
var canvasPos = canvas.getBoundingClientRect();
return {
x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
};
}
The mousePosToCanvasPos() function gets the current rendered position of the canvas (canvasPos), and calculates the offset of the cursor from the upper left corner of the canvas (mouse_ - canvasPos._). It then rounds this value down to the nearest multiple of 20 to return the upper left corner of the clicked cell (Math.floor((mouse_ - canvasPos._) / 20) * 20). If you change your cell size to something other than 20, be sure to change it in this function too. Or better yet, extract the constant (var cellSize = 20).
Adding this function to your code gives us:
var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");
// The function that draws the grid
function drawGrid() {
ctx.fillStyle = "#009EFF";
ctx.fillRect(0, 0, 400, 400);
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
// The for loop that draws the x-axis
for (x = 0; x <= 400; x += 20) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 400);
ctx.stroke();
}
// The for loop that draws the y-axis
for (y = 0; y <= 400; y += 20) {
ctx.moveTo(0, y);
ctx.lineTo(400, y);
ctx.stroke();
}
}
drawGrid();
function mousePosToCanvasPos(mouseX, mouseY) {
var canvasPos = canvas.getBoundingClientRect();
return {
x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
};
}
// Function that clicks and fill grid boxes w / color
function colorPicker() {
canvas.addEventListener("click", function(event) {
var newColor = color.value;
ctx.fillStyle = newColor;
var canvasCellPos = mousePosToCanvasPos(event.x, event.y);
ctx.fillRect(canvasCellPos.x, canvasCellPos.y, 20, 20);
console.log(event.x, event.y);
console.log(newColor);
});
}
colorPicker();
#canvas {
border: 1px solid black;
background-size: 100%;
display: block;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
padding-left: 0;
padding-right: 0;
}
<div class="color-wheel">
Color: <input type="color" id="color" />
</div>
<canvas id="canvas" width="400" height="400"></canvas>
You’ll notice that something’s still not quite right here: every time you fill a cell, it makes its border thinner. To solve this, you need to remove one pixel from each side of your fillRect:
ctx.fillRect(canvasCellPos.x + 1, canvasCellPos.y + 1, 18, 18);
var title = document.getElementById("title");
var canvas = document.getElementById("canvas");
var color = document.getElementById("color");
var btn = document.getElementById("btn");
var ctx = canvas.getContext("2d");
// The function that draws the grid
function drawGrid() {
ctx.fillStyle = "#009EFF";
ctx.fillRect(0, 0, 400, 400);
ctx.strokeStyle = "black";
ctx.lineWidth = 1;
// The for loop that draws the x-axis
for (x = 0; x <= 400; x += 20) {
ctx.moveTo(x, 0);
ctx.lineTo(x, 400);
ctx.stroke();
}
// The for loop that draws the y-axis
for (y = 0; y <= 400; y += 20) {
ctx.moveTo(0, y);
ctx.lineTo(400, y);
ctx.stroke();
}
}
drawGrid();
function mousePosToCanvasPos(mouseX, mouseY) {
var canvasPos = canvas.getBoundingClientRect();
return {
x: Math.floor((mouseX - canvasPos.x) / 20) * 20,
y: Math.floor((mouseY - canvasPos.y) / 20) * 20,
};
}
// Function that clicks and fill grid boxes w / color
function colorPicker() {
canvas.addEventListener("click", function(event) {
var newColor = color.value;
ctx.fillStyle = newColor;
var canvasCellPos = mousePosToCanvasPos(event.x, event.y);
ctx.fillRect(canvasCellPos.x + 1, canvasCellPos.y + 1, 18, 18);
console.log(event.x, event.y);
console.log(newColor);
});
}
colorPicker();
#canvas {
border: 1px solid black;
background-size: 100%;
display: block;
margin-top: 50px;
margin-left: auto;
margin-right: auto;
padding-left: 0;
padding-right: 0;
}
<div class="color-wheel">
Color: <input type="color" id="color" />
</div>
<canvas id="canvas" width="400" height="400"></canvas>
When running my program I have an image I want to draw on the mouse's x position(clientX) and y position(clientY).
When running the program regularly by not using client x and y in the position for being drawn, it works just fine.
This is the image
//variables
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var player = new Image();
player.src = "http://i.stack.imgur.com/P9vJm.png";
//functions
function start() {
setInterval(update, 10);
}
function update() {
clearRender();
render();
}
function clearRender() {
ctx.clearRect(0,0,1300,500);
}
function render() {
var mx = document.clientX;
var my = document.clientY;
ctx.drawImage(player, mx, my);
}
#canvas {
height: 500px;
width: 1300px;
background-color: black;
position: absolute;
left: 25px;
top: 50px;
}
body {
background-color: white;
}
<!DOCTYPE html>
<html>
<head>
<title> Space Invaders </title>
<link rel="stylesheet" type="text/css" href="invader.css">
</head>
<body>
<canvas id="canvas"> </canvas>
<script type="text/javascript" src="invader.js"></script>
</body>
</html>
To get you started, you would need an event handler to get your mouse position
c.addEventListener('mousemove', update, false);
JS:
//variables
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var player = new Image();
player.src = "http://i.stack.imgur.com/P9vJm.png";
c.addEventListener('mousemove', update, false);
//functions
function start() {
setInterval(update, 10);
}
function update(e) {
//clearRender();
render(e);
}
function clearRender() {
ctx.clearRect(0, 0, 1300, 500);
}
function render(e) {
var pos = getMousePos(c, e);
posx = pos.x;
posy = pos.y;
ctx.drawImage(player, posx, posy);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
Here's a fiddle: https://jsfiddle.net/vwbo8k6k/
This might help you understand more about mouse positions, but I hope the image shows this time.
http://stackoverflow.com/a/17130415/2036808