99. A-tag-not-highly-recommended

Angularで画像を読み込む

Webの可能性を感じさせる画像

そもそも

Imageオブジェクト,Fileオブジェクト,dataurlというのがキーワードになる.

FIleオブジェクトはInputタグから読み込んだもの.dataurlはブラウザ上で表示できるように文字列で表したもの.dataurlはdata:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASAB****という文字列になる.

Inputタグからファイルを読み込んでcanvasに描写したい場合,Fileオブジェクトをdataurlに変換したあと,ImageオブジェクトのSRCとしてこれを設定する.canvasはdataurlを直接受け取ることはできないためImageオブジェクトに変換する.

一方,canvasからfirebaseのStorageに書き込む場合は,canvasからdataurlを生成し,それをバイナリデータであるFileオブジェクトに変換する.FileオブジェクトはそのままStorageに保存できる.

base64, blob,もあるが,base64はdataurlと似たもので,blobはブラウザ上で生成されたFileオブジェクトのことだと理解している.

基本

Inputタグから読み込んで,canvas要素に描写する.

  <div class="upload">
    <input type="file" accept="image/*"
           (change)="fileChangeEvent($event)">
  </div>

  <div class="parent">
    <canvas #canvas></canvas>
  </div>
import { Component,ElementRef,Input,ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-tab1',
  templateUrl: 'tab1.page.html',
  styleUrls: ['tab1.page.scss']
})
export class Tab1Page {
  file: File = null;
  @ViewChild('canvas') public canvas: ElementRef;
  width:number;// = 1400;
  height:number;// = 1400;
  private cx: CanvasRenderingContext2D;

  constructor(
  ) {
  }

  ionViewDidEnter(){
    this.width=window.innerWidth;
    this.height=window.innerHeight;
    const canvasEl: HTMLCanvasElement = this.canvas.nativeElement;
    this.cx = canvasEl.getContext('2d');
  }

  fileChangeEvent(event: any): void {
    if (event.target.files.length === 0) {
      this.file = null;
      return;
    }
    console.log(this.cx,'cx');
    console.log(event.target.files[0],'event.target.files[0]');
    this.cellRender(event.target.files[0]).subscribe((dataUrl)=>{
      console.log(dataUrl,123);
      const image = new Image();
      let aa:any =this.cx;
      image.onload = function() {
        
        aa.drawImage(image, 0, 0);   
      }
      image.src = dataUrl;


    })

}

cellRender(file):Observable<any>{
  return new Observable(observer => {
    let reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = function(){
      var dataUrl:any = reader.result;
      observer.next(dataUrl);
    }
  })
}
}

Inputタグで読み込んだデータは,event.target.filesで容易にアクセスできる.配列になっているので一つしか選択していない場合はevent.target.files[0]で取得できる.

% event.target.files[0]
File {name: "スクリーンショット 2021-05-19 7.04.28.jpg", lastModified: 1621375474163, lastModifiedDate: Wed May 19 2021 07:04:34 GMT+0900 (日本標準時), webkitRelativePath: "", size: 615460, …} "event.target.files[0]"

dataURLの形式にすると便利だが,AngularだとObserverを導入するとうまくいった.

fileChangeEvent(event: any): void { if (event.target.files.length === 0) { this.file = null; return; } this.imageRender(event.target.files[0]).subscribe((dataUrl)=>{ console.log(dataUrl) //data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASAB**** }) } imageRender(file):Observable<any>{ return new Observable(observer => { let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(){ var dataUrl:any = reader.result; observer.next(dataUrl); } }) }

さらにDataURLをcanvasに描写する.canvasで画像を描く際、drawImageというメソッドを用いるが,

https://karoten512.hatenablog.com/entry/2018/03/04/131142

によると,imageはHTMLImageElement, HTMLCanvasElement, HTMLVideoElement のいずれかを取ることができるということなので,dataUrlは受け取れない.従ってconst image = new Image();のように生成しておいて,image.srcでdataURLを読み込ませる.new Image()といってもconsole.log(image)で確認すると<img src=”da” />の形式だった.

fileChangeEvent(event: any): void { //fileが選択されていなければリセット if (event.target.files.length === 0) { this.file = null; return; } console.log(event.target.files[0],'event.target.files[0]'); this.imageRender(event.target.files[0]).subscribe((dataUrl)=>{ console.log(dataUrl,123); const image = new Image(); let canvasVar:any =this.cx; image.onload = function() { canvasVar.drawImage(image, 0, 0); } image.src = dataUrl; }) } imageRender(file):Observable<any>{ return new Observable(observer => { let reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(){ var dataUrl:any = reader.result; observer.next(dataUrl); } }) }

以上でファイルオブジェクトからdataURL(base64と同等)に変換し,canvasへImageオブジェクトに変換して描写する流れができたので,次はcanvasからDataURlを生成し,ファイルオブジェクトを生成する.

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>
      Tab 1
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">Tab 1</ion-title>
    </ion-toolbar>
  </ion-header>

  <div class="upload">
    <input type="file" accept="image/*"
           (change)="fileChangeEvent($event)">
  </div>

  <div class="parent">
    <canvas #canvas></canvas>
  </div>

  + <ion-button expand="full" shape='round' (click)='save()'>Save</ion-button>


</ion-content>
save(){
const canvasEl: HTMLCanvasElement = this.canvas.nativeElement; var dataURI = canvasEl.toDataURL( "image/jpeg", 0.75 ) ; console.log(dataURI,'dataURI'); var bin = atob(dataURI.split(',').replace(/^.*,/, '')); var buffer = new Uint8Array(bin.length); for (var i = 0; i < bin.length; i++) { buffer[i] = bin.charCodeAt(i); } this.createdFileObject = new File([buffer.buffer], "name.jpg",{type: "image/jpeg"}); }
 

console.log(created)すると下記が確認できる.

{name: "name.jpg", lastModified: 1622154958219, lastModifiedDate: Fri May 28 2021 07:35:58 GMT+0900 (日本標準時), webkitRelativePath: "", size: 569, …}
Meditation Tools開発者
絹田 雅
複数の瞑想を学ぶことができるMeditation Toolsの開発者。 売上は人権段階を通じた寄附により社会をより良くすることに使われます。 利用はこちら
twitter-timeline