443 lines
9.2 KiB
JavaScript
443 lines
9.2 KiB
JavaScript
class Canvas {
|
|
constructor(el) {
|
|
const a = this;
|
|
|
|
a.el = el;
|
|
|
|
a.BorderWidth = 2;
|
|
|
|
a.#initialiseComponents();
|
|
}
|
|
|
|
#initialiseComponents() {
|
|
const a = this;
|
|
|
|
if (a.el == null) {
|
|
return;
|
|
}
|
|
|
|
a.Clear();
|
|
a.Invalidate();
|
|
}
|
|
|
|
|
|
get CanvasContext() {
|
|
return this.el.getContext("2d");
|
|
}
|
|
|
|
get Height() {
|
|
const a = this;
|
|
|
|
if (a.el == null) {
|
|
return 0;
|
|
}
|
|
|
|
return Document.getHeight(a.el);
|
|
}
|
|
|
|
set Height(value) {
|
|
const a = this;
|
|
|
|
if (a.el != null) {
|
|
a.el.style.height = value + "px";
|
|
}
|
|
|
|
if (a.CanvasContext != null) {
|
|
a.CanvasContext.canvas.height = value;
|
|
}
|
|
}
|
|
|
|
get Width() {
|
|
const a = this;
|
|
|
|
if (a.el == null) {
|
|
return 0;
|
|
}
|
|
|
|
return Document.getWidth(a.el);
|
|
}
|
|
|
|
set Width(value) {
|
|
const a = this;
|
|
|
|
if (a.el != null) {
|
|
a.el.style.width = value + "px";
|
|
}
|
|
|
|
if (a.CanvasContext != null) {
|
|
a.CanvasContext.canvas.width = value;
|
|
}
|
|
}
|
|
|
|
get Size() {
|
|
return {
|
|
W: this.Width,
|
|
H: this.Height
|
|
};
|
|
}
|
|
|
|
set Size(value) {
|
|
this.Width = value.W;
|
|
this.Height = value.H;
|
|
}
|
|
|
|
get Rectangle() {
|
|
const a = this;
|
|
|
|
return {
|
|
X: 0,
|
|
Y: 0,
|
|
W: a.Width,
|
|
H: a.Height
|
|
};
|
|
}
|
|
|
|
|
|
Clear() {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
a.CanvasContext.clearRect(0, 0, a.CanvasContext.canvas.width, a.CanvasContext.canvas.height);
|
|
}
|
|
|
|
DrawArrowS(rectangle, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: [],
|
|
FillColour: null
|
|
}, options);
|
|
|
|
// Adjust for pen discrepancy
|
|
rectangle.X += 0.5;
|
|
rectangle.Y += 0.5;
|
|
rectangle.W -= opt.LineWidth;
|
|
rectangle.H -= opt.LineWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
|
|
a.CanvasContext.moveTo(rectangle.X, rectangle.Y);
|
|
a.CanvasContext.lineTo((rectangle.X + rectangle.W), rectangle.Y);
|
|
a.CanvasContext.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
|
|
|
|
a.CanvasContext.closePath();
|
|
|
|
if (opt.FillColour != null) {
|
|
a.CanvasContext.fillStyle = opt.FillColour;
|
|
a.CanvasContext.fill();
|
|
}
|
|
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawCircle(x, y, width, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: [],
|
|
FillColour: null
|
|
}, options);
|
|
|
|
let rectangle = {
|
|
X: x + Math.half(width),
|
|
Y: y + Math.half(width),
|
|
W: Math.half(width),
|
|
H: Math.half(width)
|
|
};
|
|
|
|
// Adjust for pen discrepancy
|
|
rectangle.X += 0.5;
|
|
rectangle.Y += 0.5;
|
|
rectangle.W -= Math.half(opt.LineWidth);
|
|
rectangle.H -= Math.half(opt.LineWidth);
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
|
|
a.CanvasContext.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false);
|
|
|
|
a.CanvasContext.closePath();
|
|
|
|
if (opt.FillColour != null) {
|
|
a.CanvasContext.fillStyle = opt.FillColour;
|
|
a.CanvasContext.fill();
|
|
}
|
|
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawDiamond(rectangle, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: [],
|
|
FillColour: null
|
|
}, options);
|
|
|
|
// Adjust for pen discrepancy
|
|
rectangle.X += 0.5;
|
|
rectangle.Y += 0.5;
|
|
rectangle.W -= opt.LineWidth;
|
|
rectangle.H -= opt.LineWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
|
|
a.CanvasContext.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y);
|
|
a.CanvasContext.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H)));
|
|
a.CanvasContext.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
|
|
a.CanvasContext.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H)));
|
|
|
|
a.CanvasContext.closePath();
|
|
|
|
if (opt.FillColour != null) {
|
|
a.CanvasContext.fillStyle = opt.FillColour;
|
|
a.CanvasContext.fill();
|
|
}
|
|
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawRectangle(rectangle, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: [],
|
|
FillColour: null
|
|
}, options);
|
|
|
|
// Adjust for pen discrepancy
|
|
rectangle.X += 0.5;
|
|
rectangle.Y += 0.5;
|
|
rectangle.W -= opt.LineWidth;
|
|
rectangle.H -= opt.LineWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
a.CanvasContext.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
|
|
|
|
if (opt.FillColour != null) {
|
|
a.CanvasContext.fillStyle = opt.FillColour;
|
|
a.CanvasContext.fill();
|
|
}
|
|
|
|
a.CanvasContext.closePath();
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawLine(startX, startY, finishX, finishY, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: []
|
|
}, options);
|
|
|
|
startY -= 0.5;
|
|
// y -= penWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
a.CanvasContext.moveTo(startX, startY);
|
|
a.CanvasContext.lineTo(finishX, finishY);
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawLines(points, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
if (points == null) {
|
|
return;
|
|
}
|
|
|
|
if (points.length <= 0) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: []
|
|
}, options);
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
|
|
a.CanvasContext.moveTo(points[0].X, points[0].Y);
|
|
|
|
for (let i=1; i<points.length; i++) {
|
|
a.CanvasContext.lineTo(points[i].X, points[i].Y);
|
|
}
|
|
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawHorizontalLine(x, y, width, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: []
|
|
}, options);
|
|
|
|
y -= 0.5;
|
|
// y -= penWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
a.CanvasContext.moveTo(x, y);
|
|
a.CanvasContext.lineTo((x + width), y);
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
DrawText(x, y, text, font, foreColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
Align: "left"
|
|
}, options);
|
|
|
|
a.CanvasContext.font = font;
|
|
a.CanvasContext.fillStyle = foreColour;
|
|
a.CanvasContext.textAlign = opt.Align;
|
|
a.CanvasContext.textBaseline = "top";
|
|
|
|
a.CanvasContext.fillText(text, x, y);
|
|
}
|
|
|
|
DrawVerticalLine(x, y, height, penColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
LineWidth: 1,
|
|
LineDash: []
|
|
}, options);
|
|
|
|
x -= 0.5;
|
|
y -= opt.LineWidth;
|
|
|
|
a.CanvasContext.beginPath();
|
|
a.CanvasContext.strokeStyle = penColour;
|
|
a.CanvasContext.lineWidth = opt.LineWidth;
|
|
a.CanvasContext.setLineDash(opt.LineDash);
|
|
a.CanvasContext.moveTo(x, y);
|
|
a.CanvasContext.lineTo(x, (y + height));
|
|
a.CanvasContext.stroke();
|
|
}
|
|
|
|
FillText(rectangle, text, font, foreColour, options) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return;
|
|
}
|
|
|
|
const opt = Object.assign({
|
|
Align: "center",
|
|
VAlign: "middle"
|
|
}, options);
|
|
|
|
a.CanvasContext.font = font;
|
|
a.CanvasContext.fillStyle = foreColour;
|
|
a.CanvasContext.textAlign = opt.Align;
|
|
// a._ctx.textBaseline = verticalAlign;
|
|
a.CanvasContext.textBaseline = "top";
|
|
|
|
const size = a.CanvasContext.measureText(text);
|
|
const x = rectangle.X + Math.half(rectangle.W);
|
|
let y = rectangle.Y;
|
|
|
|
switch (opt.VAlign) {
|
|
case "center":
|
|
case "middle":
|
|
y += Math.half((rectangle.H - size.fontBoundingBoxDescent)) + size.fontBoundingBoxAscent;
|
|
break;
|
|
case "bottom":
|
|
y += (rectangle.H - size.fontBoundingBoxDescent);
|
|
break;
|
|
case "top":
|
|
default:
|
|
break;
|
|
}
|
|
|
|
a.CanvasContext.fillText(text, x, y);
|
|
}
|
|
|
|
MeasureText(font, value) {
|
|
const a = this;
|
|
|
|
if (a.CanvasContext == null) {
|
|
return null;
|
|
}
|
|
|
|
a.CanvasContext.font = font;
|
|
|
|
const size = a.CanvasContext.measureText(value);
|
|
|
|
return {
|
|
W: size.width,
|
|
H: Math.round(size.fontBoundingBoxDescent + size.fontBoundingBoxAscent)
|
|
};
|
|
}
|
|
|
|
}
|
|
|
|
|
|
export default Canvas; |