import { createBmpFile } from '../bmp.js' import { getFileExt } from '../file.js' import type { DrawImageOption, DrawLineOption, DrawLinePolygonOption, DrawPathContext, DrawRectOption, DrawTextOption } from './base.js' import { Drawing, } from './base.js' export class CanvasDrawing extends Drawing { canvas: HTMLCanvasElement ctx: CanvasRenderingContext2D // isCaching: boolean; outputType: string = 'png' orgWidth: number orgHeight: number toHTML(): string { let img = new Image(this.canvas.width, this.canvas.height) img.src = this.canvas.toDataURL(`image/${this.outputType}`) return img.outerHTML } clearAll() { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) } /** * */ constructor( canvas: HTMLCanvasElement, // isCaching: boolean = false, ) { super() this.canvas = canvas this.width = this.orgWidth = canvas.width = canvas.width this.height = this.orgHeight = canvas.height = canvas.height // this.isCaching = isCaching; this.ctx = this.canvas.getContext('2d') } drawPath(path: DrawPathContext, option: DrawLineOption) { this.ctx.beginPath() for (const item of path.data) { switch (item.method) { case 'M': this.ctx.moveTo(item.args[0], item.args[1]) break case 'L': this.ctx.lineTo(item.args[0], item.args[1]) break } } this.ctx.lineWidth = option.lineWidth this.ctx.strokeStyle = option.strokeStyle this.ctx.stroke() } drawLine( x0: number, y0: number, x1: number, y1: number, option: DrawLineOption, ) { this.ctx.lineWidth = option.lineWidth this.ctx.strokeStyle = option.strokeStyle this.ctx.beginPath() this.ctx.moveTo(x0, y0) this.ctx.lineTo(x1, y1) this.ctx.stroke() } drawRect( x: number, y: number, width: number, height: number, option: DrawRectOption, ) { this.ctx.lineWidth = option.lineWidth this.ctx.strokeStyle = option.strokeStyle this.ctx.fillStyle = option.fillStyle if (option.fillStyle) { this.ctx.fillRect(x, y, width, height) } else { this.ctx.strokeRect(x, y, width, height) } } drawText(text: string, x: number, y: number, option: DrawTextOption) { this.ctx.textAlign = option.textAlign as CanvasTextAlign this.ctx.textBaseline = option.textBaseline as CanvasTextBaseline this.ctx.fillStyle = option.fillStyle this.ctx.font = `${option.fontWeight} ${option.fontSize}px ${option.fontFamily}` this.ctx.fillText(text, x, y, option.maxWidth) } drawForeignObjectText( text: string, x: number, y: number, option: DrawTextOption, ) {} imageCache: Map = new Map() drawImage( source: CanvasImageSource, x: number, y: number, width: number, height: number, option: DrawImageOption, border: number, ) { return new Promise((resolve, reject) => { this.ctx.drawImage(source, x + border, y + border, width, height) resolve(null) }) } drawLinePolygon(points: Array, option: DrawLinePolygonOption) { this.ctx.beginPath() this.ctx.moveTo(points[0].x, points[0].y) for (let i = 1; i < points.length; i++) { this.ctx.lineTo(points[i].x, points[i].y) } this.ctx.closePath() this.ctx.stroke() if (option.isFill) { this.ctx.fillStyle = option.fillStyle this.ctx.fill() } } setScale(value: number) { this.scale = value this.canvas.width = this.width = this.orgWidth * value this.canvas.height = this.height = this.orgHeight * value this.ctx.scale(value, value) } // resize(width: number, height: number) // { // let oldWidth = this.width; // let oldHeight = this.height; // if (oldWidth != width || oldHeight != height) // { // let newCanvas = document.createElement('canvas'); // this.width = newCanvas.width = width; // this.height = newCanvas.height = height; // let newCtx = newCanvas.getContext('2d'); // newCtx.drawImage(this.canvas, 0, 0, oldWidth, oldHeight, 0, 0, width, height); // this.canvas = newCanvas; // this.ctx = newCtx; // } // } exportFile(nameOrType: string, param: string): Promise { let mimeType = 'image/png' let ext = getFileExt(nameOrType) if (ext === null) { ext = nameOrType } let paramDic: { [key: string]: string } = {} if (param != null) { for (const item of param.split('&')) { let kv = item.split('=') paramDic[kv[0]] = kv[1] } } switch (ext) { case 'bmp': let data = createBmpFile( this.ctx.getImageData(0, 0, this.width, this.height), paramDic, ) return Promise.resolve(new Uint8Array(data)) case 'jpg': case 'jpeg': mimeType = 'image/jpeg' break } return new Promise((resolve) => { this.canvas.toBlob((data: Blob) => { resolve(data) }, mimeType) }) } }