Get Original Image Width And Height From A New Image() Object - JavaScript - javascript

I have an image uploader where I have some PHP checks that happen on the server side. What I want to do is also provide frontend validations for the user, but I am having an issue getting the values to do the maths for the image resolution in megapixels. On the server side I can just use the file's width and height properties and then multiply them.
The problem I have is on the frontend when using a new Image() object, when I get the width and height properties it gives me the values of the image file in the container, not the width and height values of the source file / original image.
I thought I could just use the .src property and get the size of that instead, but this doesn't work either.
In the code below as you can see the Image() object is assigned to a thumbnailElement variable.
If you click the Select Files button and add an image it will show the thumbnails and log the original file size to the console, but not the original width ?
Note: the updateThumbnail() function is invoked in the HTML
Codepen Link: https://codepen.io/thechewy/pen/yLjvqWe
var zone = document.getElementById("zone"),
selectedImagesContainer = document.getElementById("show-selected-images"),
fileUploader = document.getElementById("standard-upload-files");
zone.addEventListener("click", (e) => {
// assigns the zone element to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
fileUploader.addEventListener("change", (e) => {
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
function updateThumbnail(file) {
let uploadImageWrapper = document.createElement("figure"), // image wrapper <figure> element
thumbnailElement = new Image(); // image
// image thumbnail
thumbnailElement.classList.add("thumbnail");
thumbnailElement.src = URL.createObjectURL(file);
// appending elements
selectedImagesContainer.append(uploadImageWrapper); // append <figure> element
uploadImageWrapper.append(thumbnailElement); // append image thumbnail
console.log("file size is: ", file.size);
console.log("file width is: ", thumbnailElement.width);
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
font-family: arial;
}
form {
width: 50%;
max-width: 600px;
}
.select-files {
padding: 1rem;
background: red;
cursor: pointer;
color: #fff;
font-weight: bold;
}
#show-selected-images {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 2rem;
}
figure {
width: 100%;
margin: 0;
}
img {
display: block;
width: 100%;
height: auto;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="zone">
<p class="select-files">SELECT FILES</p>
</div>
<div class="inner-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none;" type="file" name="standard-upload-files[]" multiple>
</div>
<button id="submit-images" oninput="updateThumbnail(this.files)">SUBMIT IMAGES</button>
</div>
<div id="show-selected-images"></div>
</form>

You need the naturalWidth property to get actual image width in pixels, also to get that value reliably you should use the HTMLImageElement.decode() method that returns a promise which is resolved once the full-resolution image is fully decoded, like this:
var zone = document.getElementById("zone"),
selectedImagesContainer = document.getElementById("show-selected-images"),
fileUploader = document.getElementById("standard-upload-files");
zone.addEventListener("click", (e) => {
// assigns the zone element to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
fileUploader.addEventListener("change", (e) => {
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
function updateThumbnail(file) {
let uploadImageWrapper = document.createElement("figure"), // image wrapper <figure> element
thumbnailElement = new Image(); // image
// image thumbnail
thumbnailElement.classList.add("thumbnail");
thumbnailElement.src = URL.createObjectURL(file);
// appending elements
selectedImagesContainer.append(uploadImageWrapper); // append <figure> element
uploadImageWrapper.append(thumbnailElement); // append image thumbnail
console.log("file size is: ", file.size);
thumbnailElement.decode().then(() => {
console.log("file width is: ", thumbnailElement.naturalWidth);
}).catch((encodingError) => {
// Do something with the error.
});
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
font-family: arial;
}
form {
width: 50%;
max-width: 600px;
}
.select-files {
padding: 1rem;
background: red;
cursor: pointer;
color: #fff;
font-weight: bold;
}
#show-selected-images {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
margin-top: 2rem;
}
figure {
width: 100%;
margin: 0;
}
img {
display: block;
width: 100%;
height: auto;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="zone">
<p class="select-files">SELECT FILES</p>
</div>
<div class="inner-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none;" type="file" name="standard-upload-files[]" multiple>
</div>
<button id="submit-images" oninput="updateThumbnail(this.files)">SUBMIT IMAGES</button>
</div>
<div id="show-selected-images"></div>
</form>

Yes, .width and .height will return the computed width and height of the element when it's visible in the doc.
Since your <img> element doesn't have an srcset attribute, you can use both its naturalWidth and naturalHeight to get the actual intrinsic size of the loaded image. If you had this srcset attribute though, these values could be divided by the size multiplier of the loaded source.
If you weren't displaying the image in a thumbnail, an efficient way to get the dimensions of the image would have been to call createImageBitmap() either on the File object you have directly, and to check the .width and .height properties of the resolved ImageBitmap object.
But since you do show the image, in your case that'd be overkill. Using .naturalWidth and .naturalHeight (after the image has loaded) is just enough.

Related

Creating ID card with HTML

I'm trying to create a simple ID card template with HTML but I got stocked for days looking for how to make passport photograph appear in the photograph box. I also noticed that the print preview of the ID card is not the same as what I see on screen, how can I fix this too please? Below is the code...
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
w = window.open();
w.document.write(printContents);
w.print();
w.close();
}
body {
background-image: url("id-template.jpg");
background-attachment: fixed;
background-repeat: no-repeat;
background-position: center;
}
#media print {
#print {
display: none;
}
}
#print {
position: fixed;
bottom: -4px;
}
div {
padding-top: 204px;
}
<div id="identity"> <span style="padding-left: 436px;">
<form style="display: inline;"><input type="file" accept="image/jpeg"
placeholder="PASSPORT PHOTO" style="border-color: grey; border-radius: 90px; height: 155px; width: 155px; text-align: center; font-family: monospace; font-size: 10px; margin-bottom: 7px" /></form></span>
<br>
<span style="padding-left: 370px">
<form style="display: inline;"><input placeholder="YOUR NAME" style="border-color: grey; border-radius: 5px; height: 25px; width: 280px; text-align: center; font-family: monospace; font-size: 20px;" /></form></span>
</div><br>
<center><input type="button" id="print" onclick="print()" value="Print" /></center>
The two helps I need
I want the photograph to appear when selected from the user's device.
I want the print preview to show exactly what on the page.
This is the id-template.jpg I'm working with.
Thanks.
The html in your question has lots of noise and was relying on odd strategies for positioning.
For the sake of showing the core of the issue you are meant to solve, I stripped it down to the bare minimum. It won't perfectly match with your expectations but the css is well commmented so it will be easy for you to restyle it according to your needs.
Displaying the picture loaded by user in an <input type=file>
Anyway the main problem there was how to show the picture in the file just loaded inside an input type="file" element.
The key is having a change event handler on your input file element so that when the user loads a new file, it will attempt to read it using a FileReader and will change the src attribute of an <img> element existing in the dom.
.noprint class to style elements when #media print
I also added a class noprint to add to all the elements that will be hidden by the media query #media print. Such class is given to the <input type="file"> and to the <button> for printing.
References
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
Demo
I did a very small demo to show the point:
function printDiv(divName) {
var printContents = document.getElementById(divName).innerHTML;
w = window.open();
w.document.write(printContents);
w.print();
w.close();
}
/*shows inside #preview the picture loaded in the #photo element*/
function previewImage() {
var preview = document.getElementById('preview');
var file = document.getElementById('photo').files[0];
//creates a FileReader with the onLoadEnd event handler
var reader = new FileReader();
reader.onloadend = function () {
//..that will change the src attribute of the preview element to show the picture loaded
preview.src = reader.result;
}
//if there's a file loaded
if (file) {
//unhide the #preview element
preview.style.display = "block";
//lets the FileReader reads the file loaded
reader.readAsDataURL(file);
} else {
preview.src = "";
}
}
body {
font-family: monospace; /* <----- here I set the font/size for all children in body */
font-size: 18px;
}
/*hides the .noprint elements when printing*/
#media print {
.noprint {
display: none !important;
}
}
/*flex container*/
#identity{
display: flex;
flex-direction: column;
gap: 1em; /* <----- here I set space between elements in the container */
}
/*flex items*/
#identity > *{
margin: 0 auto; /*horizontally centered*/
}
/*all input elements*/
input{
border-color: grey;
text-align: center;
}
/*name input*/
#name{
width: 30ch; /* <----- here I chose the name input to have 30ch*/
}
/*preview*/
#preview{
width: 30%; /* <----- here I chose the preview to have 30% container width*/
}
#print{
display: block;
margin: 1em auto 0 auto;
cursor: pointer;
}
<body>
<form id="identity">
<input
id="photo"
class="noprint"
name="photo"
type="file"
accept="image/jpeg"
placeholder="PASSPORT PHOTO"
onchange="previewImage()">
<img id="preview" src="#" alt="Image preview" style="display:none;">
<input
id="name"
name="name"
placeholder="YOUR NAME">
</form>
<button type="button" id="print" class="noprint" onclick="print()">Print</button>
</body>

Setting file input as background for an HTML element

I am creating a UI where the user wants to upload her profile picture using <input type="file"> by clicking on its corresponding <label>. I want to show the preview of the image as the background of the same <label>. I tried to use inputNode.files[0] in JavaScript but it does not work.
I am also working on a button X which clears the selected file field values and essentially the background image too but that's the next step of the goal. Some guidance regarding this is also welcome, since I have not thought about this either.
document.getElementById("avatar").onchange = function(e) {
console.log("file changed", e.target.files[0]);
// document.getElementById("preview-img");
document.getElementById("avatar-label").style.backgroundImage = e.target.files[0];
// document.getElementById("avatar-label").style.backgroundImage = 'url("https://picsum.photos/70/70")';
};
#avatar {
display: inline-block;
height: 0;
width: 0;
}
#avatar-label {
position: relative;
display: flex;
justify-content: center;
align-items: center;
height: 70px;
width: 70px;
border: solid 1px #333;
/*background: url('https://picsum.photos/70/70');*/
}
#avatar-label:hover {
cursor: pointer;
}
/* styling for unselecting the image */
#avatar-label #unselect-image {
display: none;
position: absolute;
top: 0;
right: 0;
border: none;
outline: none;
background: #fff;
}
<form action="" method="get">
<input accept="image/*" type="file" name="avatar" id="avatar">
<label for="avatar" id="avatar-label">
+
<button type="button" id="unselect-image">X</button>
</label>
<img src="" alt="" id="preview-img">
</form>
Showing in background
Use file reader instead of directly assigning the image object.
You may change your script to show background image as below
document.getElementById('avatar').onchange = function (e){
var file = e.target.files[0];
var reader = new FileReader();
reader.onloadend = function(){
document.getElementById('avatar-label').style.backgroundImage = "url(" + reader.result + ")";
document.getElementById('unselect-image').style.display = "inline";
}
if(file){
reader.readAsDataURL(file);
}
}
Clearing the background
For clearing the background image the following script may help
document.getElementById('unselect-image').onclick = function (){
document.getElementById('avatar-label').style.background = "none";
document.getElementById('unselect-image').style.display = "none";
};
The value of the background-image property in CSS is a string consisting of url(, followed by a URL, followed by ).
It is not a file object.
So you need to take that file object and convert it into a URL. This answer to another question explains how to do that.
Then you need to wrap the result in url( and ) and assign it:
.then( data => {
document.getElementById("avatar-label").style.backgroundImage = `url(${data})`;
})
Here are making thumbnail on uploading image
And to clear selected field is simple.
You assign '' into "src" property of html "img" element and value property of html "input" element.
Replace "label" with "img" if possible.

How do I prevent my image from disappearing when I use a click event on Javascript?

I'm creating an image gallery and whenever I click on the image, it displays it fully across the screen. However, whenever I try to click off of it and return to the normal website screen, the image is completely gone.
Here is a codepen showing the problem https://codepen.io/designextras/pen/WNrQMdM
In the html I am targeting the image tag by using firstElementChild in my Javascript for ".services-cell"
<div class="services-cell">
<img class="services-cell_img" src="gallery/img-1.jpg" alt="">
<div class="services-cell_text">Digital Marketing</div>
</div>
Here is the Javascript, it is also in the codepen above
let galleryImages = document.querySelectorAll('.services-cell');
let getLatestOpenedImg;
let windowWidth = window.innerWidth;
if(galleryImages) {
galleryImages.forEach(function(image, index){
image.onclick = function() {
console.log(image.firstElementChild);
getLatestOpenedImg = index + 1;
let container = document.body;
let newImgWindow = document.createElement('div');
container.appendChild(newImgWindow);
newImgWindow.setAttribute('class', 'img-window');
newImgWindow.setAttribute('onclick', 'closeImg()');
let newImg = image.firstElementChild;
newImgWindow.appendChild(newImg);
newImg.classList.remove('services-cell_img');
newImg.classList.add('popup-img');
}
})
}
function closeImg() {
document.querySelector('.img-window').remove();
}
and here is the CSS classes that I'm trying to add whenever I click on the image
.img-window {
width: 100vw;
height:100vh;
background: rgba(0,0,0,0.8);
position: fixed;
top: 0;
left: 0;
z-index: 100;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.popup-img {
max-height: 80vh;
max-width: 80vw;
z-index: 200;
}
So the bottom function closeImg() seems to be the problem, but I don't know else I'd write my code in order to close out the image pop up and return to the screen without it completely removing my image from the html
When you append the image to newImgWIndow, you're removing it from its original DIV. You should clone the image instead of moving it.
let newImg = image.firstElementChild.cloneNode();
newImgWindow.appendChild(newImg);
newImg.classList.remove('services-cell_img');
newImg.classList.add('popup-img');

How to add, fix and display text in image using HTML?

I have project in which I have to add text in image, After adding it will become new image and then I have to display new image.
I am able to get image and I can add the text in image.
HTML:
<img src="pic_mountain.jpg" style="width:304px;height:228px;"/>
<h2>A Movie in the Park<br />Kung Fu Panda</h2>
CSS:
.image {
position: relative;
width: 100%; /* for IE 6 */
}
h2 {
position: absolute;
top: 50px;
left: 50px;
width: 100%;
}
my initial image is like:
After adding text it will look like:
now I need to fix this text for this image as a new image. I also want to use that new image for display without affecting original image.
Is there any solution for this?
If there any other way to add text using jquery or else, then please suggest me..
PHP has literally COUNTLESS libraries for doing just this but were all lazy and nobody wants to learn a new framework so heres some simple php functions to do just this
Note: you would have to use php and then ajax to update it in real time i am unaware of any way to do what your asking in javascript
<?php
$image_path = "images/image.jpeg";
//Set the Content Type
header('Content-type: image/jpeg');
// Create Image From Existing File
$jpg_image = imagecreatefromjpeg($image_path);
// Allocate A Color For The Text
$white = imagecolorallocate($jpg_image, 255, 255, 255);
// Set Path to Font File
$font_path = 'fonts/font.TTF';
// Set Text to Be Printed On Image
$text = "text to write to image";
// Print Text On Image
imagettftext($jpg_image, 25, 0, 75, 300, $white, $font_path, $text);
// Send Image to Browser
imagejpeg($jpg_image);
// Clear Memory
imagedestroy($jpg_image);
?>
Please not that this is an example using jpeg but php supports the exact same functionality for png,gif, and a few other image types
Hi now you can try to this way
.imgSec {
position: relative;
width: 300px;
margin:0 auto;
}
.imgSec img{width:100%;height:228px;}
.imgSec h2 {
position: absolute;
top: 50px;
left: 50px;
width: 100%;
}
<div class="imgSec">
<img src="http://i.stack.imgur.com/8GnUj.jpg" />
<h2>A Movie in the Park<br />Kung Fu Panda</h2>
</div>
The HTML
<div class="item">
<img src="http://i.stack.imgur.com/8GnUj.jpg" style="width:304px;height:228px;"/>
<h2>A Movie in the Park<br />Kung Fu Panda</h2>
</div>
And the css is
.item {
position: relative;
width: 100%; /* for IE 6 */
}
h2 {
position: absolute;
top: 50px;
left: 50px;
width: 100%;
}
You can use the Canvas 2D API.
Two steps :
use drawImage() to draw your image.
use fillText() to fill your text.
Complete demo :
/* okay there are actually a few more steps.. */
var img = new Image();
img.crossOrigin ='anonymous'; // not needed if you're not using images from an other domain
img.onload = function(){ // remember to wait before your image has loaded
// our canvas element
var canvas = document.createElement('canvas');
// its drawing context
var ctx = canvas.getContext('2d');
// don't resize the canvas with css
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0,0)
ctx.font ='25px sans-serif';
ctx.fillText('Hello world', 10, 40);
// just using it as a backgroundImage to demonstrate that you can export the result, you could also just append the canvas into the doc, or use the `toBlob()` method for use with FileSaver.js e.g.
document.body.style.backgroundImage = 'url('+canvas.toDataURL()+')';
out.href = canvas.toDataURL();
};
img.src = 'https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png?dl=0';
body{
width: 100vw;
height:100vh;
}
<a id="out"> show me an image instead </a>

HTML2Canvas converting overflowed content to image

I have a div which is pretty overflowed. It basically includes a big organization chart. What I want to do is exporting whole content of div rather than visible part with html2canvas library but I couldn't achieve it so far. Following piece of code doesn't render full content. Is there a way to achieve it?
function export(){
html2canvas( [ document.getElementById('diagram') ], {
onrendered: function(canvas) {
var dataUrl = canvas.toDataURL();
window.open(dataUrl, "toDataURL() image", "width=800, height=800");
//Canvas2Image.saveAsPNG(canvas);
}
});
}
I am using BasicPrimitives library to generate organization charts. It takes a div and insert all elements to it. Since my chart is moderately big, it overflows from its container.
Xhtml code is as follows:
<rich:panel style="float: left; width: 100%;">
<div style="float: left; height:600px; margin-left: 1%; width: 19%; border-style: dotted; border-width:1px;">
Some irrelevant content
</div>
<div id="diagram" class='diagram' style="float: right; height:600px; width: 59%; border-style: dotted; border-width:1px;">
This is the div all charts are dynamically inserted
</div>
<div style="float: left; height:600px; margin-left: 1%; width: 19%; border-style: dotted; border-width:1px;">
Some more irrelevant content
</div>
</rich:panel>
I don't know if there's a straightforward option in html2canvas to do this (i.e. an option to set all overflow to visible) but a roundabout way might be to set the parent of the diagram element's overflow property to visible when your export function is called, then set it back to hidden again on html2canvas' onrendered callback so that the user has minimal time to perceive it:
function export(){
document.getElementById('diagram').parentNode.style.overflow = 'visible'; //might need to do this to grandparent nodes as well, possibly.
html2canvas( [ document.getElementById('diagram') ], {
onrendered: function(canvas) {
document.getElementById('diagram').parentNode.style.overflow = 'hidden';
var dataUrl = canvas.toDataURL();
window.open(dataUrl, "toDataURL() image", "width=800, height=800");
//Canvas2Image.saveAsPNG(canvas);
}
});
}
Give a try to dom-to-image, it works better for me since I have to set specific size, and show and element that hides for some screen size:
function convertCanvasAndSend(idElement, nameImage) {
var element = document.getElementById(idElement);
var styleOrig = element.getAttribute("style");
element.setAttribute("style", "width: 1400px; height: 480px;");
element.querySelector("ANY_HIDDEN_YOU NEED").setAttribute("style", "display: block;");
domtoimage.toBlob(element)
.then(function (blob) {
window.saveAs(blob, nameImage + '.png');
element.setAttribute("style", styleOrig);
element.querySelector("ANY_HIDDEN_YOU NEED").setAttribute("style", styleOrigInnDiv);
});
}

Categories