198 lines
5.0 KiB
TypeScript
198 lines
5.0 KiB
TypeScript
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<string, HTMLImageElement> = 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<any>, 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<Blob | Uint8Array> {
|
|
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<Blob>((resolve) => {
|
|
this.canvas.toBlob((data: Blob) => {
|
|
resolve(data)
|
|
}, mimeType)
|
|
})
|
|
}
|
|
}
|