Drawing app : turn pixels to grayscale or erase them - javascript

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]);

Related

Line not drawn in the right position on the canvas

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 :)

Why the last rectangle isnt delete?

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>

Image not showing in javascript

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

drawing a rectange over an image on canvas using dragging event

I am trying to draw a rectangle on an image using the mouse and dragging events on HTML5.
My code is shown below. When I draw the rectangle below, the actual image on the canvas disappears. Could you tell me what I am doing wrong? My intended goal is to have the rectangle on top of the image. I have attached a picture of what I actually want to see as the end result.
What am I doing wrong ?
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="400"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 69, 50);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
// ctx.globalAlpha = 0.5;
rect = {},
drag = false;
var rectStartXArray = new Array() ;
var rectStartYArray = new Array() ;
var rectWArray = new Array() ;
var rectHArray = new Array() ;
function init() {
canvas.addEventListener('mousedown', mouseDown, false);
canvas.addEventListener('mouseup', mouseUp, false);
canvas.addEventListener('mousemove', mouseMove, false);
}
function mouseDown(e) {
rect.startX = e.pageX - this.offsetLeft;
rect.startY = e.pageY - this.offsetTop;
drag = true;
}
function mouseUp() {
rectStartXArray[rectStartXArray.length] = rect.startX;
rectStartYArray[rectStartYArray.length] = rect.startY;
rectWArray[rectWArray.length] = rect.w;
rectHArray[rectHArray.length] = rect.h;
drag = false;
}
function mouseMove(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.clearRect(0, 0, canvas.width, canvas.height);
draw();
}
//drawOldShapes();
}
function draw() {
ctx.beginPath();
ctx.fillStyle="#FF0000";
ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);
ctx.stroke();
}
function drawOldShapes(){
for(var i=0;i<rectStartXArray.length;i++)
{
if(rectStartXArray[i]!= rect.startX && rectStartYArray[i] != rect.startY && rectWArray[i] != rect.w && rectHArray[i] != rect.h)
{
ctx.beginPath();
ctx.fillStyle="#FF0000";
ctx.fillRect(rectStartXArray[i], rectStartYArray[i], rectWArray[i], rectHArray[i]);
ctx.stroke();
}
}
}
init();
</script>
</body>
</html>
You are clearing the whole canvas inside draw() by calling ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h);. Remove the line and it works. Fiddle - http://jsfiddle.net/da8wv75k/

Moving a canvas from left to right is not smooth and fast

I want to move one canvas on top of another. when top canvas moves the base canvas displays its x and y. The event initially starts at mouse down. so press mouse and start moving the canvas moves smoothly from right to left but not left to right.
http://jsfiddle.net/happyomi/23PL3/3/
<head>
<style type="text/css">
body, html {
margin: 0;
}
canvas {
position: absolute;
/* top: 0;
left: 0;*/
}
#temp {
background-color: pink;
}
</style>
</head>
<body style="margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden;">
<canvas id="myCanvas" style="display: block;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas id="temp" style="position: relative">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script type="text/javascript">
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var hgap = 0;
var vgap = 0;
var rows, cols;
var annotation_x = 1;
var row = 0; var col = 0;
//ctx.font = "14px Arial";
c.width = $(document).width();
c.height = $(document).height();
var t = document.getElementById("temp");
tctx = t.getContext("2d");
// tctx.lineWidth = 10;
tctx.lineJoin = 'round';
tctx.lineCap = 'round';
tctx.strokStyle = 'red';
var mouse = { x: 0, y: 0 };
c.addEventListener('mousemove', function (evt) {
mouse.x = evt.pageX;
mouse.y = evt.pageY;
}, false);
c.addEventListener('mousedown', function (evt) {
// tctx.clearRect(0, 0, c.width, c.height);
evt.preventDefault();
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, c.width, c.height);
mouse.x = evt.pageX;
mouse.y = evt.pageY;
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
c.addEventListener('mousemove', onPaint, false);
}, false);
var onPaint = function () {
ctx.clearRect(0, 0, c.width, c.height);
tctx.clearRect(0, 0, t.width, t.height);
t.style.left = mouse.x + "px";
t.style.top = mouse.y + "px";
t.style.position = "absolute";
str = "x=" + mouse.x + " y=" + mouse.y;
ctx.fillText(str, 10, 10);
}
c.addEventListener('mouseup', function () {
c.removeEventListener('mousemove', onPaint, false);
}, false);
</script>
</body>
Heres A good Starting point for ya :) it does what your looking for. jsFiddle
/* Main Canvas */
var main = document.getElementById('main');
main.width = window.innerWidth;
main.height = window.innerHeight;
var mainCtx = main.getContext('2d');
var mainFill = '#000';
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
/* secondary canvas */
var cv = document.createElement('canvas');
cv.style.position = 'absolute';
cv.width = '200';
cv.height = '100';
cv.style.left = '0px';
cv.style.top = '0px';
var ctx = cv.getContext('2d');
var fillRect = '#ccc';
var fillText = '#000';
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
//draw this canvas to main canvas
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
var isHolding = false;
var mDown = function(e)
{
isHolding = true;
main.addEventListener('mousemove',mMove);
}
var mMove = function(e)
{
console.log('moving');
if(isHolding)
{
var xPos = e.pageX;
var yPos = e.pageY;
cv.style.left = (xPos-(cv.width/2))+'px';
cv.style.top = (yPos-(cv.height/2))+'px';
cv.width = cv.width; //clears canvas
ctx.fillStyle = fillRect;
ctx.rect(0,0,cv.width,cv.height);
ctx.fill();
ctx.fillStyle = fillText;
ctx.fillText('x: '+e.pageX,10,10);
ctx.fillText('y: '+e.pageY,50,10);
//draw temp canvas to main canvas
this.width = this.width;
mainCtx.fillStyle = mainFill;
mainCtx.rect(0,0,main.width,main.height);
mainCtx.fill();
mainCtx.drawImage(cv,parseInt(cv.style.left),parseInt(cv.style.top));
}
}
var mUp = function(e)
{
isHolding = false;
main.removeEventListener('mousemove',mMove);
}
main.addEventListener('mousedown',mDown);
main.addEventListener('mouseup',mUp);
also it gets rid of the move event when not being used which will help have less event dispatches in memory and help with performance.

Categories

Resources