プロフィールのアイコンとかを保存したい時に容量削減しつつ、中央部分だけトリミングしたい…ということがあったので作ったサンプル。
app.component.html
<div class="container">
<div class="row">
<div class="col">
<label for="iconUploadForm" class="btn grey">画像をアップロード</label>
<input id="iconUploadForm" type="file" accept="image/*" (change)="onChangeFileInput($event)" />
</div>
<div class="col">
<button (click)="save()" class="btn blue">保存</button>
</div>
</div>
<div id="canvas-box"></div>
</div>
app.component.ts
onChangeFileInput(event:any){
const file = event.target.files[0];
if(!file){
return;
}
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
// 縮小・トリミング後のサイズのキャンバスを作成
const canvas = document.createElement('canvas');
canvas.id = 'icon-canvas'
const ctx = canvas.getContext('2d');
const trimSize = 128; // 縮小後のサイズ
canvas.width = trimSize;
canvas.height = trimSize;
canvas.style.width = 100+'px'; // cssでの表示サイズ
canvas.style.height = 100+'px';
if(ctx){
const image = new Image();
image.src = reader.result as string;
image.onload = () =>{
let height = 0;
let width = 0;
let xOffset = 0;
let yOffset = 0;
if (image.width > image.height) {// 横長画像
height = trimSize;
width = image.width * (trimSize / image.height);
xOffset = -(width - trimSize) / 2;
yOffset = 0;
} else { // 縦長画像
width = trimSize;
height = image.height * (trimSize / image.width);
yOffset = -(height - trimSize) / 2;
xOffset = 0;
}
// キャンバスに描画
ctx.drawImage(image,xOffset,yOffset,width,height);
}
}
const div = document.getElementById('canvas-box');
if(div){
// キャンバスを追加
div.appendChild(canvas);
}
}
}
save(){
const canvas = document.getElementById('icon-canvas') as HTMLCanvasElement;
if(canvas){
const data = canvas.toDataURL();
console.log(data);
}
}
128で画像は作成しているけど、画面表示上では100pxで表示している例
540kbくらいあった画像で128px四方のアイコンを作って、53kbくらいになっていました。