rays-javascript-extension/javascript-extensions/canvas.js

540 lines
10 KiB
JavaScript

class Canvas {
constructor(el) {
const a = this;
a.container = el;
a.ctx = null;
a.flowContainer = null;
a.canvasContainer = null;
a.autoSize = true;
a.padding = {
Top: 0,
Right: 0,
Bottom: 0,
Left: 0
};
a.initialiseComponents();
}
initialiseComponents() {
const a = this;
if (a.container == null) {
return;
}
a.container.innerHTML = "<div class='border'><canvas></canvas></div>";
if (a.container != null) {
a.container.style.width = "100%";
a.container.style.height = "100%";
a.flowContainer = a.container.getElementsByTagName("div")[0];
a.canvasContainer = a.flowContainer.getElementsByTagName("canvas")[0];
a.ctx = a.canvasContainer.getContext("2d");
}
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
a.Clear();
}
get AutoSize() {
return this.autoSize;
}
set AutoSize(value) {
const a = this;
a.autoSize = value;
if (a.flowContainer != null) {
if (value == true) {
a.flowContainer.style.overflow = "hidden";
} else {
a.flowContainer.style.overflowX = ((a.Width >= a.ClientWidth) ? "hidden" : "auto");
a.flowContainer.style.overflowY = ((a.Height >= a.ClientHeight) ? "hidden" : "auto");
}
}
}
get ClientHeight() {
const a = this;
if (a.canvasContainer == null) {
return 0;
}
return a.getHeight(a.canvasContainer);
}
set ClientHeight(value) {
const a = this;
if (a.canvasContainer != null) a.canvasContainer.style.height = value + "px";
if (a.ctx != null) a.ctx.canvas.height = value;
}
get ClientWidth() {
const a = this;
if (a.canvasContainer == null) {
return 0;
}
return a.getWidth(a.canvasContainer);
}
set ClientWidth(value) {
const a = this;
if (a.canvasContainer != null) a.canvasContainer.style.width = value + "px";
if (a.ctx != null) a.ctx.canvas.width = value;
}
get Height() {
const a = this;
if (a.container == null) {
return 0;
}
return a.getHeight(a.container);
}
set Height(value) {
const a = this;
if (a.container != null) a.container.style.height = value + "px";
if (a.flowContainer != null) a.flowContainer.style.height = value + "px";
if (a.AutoSize == true) {
a.ClientHeight = value;
}
}
get Width() {
const a = this;
if (a.container == null) {
return 0;
}
return a.getWidth(a.container);
}
set Width(value) {
const a = this;
if (a.container != null) a.container.style.width = value + "px";
if (a.flowContainer != null) a.flowContainer.style.width = value + "px";
if (a.AutoSize == true) {
a.ClientWidth = value;
}
}
get Size() {
const a = this;
return {
W: a.Width,
H: a.Height
};
}
get ClientRectangle() {
const a = this;
return {
X: a.padding.Left,
Y: a.padding.Top,
W: (a.Width - (a.padding.Left + a.padding.Right)),
H: (a.Height - (a.padding.Top + a.padding.Bottom))
};
}
get Rectangle() {
const a = this;
return {
X: 0,
Y: 0,
W: a.Width,
H: a.Height
};
}
Clear() {
const a = this;
if (a.ctx == null) {
return;
}
a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height);
}
DrawArrowS(rectangle, penColour, options) {
const a = this;
if (a.ctx == 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.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(rectangle.X, rectangle.Y);
a.ctx.lineTo((rectangle.X + rectangle.W), rectangle.Y);
a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawCircle(x, y, width, penColour, options) {
const a = this;
if (a.ctx == 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.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false);
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawDiamond(rectangle, penColour, options) {
const a = this;
if (a.ctx == 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.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y);
a.ctx.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H)));
a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a.ctx.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H)));
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawRectangle(rectangle, penColour, options) {
const a = this;
if (a.ctx == 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.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.closePath();
a.ctx.stroke();
}
DrawLine(startX, startY, finishX, finishY, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
startY -= 0.5;
// y -= penWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(startX, startY);
a.ctx.lineTo(finishX, finishY);
a.ctx.stroke();
}
DrawLines(points, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
if (points == null) {
return;
}
if (points.length <= 0) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(points[0].X, points[0].Y);
for (let i=1; i<points.length; i++) {
a.ctx.lineTo(points[i].X, points[i].Y);
}
a.ctx.stroke();
}
DrawHorizontalLine(x, y, width, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
y -= 0.5;
// y -= penWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(x, y);
a.ctx.lineTo((x + width), y);
a.ctx.stroke();
}
DrawText(x, y, text, font, foreColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
Align: "left"
}, options);
a.ctx.font = font;
a.ctx.fillStyle = foreColour;
a.ctx.textAlign = opt.Align;
a.ctx.textBaseline = "top";
a.ctx.fillText(text, x, y);
}
DrawVerticalLine(x, y, height, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
x -= 0.5;
y -= opt.LineWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(x, y);
a.ctx.lineTo(x, (y + height));
a.ctx.stroke();
}
FillText(rectangle, text, font, foreColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
Align: "center",
VAlign: "middle"
}, options);
a.ctx.font = font;
a.ctx.fillStyle = foreColour;
a.ctx.textAlign = opt.Align;
// a._ctx.textBaseline = verticalAlign;
a.ctx.textBaseline = "top";
const size = a.ctx.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.ctx.fillText(text, x, y);
}
Invalidate() {
const a = this;
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
}
MeasureText(font, value) {
const a = this;
if (a.ctx == null) {
return null;
}
a.ctx.font = font;
const size = a.ctx.measureText(value);
return {
W: size.width,
H: Math.round(size.fontBoundingBoxDescent + size.fontBoundingBoxAscent)
};
}
getWidth(el) {
const result = (el.offsetWidth || el.innerWidth || el.clientWidth);
return result;
}
getHeight(el) {
const result = (el.offsetHeight || el.innerHeight || el.clientHeight);
return result;
}
}