I tried to figure it out looking at the source code but I couldn't figure it out.
I would like to know how to make a dynamic favicon with a count like Gmail does.
Any idea on how to do this?
You can make an image with the canvas element, and then just replace the current favicon. Check out the following link for a good explanation on it.
Reference
Code is from the above reference.
Markup
<link id="favicon" rel="icon" type="image/png" href="image.png" />
JS
(function () {
var canvas = document.createElement('canvas'),
ctx,
img = document.createElement('img'),
link = document.getElementById('favicon').cloneNode(true),
day = (new Date).getDate() + '';
if (canvas.getContext) {
canvas.height = canvas.width = 16; // set the size
ctx = canvas.getContext('2d');
img.onload = function () { // once the image has loaded
ctx.drawImage(this, 0, 0);
ctx.font = 'bold 10px "helvetica", sans-serif';
ctx.fillStyle = '#F0EEDD';
if (day.length == 1) day = '0' + day;
ctx.fillText(day, 2, 12);
link.href = canvas.toDataURL('image/png');
document.body.appendChild(link);
};
img.src = 'image.png';
}
})();
Edit
Must have an image set as well.
Related
PS: Is it not a research kind of question! I have been trying to do this from very long time.
I am trying to make web based an image editor where user can select multiple cropping area and after selection save/download all the image area. like below.
As of now I discovered two libraries
1.Cropper.JS where is only single selection feature is available.
2.Jcrop where only single selection area restrictions.
I am currently using cropper.Js but it seems impossible for me to make multiple selection cropping.
Any help is much appreciated.if any other method/library available in JavaScript, Angular or PHP or reactJS for multiple image area selection and crop and download in one go as in the image below.
As per #Keyhan Answer I am Updating my Jcrop library Code
<div style="padding:0 5%;">
<img id="target" src="https://d3o1694hluedf9.cloudfront.net/market-750.jpg">
</div>
<button id="save">Crop it!</button>
<link rel="stylesheet" href="https://unpkg.com/jcrop/dist/jcrop.css">
<script src="https://unpkg.com/jcrop"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
JavaScript
<script>
setImage();
var jcp;
var jcp;
Jcrop.load('target').then(img => {
//You can enable multiple cropping with this line:
jcp = Jcrop.attach(img, { multi: true });
});
// to fix security issue when trying to convert to Data URI
function setImage() {
document.getElementById('target').setAttribute('crossOrigin', 'anonymous');
document.getElementById('target').src = 'https://d3o1694hluedf9.cloudfront.net/market-750.jpg';
}
var link = document.getElementById('save');
link.onclick = function () {
//we check if at least one crop is available
if (jcp.active) {
var i = 0;
var fullImg = document.getElementById("target");
//we are looping cropped areas
for (area of jcp.crops) {
i++;
//creating temp canvas and drawing cropped area on it
canvas = document.createElement("canvas");
canvas.setAttribute('width', area.pos.w);
canvas.setAttribute('height', area.pos.h);
ctx = canvas.getContext("2d");
ctx.drawImage(fullImg, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h);
//creating temp link for saving/serving new image
temp = document.createElement('a');
temp.setAttribute('download', 'area' + i + '.jpg');
temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream"));
temp.click();
}
}
};
</script>
I tried to explain the code with comments:
var jcp;
Jcrop.load('target').then(img => {
//You can enable multiple cropping with this line:
jcp = Jcrop.attach(img,{multi:true});
});
//assuming you have a button with id="save" for exporting cropped areas
var link=document.getElementById('save');
link.onclick = function(){
//we check if at least one crop is available
if(jcp.active){
var i=0;
var fullImg = document.getElementById("target");
//we are looping cropped areas
for(area of jcp.crops){
i++;
//creating temp canvas and drawing cropped area on it
canvas = document.createElement("canvas");
canvas.setAttribute('width',area.pos.w);
canvas.setAttribute('height',area.pos.h);
ctx = canvas.getContext("2d");
ctx.drawImage(fullImg, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h);
//creating temp link for saving/serving new image
temp = document.createElement('a');
temp.setAttribute('download', 'area'+i+'.jpg');
temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream"));
temp.click();
}
}
};
EDIT: As you commented it would be nicer if we have local image loader, we can add a file input to our html
<img id="target" />
<br/>
<input type="file" id="imageLoader" name="imageLoader"/><!-- add this for file picker -->
<button id="save">save</button>
and a function to our js to handle it
var jcp;
var save=document.getElementById('save');
var imageLoader = document.getElementById('imageLoader');
var img = document.getElementById("target");
imageLoader.onchange=function handleImage(e){//handling our image picker <input>:
var reader = new FileReader();
reader.onload = function(event){
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
save.onclick = function(){
if(jcp&&jcp.active){
var i=0;
for(area of jcp.crops){
i++;
canvas = document.createElement("canvas");
canvas.setAttribute('width',area.pos.w);
canvas.setAttribute('height',area.pos.h);
ctx = canvas.getContext("2d");
ctx.drawImage(img, area.pos.x, area.pos.y, area.pos.w, area.pos.h, 0, 0, area.pos.w, area.pos.h);
temp = document.createElement('a');
temp.setAttribute('download', 'area'+i+'.jpg');
temp.setAttribute('href', canvas.toDataURL("image/jpg").replace("image/jpg", "image/octet-stream"));
temp.click();
}
}
};
Jcrop.load('target').then(img => {
jcp = Jcrop.attach(img,{multi:true});
});
Yes, #keyhan was right <input type="file"> is another question, but still, I am giving you an idea of how to implement Kayhan's code above.
<div>
<input type="file" id="image-input" accept="image/*">
<!-- img id name should be "target" as it is also using by Jcrop -->
<img id="target"></img>
</div>
and Now you can put below JavaScript Code just above setImage()
<script>
let imgInput = document.getElementById('image-input');
imgInput.addEventListener('change', function (e) {
if (e.target.files) {
let imageFile = e.target.files[0];
var reader = new FileReader();
reader.onload = function (e) {
var img = document.createElement("img");
img.onload = function (event) {
var MAX_WIDTH = 1600;
var MAX_HEIGHT = 800;
var width = img.width;
var height = img.height;
// Change the resizing logic
if (width > height) {
if (width > MAX_WIDTH) {
height = height * (MAX_WIDTH / width);
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width = width * (MAX_HEIGHT / height);
height = MAX_HEIGHT;
}
}
// Dynamically create a canvas element
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
// var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// Actual resizing
ctx.drawImage(img, 0, 0, width, height);
// Show resized image in preview element
var dataurl = canvas.toDataURL(imageFile.type);
document.getElementById("target").src = dataurl;
}
img.src = e.target.result;
}
reader.readAsDataURL(imageFile);
}
});
</script>
In Font Awesome 4x I managed to set the cursor as an icon by changing it into a base-64 image url. Now in Font Awesome 5 it does not work any more.
I've found this solution, but it's not working here.
This is what I've tried.
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var ctx = canvas.getContext("2d");
document.fonts.ready.then(function() {
ctx.font = "400 20px Font Awesome 5 Pro";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
setTimeout(function() {
ctx.fillText("\uf2ed", 10, 10)
var dataURL = canvas.toDataURL('image/png')
$('#foo').css('cursor', 'url(' + dataURL + '), auto');
}, 200)
})
All I get is a black square 20x20
Is there anyone who knows how to get it done?
see the below example ...
var hex = 0xF25A;
var unicode = String.fromCharCode(parseInt(hex, 16));
var canvas = document.getElementById("cache");
canvas.width = 64; canvas.height = 64;
var context = canvas.getContext("2d");
context.font = '900 32px "Font Awesome 5 Free"';
context.fillText(unicode, canvas.width/2, canvas.width/2);
document.fonts.ready.then(function() {
$('body').css('cursor', 'url(' + canvas.toDataURL('image/png') + '), auto');
});
html, body {height: 100%; width:100%; margin:0; padding: 0;}
canvas#cache {display: none;}
<link rel="stylesheet" href="//use.fontawesome.com/releases/v5.2.0/css/solid.css" integrity="sha384-wnAC7ln+XN0UKdcPvJvtqIH3jOjs9pnKnq9qX68ImXvOGz2JuFoEiCjT8jyZQX2z" crossorigin="anonymous">
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="cache"/>
This is an old question, but I was successful using jquery.awesomecursor, and this JS:
$('body').awesomeCursor('cut', {color: '#3097d1',
font: {cssClass: 'far fa-%s',
family:'"Font Awesome 5 Pro"'
}
});
The key things here were:
. The cssClass for FontAwesome 5 ("regular" icons are 'far fa-X', not 'fa fa-X' as they were in prior versions)
. The way "family" is specified - I needed the inner set of quotes to make it work.
FWIW, I'm using this with WebPack so I needed to make sure faCut was loaded from "#fortawesome/pro-regular-svg-icons"; You can read more about this here.
I'm trying to draw text onto a flag using a simple script. It works fine except for the Font not being loaded.
I've tried to load the font locally and from the web, but both don't work on my server.
However the code runs fine on w3 schools tryit editor
I think it has to do with the font not being loaded correctly or too late. What is the best way to make sure the font is loaded correctly?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,bold&subset=Latin">
<style>body { font-family: Ubuntu, sans-serif; }</style>
</head>
<body>
<canvas style="border-radius: 100px;" id="myCanvas" width="200" height="200">
Your browser does not support the HTML5 canvas tag.</canvas>
<script>
function getParameterByName(name, url) {
if (!url) url = window.location.href;
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return '';
return decodeURIComponent(results[2].replace(/\+/g, " "));
}
var size = 200
var textSize=size * 0.55;
var countryCode = "nl";
var text = "123";
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image;
img.onload = function(){
ctx.drawImage(img,-1,-1,size,size); // removes the 1px border the flags sometimes have
ctx.font = textSize+"px Ubuntu";
ctx.textAlign="center";
ctx.fillStyle = "#260C4D";
ctx.fillText(text,size/2,size/2 + textSize / 2.85);
};
img.src = "http://www.geonames.org/flags/x/"+countryCode+".gif";
</script>
</body>
</html>
I'm really tempted to vote to close as duplicate to this Q/A, but since you're in a particular case, I'll still post this answer, which may not be the best.
You are loading your font with a <link> element, so one way is to use its onload event handler.
The problem with this approach is that the font may be cached, and the load event may have fired before it reaches your script declarations.
So you could use the href +'&'+ new Date().getTime() trick to make a new request to the server, or you can remove the <link> from the DOM and reappend it. This way, its load event should fire again even if the cached version is used.
(Note that I only tested it on latest FF and Chrome, so it may not work in other browsers).
var link = document.querySelector('link');
link.onload = function() {
log.textContent = 'loading image...';
var size = 200
var textSize = size * 0.55;
var countryCode = "nl";
var text = "123";
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image;
img.onload = function() {
log.textContent='';
ctx.drawImage(img, -1, -1, size, size); // removes the 1px border the flags sometimes have
ctx.font = textSize + "px Ubuntu";
ctx.textAlign = "center";
ctx.fillStyle = "#260C4D";
ctx.fillText(text, size / 2, size / 2 + textSize / 2.85);
};
img.src = "http://lorempixel.com/200/200";
}
// in case it's in the cache, it seems we have to remove it from the DOM and reinsert it
link.parentNode.removeChild(link);
document.head.appendChild(link)
body {
font-family: Ubuntu, sans-serif;
}
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Ubuntu:regular,bold&subset=Latin">
<p id="log">loading font..</p>
<canvas style="border-radius: 100px;" id="myCanvas" width="200" height="200"></canvas>
I want to load two separate images in my script. I've accomplished it using:
<img src="iphone4.png" id="img1">
<img src="screenshot.png" id="img2">
<script>
window.onload = function () {
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
</script>
Problem here though is that the images should not be visible on the page but are when loaded using markup. I simply want to load them through the script without first having to add them in the markup. I realize this is an extremely trivial problem, but searching for a solution has given me nothing.
I tried this approach:
window.onload = function () {
var img1 = "iphone4.png";
var img2 = "screenshot.png";
But this did not work.
Can someone with some common JS sense please give me some input on this issue.
EDIT :
So this is how the markup/JS looks now, the images are still displayed and the final merge of the images won't show. The error I get is:
IndexSizeError: Index or size is negative or greater than the allowed amount
[Stanna vid fel]
var image1 = context.getImageData(0, 0, width, height);
And this is the syntax:
<body>
<img src="" id="img1">
<img src="" id="img2">
<p>Blended image<br><canvas id="canvas"></canvas></p>
<script>
window.onload = function () {
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
img1.src = "iphone4.png";
img2.src = "screenshot.png";
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var width = img1.width;
var height = img1.height;
canvas.width = width;
canvas.height = height;
var pixels = 4 * width * height;
context.drawImage(img1, 0, 0);
var image1 = context.getImageData(0, 0, width, height);
var imageData1 = image1.data;
context.drawImage(img2, 73, 265);
var image2 = context.getImageData(0, 0, width, height);
var imageData2 = image2.data;
while (pixels--) {
imageData1[pixels] = imageData1[pixels] * 0 + imageData2[pixels] * 1;
}
image1.data = imageData1;
context.putImageData(image1, 0, 0);
};
</script>
You can create an Image without having the actual tag in the markup:
var img = new Image();
img.src = 'iphone4.png';
//use img however you want
Hope this helps.
window.onload = function () {
var img1 = new Image();
var img2 = new Image();
//EDIT2 you can hide img, or simply not add them to the DOM...
img1.style.display = "none";
img2.style.display = "none";
img1.src = "iphone4.png";
img2.src = "screenshot.png";
EDIT: DO NOT DO THAT and your images won't be displayed
document.body.append(img1);
OR
document.getElementById("myID").append(img2);
"What I'm doing is merging two images using JS"
Your problem is probably due to the fact that you are trying to draw images that have not been loaded yet. To circumvent this issue, you could create the images dynamically and set their src attribute to start loading the image and listen to the image's load event to know when they are fully loaded so that you can perform the merge safely.
I have not tested the code, but it should give you the idea.
var images = [
'iphone4.png',
'screenshot.png'
],
len = images.length,
i = 0,
loadedCount = 0,
img;
for (; i < len; i++) {
img = document.createElement('img');
//listener has to be added before setting the src attribute in case the image is cached
img.addEventListener('load', imgLoadHandler);
img.src = images[i];
images[i] = img;
}
function mergeImages() {
var img1 = images[0],
img2 = images[1];
//do the merging stuff
}
function imgLoadHandler() {
if (++loadedCount === len) {
mergeImages();
}
}
There is a way with HTML5, but it would still require the user to have dropped the file into a drop target or use a box.
Using the File API you can read files, and potentially decode them.
Actually reading the file blob and displaying it locally may be tricky though. You may be able to use the FileReader.readAsDataURL method to set the content as a data: URL for the image tag.
example:
$('#f').on('change', function(ev) {
var f = ev.target.files[0];
var fr = new FileReader();
fr.onload = function(ev2) {
console.dir(ev2);
$('#i').attr('src', ev2.target.result);
};
fr.readAsDataURL(f);
});
see the working fiddle here :
http://jsfiddle.net/alnitak/Qszjg/
using jquery:
$('#my_image').attr('src','image.jpg');
using javasript:
document.getElementById("my_image").src="image.jpg";
just check path to your image
Write the below code in head block
<script>
window.onload = function () {
document.getElementById("img1").src="iphone4.png";
document.getElementById("img2").src="screenshot.png";
}
</script>
This will work
Thanks
I would like to draw an image opened with the HTML5 File API on a canvas.
In the handleFiles(e) method, I can access the File with e.target.files[0] but I can't draw that image directly using drawImage. How do I draw an image from the File API on HTML5 canvas?
Here is the code I have used:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script>
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles);
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
ctx.drawImage(e.target.files[0], 20,20);
alert('the image is drawn');
}
</script>
</head>
<body>
<h1>Test</h1>
<input type="file" id="input"/>
<canvas width="400" height="300" id="canvas"/>
</body>
</html>
You have a File instance which is not an image.
To get an image, use new Image(). The src needs to be an URL referencing to the selected File. You can use URL.createObjectURL to get an URL referencing to a Blob (a File is also a Blob): http://jsfiddle.net/t7mv6/86/.
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image;
img.onload = function() {
ctx.drawImage(img, 20,20);
alert('the image is drawn');
}
img.src = URL.createObjectURL(e.target.files[0]);
Note: be sure to revoke the object url when you are done with it otherwise you'll leak memory. If you're not doing anything too crazy, you can just stick a URL.revokeObjectURL(img.src) in the img.onload function.
References:
https://developer.mozilla.org/en/DOM/File
http://html5demos.com/file-api
Live Example
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var url = URL.createObjectURL(e.target.files[0]);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 20, 20);
}
img.src = url;
}
window.URL.createObjectUrldocs
You could also use the FileReader instead to create the object URL.
The FileReader has slightly better browser support.
The FileReader approach works in FF6 / Chrome. I'm not certain whether setting Img.src to a Blob is valid and cross-browser though.
Creating object urls is the correct way to do it.
Edit:
As mentioned in the commment window.URL support whilst offline seems unavailable in FF6/Chrome.
Here is a complete example (Fiddle) using FileReader (which has better browser support as mentioned by Raynos). In this example I also scale Canvas to fit the image.
In real life example you might scale the image to some maximum so that your form will not blow up ;-). Here is an example with scaling (Fiddle).
var URL = window.webkitURL || window.URL;
window.onload = function() {
var input = document.getElementById('input');
input.addEventListener('change', handleFiles, false);
// set original canvas dimensions as max
var canvas = document.getElementById('canvas');
canvas.dataMaxWidth = canvas.width;
canvas.dataMaxHeight = canvas.height;
}
function handleFiles(e) {
var ctx = document.getElementById('canvas').getContext('2d');
var reader = new FileReader();
var file = e.target.files[0];
// load to image to get it's width/height
var img = new Image();
img.onload = function() {
// setup scaled dimensions
var scaled = getScaledDim(img, ctx.canvas.dataMaxWidth, ctx.canvas.dataMaxHeight);
// scale canvas to image
ctx.canvas.width = scaled.width;
ctx.canvas.height = scaled.height;
// draw image
ctx.drawImage(img, 0, 0
, ctx.canvas.width, ctx.canvas.height
);
}
// this is to setup loading the image
reader.onloadend = function () {
img.src = reader.result;
}
// this is to read the file
reader.readAsDataURL(file);
}
// returns scaled dimensions object
function getScaledDim(img, maxWidth, maxHeight) {
var scaled = {
ratio: img.width / img.height,
width: img.width,
height: img.height
}
if (scaled.width > maxWidth) {
scaled.width = maxWidth;
scaled.height = scaled.width / scaled.ratio;
}
if (scaled.height > maxHeight) {
scaled.height = maxHeight;
scaled.width = scaled.height / scaled.ratio;
}
return scaled;
}
canvas {
border:1px solid black
}
<input type="file" id="input"/>
<div>
<canvas width="400" height="300" id="canvas"/>
</div>