i have a JavaScript project (using jquery), inside it i draw a canvas by code and then i insert array of images on it. it represents fine without any error.
problem: later on, i try to get these images inside from canvas to compare if they have the same src or the same id to don't replace it with the new image
my functions are:
var inter;
var screen;
function onClick(id){
getScreen(id, function(data){
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
if (screen.document.getElementById("screen") != null ){
screen.document.getElementById("screen").innerHTML = "";
}
screen.document.write('<div id="screen"><canvas id="screenCanvas" width=' +
data.maxX + ' height=' + data.maxY +
' style="border:2px solid #000000;color:#000000;" ></canvas></div>');
draw(data);
inter = setInterval(function(){screen(id); }, 5000);
});
}
function screen(id){
getScreen(id, function(data){
if (screen.closed == true){
clearInterval(inter);
return;
}
if((screen.document.getElementById('screenCanvas').width != data.maxX) ||
(data.maxY != screen.document.getElementById('screenCanvas').height)){
screen.close();
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
screen=window.open('',id,'width=' + data.maxX + ',height=' + data.maxY , true);
if (screen.document.getElementById("screen") != null ){
screen.document.getElementById("screen").innerHTML = "";
}
screen.document.write('<div id="screen"><canvas id="screenCanvas" width=' +
data.maxX + ' height=' + data.maxY +
' style="border:2px solid #000000;color:#000000;" ></canvas></div>');
draw(data);
});
}
function draw(data) {
var canvas = screen.document.getElementById('screenCanvas');
var context = canvas.getContext('2d');
var tileY = 0;
var tileX = 0;
var counter = 0;
var tileWidth = data.tileWidth;
var tileHeight = data.tileHeight;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var img = new Image();
img.onload = (function(img, tileX, tileY, tileWidth, tileHeight){
return function() {
context.drawImage(img,tileX, tileY, tileWidth, tileHeight);
}
})(img, tileX, tileY, tileWidth, tileHeight);
img.src = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
}
</script>
this code gets an array (data) that contains list of (id, maxX, maxY, tileWidth, tileHeight, tiles[x, y, imageId]) and open new window, then write in this window the canvas code and draw images then calls a timer to work each 5 seconds. after each 5 seconds, screen method calls to re-get the data again and check if screen open then it remove all inner html to rewrite new canvas, and it tests if sizes changes.
this code works fine without any error, but i need to edit these code to get images inside canvas and test it they has the same imageId, don't download it again.(i don't save image id, to get images by, we can store it in img.id, or get images by src since, imageId is a part of image path that makes it unique).
Note:
id[unique](is the id of the user),
maxX(maximum width of the screen),
maxY(maximum height of the screen),
tileWidth(width of each image),
tileHeight(height of each image),
tiles(list of images)
x(left position of the image)
y(top postion of the image)
imageId[unique](id of each image)
example: data[id:1,maxX:1920,maxY:1080,tileWidth:480,tileHeight:270,tiles:(x:2,y:1,imageId:1a)]
any help?
as Ravi Jain said you can't get the image drawn to canvas object, and as robertc said you can use img element.
try these functions that specify the usage of img element not canvas:
function onClick(id){
getScreen(id, function(data){
var inter;
var screen;
var width = parseInt(data.maxX) + parseInt(data.tileWidth);
var height = parseInt(data.maxY) + parseInt(data.tileHeight);
screen=window.open('',id,'width=' + width + ',height=' + height , true);
draw(screen, data);
inter = setInterval(function(){screen(screen, inter, id); }, 5000);
});
}
function screen(screen, inter, id){
getScreen(id, function(data){
if (screen.closed == true){
clearInterval(inter);
return;
}
if((screen.document.getElementById("screen").style.width != data.maxX + "px") ||
(screen.document.getElementById("screen").style.height != data.maxY + "px")){
screen.close();
var width = parseInt(data.maxX) + parseInt(data.tileWidth);
var height = parseInt(data.maxY) + parseInt(data.tileHeight);
screen=window.open('',id,'width=' + width + ',height=' + height , true);
}
draw(screen, data);
});
}
function draw(screen, data) {
var screenDiv = screen.document.getElementById("screen");
if (screenDiv == null) screen.document.write('<div id="screen" style="width:' +
data.maxX + '; height:' + data.maxY + '; " style="margin: 0 auto;" >');
var tileY = 0;
var tileX = 0;
var counter = 0;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var imageSource = screen.document.getElementById("id_" + counter);
var path = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
if (imageSource == null){
screen.document.write('<img id="id_' + counter + '" src="' + path +
'" height="' + data.tileHeight + '" width="' + data.tileWidth + '" />');
}else if(imageSource.src != path){
imageSource.src = path;
}
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
if (screenDiv == null) screen.document.write('</div>');
}
</script>
your code are working fine that's true, but for one instance only, you declare var screen and var inter at the top of the script not in the function, this means that if you click on the first user to get it's screen (as what i understood of your code, what your project did), the timer of the first user stops and of the second user starts. this code that i wrote solve this problem and your problem to replace the source of the image if it changes.
hope this help you man,
GOOD LUCK;
Once you've drawn something on canvas it's pixels. It doesn't retain the object that was used to create those pixels. If you want this sort of information then you either need to maintain it yourself outside of canvas, or use something which retains objects for you like SVG.
Related
I have svg images in my page:
And I use to convert to png images (and download them):
https://github.com/CogComp/apelles/blob/master/public/index.html#L370-L390
var mySVG = $("#" + id + " svg")[0];
var imgId = id + "-img";
$(document.body).append('<img height="' + mySVG.getBBox().height + '" width="' + mySVG.getBBox().width + '" id="' + imgId + '" style="visibility: hidden; "/>');
var tgtImage = document.getElementById(imgId); // Where to draw the result
var can = document.createElement('canvas'); // Not shown on page
var ctx = can.getContext('2d');
var loader = new Image;
loader.width = can.width = tgtImage.width;
loader.height = can.height = tgtImage.height;
loader.onload = function () {
ctx.drawImage(loader, 0, 0, loader.width, loader.height);
tgtImage.src = can.toDataURL();
};
var svgAsXML = (new XMLSerializer).serializeToString(mySVG);
loader.src = 'data:image/svg+xml,' + encodeURIComponent(svgAsXML);
sleep(500).then(() => {
var url = tgtImage.src.replace(/^data:image\/[^;]/, 'data:application/octet-stream');
window.open(url);
});
Here is the output. Why is the output turned dark?
I tried changing the background color but didn't help.
Here is the link to the page btw: http://nlp.cogcomp.org/
Update: Checking the SVG code I think I have a background:
Despite having a background, I tried adding a background to the picture, but doesn't seem to help. Here are a couple of variations I have tried:
var svgQ = $("#" + id + " svg");
var mySVG = svgQ[0];
var rect = document.createElementNS(svgQ,'rect');
rect.setAttribute('x',10);
rect.setAttribute('y',10);
rect.setAttribute('width',50);
rect.setAttribute('height',50);
rect.setAttribute('fill','#EFEFEF');
mySVG.appendChild(rect);
// or mySVG.append(rect);
$("svg").each(function(){
$(this).css({ fill: '#000' });
// or $(this).attr("fill", '#000');
// or $(this).attr("fill", '#000000');
});
svgQ.css({ fill: '#000' });
// or svgQ.attr("fill", '#000');
// or svgQ.attr("fill", '#000000');
Here is HTML and Code that draws an image into a canvas, after a user has used a file picker.
HTML
<form class='frmUpload'>
<input name="picOneUpload" type="file" accept="image/*" onchange="picUpload(this.files[0])" >
</form>
<button onclick='fncSaveAsJPG()'>Convert Img To JPEG</button>
<canvas id="cnvsForFormat" width="400" height="266"></canvas>
<img id='imgTwoForJPG' src="">
Script
<script>
window.picUpload = function(frmData) {
console.log("picUpload ran: " + frmData);
var cnvs=document.getElementById("cnvsForFormat");
console.log("cnvs: " + cnvs);
var ctx=cnvs.getContext("2d");
cnvs.style.border="1px solid #c3c3c3";
var img = new Image;
img.src = URL.createObjectURL(frmData);
console.log('img: ' + img);
img.onload = function() {
var picWidth = this.width;
var picHeight = this.height;
var wdthHghtRatio = picHeight/picWidth;
console.log('picWidth: ' + Number(picWidth));
console.log('picHeight: ' + Number(picHeight));
console.log('wdthHghtRatio: ' + wdthHghtRatio);
if (Number(picWidth) > 400) {
var newHeight = Math.round(Number(400) * wdthHghtRatio);
} else {
return false;
};
document.getElementById('cnvsForFormat').height = newHeight;
console.log('width: ' + picWidth + " h: " + picHeight);
console.log('width: 400 h: ' + newHeight);
//You must change the width and height settings in order to decrease the image size, but
//it needs to be proportional to the original dimensions.
ctx.drawImage(img,0,0, 400, newHeight);
};
cnvs.onload = function () {
console.log('Onload Canvas 2 Ran');
};
};
cnvsForFormat.onload = function () {
console.log('Onload Canvas Ran');
};
</script>
I've tried attaching the .onload() method to various elements and put the code in various places without any luck. How to I get some code to run with the <canvas> element is done with the drawImage event?
I am looking for some method to prompt the width and height of the image being uploaded using an asp file upload control. Following is the code I am using to prompt message for file size. I just want to add the width and height of the image being uploaded using that upload control. Please take a note that I can't use javascript DOM here like img.clientWidth as there is no such html object to call it.
Here's the JS Code
$(document).ready(function () {
$("#<%= fupNewImage.ClientID %>").bind("change", function () {
var fSize = ((this.files[0].size) / 1024).toFixed(2);
if (fSize <= 200) {
$("#fupSize").html('Good file size: ' + fSize + " kb Width=? and Height=?" ); // ? denotes the actual value to be put.
}
//---------More cases
});
});
Solved!!
Thanks to #Esailija
After a lot of searching I finally found a workout # REF https://stackoverflow.com/a/8904008/1584140
var _URL = window.URL || window.webkitURL;
$("#<%= fupNewImage.ClientID %>").bind("change", function () {
//================Changed Code===================
var file, img;
if ((file = this.files[0])) {
img = new Image();
img.onload = function () {
var fSize = ((file.size) / 1024).toFixed(2);
var WH = " Widht: " + this.width + "px & Height: " + this.height + "px";
if (fSize <= 200) {
$("#fupSize").html('Good file size: ' + fSize + " kb" + WH);
}
};
img.onerror = function () {
alert("not a valid file: " + file.type);
};
img.src = _URL.createObjectURL(file);
}
//====================================
});
});
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="resources/js/jquery-1.7.2.min.js"> </script>
...
...
<script>
...
...
function draw(screen, data) {
if (screen.document.getElementById("screen") == null){
screen.document.write('<div id="screen" style="width:' +
data.maxX + '; height:' + data.maxY + '; margin: auto;" >' +
'<canvas id="screenCanvas" width=' + data.maxX + ' height=' +
data.maxY + 'style="border:2px solid #000000;color:#000000;" > </canvas></div>');
}
var canvas = screen.document.getElementById('screenCanvas');
var context = canvas.getContext('2d');
var tileY = 0;
var tileX = 0;
var counter = 0;
var tileWidth = data.tileWidth;
var tileHeight = data.tileHeight;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var img = new Image();
img.onload = (function(img, tileX, tileY, tileWidth, tileHeight){
return function() {
context.drawImage(img,tileX, tileY, tileWidth, tileHeight);
}
})(img, tileX, tileY, tileWidth, tileHeight);
img.src = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
}
...
...
</script>
</head>
<body>
...
...
...
...
</body>
</html>
i call this function when i open a new window to draw a canvas in the new window contains an array of images.
problem:
1- Internet explorer 9: draw canvas but it didn't draw images (since the border that i set in the style of the canvas appears).
2- when IE try to get image this error appears
SCRIPT5022: Exception thrown and not caught
index.html, line 1 character 1
3- Opera 12: it didn't display canvas.
Note:
1- this function works fine with Firefox, google chrome, and safari.
2- i am sure that internet explorer are not in compatibility view (F12) and not Quirks mode (it is standards).
any help?
Hmm.. interesting. I think i got a similar problem i'll just tag onto this stack.
After my page is loaded, a function is called to load an image (.png) in an already created canvas element. Half the time in IE this image is not loaded. I gotta hit refresh and eventually it shows up. In firefox & chrome it works on the first try. Sometimes it works on the first try in IE too, but this irregularity is killing me....
function loadCanvas(dataURL) {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
X_max = parseInt($("#container").css('width'));
Y_max = parseInt($("#container").css('height'));
canvas.width = X_max;
canvas.height = Y_max;
ctx.fillStyle="white";
ctx.fillRect(0, 0, X_max, Y_max);
// load image from data url
var imageObj = new Image;
imageObj.onload = function() {
ctx.drawImage(this, 0, 0);
};
imageObj.src = dataURL;
}
If you're calling the draw function after page load, then you will have to replace the document.write(...) as it will create a new page and IE won't complete the image onload handler (unlike as at least chrome).
$("body").append('<div id="screen" style="width:' +
data.maxX + 'px; height:' + data.maxY + 'px; margin: auto;" >' +
'<canvas id="screenCanvas" width=' + data.maxX + ' height=' +
data.maxY + style="border:2px solid #000000;color:#000000;"></canvas</div>')
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script src="resources/js/jquery-1.7.2.min.js"> </script>
...
...
<script>
...
...
function draw(screen, data) {
var canvas;
if (screen.document.getElementById("screen") == null){
var canvasDiv = screen.document.createElement("div");
canvasDiv.id = "screen";
canvasDiv.style.margin = "0px auto";
canvasDiv.style.width = data.maxX;
canvasDiv.style.height = data.maxY;
canvasDiv.style.border='2px solid black';
screen.document.body.appendChild(canvasDiv);
canvas = screen.document.createElement('canvas');
canvas.setAttribute('width', data.maxX);
canvas.setAttribute('height', data.maxY);
canvas.setAttribute('id', 'screenCanvas');
canvasDiv.appendChild(canvas);
if(typeof G_vmlCanvasManager != 'undefined') {
canvas = G_vmlCanvasManager.initElement(canvas);
}
}else{
canvas = screen.document.getElementById('screenCanvas');
}
var context = canvas.getContext('2d');
var tileY = 0;
var tileX = 0;
var counter = 0;
var tileWidth = data.tileWidth;
var tileHeight = data.tileHeight;
for (var i=0;i<(data.maxX/data.tileWidth);i++){
for (var j=0;j<(data.maxY/data.tileHeight);j++){
var img = new Image();
img.onload = (function(img, tileX, tileY, tileWidth, tileHeight){
return function() {
context.drawImage(img,tileX, tileY, tileWidth, tileHeight);
}
})(img, tileX, tileY, tileWidth, tileHeight);
img.src = "http://myserver:8080/images/screen/tile/" +
data.tiles[counter].imageId;
tileX = tileX + parseInt(data.tileWidth);
counter ++;
}
tileY = tileY + parseInt(data.tileHeight);
tileX = 0;
}
}
...
...
</script>
</head>
<body>
...
...
...
...
</body>
</html>
reference: www.williammalone.com
since IE doesn't know what the canvas tag means, and if we used that in our markup, IE would serve us an entrée of error. Instead we create a canvas element in JavaScript.
hope this help you
// Called when image is dropped in canvas
function dropResource() {
var imgIndex = getImageIndexByID(currentDragImageID);
var newImgID = resourceData.length;
var newImage;
newImage = $('<div id="imgD' + newImgID + '" style="display:inline-block;position:absolute;"><img alt="Big" id="imgA' + newImgID + '" src="' + uploadFolder + '/' + imgData[imgIndex][1] + '" /></div>');
$('#thePage').append(newImage);
$('imgA' + newImgID).load(function() {
// Get properties
var imgW = $('#imgA' + newImgID).width(); // Native width store this
var imgH = $('#imgA' + newImgID).height(); // Native
var imgX = $('#imgA' + newImgID).position().left; // Relative, scale back
var imgY = $('#imgA' + newImgID).position().top;
var zindex = getBiggestZindex() + 1;
// Resize native dimensions to fit current scale
$('#imgA' + newImgID).width(Math.round(imgW * currentScale));
$('#imgA' + newImgID).height(Math.round(imgH * currentScale));
$('#imgA' + newImgID).css("z-index", zindex);
// Add to array (dbID, imgarrIndex, width, height, x, y)
resourceData[newImgID] = new Array(0, imgIndex, imgW, imgH, imgX, imgY, zindex);
// Make img wrapper draggable
makeResourceDrag(newImgID);
// Save this as a resource
$.ajax({
url: 'artworkAjaxHandler.ashx?type=addResource&uploadID=' + currentDragImageID + '&page=' + currentPage + '&w=' + imgW + '&h=' + imgH + '&x=' + imgX + '&y=' + imgY + '&z=' + zindex,
success: function(data) {
var splitData = data.toString().split("|");
// Success
if (splitData[0] == "1") {
} else {
$.fancybox.close();
$.jGrowl("<strong>Error during image drop! Try reloading page.</strong><br />" + splitData[1], { sticky: true });
}
},
error: function() {
$.jGrowl("<strong>Error</strong><br />There was an error when processing the Ajax request", { sticky: true });
}
});
});
The load function is never calling... I know i'm probably executing this improperly, but once the image has finished loading it resizes it's wrapper automatically then I need to grab the dimensions.
Can anyone help?
You are missing a hash:
$('imgA' + newImgID).load(function()
should be
$('#imgA' + newImgID).load(function()