0

I used the canvas tag to crop my image.

as following my code:

autoCropImage(url){
    var img = new Image();
    const cropApp = this;

let x = img.onload = function(){
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');
    const center_X = img.width/2, center_Y = img.height/2;
    let init_X=0, init_Y=0;
    ctx.drawImage(img, init_X, init_Y, img.width, img.height, 0, 0, img.width, img.height);

let dataUrl = canvas.toDataURL("image/jpeg", 1.0);
let dataUrl_short = dataUrl.replace("data:image/jpeg;base64,", "");
return dataUrl;
}();



img.src=url;
console.log(x);
return x;

}
//log result:
//data:,

I consider the log result should be a string of base64, but the callback is data:,

What's the problem in my code?

Champer Wu
  • 1,101
  • 3
  • 13
  • 32

2 Answers2

1

Your function is an IIFE. You are calling it immediately and then assigning its return value to img.onload.

(Then you assign the value of img.onload to x).

This means that you are not assigning a function to img.onload, so nothing happens after the image loads.

It also means that the image hasn't loaded when you try to pass it as an argument to ctx.drawImage.

Since the image hasn't loaded, there is no data to convert to a data URL with canvas.toDataURL.


You need to:

  1. Remove the () from after the function definition so it gets assigned to img.onload and called when the image loads
  2. Get rid of let x = because that will just be a copy of the function
  3. Read How do I return the response from an asynchronous call?
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • how can I call the function when the image loaded? use the async function? – Champer Wu Mar 15 '18 at 15:36
  • @ChamperWu — See item 1 in my list of things you need to do. – Quentin Mar 15 '18 at 15:39
  • You mean using `img.load = function(){...}` to instead of `let x = img.load = function(){}();` right? but I do it, and `console.log(img.onlaod)` will callback a function – Champer Wu Mar 15 '18 at 15:41
  • like this `ƒ () { var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); var center_X = img.width / 2, center_Y = img.height / 2; var init_X …` – Champer Wu Mar 15 '18 at 15:43
  • I want to return a base64 string – Champer Wu Mar 15 '18 at 15:43
  • You can't wait for the image to load and return a string. See item 3 in my list of things you need to do. – Quentin Mar 15 '18 at 15:44
  • I tried this `async autoCropImage(url){ ... img.onload = function(){ ... return dataUrl; } let x = await img.load; console.log(x); };` and return is undefined – Champer Wu Mar 15 '18 at 15:54
  • @ChamperWu — If you use `await`, then you have to await a function declared with `async` (you don't). A function declared with `await` has to return a Promise (you haven't created any Promises). – Quentin Mar 15 '18 at 15:58
  • In my experience, I used the async function when I use the method of ajax. the code will be `imgPost(url){return axios.post("url")} async dataCallback(file){let response = await imgurPost(file); const result = response.data.data; const link = result.link; return link}` – Champer Wu Mar 15 '18 at 16:00
  • `img.onload` is not a Promise object, but it's an asynchronous function. Is there a good way to let me get the value of dataUrl? – Champer Wu Mar 15 '18 at 16:04
  • See the question linked to in step 3. It has many examples of how to turn an callback into a promise. – Quentin Mar 15 '18 at 16:10
0

Are you wanting to return the data url without the data:image/jpeg;base64 part?

If so you're returning dataUrl instead of dataUrl_short in the method.

pixelscript
  • 392
  • 1
  • 8