Images do not appear completely until mouse click - javascript

I found a issue that images are not show like below.
It's a canvas that I use konva.js.
And the stage is draggable: true. I found the images will now show event if I click this canvas when draggable: false. It's a little like the canvas be reload so all images appear.
After I click this canvas. All images will be showen.
This is some of my code.
var rackTop = new Image();
rackTop.onload = function() {
var image = new Konva.Image({
x: 13+x,
y : y,
image: rackTop,
width: drawer_width + rack_side*2,
height: Math.ceil(70 * scale_default)
});
onerackLayer.add(image);
};
rackTop.src = 'img/rack/rack_top.png';
function createMutiRackImage(callback, number, serverObj, serverContent, type) {
var img = new Image();
if (type === 'front') {
img.src = serverObj.imgUrl.thumFront;
} else if (type === 'rear') {
img.src = serverObj.imgUrl.thumRear;
} else {
// console.log('Server img type not defined.');
return;
}
var imgData = {};
imgData.x = serverContent.x;
imgData.y = serverContent.y;
imgData.width = serverContent.width;
imgData.height = serverContent.height;
imgData.status = serverContent.health;
imgData.type = type;
imgData.location = serverObj.locationId;
imgData.imgUrl = serverObj.imgUrl;
imgData.model = serverObj.model;
imgData.imgObj = img;
imgData.rackSize = serverContent.rackSize;
imgData.name = serverObj.name;
imgData.rackid = serverObj.rackid;
imgData.nodes = serverObj.nodes;
serverImgs.push(imgData);
img.onload = function() {
callback_multi(number);
}(number);
}
function callback_multi(i) {
var kinImgObj = createrMultiKonvaImage(serverImgs[i]);
onerackLayer.add(kinImgObj);
onerackLayer.draw();
}
function createrMultiKonvaImage(imgData) {
var _imgObj = imgData.imgObj;
var x = imgData.x;
var y = imgData.y;
var width = imgData.width;
var height = imgData.height;
var position = imgData.location;
var imgUrl = imgData.imgUrl;
var light = '';
var image = new Konva.Image({
x: x,
y: y,
width : width,
height : height,
image : _imgObj,
});
return image;
}

After you added a Konva.Image into a Layer you need to redraw it:
rackTop.onload = function() {
var image = new Konva.Image({
x: 13+x,
y : y,
image: rackTop,
width: drawer_width + rack_side*2,
height: Math.ceil(70 * scale_default)
});
onerackLayer.add(image);
onerackLayer.draw(); // this line is important
};

Related

Merge images together in canvas using JS

I'm currently trying to add watermark to an image, and I'm using this script:
function mixImages(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var imageObj1 = new Image();
var imageObj2 = new Image();
var marginTop = 10;
var marginLeft = 10;
imageObj1.src = "http://localhost:8080/sisop/storage/app/public/files/16522147787.png"
imageObj1.onload = function() {
ctx.drawImage(imageObj1, 0, 0, 328, 526);
imageObj2.src = "http://localhost:8080/sisop/storage/app/public/files/165221397618.png";
imageObj2.onload = function() {
ctx.drawImage(imageObj2, marginLeft, marginTop, 100, 100);
var img = c.toDataURL("image/png");
}
};
}
Which works fine if I'm only doing it with 1 canvas. But I'm trying to do this dynamically to every image that is loaded in my PHP code. so I'm trying to do this:
foreach($collection as $file){
echo "
<div class='posts-cards'>
<canvas id='myCanvas$file->id' width='300' height='300'></canvas>
</div>
<script>
var c=document.getElementById('myCanvas$file->id');
var ctx=c.getContext('2d');
var imageObj1 = new Image();
var imageObj2 = new Image();
var marginTop = 10;
var marginLeft = 10;
imageObj1.src = 'http://localhost:8080/sisop/storage/app/public/files/16522147787.png'
imageObj1.onload = function() {
ctx.drawImage(imageObj1, 0, 0, 328, 526);
imageObj2.src = 'http://localhost:8080/sisop/storage/app/public/files/165221397618.png';
imageObj2.onload = function() {
ctx.drawImage(imageObj2, marginLeft, marginTop, 100, 100);
var img = c.toDataURL('image/png');
}
};
</script>
But for some reason, the result is this:
I have "display: flex; flex-flow: wrap; " in my css (it's supposed to be 2 rows of 4 items in each), so, for some reason, only the 5th and 8th image are being generated.. And as you can see, only the last image has actually "merged" with the other image. I'm pretty stuck in here and don't quite understand what is going on here..

Canvas doesn't work on background pages - Collaborative drawing application with NodeJS

I have a problem with an application that would allow people to draw lines on the same canvas. Currently, my application only work locally. When I have multiple pages opened, the application works fine, the same drawing is on every canvas. However, when a page is reduced or opened in another tab, this page doesn't have the same canvas, most of the lines that should appear on this canvas are missing.
To reproduce the content of a canvas every time we add a line, I use the canvas method DrawImage().
Here is the code of the client side:
var url = 'http://localhost:4000';
var socket = io.connect(url);
var mouseData= {};
var startLine= false;
var first= {};
var last= {};
var tmpPosition= {};
var canvas = document.getElementById('tableauBlanc');
var contextCanvas1 = canvas.getContext('2d');
var Images = new Image();
var data;
canvas.addEventListener('mousemove', function(MouseEvent) {
tmpPosition=.x = MouseEvent.clientX;
tmpPosition=.y = MouseEvent.clientY;
tmpPosition== adaptMousePosition(tmpPosition=.x, tmpPosition=.y);
if (startLine) {
socket.emit('deleteAndRedrawCanvas', Images);
mouseData.px = first.x;
mouseData.py = first.y;
mouseData.dx = tmpPosition=.x;
mouseData.dy = tmpPosition=.y;
mouseData.validate= false;
socket.emit('DrawLine', mouseData);
}
}
});
canvas.addEventListener('click', function(MouseEvent) {
if (startDroite) {
last.x = MouseEvent.clientX;
last.y = MouseEvent.clientY;
last= adaptMousePosition(last.x, last.y);
contextCanvas1.strokeStyle = "#FF0000";
mouseData.px = first.x;
mouseData.py = first.y;
mouseData.dx = last.x;
mouseData.dy = last.y;
mouseData.validate= true;
socket.emit('DrawLine', mouseData);
startLine= false;
} else {
first.x = MouseEvent.clientX;
first.y = MouseEvent.clientY;
first= adaptMousePosition(first.x, first.y);
startLine= true;
}
});
socket.on('Draw', function(mouseData) {
contextCanvas1.strokeStyle = "#FF0000";
DrawLine(mouseData.px, mouseData.py, mouseData.dx, mouseData.dy);
if (mouseData.fini == true) {
setTimeout(DrawCanvas, 20);
}
});
function DrawCanvas() {
data = canvas.toDataURL();
Images.src = data;
Images.onload = function() {
Images.src = data;
contextCanvas1.drawImage(Images, 0, 0, 500, 500);
}
}
function DrawLine(px, py, dx, dy) {
contextCanvas1.strokeStyle = "#FF0000";
contextCanvas1.moveTo(px, py);
contextCanvas1.lineTo(dx, dy);
contextCanvas1.stroke();
}
socket.on('deleteAndRedrawCanvas', function(Images) {
contextCanvas1.clearRect(0, 0, 500, 500);
contextCanvas1.beginPath();
});
function adaptMousePosition(posX, posY) {
var gap= canvas.getBoundingClientRect();
return {
x: posX - gap.left,
y: posY - gap.top
};
}
Thanks for any pieces of advice.
By the way, that's the first time that I'm using Javascript and NodeJS, my code may be badly structured.

wrong width of img tag

i try to build an image uploader for my app. So i need to resize the images.
But often i got the false width value in the img tag.
Not every time. But sometimes when i load the picture 3 times or sometimes if i change the picture then there is the old width in. But also not everytime.
$(document).on('pageshow', '#profil', function () {
$('#content').height(getRealContentHeight());
var max_height = getRealContentHeight();
var max_width = $(window).width();
var username = getUrlParameter('user');
var data;
var x, y, w, h;
var preview;
var reader;
var pic = document.getElementById('pic');
var jcrop_api;
$('#upload').bind("change", function () {
preview = new Image();
var file = document.querySelector('input[type=file]').files[0];
reader = new FileReader();
reader.onloadend = function () {
if (jcrop_api) {
jcrop_api.setImage(reader.result);
}
preview.src = reader.result;
document.getElementById('pic').src = preview.src;
alert(pic.height); //there is the false value...sometimes....
alert(pic.width);
var size = calculateAspectRatioFit(pic.width, pic.height, max_width, max_height);
alert("heigth:" + size.height);
alert("width:" + size.width);
// document.getElementById('pic').height = size.height;
// document.getElementById('pic').width = size.width;
jQuery(function ($) {
$('#pic').Jcrop({
aspectRatio: 1,
minSize: [50, 50],
maxSize: [300, 300],
onChange: showCoords,
onSelect: showCoords
}, function () {
jcrop_api = this;
});
});
function showCoords(c) {
x = c.x;
y = c.y;
w = c.w;
h = c.h;
};
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
return {width: srcWidth * ratio, height: srcHeight * ratio};
}
};
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}
});
$('#continue').bind("click", function () {
//ajax upload
});
});
Could be one of two issues:
1) Are you setting your '#pic' element's height or width dimensions in css or inline? You may be getting the element's dimensions, not the image's.
2) You are setting 'src' on this img but not waiting until the image has been loaded. You might try:
$("#pic").on("load", function() {
//get dimensions now
});
Do you have to display the image at all? Otherwise you can load it in js using:
var img = new Image();
Then use the jQuery load event handler on this as above. Then set:
img.src = 'image url';
Can you try the following:
$("#pic").height();
$("#pic").width();
$("#pic").outerHeight();
$("#pic").outerWidth();
Instead of:
pic.height
pic.width
And see the right one that suits?

Clickable images in a canvas

I am trying to make the images inside a canvas clickable, but I am confused on how to go about that, here is what I have currently, I just want pictures[0] to be clickable and that alert to occur once it is clicked, but for some reason it is not working. How can i make it so that when picture[0] is clicked the alert goes off.
var images = document.getElementsByTagName("img");
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var left = c.offsetLeft;
var top = c.offsetTop;
var pictures = [];
//wheel
pictures[0] = new Image();
pictures[0].src = 'images/Layer8.png';
//bg
pictures[1] = new Image();
pictures[1].src = 'images/Layer0.png';
//gear
pictures[2] = new Image();
pictures[2].src = 'images/Layer7.png';
//speed
pictures[3] = new Image();
pictures[3].src = 'images/Layer14.png';
//dial1
pictures[4] = new Image();
pictures[4].src = 'images/Layer18.png';
//dial2
pictures[5] = new Image();
pictures[5].src = 'images/Layer16.png';
//dial3
pictures[6] = new Image();
pictures[6].src = 'images/Layer17.png';
c.addEventListener('click', function(event){
var x = event.pageX - left,
y = event.pageY - top;
pictures.forEach(function(fx,fy,fwidth,fheight,x,y) {
if (y > fy && y < fy + fheight
&& x > fx && x < fx + fwidth) {
alert('clicked an element');
}
});
}, false);
function load(){
ctx.drawImage(pictures[1],0,0);
ctx.drawImage(pictures[2],468,263);
ctx.drawImage(pictures[3],89,77);
ctx.drawImage(pictures[4],146,153);
ctx.drawImage(pictures[5],278,153);
ctx.drawImage(pictures[6],206,119);
ctx.drawImage(pictures[0],fx,fy,fwidth,fheight);
}
var fx = 84;
var fy = 60;
var fwidth = 283;
var fheight = 276;
window.onload = load;
Ok I understand what you are trying to do. Unfortunately, images in the canvas are not DOM elements, only the canvas itself is one. This means using jQuery you can call:
$('#myCanvas').on('click', function() {});
or natively:
c.addEventListener('click', function(){});
However, the fabricjs.com library may prove to be useful to you in this case.

Save a distorted image on the canvas

I can distort the image using the perspective transform js and then I am trying to draw the image on the canvas which should be the distorted image. The canvas needs to be generated dynamically and may contain a background image as well.
I am unable to figure out how can I redraw the distorted image on the canvas.
Here's the fiddle
$('#btnDistort').on('click touchstart', function (e) {
if (!jaaliApp.currentJaali.jaali) {
jaaliApp.currentJaali.jaali = $('.img');
var url = $('.img').css('backgroundImage');
url = url.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
jaaliApp.currentJaali.url = url;
}
jaaliApp.distort(jaaliApp.currentJaali.jaali);
});
var jaaliApp = {
distort: function (image) {
var img;
while (!$(image).is('.img')) {
image = $(image).parent();
}
img = $(image);
var container = $(img).parent();
function createHandles() {
$(container).find(".pt").remove();
var topLeft = document.createElement("div");
topLeft.className = "pt tl";
$(container).append(topLeft);
var topRight = document.createElement("div");
topRight.className = "pt tr";
$(container).append(topRight);
var bottomLeft = document.createElement("div");
bottomLeft.className = "pt bl";
$(container).append(bottomLeft);
var bottomRight = document.createElement("div");
bottomRight.className = "pt br";
$(container).append(bottomRight);
}
createHandles();
var pts = $(container).find(".pt");
var IMG_WIDTH = $(img).parent().width();
var IMG_HEIGHT = $(img).parent().height();
var IMG_OFFSET = {
left: 0,
top: 0
}; /*$(img).parent().offset();*/
var transform = new PerspectiveTransform(img[0], IMG_WIDTH, IMG_HEIGHT, true);
var tl = pts.filter(".tl").css({
left: transform.topLeft.x + IMG_OFFSET.left,
top: transform.topLeft.y + IMG_OFFSET.top
});
var tr = pts.filter(".tr").css({
left: transform.topRight.x + IMG_OFFSET.left,
top: transform.topRight.y + IMG_OFFSET.top
});
var bl = pts.filter(".bl").css({
left: transform.bottomLeft.x + IMG_OFFSET.left,
top: transform.bottomLeft.y + IMG_OFFSET.top
});
var br = pts.filter(".br").css({
left: transform.bottomRight.x + IMG_OFFSET.left,
top: transform.bottomRight.y + IMG_OFFSET.top
});
var target;
var targetPoint;
function onMouseMove(e) {
console.log($(this))
targetPoint.x = e.pageX - container.offset().left;
targetPoint.y = e.pageY - container.offset().top;
target.css({
left: targetPoint.x,
top: targetPoint.y
});
// check the polygon error, if it's 0, which mean there is no error
if (transform.checkError() == 0) {
transform.update();
img.show();
} else {
img.hide();
}
e.stopPropagation();
}
$(pts).draggable({
containment: '#jaaliContainer',
start: function (e) {
console.log(e);
target = $(this);
targetPoint = target.hasClass("tl") ? transform.topLeft : target.hasClass("tr") ? transform.topRight : target.hasClass("bl") ? transform.bottomLeft : transform.bottomRight;
onMouseMove.apply(this, Array.prototype.slice.call(arguments));
},
stop: function (e) {
console.log(e)
},
drag: onMouseMove
});
}
}
On the click of the save button the image as is should be drawn on the canvas. How can I achieve the same?
It is unfortunately not possible to save an image of a CSS distorted element. In this context the canvas is just an element as any other and the distortion is at a lower level than the bitmap we are exposed to when updating the canvas bitmap.
If you want to do a quadrilateral transform as here you would have to implement the low-level maths and algorithm yourself to modify the exposed bitmap itself.
Only then can you save the content as-is.
You may get around it using SVG in the future but currently there are many restrictions with it (for example external references such as images are not allowed).

Categories

Resources