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
Related
So far, I create a canvas and I add two images one over another.how to create a eraser to scratch upper image and then shows it lower image ..pls help me..
It's very essential to me ..I surprise to my brother birthday...pls help me..Thank you..
I just want to know..
how to add two images on canvas? In my code is it right..?
how to create eraser for clearing upper image.. with touchmove in javaScript
javaScript
window.addEventListener("click",play);
function play() { document.getElementById("song").play();
}
window.onload = function () {
var img1= new Image();
img1.src = 'https://dl.dropbox.com/s/xxz0nbrplhst2w2/20201010_174008.jpg?';
img1.onload = function ()
{
filling1(img1);
}
var img2=new Image();
img2.src=
"https://dl.dropbox.com/s/zpoxft30lzrr5mg/20201012_102150.jpg";
img2.onload = function ()
{
filling2(img2);
}
function filling1(img) {
var canvas= document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0,1012,1012);
}
function filling2(img) {
var canvas= document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0,1078,1260);
}
}
CSS
body { background: #dddddd;
}
canvas
{
margin: 50px;
padding: 0px;
border: thin inset #aaaaaa;
width: 300px;
height: 400px;
position:absolute;
background-image:url("");
}
HTML
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2#9"></script>
</head>
<body>
<div>
<canvas id="canvas"> Canvas not supported </canvas>
</div>
<audio controls style="display:none;"loop id="song" >
<source src="https://dl.dropbox.com/s/bsgain4rsi5q44m/Happy-Birthday-Instrumental">
<!-- <source src="https://dl.dropbox.com/s/bbxas9a8jvts3ng/birthday%20wishes%20song%20slow%20motion"> -->
<script>
Swal.fire("Just Scratch It").then((value)=> {Swal.fire('I hope you like it','Thank you','success');});
</script>
</audio>
</body>
</html>
It is another code for touchmove but it doesn't work as a eraser ..why..?
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById("canvas");
var c = canvas.getContext("2d");
canvas.width = 300;
canvas.height = 380;
var mx, my;
function Circle(x, y){
this.x = x;
this.y = y;
this.radius = 30;
this.draw = function(){
c.beginPath();
c.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
c.stroke();
}
this.update = function(){
canvas.addEventListener("touchmove",
function(e){
mx = e.touches[0].clientX;
my = e.touches[0].clientY;
circle.x = mx;
circle.y = my;
});
if(this.x + this.radius > canvas.width){
this.x = canvas.width / 2;
}
if(this.x - this.radius < 0){
this.x = canvas.width / 2;
}
if(this.y + this.radius > canvas.height){
this.y = canvas.height / 2;
}
if(this.y - this.radius < 0){
this.y = canvas.height / 2;
}
circle.draw()
}
}
var circle = new Circle(100, 100);
function a(){
requestAnimationFrame(a);
c.clearRect(0, 0, canvas.width, canvas.height);
circle.update();
}
a();
</script>
</body>
</html>
window.addEventListener("click",play);
function play() { document.getElementById("song").play();}
var canvas= document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 400;
window.onload = function () {
var img = new Image();
img.onload = () => ctx.drawImage(img,0,0,300,400);
img.src = "https://dl.dropbox.com/s/zpoxft30lzrr5mg/20201012_102150.jpg";
}
function Circle(x, y){
this.x = x;
this.y = y;
this.radius = 30;
this.draw = function(){
ctx.save();
ctx.globalCompositeOperation = 'destination-out';
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.fill();
ctx.closePath();
ctx.restore();
}
}
var circle = new Circle(100, 100);
canvas.addEventListener("touchmove", function(e){
var mx = e.touches[0].clientX;
var my = e.touches[0].clientY;
move(mx, my);
});
canvas.addEventListener("mousemove", function(e){
var mx = e.offsetX;
var my = e.offsetY;
move(mx, my);
});
function move(x,y){
circle.x = x;
circle.y = y;
circle.draw();
}
body { background: #dddddd;}
canvas {
margin: 20px;
padding: 0px;
border: thin inset #aaaaaa;
width: 300px;
height: 400px;
position:absolute;
background-image: url("https://dl.dropbox.com/s/xxz0nbrplhst2w2/20201010_174008.jpg");
background-size: 100% 100%;;
}
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2#9"></script>
</head>
<body>
<div>
<canvas id="canvas"> Canvas not supported </canvas>
</div>
<audio controls style="display:none;"loop id="song" >
<source src="https://dl.dropbox.com/s/bsgain4rsi5q44m/Happy-Birthday-Instrumental">
<!-- <source src="https://dl.dropbox.com/s/bbxas9a8jvts3ng/birthday%20wishes%20song%20slow%20motion"> -->
</audio>
<script>
Swal.fire("Just Scratch It").then((value)=> {Swal.fire('I hope you like it','Thank you','success');});
</script>
</body>
</html>
I've set up a canvas where I am drawing a line on top of an image (second canvas underneath it). The canvas is fitted into a container. My problem is that when I draw a line (two clicks needed), it is not drawn in the right place.
The goal is to be able that the line will be drawn exactly where I click, even after the canvas is resized to fit the container's size.
My code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="/Scripts/jquery-1.10.2.min.js"></script>
</head>
<body>
<style>
.container {
position: relative;
width: 50%;
}
canvas {
max-width: 100%;
height: auto;
}
.container > canvas {
position: absolute;
top: 100px;
left: 100px;
}
.container .buttons {
position: absolute;
top: 0;
left: 0;
}
#canvas-bg {
z-index: 0;
}
#canvas-draw {
z-index: 1;
}
</style>
<div class="container">
<canvas id="canvas-draw" width="300" height="150" style="border: 1px solid #d3d3d3;">Your browser does not support the HTML5 canvas tag.</canvas>
<canvas id="canvas-bg" width="300" height="150" style="border: 1px solid #d3d3d3;">Your browser does not support the HTML5 canvas tag.</canvas>
</div>
<script>
var needFirstPoint = true;
function drawNextLine(ctx, x, y) {
if (needFirstPoint) {
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(x, y);
needFirstPoint = false;
}
else {
ctx.lineTo(x, y);
ctx.stroke();
}
}
var canvasDrawing = null;
var canvasImage = null;
var ctxDrawing = null;
var ctxImage = null;
$(document).ready(function () {
canvasDrawing = $('#canvas-draw').get(0);
canvasImage = $("#canvas-bg").get(0);
if (!canvasDrawing.getContext) { return; }
ctxDrawing = canvasDrawing.getContext('2d');
ctxImage = canvasImage.getContext('2d');
function isCanvasBlank(canvas) {
var blank = document.createElement('canvas');
blank.width = canvas.width;
blank.height = canvas.height;
return canvas.toDataURL() == blank.toDataURL();
}
$('#canvas-draw').on('click', function (e) {
if (needFirstPoint == false && isCanvasBlank(canvasDrawing) == false) {
ctxDrawing.clearRect(0, 0, canvasDrawing.width, canvasDrawing.height);
needFirstPoint = true;
return false;
}
var offset = $(this).offset();
var x = e.pageX - offset.left;
var y = e.pageY - offset.top;
drawNextLine(ctxDrawing, x, y);
});
////////////
var imageLoader = document.getElementById('imageLoader');
imageLoader.addEventListener('change', handleImage, false);
function handleImage(e) {
var reader = new FileReader();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
canvasImage.width = img.width;
canvasImage.height = img.height;
ctxImage.drawImage(img, 0, 0);
// refresh drawing canvas
$('#canvas-draw').width(img.width);
$("#canvas-draw").height(img.height);
canvasDrawing = $('#canvas-draw').get(0);
ctxDrawing = canvasDrawing.getContext('2d');
canvasDrawing.width = img.width;
canvasDrawing.height = img.height;
ctxDrawing.clearRect(0, 0, canvasDrawing.width, canvasDrawing.height);
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
});
</script>
<div class="buttons">
Clear canvas
<input type="file" id="imageLoader" name="imageLoader" />
</div>
To accurately poll the pointer position on the Canvas you have to account for it's offset relative to the top-left corner of the screen - as .clientX (.pageX) and .clientY (.pageY) events return the pointer position relative to the browser window not the Canvas itself.
In plain JavaScript something like the following is often used...
/* click event handler */
function canvasClicked(e) {
var cnvBox = document.getElementById('canvas').getBoundingClientRect();
/* canvas-relative values */
var X = e.clientX - cnvBox.left,
Y = e.clientY - cnvBox.top;
}
... and the JQuery way goes something like this...
$("#canvas").click(function(e){
var cnvOffset = $(this).offset();
/* canvas-relative values */
var X = e.pageX - cnvOffset.left,
Y = e.pageY - cnvOffset.top;
});
Hoped that helped :)
I want do box selection of window desk as shown for the image below but then with my canvas code.
I'm a newbie on canvas, and I had assumed that drawing the image with requestAnimationFrame would be the same as clearRect () and thus eliminate the previously drawn rectangles.
My problem is that all the previous rectangles are not deleted, how can this be achieved?
My code:
window.addEventListener("load", _init);
function _init(w = window, d = document) {
var canvas = d.getElementsByTagName("CANVAS")[0],
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var cW = canvas.width,
cH = canvas.height,
flag = 0,
obj = {
initX: null,
initY: null,
curX: null,
curY: null
};
canvas.addEventListener("mousedown", e => {
flag = 1;
obj.initX = e.clientX;
obj.initY = e.clientY;
});
canvas.addEventListener("mouseup", e => {
console.log("Mouseup!");
flag = 0;
});
canvas.addEventListener("mousemove", e => {
if(flag === 1) {
flag = 2;
}
if(flag === 2) {
obj.curX = e.clientX;
obj.curY = e.clientY;
}
});
function scene() {
drawBackground();
if(flag === 2) drawRectangle(obj);
requestAnimationFrame(scene);
}
function drawBackground() {
var image = new Image();
image.src = "http://wallpaperswide.com/download/background_logon_default_windows_7-wallpaper-1920x1200.jpg";
image.onload = _ => {
ctx.drawImage(image, 0, 0, cW, cH);
};
}
function drawRectangle(data) {
ctx.save();
ctx.strokeStyle = "rgba(48, 242, 62, 0.75)";
ctx.moveTo(data.initX, data.initY);
ctx.lineTo(data.curX, data.initY);
ctx.lineTo(data.curX, data.curY);
ctx.lineTo(data.initX, data.curY);
ctx.lineTo(data.initX, data.initY);
ctx.stroke();
ctx.restore();
}
requestAnimationFrame(scene);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Square Generator </title>
<script src="square.js"></script>
<style>
body,html {
padding: 0; border: 0; margin: 0; top: 0; left: 0; overflow: hidden;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
</html>
You need to call the ctx.beginPath() function
The CanvasRenderingContext2D.beginPath() method of the Canvas 2D API starts a new path by emptying the list of sub-paths. Call this method when you want to create a new path.
//Call that function within your `drawRectangle`logic
function drawRectangle(data) {
ctx.beginPath();
ctx.strokeStyle = "rgba(48, 242, 62, 0.75)";
....
}
window.addEventListener("load", _init);
function _init(w = window, d = document) {
var canvas = d.getElementsByTagName("CANVAS")[0],
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var cW = canvas.width,
cH = canvas.height,
flag = 0,
obj = {
initX: null,
initY: null,
curX: null,
curY: null
};
canvas.addEventListener("mousedown", e => {
flag = 1;
obj.initX = e.clientX;
obj.initY = e.clientY;
});
canvas.addEventListener("mouseup", e => {
flag = 0;
});
canvas.addEventListener("mousemove", e => {
if (flag === 1) {
flag = 2;
}
if (flag === 2) {
obj.curX = e.clientX;
obj.curY = e.clientY;
}
});
function scene() {
drawBackground();
if (flag === 2) drawRectangle(obj);
requestAnimationFrame(scene);
}
function drawBackground() {
var image = new Image();
image.src = "http://wallpaperswide.com/download/background_logon_default_windows_7-wallpaper-1920x1200.jpg";
image.onload = _ => {
ctx.drawImage(image, 0, 0, cW, cH);
};
}
function drawRectangle(data) {
ctx.beginPath();
ctx.strokeStyle = "rgba(48, 242, 62, 0.75)";
ctx.moveTo(data.initX, data.initY);
ctx.lineTo(data.curX, data.initY);
ctx.lineTo(data.curX, data.curY);
ctx.lineTo(data.initX, data.curY);
ctx.lineTo(data.initX, data.initY);
ctx.stroke();
ctx.restore();
}
requestAnimationFrame(scene);
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Square Generator </title>
<script src="square.js"></script>
<style>
body,
html {
padding: 0;
border: 0;
margin: 0;
top: 0;
left: 0;
overflow: hidden;
}
</style>
</head>
<body>
<canvas></canvas>
</body>
</html>
I have a drawing app which consists of a container with a background image in grayscale and over it, there's another image (the same but not in grayscale).
When I draw on my image, I would to erase where I drawn or turn in grayscale (to reproduce the image in background).
How can I achieve that ?
Here is my code :
<!DOCTYPE html>
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#wrapper {
width: 600px;
height: 400px;
border: 1px solid black;
margin: 0 auto;
background-image: url('elephant-nb-400.jpg');
}
</style>
</head>
<body>
<div id="wrapper">
<canvas width="600" height="400"></canvas>
</div>
<script>
window.onload = function() {
var wrapper = document.querySelector("#wrapper");
var canvas = document.querySelector("#wrapper canvas");
var context = canvas.getContext("2d");
var image = document.createElement("img");
image.setAttribute("src", "elephant-400.jpg");
image.onload = function() {
context.drawImage(image, 0, 0, 600, 400);
};
var positionsX = new Array();
var positionsY = new Array();
var movements = new Array();
var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
var data = imageData.data;
var isErasing;
canvas.addEventListener("mousedown", function(e) {
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
isErasing = true;
addPositions(mouseX, mouseY);
draw();
});
canvas.addEventListener("mousemove", function(e) {
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
if(isErasing) {
addPositions(mouseX, mouseY, true);
draw();
}
});
canvas.addEventListener("mouseup", function(e) {
isErasing = false;
});
var addPositions = function(x, y, isMoving) {
positionsX.push(x);
positionsY.push(y);
movements.push(isMoving);
}
var draw = function(){
//context.clearRect(0, 0, context.canvas.width, context.canvas.height); // Clears the canvas
for(var i=0; i < positionsX.length; i++) {
context.beginPath();
if(movements[i] && i){
}else{
}
context.lineTo(positionsX[i], positionsY[i]);
context.closePath();
context.stroke();
}
}
}
</script>
</body>
My problem is solved.
You need to get the image data : var imageData = context.getImageData(0, 0, canvas.width, canvas.height);
In function draw(), you need to add : context.putImageData(imageData, 0, 0, positionsX[i]-1, positionsY[i], 20, 20); after context.moveTo(positionsX[i-1], positionsY[i-1]);and context.moveTo(positionsX[i]-1, positionsY[i]);
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>