Making images draggable to HTML5 Canvas, moving images out of canvas - javascript

I'm trying to make a custom avatar maker, where my users can drag & drop images to the position they want (clothes etc. I take the image urls from database based on what they own). Then they can save the look as png image to my site (using php). I have no experience on javascript/jquery but I don't think that this can be without them. So I've found amazing code for this from here:
http://www.fabiobiondi.com/blog/2012/10/export-and-save-a-screenshot-of-an-html5-canvas-using-php-jquery-and-easeljs/
But the images are already in the canvas and can't go outside of it, which is bad considering that someone could have 100 pieces of clothing and didn't want to display them all. Also I have to make custom code for each piece, which is also bad because not all users have the same images to drag.
Is there a way to put all images draggable (to the canvas), so I could easily add the image urls from my database as basic html/css? Is it possible that the images would be outside of the canvas first? Or should I create another canvas for the items users don't want?

the script in the article uses a static image because its goal is only explain how to export a canvas to bitmap : )
I have written another small article where I describe how to upload N images from your hard drive into a canvas ( using CreateJS ) so as you can see the process to load dynamic sources is not so hard.
http://www.fabiobiondi.com/blog/2012/10/upload-images-from-the-user-hard-driveto-an-html5-canvas-easel-js-application/
Anyway, if you need to load an image into a canvas you can simply use a syntax like this:
var img = new createjs.Bitmap('http://uri/image.jpg')
img.x = 50;
img.y = 50;
stage.addChild(img)
stage.update();
and if you need to know when an image is completely loaded you should listen for the onload event:
var image = new Image();
image.onload = onImageLoaded;
image.src = "http://uri/image.jpg";
function onImageLoaded (event) {
var img = new createjs.Bitmap(event.target)
img.x = 50;
img.y = 50;
stage.addChild(img)
stage.update();
}
hope it's useful

Related

Image on HTML5 canvas only appearing for one frame

Long time lurker but never made an account. Just wanted to preface that I'm by no means a dev and just tinkering and experimenting for fun, so I apologise in advance if I seem really dumb.
I'm working on a dynamic overlay for Twitch streaming and was previously using AS3 but I've switched over to HTML5 now. I'm trying to load an image onto the canvas (which will eventually be a profile picture fetched using Twitch API... but one step at a time). I'm using Adobe Animate and I have the following so far applied in Actions on the first frame of the layer:
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d');
show_image();
function show_image() {
source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function () {
context.drawImage(source_image, 100, 100);
}
}
When I hit Ctrl+Enter and see it in Chrome, the image appears for the first frame then disappears. I'm not sure how I'm supposed to get it to stay indefinitely. I need to be able to animate it later, and it'll change depending on the latest follow/donation/sub, etc.
I tried extending the frame itself in the timeline, however, this just changed long how it took to loop and didn't make the image itself stay longer. I'm probably missing something really simple!
Any help would be appreciated. Thanks!
Your code is okay if your approach is using a canvas with HTML and JS, without any libraries involved. However, this is not the case, as you are using Animate, and the way to draw graphics with it is different than using default canvas methods like drawImage().
Animate includes the CreateJS suite, which includes the EaselJS library ,and this allows you to use another tools to draw to your canvas. Two or them are the Stage object, the visual container of your animate project, and the Bitmap object, who represents an image, canvas or video. For effects of this question, only both objects are required.
Note that the code below is only for the first frame:
/* It is not necessary to declare the canvas or stage element,
as both are already declared. At this point the stage is ready to be drawn */
show_image();
function show_image() {
var source_image = new Image();
source_image.src = 'https://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png';
source_image.onload = function(event) {
/* A new Bitmap object is created using your image element */
var bmp = new createjs.Bitmap(event.currentTarget);
/* The Bitmap is added to the stage */
stage.addChild(bmp);
}
}

Using globalCompositeOperation for a limited number of images

I have a very simple question : is it possible to use globalCompositeOperation for only a restricted number of images?
For example, I draw a lot of stuff into my canvas. And on top of everything, and completed unrelated, I want to do some operations on two images (and I just want the result to be displayed, not both images). How can that be done?
For now, doing such operations affects everything that's already drawn underneath.
So a solution I found is doing the operations in another canvas, which I display on top of my main, first canvas. But this looks bad. First, it hits performances. Then, it doesn't feel intuitive. And last, I loose control over the layers : whatever is in my second canvas will always be on top of the first canvas.
This looks like a pretty simple feature, I hope I'm just bad at googling!
Thanks a lot!
Create a offscreen canvas and use it as a work space. You can create many as long as you have the RAM to store them.
To create an offscreen canvas
function createCanvas(w,h){
var canvas = document.createElement("canvas");
canvas.width = w;
canvas.height = h;
canvas.ctx = ctx.getContext("2d");
return canvas;
}
Easy as that and then you just treat it as an image. To draw to another canvas
var offScreenCan = createCanvas(1024,1024);
offScreenCan.ctx.drawImage(myImage); // put something on the canvas
ctx.drawImage(offScreenCan,0,0); // draw that canvas to another
I attach the context to the canvas rather than wrap the canvas in a containing object. I used to worry that the canvas would affect performance now I convert all images to canvas as soon as I load them and it does not impact performance at all.

Is it possible to draw multiple SVG's to a canvas?

Background
I've got a bunch of svg's in a document (with rect, path, and whatnot inside each) and I need to draw this out to a downloadable PNG image. I understand that in order to do this there are two methods: either draw the page's HTML structure to a canvas and then export from there or render an SVG and its contents straight onto a canvas.
Hypotheses
The first hypothesis I tried to render the HTML structure using html2canvas and only found out that SVG's could not be rendered via an HTML structure at all (due to security issues). The second hypothesis I tried to render an SVG to canvas via canvg only to find out that it only allowed for one SVG element to be rendered and that only the first one would be rendered.
Results
To prove the first one wrong, type in http://www.w3schools.com/svg/tryit.asp?filename=trysvg_rect to this URL and disable Javascript. To prove the second one wrong I have a fiddle to try out.
The Question
I want to make it clear that my reasoning for having multiple svg's is so that I can place them within a responsive grid system and resize via aspect ratio. Without further ado, I ask my question: How can you render multiple svg elements to a canvas? If the answer to that question is "it isn't possible", then next my question would be: Should I be rendering one svg instead and handle responsiveness another way?
You should be able to draw SVG to canvas just as any other image:
var img1 = document.createElement('img'),
img2 = document.createElement('img')
count = 2;
/// image loading is async, make sure they are loaded
img1.onload = img2.onload = function() {
count--;
if (count === 0) drawImages();
}
img1.src = 'some1.svg';
img2.src = 'some2.svg';
/// when loaded, draw them somewhere on the canvas
function drawImages() {
ctx.drawImage(img1, 0, 0);
ctx.drawImage(img2, someX, someY);
}
That being said - there are a couple of restrictions:
FireFox currently does not want to draw images properly without width and height set inside the SVG file.
CORS (Cross-Origin Resource Sharing) applies if you want to extract images as bitmap (toDataURL/getImageData). If not they should work as normal.

How to resize an image with JavaScript / jQuery without pixelation like the browser does?

I'm making a javascript / jquery program for a webpage to let a user open an image file locally from their computer, and then the program resizes it to a 16 x 16 icon size and saves it as a data url.
Everything works fine, except the resized image is very pixelated. I currently am taking the local image file, and making a data url from it. Then creating a 16 x 16 canvas element, and then drawing the image onto the canvas, and making a new data url from that.
I would like some different way to do it, as the newly resized image is very pixelated and not smooth, and does not seem anti-aliased. When the browser displays the original image with the width and height attributes set to 16, it looks very nice and smooth. This is what I would like. I don't understand how to get the same result as what is displayed when the browser does it. I am using Google Chrome.
I made a small example of it here: http://jsfiddle.net/5Pj8m/
In the example I used the jsFiddle logo, although you could test it with any local file, and see the results. Maybe this code can help someone else learn how to do it, but still, I think the resulting resize image could or should look much better!
I hope I have explained what I am trying to do, and that it is somehow possible. Can anyone help me or figure this out?
Here is the code.
HTML:
<input type='file' id='inputFile'>
<table border=1><tr><td>
<span id='spanDisplayOrigFull'>OrigFull:
<img src=http://doc.jsfiddle.net/_images/jsfiddle-logo-thumb.png>
</span>
</td><td>
<span id='spanDisplayOrigIcon'>OrigIcon:
<img src=http://doc.jsfiddle.net/_images/jsfiddle-logo-thumb.png width='16' height='16'>
</span>
</td></tr><tr><td>
<span id='spanDisplayNewFull'>NewFull: </span>
</td><td>
<span id='spanDisplayNewIcon'>NewIcon: </span>
</td></tr></table>
JAVASCRIPT:
$('#inputFile').bind('change', function()
{
var file = inputFile.files[0];
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function()
{
var imageUrlFull = reader.result;
var imageLocalFull = new Image();
imageLocalFull.src = imageUrlFull;
imageLocalFull.id = 'imageLocalFull';
imageLocalFull.onload = function()
{
var canvas = document.createElement('canvas');
canvas.width = 16; canvas.height = 16;
var context = canvas.getContext('2d');
context.drawImage(imageLocalFull, 0, 0, 16, 16);
var imageUrlIcon = canvas.toDataURL(file.type);
var imageLocalIcon = new Image();
imageLocalIcon.src = imageUrlIcon;
imageLocalIcon.id = 'imageLocalIcon';
imageLocalIcon.onload = function()
{
spanDisplayNewFull.appendChild(imageLocalFull);
spanDisplayNewIcon.appendChild(imageLocalIcon);
};
};
};
});
You could use a php base like timthumb script to scale.
So the basic idea is using js detect when the browser or div or whatever change or resize. Then trigger the php script to resize the image.
script.setAttribute( 'src', 'remote.php?value=my message' );
remote.php
you have your php code.
Well, from your code it looks like the image scaling job is actually left to your browser's implementation, so I think you're going to have varying results with different browsers. Some might smooth it, some might not.
I see two ways to go about trying to tackle this problem. One way is to use active content, such as a Java applet/Flash or to use an actual back-end to do the scaling. I.e. you receive the file, send it to a server and the server returns the scaled-down image, as most image scaling sites do.
The second way is to try HTML5 and implement a down-scaling algorithm yourself. The best I can do there for guidance is point you to this and this as a starting point.
Sorry if that doesn't help.

Image readystate in canvas

Is it possible to use imagename.readyState in canvas?
If not does anyone know a way of detecting when an image being drawn to the canvas using "drawImage" has loaded and is ready to display?
I am creating an image showcase using the canvas - when an image is selected I want to have a loading animation (which I have already created) display until the loaded condition is met.
I am still learning to use javascript and have been trying all day to no avail - so apologies for the lack of example code to display and illustrate what I'm asking!
You might try loading the image by using new Image() and setting the .onload event to draw the image on the canvas after the image has been loaded.
var img = new Image();
img.onload = function() {
// code to draw image on the canvas...
}
img.src = "/path/to/img.jpg";
See also: https://developer.mozilla.org/samples/canvas-tutorial/3_1_canvas_drawimage.html

Categories