rotate is not defined cropper.js - javascript

I am using the awesome jquery-cropper plugin from fengyuanchen.
I'm having the issue of when certain images get uploaded it rotates and it is not on the right side which I have to make the user rotate them. I will upload the image via ajax. I'm getting the error rotate is not defined which I have been stuck a couple of hours.
$('#profilePhoto').on( 'change', function(){
if (this.files && this.files[0]) {
if ( this.files[0].type.match(/^image\//) ) {
var reader = new FileReader();
reader.onload = function(evt) {
var img = new Image();
img.onload = function() {
$("#profileImageContainer").hide();
$("#rotateImg").show();
context.canvas.height = img.height;
context.canvas.width = img.width;
context.drawImage(img, 0, 0);
cropper = canvas.cropper({
aspectRatio: 1 / 1,
rotatable: true,
});
$('#btnCrop').click(function() {
// Get a string base 64 data url
var croppedImageDataURL = canvas.cropper('getCroppedCanvas').toDataURL("image/png");
});
$('#rotateImg').click(function () {
cropper.cropper.rotate(90);
});
};
img.src = evt.target.result;
};
reader.readAsDataURL(this.files[0]);
}
else {
alert("Invalid file type! Please select an image file.");
}
}
else {
alert('No file(s) selected.');
}
});
The main problem here is about scopes since it looks like it is not reconizing the cropper variable.
This problems surfaces because when the user upload a photo sometimes this photo rotate automatically. If I could solve this problem first without having to make the user rotate the image would be better

Really stupid mistake. Instead of:
cropper.cropper().rotate(90);
I should apply:
cropper.cropper('rotate', 90);

Related

Why is this FileReader onload not firing?

I am starting with this working JavaScript code:
// Begin File Open Code.
function fileOpen()
{
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('iDisplay');
fileInput.addEventListener('change', function(e)
{
file = fileInput.files[0];
var imageType = /image.*/;
if (file.type.match(imageType))
{
var reader = new FileReader();
reader.onload = function(e)
{
iDisplay.innerHTML = "";
image = new Image();
image.src = reader.result;
image.id = "I"; // Add an id attribute so the image editor code can access the image.
iDisplay.appendChild(image);
image.onload = function()
{
c = document.getElementById("canvas1");
context = c.getContext("2d");
c.width = image.width;
c.height = image.height;
context.drawImage(image,0,0);
}
}
reader.readAsDataURL(file);
moreFiles++;
document.getElementById("fileInput").disabled = true;
document.getElementById("fileInputD").innerHTML = '<p>Please refresh page to open a new image</p>';
}
else
{
iDisplay.innerHTML = "File type not supported."
}
});
}
// End File Open Code
And trying to break it up into two separate functions, fileOpen() and loadImage(). The reason is that loadImage will also be used to load default images. I came up with several non-working versions. After reading about the topic here, most recently this answer Javascript FileReader onload not firing I adjusted the code as follows:
// Begin File Open Code
function fileOpen(radio)
{
fileInput = document.getElementById('fileInput');
fileDisplayArea = document.getElementById('iDisplay');
fileInput.addEventListener('change', function(e)
{
file = fileInput.files[0];
var imageType = /image.*/;
if (file.type.match(imageType))
{
reader = new FileReader();
reader.onload = fileSelected;
function fileSelected(e)
{
iDisplay.innerHTML = "";
image = new Image();
image.src = reader.result;
image.id = "I"; // Add an id attribute so the image editor code can access the image.
iDisplay.appendChild(image);
image.onload = loadImage();
}
}
else
{
iDisplay.innerHTML = "File type not supported."
}
})
}
// End File Open Code
// Begin Load Image Code - This will be used to load a preselected image
function loadImage()
{
c = document.getElementById("canvas1");
context = c.getContext("2d");
c.width = image.width;
c.height = image.height;
context.drawImage(image,0,0);
reader.readAsDataURL(file);
document.getElementById("fileInput").disabled = true;
document.getElementById("fileInputD").innerHTML = '<p>Please refresh page to open a new image</p>';
}
// End Load Image Code
But, after reviewing in the Chrome Inspector, the code never gets past
reader.onload = fileSelected;
After that line, the function exits, and nothing is loaded. I have spent hours on variations of this code and cannot get it to fire past that line. So, my question is "why?" I should note that I want to stay with pure JavaScript.
Thank you in advance.
There appears to be a bug in Chrome 73 where it isn't fired if you have a debugger statement.
I literally have
reader.readAsText(blob);
debugger;
and it never hits the onload
If I change it to
debugger;
reader.readAsText(blob);
then it works.
Fixed by Chrome 75.
You can also use FileReader.readAsDataURL() to parse the file from your . This will create a string in memory containing a base64 representation of the image.
<input type="file" accept="image/*" onchange="loadFile(event)">
<img id="output"/>
<script>
var loadFile = function(event) {
var reader = new FileReader();
reader.onload = function(){
var output = document.getElementById('output');
output.src = reader.result;
};
reader.readAsDataURL(event.target.files[0]);
};
</script>
Ref: Preview an image before it is uploaded

How should I crop an image at client side using jcrop and upload it?

I am working on a component in which there is file-upload HTML control, upon selecting an image using the file-upload element, the image would be rendered on the HTML5 Canvas element.
Here is JSFiddle with sample code: https://jsfiddle.net/govi20/spmc7ymp/
id=target => selector for jcrop element
id=photograph => selector for fileupload element
id=preview => selector for canvas element
id=clear_selection => selector for a button which would clear the canvas
Third-party JS libraries used:
<script src="./js/jquery.min.js"></script>
<script src="./js/jquery.Jcrop.js"></script>
<script src="./js/jquery.color.js"></script>
Setting up the JCrop:
<script type="text/javascript">
jQuery(function($){
var api;
$('#target').Jcrop({
// start off with jcrop-light class
bgOpacity: 0.5,
keySupport: false,
bgColor: 'black',
minSize:[240,320],
maxSize:[480,640],
onChange : updatePreview,
onSelect : updatePreview,
height:160,
width:120,
addClass: 'jcrop-normal'
},function(){
api = this;
api.setSelect([0,0,240,320]);
api.setOptions({ bgFade: true });
api.ui.selection.addClass('jcrop-selection');
});
});
clear canvas event which will be triggered on clear button click event:
jQuery('#clear_selection').click(function(){
$('#target').Jcrop({
setSelect: [0,0,0,0],
});
});
code that renders image on HTML5 Canvas:
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#target').attr('src', e.target.result);
setProperties();
}
reader.readAsDataURL(input.files[0]);
}
}
function setProperties(){
$('#target').Jcrop({
setSelect: [0,0,240,320]
});
}
$("#photograph").change(function(){
readURL(this);
});
code to crop and render an image on the canvas:
var canvas = document.getElementById('preview'),
context = canvas.getContext('2d');
make_base();
function updatePreview(c) {
console.log("called");
if(parseInt(c.w) > 0) {
// Show image preview
var imageObj = $("#target")[0];
var canvas = $("#preview")[0];
var context = canvas.getContext("2d");
context.drawImage(imageObj, c.x, c.y, c.w, c.h, 0, 0, canvas.width, canvas.height);
}
};
function make_base() {
console.log("make_base called");
var base_image = new Image();
base_image.src = '';
base_image.onload = function () {
context.drawImage(base_image, 0, 0);
}
}
Here are a bunch of issues I am facing with the above setup:
updatePreview function is not getting called on selection, hence the canvas is not getting rendered.
crop selection box is not draggable (I am using bootstrap CSS, I suspect it is due to missing/mismatching dependency).
Canvas is HTML5 element, which means the end-user must have an HTML5 compatible browser, I am working on an app that has millions of users. Forcing users to use the latest browser is not a feasible option. What should be the fallback mechanism here?
Here's basic html 5 code:
https://jsfiddle.net/zm7e0jev/
This code crops the image, shows a preview and sets the value of an input element to the base64 encoded cropped image.
You can fetch the image file in php the following way:
//File destination
$destination = "/folder/cropped_image.png";
//Get convertable base64 image string
$image_base64 = $_POST["png"];
$image_base64 = str_replace("data:image/png;base64,", "", $image_base64);
$image_base64 = str_replace(" ", "+", $image_base64);
//Convert base64 string to image data
$image = base64_decode($image_base64);
//Save image to final destination
file_put_contents($destination, $image);
Submitting base64 image string as a post variable has it's server post size limits and base64 encoding makes the cropped image file size even bigger (~33%) then the raw data of the cropped image would be which makes the upload take even longer.
To set the post size limit: What is the size limit of a post request?
Keep in mind that an increased post size limit can be abused for a DoS attack as example.
Instead I suggest converting the base64 cropped image to a data blob and then add it to the form on submit as a file:
https://jsfiddle.net/g3ysk6sf/
Then you can fetch the image file in php the following way:
//File destination
$destination = "/folder/cropped_image.png";
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);
Update:
FormData() is only partially support in IE10 and not supported in older versions of IE
So I suggest sending the base64 string as a fallback, though this will cause problems with bigger images so it needs to check the filesize and show an error popup when the image is above a specific size.
I'll post an update with the fallback code below when I've got it working.
Update 2:
I added a fallback for IE10 and below:
https://jsfiddle.net/oupxo3pu/
The only limitation is the image size that can be submitted when using IE10 and below, in case the image size is too big the js code will throw an error. The maximum size to work for post values is different between each server, the js code has a variable to set the maximum size.
The php code below is adapted to work with above fallback:
//File destination
$destination = "/folder/cropped_image.png";
if($_POST["png"]) {//IE10 and below
//Get convertable base64 image string
$image_base64 = $_POST["png"];
$image_base64 = str_replace("data:image/png;base64,", "", $image_base64);
$image_base64 = str_replace(" ", "+", $image_base64);
//Convert base64 string to image data
$image = base64_decode($image_base64);
//Save image to final destination
file_put_contents($destination, $image);
} else if($_FILES["cropped_image"]) {//IE11+ and modern browsers
//Get uploaded image file it's temporary name
$image_tmp_name = $_FILES["cropped_image"]["tmp_name"][0];
//Move temporary file to final destination
move_uploaded_file($image_tmp_name, $destination);
}
There is no fallback code for the canvas element yet, I'm looking into it.
The post size limitation in the fallback for older browsers is one of the reasons I dropped support for older browsers myself.
Update 3:
The fallback I recommend for the canvas element in IE8:
http://flashcanvas.net/
It supports all the canvas functions the cropping code needs.
Keep in mind it requires flash. There is a canvas fallback (explorercanvas) that does not require flash but it does not support the function toDataURL() which we need to save our cropped image.
Seahorsepip's answer is fantastic. I made a lot of improvements on the non-fallback answer.
http://jsfiddle.net/w1Lh4w2t/
I would recommend not doing that strange hidden png thing, when an Image object works just as well (so long as we're not supporting fallbacks).
var jcrop_api;
var canvas;
var context;
var image;
var prefsize;
Though even then we are, you're better off getting that data out of the canvas at the end and putting it in that field only at the end.
function loadImage(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
image = new Image();
image.src = e.target.result;
validateImage();
}
reader.readAsDataURL(input.files[0]);
}
}
But, if you want more functions than just crop, if we attach the jcrop to an inserted canvas (which we destroy with the jcrop on refresh). We can easily do anything we can do with a canvas, then validateImage() again and have the updated image visible in place.
function validateImage() {
if (canvas != null) {
image = new Image();
image.src = canvas.toDataURL('image/png');
}
if (jcrop_api != null) {
jcrop_api.destroy();
}
$("#views").empty();
$("#views").append("<canvas id=\"canvas\">");
canvas = $("#canvas")[0];
context = canvas.getContext("2d");
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0);
$("#canvas").Jcrop({
onSelect: selectcanvas,
onRelease: clearcanvas,
boxWidth: crop_max_width,
boxHeight: crop_max_height
}, function() {
jcrop_api = this;
});
clearcanvas();
}
Then on submit we submit any pending operations, like applyCrop() or applyScale(), adding data into hidden fields for fallback stuff, if we have those things needed. We then have a system we can easily just modify the canvas, in any way, then when we submit the canvas data gets sent properly.
function applyCrop() {
canvas.width = prefsize.w;
canvas.height = prefsize.h;
context.drawImage(image, prefsize.x, prefsize.y, prefsize.w, prefsize.h, 0, 0, canvas.width, canvas.height);
validateImage();
}
The canvas is added to a div views.
<div id="views"></div>
To catch the attached file in PHP (drupal), I used something like:
function makeFileManaged() {
if (!isset($_FILES['croppedfile']))
return NULL;
$path = $_FILES['croppedfile']['tmp_name'];
if (!file_exists($path))
return NULL;
$result_filename = $_FILES['croppedfile']['name'];
$uri = file_unmanaged_move($path, 'private://' . $result_filename, FILE_EXISTS_RENAME);
if ($uri == FALSE)
return NULL;
$file = File::Create([
'uri' => $uri,
]);
$file->save();
return $file->id();
}

Uploading an image from computer to Fabric.JS Canvas

Are there any Fabric.JS Wizards out there?
I've done my fair research and I can't seem to find much of an explanation on how to add an image to the fabric.JS canvas.
User Journey:
a) User uploads an image from an input file type button.
b) As soon as they have selected an image from their computer I want to place it into the users canvas.
So far I've got to storing the image into an expression, this is my code below:
scope.setFile = function(element) {
scope.currentFile = element.files[0];
var reader = new FileReader();
/**
*
*/
reader.onload = function(event) {
// This stores the image to scope
scope.imageSource = event.target.result;
scope.$apply();
};
// when the file is read it triggers the onload event above.
reader.readAsDataURL(element.files[0]);
};
My HTML/Angular:
<label class="app-file-input button">
<i class="icon-enter"></i>
<input type="file"
id="trigger"
onchange="angular.element(this).scope().setFile(this)"
accept="image/*">
</label>
If you haven't guessed yet I am using a MEAN stack. Mongoose, Express, Angular and Node.
The scope imageSource is what the image is store in. I've read this SO
and it talks about pushing the image to the Image object with my result, and then pass it to the fabric.Image object. Has anyone done a similar thing that they can help me with?
Thanks in advance
**** UPDATE ****
Directive defines the canvas variable:
var canvas = new fabric.Canvas(attrs.id, {
isDrawingMode: true
});
Upload image from computer with Fabric js.
var canvas = new fabric.Canvas('canvas');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({left: 0, top: 0, angle: 00,width:100, height:100}).scale(0.9);
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({format: 'png', quality: 0.8});
});
};
reader.readAsDataURL(file);
});
canvas{
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://rawgit.com/kangax/fabric.js/master/dist/fabric.min.js"></script>
<input type="file" id="file"><br />
<canvas id="canvas" width="450" height="450"></canvas>
once you have a dataURL done, you can do either:
reader.onload = function(event) {
// This stores the image to scope
fabric.Image.fromURL(event.target.result, function(img) {
canvas.add(img);
});
scope.$apply();
};
Or you put on your image tag an onload event where you do:
var img = new fabric.Image(your_img_element);
canvas.add(img);
This is for drag and drop from desktop using the dataTransfer interface.
canvas.on('drop', function(event) {
// prevent the file to open in new tab
event.e.stopPropagation();
event.e.stopImmediatePropagation();
event.e.preventDefault();
// Use DataTransfer interface to access the file(s)
if(event.e.dataTransfer.files.length > 0){
var files = event.e.dataTransfer.files;
for (var i = 0, f; f = files[i]; i++) {
// Only process image files.
if (f.type.match('image.*')) {
// Read the File objects in this FileList.
var reader = new FileReader();
// listener for the onload event
reader.onload = function(evt) {
// put image on canvas
fabric.Image.fromURL(evt.target.result, function(obj) {
obj.scaleToHeight(canvas.height);
obj.set('strokeWidth',0);
canvas.add(obj);
});
};
// Read in the image file as a data URL.
reader.readAsDataURL(f);
}
}
}
});
Resources
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop

"canvas.toDataURL("image/png")" not working properly in firefox

I have a web page with file input field.I wanted to ,
Upload a image file.
create image element using uploaded image.
draw it on canvas
get "DataURL" of canvas.
This process works on Google Chrome,but not working on Mozilla Firefox.When i console.log the canvas.toDataURL output it shows
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABBoAAAJYCAYAAADMnIUCAAAJoUlEQVR4nO3BAQ0AAADCoPdPbQ8HFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8GeFIAAU/iP9QAAAAASUVORK5CYII=
This is not the correct output.How can i generate cross browser DataURL from the canvas.
Here is my code.
$scope.importImageForBackground = function (event)
{
$scope.file = event.target.files[0];
var img = document.createElement("img");
var reader = new FileReader();
reader.onloadend = function (e) {
$scope.$apply(function () {
img.src = e.target.result;
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 1050;
canvas.height = 600;
ctx.drawImage(img, 0, 0, 1050, 600);
$scope.data = canvas.toDataURL("image/png");
console.log($scope.data);
});
};
reader.readAsDataURL($scope.file);
};
Wait for the image to load.
img.onload = function(){
var canvas = ...
};
img.src = e.target.result;
Please note that this is a copy-n-paste of #kaiido's comment, as he refused to repost it as an answer. Credit goes to him.
I faced the same issue, You can fix this using Javascript shown as below
var canvas=document.getElementById(canvasId);
var href=canvas.toDataURL("image/png");
var windowtab=window.open('about:blank','image from canvas');
windowtab.document.write("<img src='"+href+"' alt='from canvas'/>");

Add image to HTML5 canvas on file upload issue

Allright, this is going to be quite hard to explain but I will try to explain my problem as clear as possible.
I currently have a HTML5 Canvas with a couple of preloaded shapes which I changed to images. I am using a modified version of this example. On the canvas I have now I can drag, drop and select the shapes which are preloaded.
I have implemented an option to upload a new image to the canvas using this:
var imageLoader = document.getElementById('uploader');
imageLoader.addEventListener('change', handleImage, false);
var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext('2d');
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var imgNew = new Image();
imgNew.onload = function(){
ctx.drawImage(imgNew, 0, 0);
}
imgNew.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
This will now just put an image in the top-left corner of the canvas and when I select another shape this image will disappear. All shapes that are already in the canvas are in an array called 'shapes'. In the example there is an option to add a new shape when you dubbelclick on the canvas, this is the code:
// double click for making new shapes
canvas.addEventListener('dblclick', function(e) {
var mouse = myState.getMouse(e);
myState.addShape(new Shape(mouse.x - 10, mouse.y - 10, 20, 20, 'rgba(0,255,0,.6)'));
}, true);
This is the addShape part which is called when double clicking:
CanvasState.prototype.addShape = function(shape) {
this.shapes.push(shape);
this.valid = false;
}
What I am trying to do is when I upload an image using the file upload the image should be added to the 'shapes' array so I can also drag,drop and select the uploaded image. (basically I need to do the same with the uploaded image as I can do with the preloaded ones) My guess is that it should be done something like the doubleclick method and addShape but I can't get this to work.
A working version of my current version can be found here:
http://codepen.io/anon/pen/qLuCy/
If anyone knows how I can get this to work it would be great!
first the result, here : http://codepen.io/anon/pen/qBmnC/
Your shape object can only draw one single hard-coded image, so change this and have shape be either a color or an image. In fact for this you just have to change shape.draw since the 'type' of the fill does not matter in the constructor.
So just test the fill and draw accordingly :
// Tekent de Shape
Shape.prototype.draw = function(ctx) {
var locx = this.x;
var locy = this.y;
var fill = this.fill ;
if (typeof fill == 'string' )
{
ctx.fillStyle = fill;
ctx.fillRect(locx, locy, this.w, this.h);
}
else
{
ctx.drawImage(fill, locx, locy, this.w, this.h);
}
}
then on image load i just add a shape that has this image as fill :
function handleImage(e){
var reader = new FileReader();
reader.onload = function(event){
var imgNew = new Image();
imgNew.onload = function(){
s.addShape(new Shape(60,60,imgNew.width,imgNew.height,imgNew));
}
imgNew.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
I had to put the shape collection, s, as a global var.
You can also see that i used the same scheme in init() to
add an image once it's loaded.

Categories

Resources