fill-in image with canvas drawing - javascript

code description:
i am using canvas to draw using some java-script .. i am expecting the user to draw some thing in the canvas area then save it or clean the canvas area ..
this is what i have done so far .. here is the code/; but it needs a browser to work
https://jsfiddle.net/RababAlkhalifa/k0y1yzh8/
java script:
var lastPt = null;
var canvas;
var ctx;
function init() {
canvas = document.getElementById("mycanvas");
ctx = canvas.getContext("2d");
var offset = getOffset(canvas);
if (window.PointerEvent) {
canvas.addEventListener("pointerdown", function() {
canvas.addEventListener("pointermove", draw, false);
}, false);
canvas.addEventListener("pointerup", endPointer, false);
} else {
//Provide fallback for user agents that do not support Pointer Events
canvas.addEventListener("mousedown", function() {
canvas.addEventListener("mousemove", draw, false);
}, false);
canvas.addEventListener("mouseup", endPointer, false);
}
}
// Event handler called for each pointerdown event:
function draw(e) {
if (lastPt != null) {
ctx.beginPath();
// Start at previous point
ctx.moveTo(lastPt.x, lastPt.y);
// Line to latest point
ctx.lineTo(e.pageX, e.pageY);
// Draw it!
ctx.stroke();
}
//Store latest pointer
lastPt = { x: e.pageX, y: e.pageY };
}
function getOffset(obj) {
//...
}
function endPointer(e) {
//Stop tracking the pointermove (and mousemove) events
canvas.removeEventListener("pointermove", draw, false);
canvas.removeEventListener("mousemove", draw, false);
//Set last point to null to end our pointer path
lastPt = null;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var w = canvas.width;
canvas.width = 1;
canvas.width = w;
}
function download() {
var dt = canvas.toDataURL();
this.href = dt; //this may not work in the future..
clearCanvas();
}
document.getElementById('download').addEventListener('click', download, false);
html:
<canvas id="mycanvas" width="600px" height="600px" style="border:1px solid black;"></canvas>
<div class="convas_contrllers">
<button onclick="clearCanvas()">Clear</button>
<a id="download" download="CanvasDemo.png">Download as image</a>
</div>
<a id="download" download="CanvasDemo.png">Download as image</a>
<div class="slide" id="img1"><img src="http://placehold.it/300x100&text=FooBar1" /></div>
the problem:
i need to put the saved canvas in the image id=img1 element before clear or saving the canvas .. is this possible ?

Yes, this is possible. Here's how you could achieve that ...
var image = document.querySelector('#img1');
var canvas = document.querySelector('#mycanvas');
var ctx = canvas.getContext('2d');
var isMousePressed = false;
canvas.onmousedown = function(e) {
isMousePressed = true;
ctx.beginPath();
ctx.moveTo(e.offsetX, e.offsetY);
};
canvas.onmouseup = function() {
isMousePressed = false;
};
canvas.onmousemove = function(e) {
if (isMousePressed) {
ctx.lineTo(e.offsetX, e.offsetY);
ctx.stroke();
}
};
function clearCanvas() {
image.src = canvas.toDataURL();
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function download() {
image.src = canvas.toDataURL();
var a = document.createElement('a');
a.href = canvas.toDataURL();
a.download = 'myImage.png'; //image name
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
body{margin:10px 0 0 0;overflow:hidden}.slide{position:absolute;top:10px;left:200px}
<canvas id="mycanvas" width="180" height="180" style="border:1px solid black; cursor: default;"></canvas>
<div class="convas_contrllers">
<button id="clear" onclick="clearCanvas()">Clear</button>
<button id="download" onclick="download()">Download as image</button>
</div>
<div class="slide"><img id="img1" src="https://placehold.it/300x100&text=FooBar1"></div>

Related

JavaScript, canvas - drawn lines disappear after placing mouse over other element

my idea for the page is to load an image (done by <input type="file/>) and to draw some lines on it (those will represent spool points on welding map drawing.
I have tag in order to do that. However my current code is not working because I add canvas.addEventListener("mouseover", handler, false); event. Adding extra mouseout event doesn't solve the problem. Lines disappear when mouse proceed event over other elements in document. I tried to add arrow function, or add document.addEventListener('DOMContentLoaded') event. Both are not helpful.
Please answer how to keep lines visible as long as file is loaded.
Moreover I have some problems adding event listeners to clear and undo buttons - my variable lines = []; seems to store more data that I expected. How should I prepare this feature to undo last drawn line?
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://unpkg.com/chota">
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<h1 id="header" name="header">Spool assistant</h1>
<div>
<p>Click to draw lines</p>
</div>
<br/>
<div id="main-area">
<div id="draftsman-menu">
<input type="button" id="file-selector-button" value="Load pdf" onclick="document.querySelector('#file-selector').click();" />
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png, .pdf" style="display:none;">
</div>
<div id="canvas-area">
<canvas id="canvas" width=1000 height=400></canvas>
</div>
<div id="edit-menu">
<button id="clear">Clear</button>
<button id="undo">Undo</button>
<button id="save">Save</button>
</div>
</div>
<p id="status"></p>
<img id="output" style="display:none;">
<script type="text/javascript" src="../static/js/drawing_events.js"></script>
</body>
</html>
JS
// constants and variables
const status = document.querySelector("#status");
const output = document.querySelector("#output");
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
var canvasOffset = $("#canvas").offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var startX, startY, mouseX, mouseY;
var isDown = false;
var lines = [];
var imageOpacity = 1;
const canvasPosition = canvas.getBoundingClientRect();
const clearButton = document.querySelector("#clear");
const undoButton = document.querySelector("#undo");
var imageData;
// start with image change event
if (window.FileList && window.File && window.FileReader) {
document.getElementById("file-selector").addEventListener("change", event => {
output.src = "";
status.textContent = "";
// allow only one file even if user selected more
const file = event.target.files[0];
// validations
if (!file.type) {
status.textContent = "Error: The File.type property does not appear to be supported on this browser.";
return;
};
if (!file.type.match("image.*")) {
status.textContent = "Error: The selected file does not appear to be an image."
return;
};
const reader = new FileReader();
reader.addEventListener("load", event => {
output.src = event.target.result;
output.onload = function() {
lines = [];
ctx.drawImage(output, 0, 0);
};
});
reader.readAsDataURL(file);
});
};
// drawing events
canvas.addEventListener("mouseover", handler, false);
function handler(event) {
var img = new Image();
img.onload = start;
img.src = output.src;
function start() {
canvas.width = canvas.width = img.width;
canvas.height = img.height;
ctx.strokeStyle = "black";
ctx.lineWidth = 3;
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mousemove(function(e){handleMouseMove(e);});
$("#canvas").mouseup(function(e){handleMouseUp(e);});
$("#canvas").mouseout(function(e){handleMouseUp(e);});
// redraw the image
drawTheImage(img, imageOpacity);
};
function drawLines(toX, toY) {
// clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// redraw the image
drawTheImage(img,imageOpacity);
// redraw all previous lines
for(var i = 0; i < lines.length; i++) {
drawLine(lines[i]);
};
// draw the current line
drawLine({x1:startX,y1:startY,x2:mouseX,y2:mouseY});
};
function drawTheImage(img, opacity) {
ctx.globalAlpha = opacity;
ctx.drawImage(img, 0, 0);
ctx.globalAlpha = 1.00;
};
function drawLine(line){
ctx.beginPath();
ctx.moveTo(line.x1, line.y1);
ctx.lineTo(line.x2, line.y2);
ctx.stroke();
};
function handleMouseDown(e){
e.stopPropagation();
e.preventDefault();
mouseX = parseInt(e.clientX - canvasPosition["x"] + window.scrollX);
mouseY = parseInt(e.clientY - canvasPosition["y"] + window.scrollY);
// Put your mousedown stuff here
startX = mouseX;
startY = mouseY;
isDown = true;
};
function handleMouseUp(e) {
e.stopPropagation();
e.preventDefault();
// Put your mouseup stuff here
isDown = false;
lines.push({x1:startX, y1:startY, x2:mouseX, y2:mouseY});
};
function handleMouseMove(e) {
if (!isDown) {return;}
e.stopPropagation();
e.preventDefault();
mouseX = parseInt(e.clientX - canvasPosition["x"] + window.scrollX);
mouseY = parseInt(e.clientY - canvasPosition["y"] + window.scrollY);
// Put your mousemove stuff here
drawLines(mouseX, mouseY);
};
// clearing
// TODO
// function has to be replaced with undoing or loading blank page
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
lines = []
};
function undoLine() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawTheImage(img, imageOpacity);
lines.pop();
for(var i = 0; i < lines.length; i++) {
drawLine(lines[i]);
};
};
clearButton.addEventListener("click", clearCanvas);
undoButton.addEventListener("click", undoLine);
};

I'm trying to make a javascript drawing program within the browser and things are misaligned. Is there something wrong with my code?

I've been working on this really basic drawing program for a while now and just can't seem to get it to work correctly.
The user can draw in the canvas element now, but things are somehow misaligned; the lines appear far from the cursor when you attempt to draw, and I'm not sure what's causing it.
Here's my code...
html
<div class="info">
<canvas id="canvas" height="480" width="640" style="border:1px solid #000000; width: 640px; height:480px; background-color: white">Please update your browser.</canvas>
<script src="paint.js"></script>
</div>
javascript
// paint.js
(function () {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//resizing
//canvas.height = window.innerHeight;
//canvas.width = window.innerWidth;
//variables
var painting = false;
function startPosition(e) {
painting = true;
draw(e);
}
function endPosition() {
painting = false;
context.beginPath();
}
function draw(e) {
if (!painting) return;
context.lineWidth = 7;
context.lineCap = "round";
context.strokeStyle = "green";
context.lineTo(e.clientX, e.clientY);
context.stroke();
context.beginPath();
context.moveTo(e.clientX, e.clientY);
}
//EventListeners
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousemove", draw);
})();
change the clientX and clientY with offsetX and offsetY to get the right coords according to mouse position inside the element
you can read more about MouseEvent and figure out the differences between
clientX/Y
screenX/Y
offsetX/Y
try the snippet
// paint.js
(function () {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
//resizing
//canvas.height = window.innerHeight;
//canvas.width = window.innerWidth;
//variables
var painting = false;
function startPosition(e) {
painting = true;
draw(e);
}
function endPosition() {
painting = false;
context.beginPath();
}
function draw(e) {
if (!painting) return;
context.lineWidth = 4;
context.lineCap = "round";
context.strokeStyle = "green";
context.lineTo(e.offsetX, e.offsetY);
context.stroke();
context.beginPath();
context.moveTo(e.offsetX, e.offsetY);
}
//EventListeners
canvas.addEventListener("mousedown", startPosition);
canvas.addEventListener("mouseup", endPosition);
canvas.addEventListener("mousemove", draw);
})();
div {
width: 460px;
height: 460px;
border: 1px solid black;
}
<div class="info">
<canvas id="canvas" height="460" width="460" style="border:1px solid #000000; background-color: white">Please update your browser.</canvas>
<script src="paint.js"></script>
</div>

How to upload image to canvas and draw squares on it and get the squares' coordinates

I'm trying to upload an image to canvas and draw squares on it and get the squares' coordinates to send it to the backend for keys identification.
But something not right, I can't draw squares on my images.
This is my javascript which I use:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var imageObj = null;
function init() {
imageObj = new Image();
imageObj.onload = function () { ctx.drawImage(imageObj, 0, 0); };
imageObj.src =
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() { drag = false; }
function mouseMove(e) {
if (drag) {
ctx.clearRect(0, 0, 500, 500);
ctx.drawImage(imageObj, 0, 0);
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'red';
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
}
//
init();
</script>
<script type="text/javascript">
document.getElementById('imageLoader').onchange = function(e) {
var img = new Image();
img.onload = draw;
img.onerror = failed;
img.src = URL.createObjectURL(this.files[0]);
};
function draw() {
var canvas = document.getElementById('canvas');
canvas.width = this.width;
canvas.height = this.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(this, 0,0);
}
function failed() {
console.error("The provided file couldn't be loaded as an Image media");
}
and HTML:
<canvas id="canvas" ></canvas>
<input type="file" id="imageLoader" name="imageLoader"/>
You just need to assign the image to imageObj.
function draw() {
canvas.width = this.width;
canvas.height = this.height;
ctx.drawImage(this, 0,0);
imageObj = this; //here
}
JSFiddle here

How to make an area in canvas html droppable?

How do you transfer an image of a div or file to some droppable canvas area (inside canvas)? My intention is to make a photobook.
I was doing it with div tags, but I have seen that all photobooks do it with canvas. They even send the photo as drop as canvas.
<canvas id="canvas" style="position:absolute;"></canvas>
<canvas id="canvas-encima" style="position:absolute;left:8em;top:7em;"></canvas>
<script>
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width= 1000;
canvas.height = 481;
var background = new Image();
background.src = "upload/plantilla5prueba.jpg";
background.onload = function() {
ctx.drawImage(background,0,0);
}
var canvas2 = document.getElementById("canvas-encima"),
ctx2 = canvas2.getContext("2d");
canvas2.width= 330;
canvas2.height = 280;
var image2 = new Image();
image2.src = "upload/celular.png";
image2.onload = function() {
ctx2.drawImage(image2,0,0);
;}
</script>
I believe that with the drag and drop of a blob or uploaded file to the canvas droppable, the photobook would almost be made.
In order to make an area in the canvas droppable I mark first the droppable zone. See the markDroppableZone() function. On dragenter, dragover and drop I check first if the mouse is inside the droppable zone using isPointInPath. Please see onEvent() function.
If the mouse is in path I use e.stopPropagation(); e.preventDefault();. This is preventing the opening of the dragged image in a new window.
Next on drop I procede to handle the dropped files. See the handleFiles() function.
const ctx = canvas.getContext("2d")
let cw = canvas.width;
let ch = canvas.height;
//the mouse
let m = {}
ctx.setLineDash([4]);
markDroppableZone();
ctx.stroke();
ctx.setLineDash([]);
function markDroppableZone(){
ctx.beginPath();
ctx.rect(10,10,160,160);
}
canvas.addEventListener("dragenter", dragenter, false);
canvas.addEventListener("dragover", dragover, false);
canvas.addEventListener("drop", drop, false);
function dragenter(e) {
onEvent(e);
}
function dragover(e) {
onEvent(e);
}
function drop(e) {
onEvent(e);
let data = e.dataTransfer;
let files = data.files;
// handle files
handleFiles(files);
}
function handleFiles(files){
for (var i = 0; i < files.length; i++) {
var theFile = files[i];
// check if the file is an image
var isImagen = /^image\//;
// if it's not an image continu
if (!isImagen.test(theFile.type)) {
continue;
}
var img = new Image();
img.src = window.URL.createObjectURL(theFile);
img.onload = function() {
ctx.save();
markDroppableZone();
// clip the context
ctx.clip();
// draw the image
ctx.drawImage(this, 10, 10);
ctx.restore();
window.URL.revokeObjectURL(this.src);
}
}
}
function onEvent(e){
m = oMousePos(canvas, e);
markDroppableZone();
if (ctx.isPointInPath(m.x, m.y)){
e.stopPropagation();
e.preventDefault();
}
}
function oMousePos(canvas, evt) {
var ClientRect = canvas.getBoundingClientRect();
return { //objeto
x: Math.round(evt.clientX - ClientRect.left),
y: Math.round(evt.clientY - ClientRect.top)
}
}
canvas{background:#e9e9e9}
<canvas id="canvas" width="500" height="500"></canvas>

Why can I not create a element of canvas with createElement?

I want to create the canvas internally and then just use it normally in my javascript. The following code creates the canvas.
Question: I should be able to create a canvas with the document.createElement("sketchpad")?
var canvas = document.createElement("sketchpad");
Code:
function init()
{
//canvas = document.getElementById('sketchpad');
var canvas = document.createElement("sketchpad");
//var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
if (canvas.getContext)
{
ctx = canvas.getContext('2d');
}
if (ctx)
{
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
window.addEventListener('mouseup', sketchpad_mouseUp, false);
}
}
All the code below:
<html>
<head>
<title>Sketchpad</title>
<script type="text/javascript">
var canvas;
var ctx;
var mouseX = 0;
var mouseY = 0;
var mouseDown = 0;
function drawDot(ctx,x,y,size)
{
r=0;
g=0;
b=0;
a=256;
ctx.beginPath();
ctx.arc(x, y, size, 0, Math.PI*2, true);
ctx.closePath();
ctx.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")";
ctx.fill();
}
function clearCanvas(canvas,ctx)
{
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function sketchpad_mouseDown()
{
mouseDown=1;
drawDot(ctx,mouseX,mouseY,4);
}
function sketchpad_mouseUp()
{
mouseDown=0;
}
function sketchpad_mouseMove(e)
{
getMousePos(e);
if (mouseDown==1)
{
drawDot(ctx,mouseX,mouseY,4);
}
}
function getMousePos(e)
{
if (!e)
{
var e = event;
}
if (e.offsetX)
{
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if (e.layerX)
{
mouseX = e.layerX;
mouseY = e.layerY;
}
}
function init()
{
//canvas = document.getElementById('sketchpad');
var canvas = document.createElement("sketchpad");
//var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
document.body.appendChild(canvas);
if (canvas.getContext)
{
ctx = canvas.getContext('2d');
}
if (ctx)
{
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
window.addEventListener('mouseup', sketchpad_mouseUp, false);
}
}
</script>
<style>
.leftside
{
float:left;
width:120px;
height:25px;
background-color:#def;
padding:10px;
border-radius:4px;
}
.rightside
{
float:left;
margin-left:10px;
}
#sketchpad
{
float:left;
border:4px solid #888;
border-radius:4px;
position:relative;
}
</style>
</head>
<body onload="init()">
<div class="leftside">
<input type="submit" value="Clear Sketchpad" onclick="clearCanvas(canvas,ctx);">
</div>
<div class="rightside">
<!-- <canvas id="sketchpad" height="500" width="500">-->
</canvas>
</div>
</body>
</html>
This new code did not work:
This new code does not work, this is how a person has to create the canvas correct.
var canvas = document.createElement("canvas"); //or what ever name that I want
canvas.id = "sketchpad";
The if statement is not necessary, is it?
function init()
{
//canvas = document.getElementById('sketchpad');
var canvas = document.createElement("canvas");
canvas.id = "sketchpad";
if (canvas.getContext)
{
ctx = canvas.getContext('2d');
}
if (ctx)
{
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
window.addEventListener('mouseup', sketchpad_mouseUp, false);
}
}
Code here: This code does not seem to work either. I appended the sketchpad to the canvas but it still is not adding it to the document.
function init()
{
//canvas = document.getElementById('sketchpad');
var canvas = document.createElement("canvas");
canvas.id = "sketchpad";
document.getElementById('sketchpad').appendChild(canvas);
if (canvas.getContext)
{
ctx = canvas.getContext('2d');
}
if (ctx)
{
canvas.addEventListener('mousedown', sketchpad_mouseDown, false);
canvas.addEventListener('mousemove', sketchpad_mouseMove, false);
window.addEventListener('mouseup', sketchpad_mouseUp, false);
}
}
sketchpad is not a valid DOM element so it will create a HTMLUnknownElement. This is not what you are looking for.
You want to create a canvas, so lets just create a canvas:
var canvas = document.createElement("canvas");
And give it the ID "sketchpad" if you want:
canvas.id = "sketchpad";
Once you canvas is created, you will need to append it to an existing element of your HTML if you want it to be shown. Ex. if you want your canvas to appear in a div that looks like this:
<div id="rightside" class="rightside">
You would append your canvas like this:
document.getElementById('rightside').appendChild(canvas);
Here is a jsFiddle using your code!
Thats it!
--
Additional source for createElement

Categories

Resources