サードパーティのライブラリを使用せずにイメージコンプレッサーを作成しようとしています。
これが私のコードです(最終的に圧縮された画像のblobを返します):
async function CompressImage(File, Quality, FileType) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image;
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob(function (blob) {
return blob;
}, FileType, Quality);
}
}
img.src = URL.createObjectURL(File);
}
常に未定義の値を返しますが、私のコードには何の問題もないようです。
多分それは非同期の問題であることがわかりました。非同期メソッドです。img.onload
canvas.toBlob
promise
これらのメソッドを1つずつ実行し、最終的に値を返すように順序付けする方法がわからない場合は、がこれに役立つと思います。
どうすればこれを解決できますか?ありがとうございました。
のPromise
代わりに使用します。async
最終的には同じですが、構文的には異なります。Promiseでは、パラメーターとして2つの関数(通常はresolve
andと呼ばれます)を取得しますreject
。これらの関数は、コールバック内で問題なく実行できますが、async
関数内では問題が発生します。await
コールバックを受け取る関数を探す方法はありません(あなたができる約束ではないためawait
)。
TLDR; async
関数は、コールバックを実行する関数を適切に実行しませんresolve()
。コールバック関数上にある場合でも、どこでも実行できるようにPromiseを直接使用します。
例えば:
function CompressImage(File, Quality, FileType) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image;
var prom = new Promise(function(resolve) {
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob(function (blob) {
return resolve(blob);
}, FileType, Quality);
}
}
img.src = URL.createObjectURL(File);
});
return prom;
}
これでうまくいくはずです。のコールバックで解決するpromiseをどのように作成しているかを見てcanvas.toBlob
ください。気付いた場合、関数はasync
Promiseを直接返すためではありませんが、コードでは非同期のように扱うことができます。関数。
もう少し更新された構文でそれを行う別の方法は次のとおりです。
const CompressImage = async (File, Quality, FileType) => {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const img = new Image;
return await (new Promise(resolve => {
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
canvas.toBlob(resolve, FileType, Quality);
}
}
img.src = URL.createObjectURL(File);
}));
};
そして、同じである必要があります。
私はこれをテストしていませんが、壊れている場合はかなり近いです。
更新:
さて、あなたが提供したjsfiddleで遊んだ後、私は興味深い発見があります:
$(function () {
$("#FileUploader").change(function () {
StartCompress(this.files[0]);
});
function StartCompress(input) {
$("#beforesize").text(input.size);
CompressFile(input, 0.8).then(blob => $("#afteresize").text(blob.size));
}
function CompressFile(file, quality) {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
var prom = new Promise(resolve => {
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
canvas.toBlob(blob => {
resolve(blob)
}, file.type, quality);
}
img.src = URL.createObjectURL(file);
});
return prom;
}
});
私のocdが安心できるようにコードを少し変更しましたが、問題はMIME(FileType
)canvas
です。ファイルタイプを提供していないため、ファイルタイプを取得して変換するだけでpng
、ロスレス形式です。 、したがって、jpg画像(損失を許容する)を選択し、基本的に同じサイズに合うように拡大縮小すると、サイズが大きくなります。
今すぐコードを試してみてください(私はfile.type
ファイルのタイプを提供するために使用していますcanvas.toBlob
)、それは地獄に行きpng
、私が指摘した問題に関連していると思います。
それが役に立てば幸い。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加