오늘이 어쩌고 내일이 저쩌고 포기했다.
그냥 살기로 결정했다.
그래프와 이미지를 압축 파일로 다운로드하는 방법이다.
다운로드할 파일은 Apache ECharts와 PC에 있는 이미지를 사용했다.
압축에는 JSZip를 사용했다.
내가 보려고 메모하는 게 목적이라 코드에 대한 자세한 설명은 생략한다.
<button (click)="imageDownload('canvas')">Download</button>
<article #canvas>
<section *ngFor="let chart of [1, 2, 3, 4, 5]">
<div echarts [options]="chartOption"></div>
</section>
</article>
그래프를 컴포넌트로 분리하고 *ngFor 디렉티브와 @Input 데코레이터를 사용하면
하나의 그래프 컴포넌트로 여러 개의 데이터를 출력할 수 있다.
<button (click)="imageDownload('img')">Download</button>
<article #image>
<section>
<img src="../content/image/tiger1.jpg" alt="tiger1">
<img src="../content/image/tiger2.jpg" alt="tiger2">
</section>
</article>
chartOption: EChartsOption = {};
container = new Map;
@ViewChild('canvas') canvas! : ElementRef;
@ViewChild('image') image!: ElementRef;
constructor() {}
ngOnInit(): void {
this.createChart();
}
ngAfterViewInit(): void {
this.container.set('canvas', this.canvas);
this.container.set('img', this.image);
}
createChart(): void {...}
imageDownload(type: string): void {
const zip = new JSZip();
const targetImages = this.container.get(type).nativeElement.getElementsByTagName(type);
for (let i = 0; i < targetImages.length; i++) {
let canvas = targetImages[i];
let fileName = `image_${i+1}.jpg`;
if (type === 'img') {
fileName = `${canvas.alt}.jpg`;
canvas = document.createElement('canvas');
canvas.width = targetImages[i].width;
canvas.height = targetImages[i].height;
const ctx = canvas.getContext('2d');
ctx.drawImage(targetImages[i], 0, 0);
}
const url = canvas.toDataURL('image/*');
const base64 = url.replace(/^data:image\/[a-z]+;base64,/, "");
zip.file(fileName, base64, {'base64': true});
}
zip.generateAsync({type: 'base64'}).then(
file => {
const link = document.createElement('a');
link.setAttribute('href', 'data:application/octastream;base64, '+ file);
link.setAttribute('download', 'example.zip');
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
)
}
두 번 쓰기 번거로워 한 번에 정리했다.
혹시나 개발에 참고한다면 잘 구분하고 수정해서 사용할 것을 권장한다.
// canvas background color setting, 설정하지 않으면 배경이 투명하게 나오는 경우가 있음
const ctx = canvas.getContext('2d');
ctx.globalCompositeOperation = 'color-burn' || 'destination-atop' || 'destination-over';
ctx.fillStyle = "white";
ctx.fillRect(0, 0, canvas.width, canvas.height);