HTML5 Canvas - lines drawn disappears in a flash - javascript

I have two canvases layered one over the other.
<div class="center">
<canvas id="imgcanvas" style="position:absolute;margin:0 0 0 0;z-index:1"></canvas>
<canvas id="drawcanvas" style="position:absolute;margin:0 0 0 0;z-index:2"></canvas>
</div>
Below the canvas, I have a horizontal thumbnail pallete. Upon clicking the thumbnail, the clicked image renders in the image canvas. I am using the drawcanvas to draw lines on the canvas. The coordinates for drawing the lines are stored in the localStorage.
Upon clicking the thumbnail, along with loading the image, I am trying to draw the lines taking the coordinates from the localStorage. However, the lines get drawn and disappears in a flash of a second.
The following is the code:
//clicked_id is returned by the thumbnail
function clickedImage(clicked_id) {
localStorage.setItem('sel_id', clicked_id);
//Get the complete path of the image
var clickedImg = document.getElementById(clicked_id).src;
var activeImg = document.getElementById(clicked_id).src;
//store the complete path
localStorage.setItem("activeImg",activeImg);
var clickedImg = basename(clickedImg,"/");
localStorage.setItem("clickedImage", clickedImg);
var clickedImg = clickedImg.replace(/^.*[\\\/]/, '');
//draw lines on canvas
var canvas = document.getElementById("imgcanvas");
var regcanvas = document.getElementById("drawcanvas");
var ctx = canvas.getContext("2d");
var ctxr = regcanvas.getContext("2d");
var arr = new Array();
//Perform calculations to get the fourth coordinate
arr = fourthCoord(getArray(arr));
for (var i = 0; i < arr.length; i++) {
if (arr[i][0] === clickedImg) {
first.x = arr[i][3];
first.y = arr[i][4];
second.x = arr[i][5];
second.y = arr[i][6];
third.x = arr[i][7];
third.y = arr[i][8];
fourth.x = arr[i][9];
fourth.y = arr[i][10];
ctxr.lineCap = "round";
ctxr.lineWidth = 3;
ctxr.strokeStyle = '#f4d03f';
ctxr.beginPath();
ctxr.moveTo(first.x,first.y);
ctxr.lineTo(second.x,second.y);
ctxr.lineTo(third.x,third.y);
ctxr.lineTo(fourth.x,fourth.y);
ctxr.lineTo(first.x,first.y);
ctxr.stroke();
console.log(first,second,third,fourth);
}
}
//Load the image
var thumbNails = document.getElementById("loaded_img_panel");
var pic = new Image();
pic.onload = function() {
canvas.width = pic.width;
canvas.height = pic.height;
regcanvas.width = pic.width;
regcanvas.height = pic.height;
ctx.drawImage(pic, 0,0)
}
thumbNails.addEventListener('click',function(event) {
pic.src = event.target.src;
});
}
The getArray() function gets the coordinates for the lines. I am using the same codes on a sample canvas, where clicking on the canvas (instead of clicking on the image) draws the lines. However on this application, the lines get drawn (which I could see for a fraction of a second) and then disappears.
Trial 1:
I called in two functions onclick of thumbNail - clickedImage() and drawAnnotations(). I moved all the codes pertaining to drawing lines into drawAnnotations(). This did not work.
Trial 2:
I called in the first function clickedImage() on mousedown event of the thumbnail and drawAnnotations() on the mouseup event of the thumbnail. This too did not work.
Trial 3:
I created a window.addEventListener...and called drawAnnotation function onload
window.addEventListener("DOMContentLoaded", function(event) {
document.getElementById('drawcanvas').addEventListener("load", drawAnnotations);
});
this too did not work...meaning...it draws the lines...but disappears in a flash.

Related

I made a script that detects if there is white space surrounding an image and automatically removes it, sometimes, it still leaves some of it

The code is a simple image cropper that allows the user to select an image file, crop the image to remove any surrounding white space, and then download the resulting cropped image.
My problem is that sometimes the code leaves a little bit of white space around some images and i don't have any idea on why it does that.
Here is my code:
// Add an event listener to the file input field to process the selected file
document
.getElementById("fileInput")
.addEventListener("change", function () {
// Get the file object
var file = this.files[0];
// Create a FileReader object
var reader = new FileReader();
// Add an event listener to the FileReader object to process the file when it's loaded
reader.addEventListener("load", function () {
// Create an image object and set its src to the data URL of the file
var img = new Image();
img.src = this.result;
// Wait for the image to load
img.onload = function () {
// Get the width and height of the image
var width = img.naturalWidth;
var height = img.naturalHeight;
// Create a canvas element and draw the image onto it
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
// Get the image data of the canvas
var imageData = ctx.getImageData(0, 0, width, height);
var data = imageData.data;
// Iterate through the image data and determine the edges of the non-white pixels
var top = height;
var bottom = 0;
var left = width;
var right = 0;
for (var y = 0; y < height; y++) {
for (var x = 0; x < width; x++) {
var index = (y * width + x) * 4;
if (
data[index] !== 255 ||
data[index + 1] !== 255 ||
data[index + 2] !== 255
) {
// This pixel is not white, so update the edges if necessary
top = Math.min(top, y);
bottom = Math.max(bottom, y);
left = Math.min(left, x);
right = Math.max(right, x);
}
}
}
// Calculate the dimensions of the cropped image
var croppedWidth = right - left;
var croppedHeight = bottom - top;
// Create a second canvas element and draw the cropped image onto it
var croppedCanvas = document.createElement("canvas");
croppedCanvas.width = croppedWidth;
croppedCanvas.height = croppedHeight;
var croppedCtx = croppedCanvas.getContext("2d");
croppedCtx.drawImage(
img,
left,
top,
croppedWidth,
croppedHeight,
0,
0,
croppedWidth,
croppedHeight
);
// Get the data URL of the cropped image and set it as the href of the download link
var downloadLink = document.getElementById("downloadLink");
downloadLink.href = croppedCanvas.toDataURL();
// Set the download attribute of the link to the file name of the original image
downloadLink.download = file.name;
// Set the src of the cropped image element to the data URL of the cropped image
var croppedImage = document.getElementById("croppedImage");
croppedImage.src = croppedCanvas.toDataURL();
};
});
// Read the file as a data URL
reader.readAsDataURL(file);
});
I tried adding a little bit of white tolerance but it seems not to fix the problem.

How can I get full image after zooming in canvas

I am facing this issue where once I zoom in on some image in the canvas in javascript, some part of the image goes outside of the canvas. Then I am drawing something on it. But now, I want the latest total image instead of just what is on the canvas frame. How can I get that?
Here is my code for it. Whenever a scroll-up or scroll-down happens, the below function gets called.
var zoom = function(clicks)
{
original = canvas.toDataURL();
// clear the canvas
var p1 = ctx.transformedPoint(0,0);
var p2 = ctx.transformedPoint(canvas.width,canvas.height);
ctx.clearRect(p1.x,p1.y,p2.x-p1.x,p2.y-p1.y);
// translate the image according to zoom factor and location of zoom
var pt = ctx.transformedPoint(lastX,lastY);
ctx.translate(pt.x,pt.y);
var factor = Math.pow(scaleFactor,clicks);
ctx.scale(factor,factor);
ctx.translate(-pt.x,-pt.y);
// draw te image on canvas
const img = document.createElement("img");
img.setAttribute("src", original);
img.onload = function () {
ctx.drawImage( img, 0, 0, canvas.width, canvas.height);
};
}

Can't seem to get an old image off the canvas

I'm importing an image (that has to come in portrait) onto a canvas object, rotating it (because it's actually landscape) and running some OCR on the base64 from the canvas. That all works fine. However when I put a new image onto the canvas, the old one is retained and never replaced. I've tried clearRect, even gone to the extent of creating a new dom element each time and destroying it when I have everything I need (which is still in the code below) but I just cannot get the first image to clear.
Here's the relevant bit of the code
function onSuccess(imageURI) {
//CREATE NEW CANVAS ELEMENT
g = document.createElement('canvas');
g.setAttribute("id", "thePic");
g.style.overflow = "visible";
document.body.appendChild(g);
const canvas = document.getElementById('thePic'),
context = canvas.getContext('2d');
make_base();
function make_base()
{
base_image = new Image();
base_image.src = imageURI;
base_image.onload = function(){
const uriheight = base_image.naturalHeight;
const uriwidth = base_image.naturalWidth;
console.log(uriwidth + " " + uriheight);
context.canvas.width = uriheight;
context.canvas.height = uriheight;
context.drawImage(base_image, 0, 0);
//ROTATE THE IMAGE 90
context.clearRect(0,0,canvas.width,canvas.height);
context.save();
context.translate(canvas.width/2,canvas.height/2);
context.rotate(90*Math.PI/180);
context.drawImage(base_image,-base_image.width/1.2,-base_image.width/1.2);
context.restore();
var theCanvas = document.getElementById('thePic');
var rotImg = theCanvas.toDataURL();
var rotImg = rotImg.substring(21);
textocr.recText(4, rotImg, onSuccess, onFail);
function onSuccess(recognizedText) {
var recdata = recognizedText.lines.linetext;
var blockData = recognizedText.blocks.blocktext;
context.clearRect(0, 0, 10000,10000);
base_image = "";
rotImg = "";
document.getElementById('thePic').outerHTML = "";
document.getElementById('cgh').innerHTML = "";
}
}
}
Any advice much appreciated.
So it turned out to not be the canvas at all, it was image caching in a previous function that give the image to the canvas.
Thanks to everyone who took the time to have a squiz.

Redraw images on canvas

I need to have a couple of images on one canvas.
I have a trouble with a function clear(); which is used when I need to drag images on canvas.
The problem is that we are Canvas appears only on the last image.
I try to use context.save() and context.restore() but it was not usefull in my case.
switch(i)
{
case 0:
challengerImg = new Image();
challengerImg.onload = function(){
drawImage(this,x,y,i);
};
challengerImg.src = "<?php echo $base_url; ?>/themes/bartik/images/sheep.png";
break;
case 1:
tshirt = new Image();
tshirt.onload = function(){
drawImage(this,x,y,i);
};
tshirt.src = "<?php echo $base_url; ?>/themes/bartik/images/tshirt.png";
break;
}
And function which draw on canvas:
function drawImage(challengerImg,x,y,i){
console.log("Function drawImage start");
var events = new Events("layer0");
var canvas = events.getCanvas();
var context = events.getContext();
var rectX = x;
var rectY = y;
var draggingRect = false;
var draggingRectOffsetX = 0;
var draggingRectOffsetY = 0;
events.setStage(function(){
var mousePos = this.getMousePos();
if (draggingRect) {
rectX = mousePos.x - draggingRectOffsetX;
rectY = mousePos.y - draggingRectOffsetY;
}
this.clear(); //Here is trouble
this.beginRegion();
context.drawImage(challengerImg, rectX, rectY, challengerImg.width, challengerImg.height);
// draw rectangular region for image
context.beginPath();
context.rect(rectX, rectY, challengerImg.width, challengerImg.height);
context.closePath();
this.addRegionEventListener("mousedown", function(){
draggingRect = true;
var mousePos = events.getMousePos();
draggingRectOffsetX = mousePos.x - rectX;
draggingRectOffsetY = mousePos.y - rectY;
});
this.addRegionEventListener("mouseup", function(){
draggingRect = false;
});
this.addRegionEventListener("mouseover", function(){
document.body.style.cursor = "pointer";
});
this.addRegionEventListener("mouseout", function(){
document.body.style.cursor = "default";
});
this.closeRegion();
});
}
context.save and context.restore only works for state of the context (transformation, globalAlpha,...), but not for what is rendered inside.
When you clear your context, it makes it empty.
What you have to do is to :
catch mouse events and change position variables
clear the canvas
redraw all images at their new position
save(), restore() do not handle bitmap data at all :).
To drag stuff around, basically you need to have an offscreen canvas which doesn't contain the element you are drawing, and after each update draw the offscreen canvas plus the element being dragged.
It's probably simpler to use a library that already does it, most do, like http://www.html5canvastutorials.com/labs/html5-canvas-interactive-scatter-plot-with-20000-nodes-using-kineticjs/
The canvas is a flat object - once you draw an image onto it, the image has no more context as it renders as part of the canvas. You can either create an array of rectangle objects with their coordinates to keep track of what's already on the canvas or test the mouse position for the background color to determine whether there is an image or not. Then you can remove the item where the event happened by clearing the canvas and redrawing all the other items again.
Hope this helps!

creating a hierarchical tree structure of images in html5 canvas tag?

There is a tree hierarchical relation between a group of images, I want images to be represented as a tree structure in canvas tag with child node images smaller than parent node images and all the images should scale up with some value on mouseover.
The setscale and translate javascript functions let me do the scaling effect all right but I cannot get mouse event listener functions working right, mouseover and mouseout are not being detected although the images are displayed. I do not get the alert messages I have used for debugging. This is just a test code:-
function loadImages(sources, callback){
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for (var src in sources) {
numImages++;
}
for (var src in sources) {
images[src] = new Image();
images[src].onload = function(){
if (++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var destX = 20;
var destY = 20;
var destWidth = 200;
var destHeight = 137;
var sources = new Array();
sources[0]="darth-vader.jpg";
sources[1]="darth-vader.jpg";
var imageObj = new Image();
loadImages(sources, function(images){
context.drawImage(images[0], destX, destY, destWidth, destHeight);
images[0].onmouseover=function()
{
alert('1');
}
images[0].onmouseout=function()
{
alert('2');
}
context.drawImage(images[1], destX+200,destY, destWidth, destHeight);
images[1].onmouseover=function()
{
alert('3');
}
images[1].onmouseout=function()
{
alert('4');
}
});
};
Events are triggered on dom elements not on images painted on a canvas. If you want to simulate those events try to set a mousemove event on the canvas and then if the mouse is inside the area where you have drawn the image trigger the mouseover.
You can only put mouse events on the canvas itself, not on the images drawn to it.
You're going to have to start keeping track of the size and location of images drawn so you can do relevant things when the user clicks on the canvas. See A Gentle Introduction to Making Canvas Useful for examples of how to keep track of multiple selectable objects on a canvas.

Categories

Resources