Clearing drawing from Canvas permanently - javascript

I have a function that clears all drawings off of the background image in canvas when a button is clicked, but when you go to draw again, the old (previously cleared drawings) reappears. How can I make a hard delete so that I can draw again without reloading the page
'use strict';
function initCanvas() {
let bMouseIsDown = false;
let canvas = document.getElementById('cvs');
let ctx = canvas.getContext('2d');
let convert = document.getElementById('convert');
let sel = 'png';
let imgs = document.getElementById('imgs');
let imgW = 300;
let imgH = 200;
let background = new Image();
background.crossOrigin = '';
background.src = "http://i.imgur.com/yf6d9SX.jpg";
background.onload = function(){
ctx.drawImage(background,0,0,600,400);
}
bind(canvas,ctx,convert,sel,imgs,imgW,imgH,bMouseIsDown);
};
initCanvas()
function bind (canvas,ctx,convert,sel,imgs,imgW,imgH,bMouseIsDown) {
let iLastX = 0;
let iLastY = 0;
let iX;
let iY;
canvas.onmousedown = function(e) {
bMouseIsDown = true;
iLastX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
iLastY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
}
canvas.onmouseup = function() {
bMouseIsDown = false;
iLastX = -1;
iLastY = -1;
}
canvas.onmousemove = function(e) {
if (bMouseIsDown) {
iX = e.clientX - canvas.offsetLeft + (window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft);
iY = e.clientY - canvas.offsetTop + (window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop);
ctx.moveTo(iLastX, iLastY);
ctx.lineTo(iX, iY);
ctx.stroke();
ctx.strokeStyle = "blue";
ctx.lineJoin = "round";
ctx.lineWidth = 5;
iLastX = iX;
iLastY = iY;
}
};
document.getElementById('clear').addEventListener('click', function() {
rerenderImg();
});
function rerenderImg() {
iY = [];
iX=[];
initCanvas()
}
};

You need to call ctx.beginPath(); before drawing on the canvas again.
The logical place to put this is just before your call to ctx.moveTo.
An explanation of why this is needed is given here.

You should actually run clearRect on the canvas:
ctx.clearRect(0, 0, canvas.width, canvas.height);

Related

Loading video frames into javascript in google colab

I wish to present a video, frame by frame with the possibility of flipping between frames in google colab. I also wish to mark some rectangles and get the x,y,w,h of each rectangle.
As far as I could understand, the only way to click the output and gather data in google Collab is via a javascript call, which I am new to. I have split my video into a list called frames and written the following python\javascript code for my task:
def get_fxy_val(base64imgs):
js = Javascript('''
async function showImage(base64) {
var canvas = document.createElement('canvas');
var rect = {};
var drag = false;
var finish = false;
var clicks = [];
var img = document.createElement('img');
var frame = 0
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
img = new Image();
img.onload = function () {
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
};
img.src = 'data:image/jpeg;base64,'+base64[frame];
var prev = document.createElement('button');
prev.innerHTML = '<';
prev.onclick = function() {
frame = frame -1;
if(frame<0){
frame = 0;
}
else{
// console.log(frame)
img.src = 'data:image/jpeg;base64,'+base64[frame];
};
};
document.body.appendChild(prev);
var next = document.createElement('button');
next.innerHTML = '>';
next.onclick = function() {
frame = frame+1;
if (frame>base64.length-1) {
// console.log(frame)
frame = base64.length-1
}
else{
img.src = 'data:image/jpeg;base64,'+base64[frame];
}
};
document.body.appendChild(next);
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;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
if (rect.w<0){
rect.startX = rect.startX + rect.w
rect.w = rect.w*(-1)
}
if (rect.h<0){
rect.startY = rect.startY + rect.h
rect.h = rect.h*(-1)
}
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
function mouseMove(e) {
if (drag) {
rect.w = (e.pageX - this.offsetLeft) - rect.startX;
rect.h = (e.pageY - this.offsetTop) - rect.startY;
ctx.strokeStyle = 'red';
ctx.lineWidth = 2;
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
}
}
var saver = document.createElement('button');
saver.innerHTML = 'save rectangle';
saver.onclick = function() {
clicks.push([frame, rect.startX, rect.startY, rect.w, rect.h]);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
document.body.appendChild(saver);
var finisher = document.createElement('button');
finisher.innerHTML = 'Done!';
finisher.onclick = function() {
};
document.body.appendChild(finisher);
await new Promise((resolve) => finisher.onclick = resolve);
document.body.removeChild(finisher)
document.body.removeChild(saver)
document.body.removeChild(next)
document.body.removeChild(prev)
document.body.removeChild(canvas)
return clicks
}
''')
display(js)
imgs = ["'"+b64img+"'" for b64img in base64imgs]
imgs = '[' + ','.join(imgs) +']'
data = eval_js(f"showImage({imgs})")
return data
I call it using:
base64imgs = [base64.b64encode(cv2.imencode('.jpg', img)[1]).decode() for img in frames]
data = get_fxy_val(base64imgs)
Everything works well for a small number of images, however for the full video Collab crushes and I cannot manage to find any logs to verify what is going on.
Two thoughts I had, which I do not know how to implement:
Reduce the images' memory size somehow. I cannot harm the aspect ratio so downsampling is not a possibility.
Load images directly from memory inside the javascript code. I have no idea how to implement this or if it is even possible.
Can I implement any of these? Is there another approach?
B.T.W, my video has images with size h,w,c = (1080, 1920, 3).

How to draw rectangle in canvas which is already in pdf.js

am using pdf.js here am rendering my pdf in canvas,
My code is:
<div id="viewerContainer" tabindex="0">
<div id="viewer" class="pdfViewer"></div>
</div>
The above canvas is generating through viewer.js
Now I am trying to draw rectangle on my pdf, but its not showing my rectangle,
My script is in below:
<script type="text/javascript">
var canvas, context, startX, endX, startY, endY;
var mouseIsDown = 0;
function init() {
canvas = document.getElementById("page1");
context = canvas.getContext("2d");
canvas.addEventListener("mousedown", mouseDown, false);
canvas.addEventListener("mousemove", mouseXY, false);
canvas.addEventListener("mouseup", mouseUp, false);
}
function mouseUp() {
if (mouseIsDown !== 0) {
mouseIsDown = 0;
drawSquare(); //update on mouse-up
}
}
function mouseDown() {
mouseIsDown = 1;
startX = endX = event.clientX - canvas.offsetLeft; //remember to subtract
startY = endY = event.clientY - canvas.offsetTop; //canvas offset
drawSquare(); //update
}
function mouseXY(eve) {
if (mouseIsDown !== 0) {
if (!eve) {
var eve = event;
}
endX = event.pageX - canvas.offsetLeft;
endY = event.pageY - canvas.offsetTop;
drawSquare();
}
}
function drawSquare() {
// creating a square
var width = Math.abs(startX - endX);
var height = Math.abs(startY - endY);
context.clearRect(0, 0, context.width, context.height);
//or use fillRect if you use a bg color
context.beginPath();
context.rect(startX, startY, width, height);
context.fillStyle = "yellow";
context.fill();
context.lineWidth = 7;
context.strokeStyle = 'black';
context.stroke();
}
</script>
viwer.js code:
var canvasWrapper = document.createElement('div');
canvasWrapper.style.width = div.style.width;
canvasWrapper.style.height = div.style.height;
canvasWrapper.classList.add('canvasWrapper');
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(canvasWrapper, this.annotationLayer.div);
} else {
div.appendChild(canvasWrapper);
}
var textLayer = null;
if (this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(textLayerDiv, this.annotationLayer.div);
} else {
div.appendChild(textLayerDiv);
}
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.enhanceTextSelection);
}
var viewport = this.viewport;
var canvas = document.createElement('canvas');
canvas.id = this.renderingId;
canvas.setAttribute('hidden', 'hidden');
var isCanvasHidden = true;
var showCanvas = function showCanvas() {
if (isCanvasHidden) {
canvas.removeAttribute('hidden');
isCanvasHidden = false;
}
};
canvasWrapper.appendChild(canvas);
Is there any mistake in my code? I have searched many source but I could not able to find the correct one. Kindly help me in this issue.

Touch move event not correct

I'm busy creating a small real time drawing app and got stuck trying to create a touchscreen system. It's partially working but when I touch and move the line connects to the last line.
Here's my code:
document.addEventListener("DOMContentLoaded", function() {
var mouse = {
click: false,
move: false,
pos: {x:0, y:0},
pos_prev: false,
colour: "blue"
};
var canvas = document.getElementById('drawing');
var ctx = canvas.getContext('2d');
var width = window.innerWidth;
var height = window.innerHeight;
var socket = io.connect();
canvas.width = width;
canvas.height = height;
/* window.onresize= function(){
var width = window.innerWidth;
var height = window.innerHeight;
console.log(height);
canvas.style.width = width;
canvas.style.height = height;
}; */
canvas.onmousedown = function(e){ mouse.click = true; };
canvas.onmouseup = function(e){ mouse.click = false; };
canvas.ontouchstart = function(e){ mouse.click = true; };
canvas.ontouchend = function(e){ mouse.click = false; };
canvas.onmousemove = function(e) {
mouse.pos.x = e.clientX / width;
mouse.pos.y = e.clientY / height;
mouse.pos.w = document.getElementById("rag").value;
mouse.move = true;
};
canvas.ontouchmove = function(e) {
var touch = e.touches[0];
var x = touch.pageX - canvas.offsetLeft;
var y = touch.pageY - canvas.offsetTop;
mouse.pos.x = x / width;
mouse.pos.y = y / height;
console.log(mouse.pos.x);
mouse.pos.w = document.getElementById("rag").value;
mouse.move = true;
};
socket.on('draw_line', function (data) {
var line = data.line;
ctx.strokeStyle = line[2];
ctx.lineWidth = line[0].w;
ctx.beginPath();
ctx.moveTo(line[0].x * width, line[0].y * height);
ctx.lineTo(line[1].x * width, line[1].y * height);
ctx.stroke();
});
socket.on('clear', function () {
ctx.clearRect(0,0,width,height);
});
function mainLoop() {
if (mouse.click && mouse.move && mouse.pos_prev) {
mouse.colour = document.getElementById("col").value;
socket.emit('draw_line', { line: [ mouse.pos, mouse.pos_prev, mouse.colour]});
mouse.move = false;
}
mouse.pos_prev = {x: mouse.pos.x, y: mouse.pos.y};
setTimeout(mainLoop, 20);
}
mainLoop();
});
A life example can be found here:
http://80.61.54.121:88/
Does anyone know how to fix the lines connecting with eacother? Thanks in advance.

Picture background for canvas particle

I'm trying to create background for every created particle.
Canvas pattern is not working properly. I'm getting this error >> "SyntaxError: An invalid or illegal string was specified"
HTML
<canvas id="canvas"></canvas>
JS
(function(){
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d'),
particles = {},
particleIndex = 0,
particleNum = 1;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.width);
function Particle(){
this.x = canvas.width / 2;
this.y = 0;
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = 0.2;
particleIndex++;
particles[particleIndex] = this;
this.id = particleIndex;
this.test = 0;
this.maxLife = 100;
}
Particle.prototype.draw = function(){
this.x += this.vx;
this.y += this.vy;
this.vy += this.gravity;
this.test++;
if ( this.test >= this.maxLife ) {
delete particles[this.id];
};
var img = new Image();
img.src = 'img/aaa.png';
var pattern = ctx.createPattern(img,'repeat');
ctx.fillStyle = pattern;
ctx.fillRect(this.x, this.y, 20, 20);
};
setInterval(function(){
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < particleNum; i++) {
new Particle();
};
for(var i in particles) {
particles[i].draw();
}
},30)
}})();
I was trying to do this also with ctx.drawImage(), but picture was displayed one time only.
Any tips?:)
Fiddle
I think the issue is the image being loaded later than its used.
Inside your draw() you have:
var img = new Image();
img.src = 'img/aaa.png';
var pattern = ctx.createPattern(img,20,20);
It is a bad idea to create new images everytime you want to draw. I strongly suggest you create the img variable outside of the draw loop. Once you set the .src of an image, you have to wait until it is loaded to use it. There is an onload event you can use to let you know when its ready.
Here is an example:
var imgLoaded = false;
var img = new Image();
img.src = 'img/aaa.png';
img.onload = function() { imgLoaded = true; };
function draw() {
...
if (imgLoaded) {
var pattern = ctx.createPattern(img, 'repeat');
...
}
...
}

default polygonal area of an image using JavaScript / jQuery on load of page

i have one image i want ploygonal area of image on load like this :
i got one reference form internet : http://jsfiddle.net/MFELx/
but its happening only when i click on the image multiple time but my requirement is if i load the page few node by default come on the page and that i can increse or decrease by code or change the axis..
js code in fiddle :
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', 500);
canvas.setAttribute('height', 500);
canvas.setAttribute('id', 'canvas');
$(canvasDiv).prepend(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
$(canvas).attr({width : 500, height: 500});
context.drawImage(imageObj,0,0);
};
imageObj.src = 'img/1370800.jpg';
var clickX = new Array();
var clickY = new Array();
var clickDrag = new Array();
var paint;
function addClick(x, y, dragging)
{
clickX.push(x);
clickY.push(y);
clickDrag.push(dragging);
}
function redraw(){
canvas.width = 500; // Clears the canvas
context.drawImage(imageObj,0,0);
context.strokeStyle = "#df4b26";
context.lineJoin = "round";
context.lineWidth = 5;
for(var i=0; i < clickX.length; i++)
{
context.beginPath();
context.arc(clickX[i], clickY[i], 3, 0, 2 * Math.PI, false);
context.fillStyle = '#ffffff';
context.fill();
context.lineWidth = 5;
context.stroke();
}
}
$('#canvas').click(function(e){
var mouseX = e.pageX - this.offsetLeft;
var mouseY = e.pageY - this.offsetTop;
addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop);
// redraw();
});
$('#generate').click(function(){
$(".clipParent").empty();
$(".clipParent").prepend('<img width=" 500" height="500" src="img/1370800.jpg" id="genimg" />');
var arr = [];
for(var i=0; i < clickX.length; i++){
arr.push(clickX[i]);
arr.push(clickY[i]);
}
$("#genimg")[0].setAttribute("data-polyclip",arr.join(", "));
clickX=[];
clickY=[];
redraw();
polyClip.init();
});
This requires object manipulation inside canvas... I would suggest to use createjs.
Here you go... An updated version of your app (fiddle) :
var canvasDiv = document.getElementById('canvasDiv');
canvas = document.createElement('canvas');
canvas.setAttribute('width', 500);
canvas.setAttribute('height', 500);
canvas.setAttribute('id', 'canvas');
$(canvasDiv).prepend(canvas);
$(canvas).click(onClick);
if (typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function () {
$(canvas).attr({
width: this.width,
height: this.height
});
stage = new createjs.Stage("canvas");
var img = new createjs.Bitmap(imageObj);
stage.addChild(img);
points = new createjs.Container();
stage.mouseEnabled = true;
stage.addChild(points);
stage.update();
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
var clickX = new Array();
var clickY = new Array();
var paint, stage, points;
function drag(evt) {
evt.target.x = evt.stageX;
evt.target.y = evt.stageY;
stage.update();
}
function onClick(e) {
var mouseX = e.clientX;
var mouseY = e.clientY;
clickX.push(mouseX);
clickY.push(mouseY);
redraw();
}
function redraw() {
points.removeAllChildren();
for (var i = 0; i < clickX.length; i++) {
var point = new createjs.Shape();
point.graphics.beginFill('#df4b26').drawCircle(0, 0, 6);
point.x = clickX[i];
point.y = clickY[i];
points.addChild(point);
point.on("pressmove", drag);
}
stage.update();
}
$('#generate').click(function () {
$(".clipParent").empty();
var resImg = $(imageObj).clone();
$(".clipParent").prepend(resImg);
var arr = [];
for (var i = 0; i < clickX.length; i++) {
arr.push(clickX[i]);
arr.push(clickY[i]);
}
resImg.attr("data-polyclip", arr.join(", "));
clickX = [];
clickY = [];
redraw();
polyClip.init();
});

Categories

Resources