【JavaScript】【Fabric.js】コントロールキーとマウスホイール操作でキャンバスを拡大縮小する
MAX
MAX999blog
JPEG画像はフォトビューワー等で表示すると正しい向きに表示されていても、ブラウザにアップロードすると、向きがおかしく表示されることがある。
JPEG画像はEXIFデータを保持しており、その中のOrientationが画像の回転や反転情報となるため、Orientationの値を反映してブラウザで表示させる。
EXIF情報の取得はexif.jsを用いる。
exif.jsはCDNでも公開されており、本記事ではCDNを利用する。
exif情報の取得や画像の読込処理は非同期で行われるため、ネストが深くなるのを避けるために、async/awaitを用いる。
1<script type="text/javascript" src="{{ url_for('static', filename='js/rotate_image.js') }}"></script>
2<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.min.js"></script>
3<form method="post" enctype="multipart/form-data">
4 <input type="file" name="imgFile" id="imgFile">
5</form> <img id="imgPreview">
ファイルが選択された時に、JavaScriptでブラウザに表示する。
1/*
2 * 画像ファイル選択時にブラウザに表示する
3 */
4document.getElementById("imgFile")
5 .addEventListener("change", async function (e) {
6
7 let imgElement = new Image();
8
9 //imgタグの要素取得
10 let imgPreview = document.getElementById("imgPreview");
11
12 if (e.target.files[0]){
13 //exif情報を取得する。
14 //取得には時間がかかるのでasync/awaitを使って処理を待つ。
15 let orientation = await getOrientation(e.target.files[0]);
16
17 //orientationから回転角度を設定する
18 const angle = setAngle(orientation);
19
20 //blobUrlを作成する
21 let blobUrl = window.URL.reateObjectURL(e.target.files[0]);
22
23 //blobURLから画像データを読み込む
24 //画像の読込には時間がかかるのでasync/awaitで処理を待つ。
25 imgElenent = await loadImage(blobUrl);
26
27 imgPreview.src = imgElement.src;
28
29 //transformで回転角度を設定する。
30 imgPreview.style.transform = "rotate(" + angle + "deg)";
31
32 }
33});
exif情報の取得は非同期で行われるため、Promiseを使って処理を待つ。exif情報を取得した際に、そのままfunction内で処理を進めることも可能だが、コールバックが重なってネストが深くなるのを避けるために、Promiseを使う。
1function getOrientation(imgFile){
2 return new Promise( (resolve, reject) => {
3 EXIF.getData(imgFile, function() {
4 resolve(imgFile.exifdata.Orientation);
5 //取得したimgFile.exifdata.Orientationに対し、function内で処理を進めることも可能
6 });
7 });
8}
取得したOrientationの値に合わせて、回転させる角度を設定する。
1function setAngle(orientation){
2 switch(orientation){
3 case 1: //回転なし
4 angle = 0;
5 break;
6 case 3: //元画像を180度回転しているので、180度回転させて元に戻す。
7 angle = 180;
8 break;
9 case 6: //元画像を270度回転しているので、90度回転させて元に戻す。
10 angle = 90;
11 break;
12 case 8: //元画像を90度回転しているので、270度回転させて元に戻す。
13 angle = 270;
14 break;
15 default:
16 angle = 0;
17 break;
18 }
19 return angle;
20}
ここまでで必要な回転角度は取得できたので、画像データを取得して回転表示させる。画像データ読込も非同期なのでPromiseを使用する。
1function loadImage(blobImg){
2 return new Promise( (resolve, reject) => {
3 const img = new Image();
4 img.onload = () => resolve(img);
5 img.onerror = (e) => reject(e);
6 img.src = blobImg;
7 });
8}
画像を90度回転させると、縦と横が入れ替わるため、場合によっては、画像のサイズを取得し、回転角度に合わせて表示させることも必要かもしれない。