Implemented multiple canvas layers

This commit is contained in:
Ray 2023-10-20 00:22:29 +01:00
parent e48dca5da1
commit 5637d8d3b9
7 changed files with 348 additions and 563 deletions

View File

@ -28,7 +28,7 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas {
X: a.ClientRectangle.X, X: a.ClientRectangle.X,
Y: a.ClientRectangle.Y, Y: a.ClientRectangle.Y,
W: a.ClientRectangle.W, W: a.ClientRectangle.W,
H: (a.ClientRectangle.H - a.calcXAxisHeight()) H: (a.ClientRectangle.H - a.XAxisHeight)
}; };
a.Margin = (a.Parent.Marker.BorderWidth * 2); a.Margin = (a.Parent.Marker.BorderWidth * 2);
@ -38,6 +38,43 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas {
a.Invalidate(); a.Invalidate();
} }
get XAxisHeight() {
const a = this;
const labelSize = a.measureText(a.Parent.Axis.Font, "0");
return labelSize.Height + a.Parent.Axis.LabelSpacing + (a.Parent.Axis.X.DayLineHeight * 2);
}
get XAxisPositions() {
const a = this;
const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W);
let result = [];
let x = a.GraphRectangle.X;
let date = a.Parent.ConvertToDate(a.Parent.ShowDate);
// Rollback one day
date.setDate(date.getDate() - 1);
while (true) {
if (x >= endPosX) {
break;
}
result.push({
Date: a.Parent.DateToInternalString(date),
X: x
});
x += (a.Parent.Axis.X.HourLineSpace * a.Parent.Axis.X.NoPartPerDay);
date.setDate(date.getDate() + 1);
}
return result;
}
Invalidate() { Invalidate() {
const a = this; const a = this;
@ -64,6 +101,36 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas {
a.CTX.stroke(); a.CTX.stroke();
} }
drawXAxisLabels() {
const a = this;
const posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Parent.Axis.LineWidth;
a.XAxisPositions.forEach(function(e, i) {
const date = a.Parent.ConvertToDate(e.Date);
let writeLabel = false;
if ((i == 0)) {
// Don't label first entry if too close to the next month
if (date.getDate() < 25) {
writeLabel = true;
}
} else if (date.getDate() == 1) {
writeLabel = true;
}
// if (i == 0) {
// return;
// }
const labelSize = a.drawText(e.X, (posY + a.Parent.Axis.X.DayLineHeight), a.Parent.DateToString(date, "dd"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "center");
// Write month on first of the month
if (writeLabel) {
a.drawText(e.X, (posY + a.Parent.Axis.X.DayLineHeight + labelSize.Height + a.Parent.Axis.LabelSpacing), a.Parent.DateToString(date, "MMMM yyyy"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "left");
}
});
}
drawXAxisTicks() { drawXAxisTicks() {
const a = this; const a = this;
@ -98,78 +165,4 @@ class BBTimelineBackgroundCanvas extends BBTimelineCanvas {
} }
} }
drawXAxisLabels() {
const a = this;
const result = a.calcXAxisPositions();
const posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Parent.Axis.LineWidth;
result.forEach(function(e, i) {
const date = a.Parent.ConvertToDate(e.Date);
let writeLabel = false;
if ((i == 0)) {
// Don't label first entry if too close to the next month
if (date.getDate() < 25) {
writeLabel = true;
}
} else if (date.getDate() == 1) {
writeLabel = true;
}
// if (i == 0) {
// return;
// }
const labelSize = a.drawText(e.X, (posY + a.Parent.Axis.X.DayLineHeight), a.Parent.DateToString(date, "dd"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "center");
// Write month on first of the month
if (writeLabel) {
a.drawText(e.X, (posY + a.Parent.Axis.X.DayLineHeight + labelSize.Height + a.Parent.Axis.LabelSpacing), a.Parent.DateToString(date, "MMMM yyyy"), a.Parent.Axis.Font, a.Parent.Axis.LabelColour, "left");
}
});
}
calcXAxisPositions() {
const a = this;
const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W);
let result = [];
let x = a.GraphRectangle.X;
let date = a.Parent.ConvertToDate(a.Parent.ShowDate);
// Rollback one day
date.setDate(date.getDate() - 1);
while (true) {
if (x >= endPosX) {
break;
}
result.push({
Date: a.Parent.DateToString(date, a.Parent.DateParsePattern),
X: x
});
x += (a.Parent.Axis.X.HourLineSpace * a.Parent.Axis.X.NoPartPerDay);
date.setDate(date.getDate() + 1);
}
return result;
}
calcXAxisHeight() {
const a = this;
const labelSize = a.measureText(a.Parent.Axis.Font, "0");
return labelSize.Height + a.Parent.Axis.LabelSpacing + (a.Parent.Axis.X.DayLineHeight * 2);
}
// OnMouseDown(sender, e, event) {
// }
// OnClick(sender, e, event) {
// }
} }

View File

@ -11,16 +11,6 @@ class BBTimelineCanvas {
a.initialiseComponents(); a.initialiseComponents();
} }
Clear() {
const a = this;
a.CTX.clearRect(0, 0, a.CTX.canvas.width, a.CTX.canvas.height);
}
Invalidate() {
// placeholder
}
initialiseComponents() { initialiseComponents() {
const a = this; const a = this;
@ -36,6 +26,17 @@ class BBTimelineCanvas {
} }
Clear() {
const a = this;
a.CTX.clearRect(0, 0, a.CTX.canvas.width, a.CTX.canvas.height);
}
Invalidate() {
// placeholder
}
drawText(x, y, label, font, foreColour, align) { drawText(x, y, label, font, foreColour, align) {
const a = this; const a = this;

View File

@ -0,0 +1,22 @@
class BBTimelineFlourishCanvas extends BBTimelineCanvas {
constructor(parentEl, el) {
super(parentEl, el);
}
DrawVerticalLine(x) {
const a = this;
const rect = a.Parent.Layer.Background.GraphRectangle;
const linePosY = (rect.Y + rect.H);
a.Clear();
a.CTX.beginPath();
a.CTX.moveTo(x, rect.Y);
a.CTX.lineTo(x, (linePosY - a.Parent.Marker.Line.Width));
a.CTX.lineWidth = 1;
a.CTX.strokeStyle = a.Parent.HotTrack.Colour;
a.CTX.stroke();
}
}

View File

@ -4,7 +4,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
const a = this; const a = this;
a.initialiseComponents(); // a.initialiseComponents();
} }
initialiseComponents() { initialiseComponents() {
@ -12,6 +12,75 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
const a = this; const a = this;
a.CTX.canvas.addEventListener('mousedown', function (e) {
if (!a.Parent.Enabled) {
return;
}
var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY);
if (event == null) {
return;
}
if (a.Parent.Debug) console.log(event);
a.Parent.OnMouseDown(this, e, event);
});
a.CTX.canvas.addEventListener('click', function (e) {
if (!a.Parent.Enabled) {
return;
}
var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY);
if (event == null) {
return;
}
if (a.Parent.Debug) console.log(event);
a.Parent.OnClick(this, e, event);
});
a.CTX.canvas.addEventListener('dblclick', function (e) {
if (!a.Parent.Enabled) {
return;
}
var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY);
if (event == null) {
return;
}
if (a.Parent.Debug) console.log(event);
a.Parent.OnDblClick(this, e, event);
});
if (a.Parent.EnableHotTracking) {
a.CTX.canvas.addEventListener('mousemove', function (e) {
if (!a.Parent.Enabled) {
return;
}
if (!a.Parent.EnableHotTracking) {
return;
}
const point = { X: e.offsetX, Y: e.offsetY };
if (a.Parent.HasInterception(a.Parent.Layer.Background.GraphRectangle, point)) {
if (a.Parent.Debug) console.log(point);
a.Parent.DrawHotTracking(point.X);
a.Parent.OnMouseMove(this, e, point);
} else {
// Clear hot tracking
a.Parent.DrawHotTracking(-1);
}
});
}
a.Invalidate(); a.Invalidate();
} }
@ -24,7 +93,7 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
const startPosY = (rect.Y + a.Parent.Marker.Width); const startPosY = (rect.Y + a.Parent.Marker.Width);
const visibleEvents = a.Parent.FindVisibleEvents(); const visibleEvents = a.Parent.VisibleEvents;
visibleEvents.forEach(function (e, i) { visibleEvents.forEach(function (e, i) {
// Calculate Y position // Calculate Y position
let posY = a.calcMarkerPosition(e.Position.X, startPosY); let posY = a.calcMarkerPosition(e.Position.X, startPosY);
@ -48,6 +117,21 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
}); });
} }
OnMouseDown(e) {
if (!a.Parent.Enabled) {
return;
}
var event = a.Parent.FindEventsByCoords(e.offsetX, e.offsetY);
if (event == null) {
return;
}
if (a.Parent.Debug) console.log(event);
console.log("!");
a.Parent.OnMouseDown(this, e, event);
}
calcMarkerPosition(x, y) { calcMarkerPosition(x, y) {
const a = this; const a = this;
@ -92,18 +176,17 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
drawVerticalLine(x, y) { drawVerticalLine(x, y) {
const a = this; const a = this;
const rect = a.Parent.Layer.Background.GraphRectangle; const rect = a.Parent.Layer.Background.GraphRectangle;
const highlightLine = a.Parent.HighlightLine;
const linePosY = (rect.Y + rect.H); const linePosY = (rect.Y + rect.H);
if (y <= 0) { if (y <= 0) {
y = (rect.Y + highlightLine.Width); y = (rect.Y + a.Parent.Marker.Line.Width);
} }
a.CTX.beginPath(); a.CTX.beginPath();
a.CTX.moveTo(x, y); a.CTX.moveTo(x, y);
a.CTX.lineTo(x, (linePosY - highlightLine.Width)); a.CTX.lineTo(x, (linePosY - a.Parent.Marker.Line.Width));
a.CTX.lineWidth = highlightLine.Width; a.CTX.lineWidth = a.Parent.Marker.Line.Width;
a.CTX.strokeStyle = highlightLine.Colour; a.CTX.strokeStyle = a.Parent.Marker.Line.Colour;
a.CTX.stroke(); a.CTX.stroke();
} }
@ -121,5 +204,4 @@ class BBTimelineForegroundCanvas extends BBTimelineCanvas {
return result; return result;
} }
} }

View File

@ -48,33 +48,112 @@ class BBTimeline {
Width: 10, Width: 10,
ForeColour: "#3A5D9C", ForeColour: "#3A5D9C",
Font: "9pt Arial", Font: "9pt Arial",
CollisionMargin: 8 CollisionMargin: 8,
}; Line: {
a.HighlightLine = {
Colour: "#A6A6A6", Colour: "#A6A6A6",
Width: 1, Width: 1,
}
};
a.HotTrack = {
Colour: "#1D7F1D"
}; };
a.Events = []; a.Events = [];
a.StartDate = a.DateToString(new Date(), a.DateParsePattern); a.StartDate = a.DateToInternalString(new Date());
a.ShowDate = a.StartDate; a.ShowDate = a.StartDate;
// a.GraphRectangle = a.calcGraphRectangle();
a.Enabled = false; a.Enabled = false;
a.Debug = false; a.Debug = false;
a.EnableHotTracking = true;
a.initialiseComponents(); a.initialiseComponents();
} }
get CTX() {
return a.Layer.Markers.CTX;
}
get NewEvent() {
const a = this;
return {
Date: "",
Label: "",
Position: { X: 0, Y: 0 },
Events: [],
HitBox: null,
BorderColour: a.Marker.BorderColour,
BackColour: a.Marker.BackColour
};
}
get NewEventItem() {
return {
Title: "",
Description: "",
Link: "",
Tag: null
};
}
get VisibleDays() {
const a = this;
const clientWidth = (a.Size.W - (a.Padding.Left + a.Padding.Right));
return Math.floor(clientWidth / (a.Axis.X.NoPartPerDay * a.Axis.X.HourLineSpace));
}
get VisibleStartDate() {
const a = this;
return a.ConvertToDate(a.ShowDate);
}
get VisibleEndDate() {
const a = this;
let date = a.ConvertToDate(a.ShowDate);
date.setDate(date.getDate() + a.VisibleDays);
// Minus one for lead up
date.setDate(date.getDate() - 1);
return a.DateToString(date, a.DateParsePattern);
}
get VisibleEvents() {
const a = this;
let result = [];
a.Layer.Background.XAxisPositions.forEach(function (e) {
const event = a.FindEvent(e.Date);
if (event == null) {
return;
}
// Set offsetX on current view
event.Position.X = e.X;
result.push(event);
});
return result;
}
AddEvent(date, label, options) { AddEvent(date, label, options) {
const a = this; const a = this;
const _options = Object.assign(a.GenerateEventItem(), options); const _options = Object.assign(a.NewEventItem, options);
let event = a.FindEvent(date); let event = a.FindEvent(date);
if (event == null) { if (event == null) {
a.Events.push(a.GenerateEvent(date)); let newEvent = a.NewEvent;
newEvent.Date = date;
a.Events.push(newEvent);
event = a.FindEvent(date); event = a.FindEvent(date);
} }
@ -86,20 +165,6 @@ class BBTimeline {
event.Events.push(_options); event.Events.push(_options);
} }
CalcEndDate() {
const a = this;
const clientWidth = (a.Size.W - (a.Padding.Left + a.Padding.Right));
const calcdays = Math.floor(clientWidth / (a.Axis.X.NoPartPerDay * a.Axis.X.HourLineSpace));
let date = a.ConvertToDate(a.ShowDate);
date.setDate(date.getDate() + calcdays);
// Minus one for lead up
date.setDate(date.getDate() - 1);
return a.DateToString(date, a.DateParsePattern);
}
Clear() { Clear() {
const a = this; const a = this;
@ -107,7 +172,7 @@ class BBTimeline {
a.Layer.Flourish.Clear(); a.Layer.Flourish.Clear();
a.Layer.Markers.Clear(); a.Layer.Markers.Clear();
a.StartDate = a.DateToString(new Date(), a.DateParsePattern); a.StartDate = a.DateToInternalString(new Date());
a.ShowDate = a.StartDate; a.ShowDate = a.StartDate;
a.Enabled = false; a.Enabled = false;
a.Events = []; a.Events = [];
@ -128,8 +193,8 @@ class BBTimeline {
FindDatePosition(date) { FindDatePosition(date) {
const a = this; const a = this;
const points = a.Layer.Background.XAxisPositions;
const points = a.Layer.Background.calcXAxisPositions();
for (let i=0; i<points.length; i++) { for (let i=0; i<points.length; i++) {
if (points[i].Date == date){ if (points[i].Date == date){
return points[i]; return points[i];
@ -139,27 +204,6 @@ class BBTimeline {
return null; return null;
} }
FindVisibleEvents() {
const a = this;
let result = [];
const availableX = a.Layer.Background.calcXAxisPositions();
availableX.forEach(function (e) {
const event = a.FindEvent(e.Date);
if (event == null) {
return;
}
// Set offsetX on current view
event.Position.X = e.X;
result.push(event);
});
return result;
}
FindEvent(date) { FindEvent(date) {
const a = this; const a = this;
@ -213,23 +257,23 @@ class BBTimeline {
a.Invalidate(true, true); a.Invalidate(true, true);
} }
// ShowNext() { ShowNext() {
// const a = this; const a = this;
// let date = a.ConvertToDate(a.ShowDate); let date = a.VisibleStartDate;
// date.setMonth(date.getMonth() + 1); date.setDate(date.getDate() + (a.VisibleDays - 1));
// a.Show(a.DateToString(date, a.DateParsePattern)); a.Show(a.DateToInternalString(date));
// } }
// ShowPrevious() { ShowPrevious() {
// const a = this; const a = this;
// let date = a.ConvertToDate(a.ShowDate); let date = a.VisibleStartDate;
// date.setMonth(date.getMonth() - 1); date.setDate(date.getDate() - (a.VisibleDays - 1));
// a.Show(a.DateToString(date, a.DateParsePattern)); a.Show(a.DateToInternalString(date));
// } }
UpdateLabel(date, label) { UpdateLabel(date, label) {
const a = this; const a = this;
@ -258,40 +302,6 @@ class BBTimeline {
a.Invalidate(false, true); a.Invalidate(false, true);
} }
// initialiseComponents2() {
// const a = this;
// a.ctx.canvas.addEventListener('mousedown', function (e) {
// if (!a.Enabled) {
// return;
// }
// var event = a.FindEventsByCoords(e.offsetX, e.offsetY);
// if (event == null) {
// return;
// }
// if (a.Debug) console.log(event);
// a.OnMouseDown(this, e, event);
// });
// a.ctx.canvas.addEventListener('click', function (e) {
// if (!a.Enabled) {
// return;
// }
// var event = a.FindEventsByCoords(e.offsetX, e.offsetY);
// if (event == null) {
// return;
// }
// if (a.Debug) console.log(event);
// a.OnClick(this, e, event);
// });
// }
Invalidate(redrawAxis, redrawMarkers) { Invalidate(redrawAxis, redrawMarkers) {
const a = this; const a = this;
@ -299,77 +309,12 @@ class BBTimeline {
a.Layer.Background.Invalidate(); a.Layer.Background.Invalidate();
} }
a.Layer.Flourish.Clear();
if (redrawMarkers) { if (redrawMarkers) {
a.Layer.Markers.Invalidate(); a.Layer.Markers.Invalidate();
} }
return;
if (redrawAxis) {
a.ctx.clearRect(0, 0, a.ctx.canvas.width, a.ctx.canvas.height);
a.drawAxis();
a.drawXAxis();
a.drawXAxisLabels();
}
if (redrawMarkers) {
// a.clearChart();
// const startPosY = (a.GraphRectangle.Y + a.Marker.Width);
// const visibleEvents = a.FindVisibleEvents();
// if (a.Debug) console.log(visibleEvents);
visibleEvents.forEach(function (e, i) {
// Calculate Y position
let posY = a.calcMarkerPosition(e.Position.X, startPosY);
a.drawVerticalLine(e.Position.X, posY);
const markerRectangle = a.drawMarker(e.Position.X, posY, e.BorderColour, e.BackColour);
const labelSize = a.drawText((markerRectangle.X + markerRectangle.W + a.GraphRectangle.Margin), markerRectangle.Y, e.Label, a.Marker.Font, a.Marker.ForeColour, "left");
e.Position = { X: e.Position.X, Y: posY };
e.HitBox = {
X: markerRectangle.X,
Y: markerRectangle.Y,
W: (markerRectangle.W + a.GraphRectangle.Margin + labelSize.Width + a.Marker.CollisionMargin),
H: markerRectangle.H
};
if (a.Debug) a.drawRectangle(e.HitBox);
if (a.Debug) console.log(e);
});
}
if (a.Debug) a.drawRectangle(a.GraphRectangle);
}
GenerateEvent(date) {
const a = this;
return {
Date: date,
Label: "",
Position: { X: 0, Y: 0 },
Events: [],
HitBox: null,
BorderColour: a.Marker.BorderColour,
BackColour: a.Marker.BackColour
};
}
GenerateEventItem() {
return {
Title: "",
Description: "",
Link: "",
Tag: null
};
} }
DateToString(date, pattern) { DateToString(date, pattern) {
@ -418,313 +363,41 @@ class BBTimeline {
return result; return result;
} }
OnMouseDown(sender, e, event) { DateToInternalString(date) {
const a = this;
return a.DateToString(date, a.DateParsePattern);
} }
OnClick(sender, e, event) { DrawHotTracking(x) {
const a = this;
if (x < 0) {
a.Layer.Flourish.Clear();
} else {
a.Layer.Flourish.DrawVerticalLine(x);
}
} }
// calcGraphRectangle() {
// const a = this;
// // const xAxisHeight = a.calcXAxisHeight();
// // let result = {
// // X: a.Padding.Left,
// // Y: a.Padding.Top,
// // W: (a.Size.W - (a.Padding.Left + a.Padding.Right)),
// // H: (a.Size.H - (a.Padding.Top + a.Padding.Bottom) - xAxisHeight),
// // Margin: (a.Marker.BorderWidth * 2)
// // };
// let result = {
// X: a.Padding.Left,
// Y: a.Padding.Top,
// W: (a.Size.W - (a.Padding.Left + a.Padding.Right)),
// H: (a.Size.H - (a.Padding.Top + a.Padding.Bottom)),
// Margin: (a.Marker.BorderWidth * 2)
// };
// result.StepHeight = a.Marker.Width + result.Margin;
// result.NoStep = Math.floor(result.H / result.StepHeight);
// return result;
// }
// calcXAxisHeight() {
// const a = this;
// const labelSize = a.measureText(a.Axis.Font, "0");
// const result = labelSize.Height + a.Axis.LabelSpacing + (a.Axis.X.DayLineHeight * 2);
// return result;
// }
// calcMarkerPosition(x, y) {
// const a = this;
// // Calculate Y position
// let hasMoved = false;
// let posY = y;
// for (let i=0; i<a.GraphRectangle.NoStep; i++)
// {
// posY = y + (a.GraphRectangle.StepHeight * i);
// var clippedEvent = a.FindEventsByCoords(x, posY);
// if (clippedEvent == null) {
// hasMoved = true;
// break;
// }
// }
// if (!hasMoved) {
// posY = y;
// }
// return posY;
// }
// clearChart() {
// const a = this;
// const rect = {
// X: a.GraphRectangle.X,
// Y: a.GraphRectangle.Y,
// W: a.GraphRectangle.W,
// H: a.GraphRectangle.H
// };
// rect.X += a.Axis.LineWidth;
// rect.Y -= a.Padding.Top;
// rect.W -= a.Axis.LineWidth;
// rect.W += a.Padding.Right;
// rect.H -= a.Axis.LineWidth;
// rect.H += a.Padding.Top;
// a.ctx.clearRect(rect.X, rect.Y, rect.W, rect.H);
// if (a.Debug) a.drawRectangle(rect);
// // Clear marker positions
// const visibleEvents = a.FindVisibleEvents();
// visibleEvents.forEach(function (e, i) {
// e.Position = { X: 0, Y: 0 };
// e.HitBox = null;
// });
// }
// drawAxis() {
// const a = this;
// a.ctx.beginPath();
// a.ctx.moveTo(a.GraphRectangle.X, a.GraphRectangle.Y);
// a.ctx.lineTo(a.GraphRectangle.X, (a.GraphRectangle.H + a.GraphRectangle.Y));
// a.ctx.lineTo((a.GraphRectangle.W + a.GraphRectangle.X), (a.GraphRectangle.H + a.GraphRectangle.Y));
// a.ctx.lineWidth = a.Axis.LineWidth;
// a.ctx.strokeStyle = a.Axis.LineColour1;
// a.ctx.stroke();
// }
// drawXAxis() {
// const a = this;
// let startPosX = a.GraphRectangle.X;
// const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W);
// const posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Axis.LineWidth;
// let i = 0;
// while (true) {
// if (startPosX >= endPosX) {
// break;
// }
// a.ctx.beginPath();
// a.ctx.moveTo(startPosX, posY);
// if ((i % a.Axis.X.NoPartPerDay) == 0) {
// a.ctx.lineTo(startPosX, (posY + a.Axis.X.DayLineHeight));
// a.ctx.strokeStyle = a.Axis.X.DayLineColour;
// } else {
// a.ctx.lineTo(startPosX, (posY + a.Axis.X.HourLineHeight));
// a.ctx.strokeStyle = a.Axis.X.HourLineColour;
// }
// a.ctx.lineWidth = a.Axis.LineWidth;
// a.ctx.stroke();
// startPosX += a.Axis.X.HourLineSpace;
// i++;
// }
// }
// drawXAxisLabels() {
// const a = this;
// const result = a.getXAxis();
// const posY = (a.GraphRectangle.Y + a.GraphRectangle.H) + a.Axis.LineWidth;
// result.forEach(function(e, i) {
// const date = a.ConvertToDate(e.Date);
// let writeLabel = false;
// if ((i == 0)) {
// // Don't label first entry if too close to the next month
// if (date.getDate() < 25) {
// writeLabel = true;
// }
// } else if (date.getDate() == 1) {
// writeLabel = true;
// }
// // if (i == 0) {
// // return;
// // }
// const labelSize = a.drawText(e.X, (posY + a.Axis.X.DayLineHeight), a.DateToString(date, "dd"), a.Axis.Font, a.Axis.LabelColour, "center");
// // Write month on first of the month
// if (writeLabel) {
// a.drawText(e.X, (posY + a.Axis.X.DayLineHeight + labelSize.Height + a.Axis.LabelSpacing), a.DateToString(date, "MMMM yyyy"), a.Axis.Font, a.Axis.LabelColour, "left");
// }
// });
// }
// drawMarker(x, y, borderColour, backColour) {
// const a = this;
// const width = a.Marker.Width - (a.Marker.BorderWidth * 2);
// a.ctx.beginPath();
// a.ctx.arc(x, y, width, 0, 2 * Math.PI, false);
// a.ctx.fillStyle = backColour;
// a.ctx.fill();
// a.ctx.lineWidth = a.Marker.BorderWidth;
// a.ctx.strokeStyle = borderColour;
// a.ctx.stroke();
// return a.measureMarker(x, y);
// }
// drawText(x, y, label, font, foreColour, align) {
// const a = this;
// a.ctx.font = font;
// a.ctx.fillStyle = foreColour;
// const size = a.measureText(font, label);
// switch (align) {
// case "center":
// x = (x - size.OffsetLeft);
// break;
// case "right":
// x = (x - size.Width);
// break;
// case "left":
// default:
// // do nothing
// break;
// }
// a.ctx.fillText(label, x, (y + size.Height));
// return size;
// }
// drawRectangle(rectangle) {
// const a = this;
// a.ctx.beginPath();
// a.ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
// //a.ctx.fillStyle = 'yellow';
// //a.ctx.fill();
// a.ctx.lineWidth = 1;
// a.ctx.strokeStyle = 'red';
// a.ctx.stroke();
// }
// drawVerticalLine(x, y) {
// const a = this;
// const linePosY = (a.GraphRectangle.Y + a.GraphRectangle.H);
// if (y <= 0) {
// y = (a.GraphRectangle.Y + a.HighlightLine.Width);
// }
// a.ctx.beginPath();
// a.ctx.moveTo(x, y);
// a.ctx.lineTo(x, (linePosY - a.HighlightLine.Width));
// a.ctx.lineWidth = a.HighlightLine.Width;
// a.ctx.strokeStyle = a.HighlightLine.Colour;
// a.ctx.stroke();
// }
// getXAxis() {
// const a = this;
// const endPosX = (a.GraphRectangle.X + a.GraphRectangle.W);
// let result = [];
// let x = a.GraphRectangle.X;
// let date = a.ConvertToDate(a.ShowDate);
// // Rollback one day
// date.setDate(date.getDate() - 1);
// while (true) {
// if (x >= endPosX) {
// break;
// }
// result.push({
// Date: a.DateToString(date, a.DateParsePattern),
// X: x
// });
// x += (a.Axis.X.HourLineSpace * a.Axis.X.NoPartPerDay);
// date.setDate(date.getDate() + 1);
// }
// return result;
// }
// half(value) {
// return (value / 2);
// }
// measureMarker(x, y) {
// const a = this;
// const offset = a.half(a.Marker.Width);
// const result = {
// X: x - (offset + a.Marker.BorderWidth),
// Y: y - (offset + a.Marker.BorderWidth),
// W: (a.Marker.Width + (a.Marker.BorderWidth * 2)),
// H: (a.Marker.Width + (a.Marker.BorderWidth * 2))
// };
// return result;
// }
// measureText(font, value) {
// const a = this;
// a.ctx.font = font;
// const size = a.ctx.measureText(value);
// return {
// Width: size.width,
// Height: size.fontBoundingBoxAscent,
// OffsetLeft: a.half(size.width),
// OffsetTop: a.half(size.fontBoundingBoxAscent)
// };
// }
ConvertToDate(value) { ConvertToDate(value) {
return new Date(Date.parse(value)); return new Date(Date.parse(value));
} }
HasInterception(rect, point) {
const x2 = (rect.X + rect.W);
const y2 = (rect.Y + rect.H);
return ((point.X >= rect.X) && (point.X <= x2) && (point.Y >= rect.Y) && (point.Y <= y2));
}
OnMouseDown(sender, e, event) { /* delegate */ }
OnMouseMove(sender, e, event) { /* delegate */ }
OnClick(sender, e, event) { /* delegate */ }
OnDblClick(sender, e, event) { /* delegate */ }
initialiseComponents() { initialiseComponents() {
@ -735,7 +408,7 @@ class BBTimeline {
const canvasList = a.Container.getElementsByTagName("canvas"); const canvasList = a.Container.getElementsByTagName("canvas");
a.Layer.Background = new BBTimelineBackgroundCanvas(a, canvasList[0]); a.Layer.Background = new BBTimelineBackgroundCanvas(a, canvasList[0]);
a.Layer.Flourish = new BBTimelineCanvas(a, canvasList[1]); a.Layer.Flourish = new BBTimelineFlourishCanvas(a, canvasList[1]);
a.Layer.Markers = new BBTimelineForegroundCanvas(a, canvasList[2]); a.Layer.Markers = new BBTimelineForegroundCanvas(a, canvasList[2]);
} }

1
bbtimeline.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@
<script src="bbtimeline.js"></script> <script src="bbtimeline.js"></script>
<script src="bbtimeline-canvas.js"></script> <script src="bbtimeline-canvas.js"></script>
<script src="bbtimeline-background-canvas.js"></script> <script src="bbtimeline-background-canvas.js"></script>
<script src="bbtimeline-flourish-canvas.js"></script>
<script src="bbtimeline-foreground-canvas.js"></script> <script src="bbtimeline-foreground-canvas.js"></script>
<!-- <script src="bbtimeline.min.js"></script> --> <!-- <script src="bbtimeline.min.js"></script> -->
@ -34,6 +35,7 @@
<p> <p>
<button onclick="Clear()">Clear</button> <button onclick="Clear()">Clear</button>
<button onclick="ToggleDebug()">Toggle Debug</button> <button onclick="ToggleDebug()">Toggle Debug</button>
<button onclick="ToggleHotTracking()">Toggle Hot Tracking</button>
<button onclick="Refresh()">Refresh</button> <button onclick="Refresh()">Refresh</button>
</p> </p>
<hr /> <hr />
@ -50,8 +52,8 @@
<p> <p>
<button onclick="GoToToday()">Show Start Date</button> <button onclick="GoToToday()">Show Start Date</button>
<button onclick="GoToPreviousMonth()">Show Previous Month</button> <button onclick="GoToPrevious()">Show Previous</button>
<button onclick="GoToNextMonth()">Show Next Month</button> <button onclick="GoToNext()">Show Next</button>
</p> </p>
<hr /> <hr />
@ -145,6 +147,14 @@ timeline1.OnClick = function(sender, e, event) {
LogInfo(JSON.stringify(event)); LogInfo(JSON.stringify(event));
LogInfo(""); LogInfo("");
} }
timeline1.OnDblClick = function(sender, e, event) {
LogInfo("");
LogInfo("OnDblClick");
LogInfo(JSON.stringify(sender));
LogInfo(JSON.stringify(e));
LogInfo(JSON.stringify(event));
LogInfo("");
}
SetToday(); SetToday();
@ -161,17 +171,22 @@ function ToggleDebug() {
timeline1.Invalidate(true, true); timeline1.Invalidate(true, true);
} }
function ToggleHotTracking() {
timeline1.EnableHotTracking = !timeline1.EnableHotTracking;
timeline1.Invalidate(true, true);
}
function Refresh() { function Refresh() {
timeline1.Invalidate(true, true); timeline1.Invalidate(true, true);
} }
function SetToday() { function SetToday() {
const msPerDay = 1000 * 60 * 60 * 24; const msPerDay = 1000 * 60 * 60 * 24;
const startDate = timeline1.DateToString(new Date(), "yyyy-MM-dd"); const startDate = timeline1.DateToInternalString(new Date());
timeline1.Load(startDate); timeline1.Load(startDate);
const endDate = timeline1.CalcEndDate(); const endDate = timeline1.VisibleEndDate;
const noDays = Math.floor((timeline1.ConvertToDate(endDate) - timeline1.ConvertToDate(startDate)) / msPerDay); const noDays = Math.floor((timeline1.ConvertToDate(endDate) - timeline1.ConvertToDate(startDate)) / msPerDay);
LogInfo("Set start date to today (" + startDate + ")"); LogInfo("Set start date to today (" + startDate + ")");
@ -180,7 +195,7 @@ function SetToday() {
function GenerateRandomMarker() { function GenerateRandomMarker() {
const msPerDay = 1000 * 60 * 60 * 24; const msPerDay = 1000 * 60 * 60 * 24;
const endDate = timeline1.CalcEndDate(); const endDate = timeline1.VisibleEndDate;
const noDays = Math.floor((timeline1.ConvertToDate(endDate) - timeline1.ConvertToDate(timeline1.ShowDate)) / msPerDay); const noDays = Math.floor((timeline1.ConvertToDate(endDate) - timeline1.ConvertToDate(timeline1.ShowDate)) / msPerDay);
let randomDay = GetRandy(1, (noDays - 1)); let randomDay = GetRandy(1, (noDays - 1));
@ -188,7 +203,7 @@ function GenerateRandomMarker() {
let date = timeline1.ConvertToDate(timeline1.ShowDate); let date = timeline1.ConvertToDate(timeline1.ShowDate);
date.setDate(date.getDate() + randomDay); date.setDate(date.getDate() + randomDay);
const markerDate = timeline1.DateToString(date, timeline1.DateParsePattern); const markerDate = timeline1.DateToInternalString(date);
const markerName = "Random Marker #" + GetRandy(10000, 99999); const markerName = "Random Marker #" + GetRandy(10000, 99999);
@ -204,20 +219,20 @@ function GoToToday() {
LogInfo("Go to " + timeline1.ShowDate); LogInfo("Go to " + timeline1.ShowDate);
} }
function GoToPreviousMonth() { function GoToPrevious() {
timeline1.ShowPrevious(); timeline1.ShowPrevious();
LogInfo("Go to " + timeline1.ShowDate); LogInfo("Go to " + timeline1.ShowDate);
} }
function GoToNextMonth() { function GoToNext() {
timeline1.ShowNext(); timeline1.ShowNext();
LogInfo("Go to " + timeline1.ShowDate); LogInfo("Go to " + timeline1.ShowDate);
} }
function UpdateLabel() { function UpdateLabel() {
const visibleMarkers = timeline1.FindVisibleEvents(); const visibleMarkers = timeline1.VisibleEvents;
if (visibleMarkers.length <= 0) { if (visibleMarkers.length <= 0) {
LogInfo("No visible markers"); LogInfo("No visible markers");
return; return;
@ -232,7 +247,7 @@ function UpdateLabel() {
} }
function UpdateMarker() { function UpdateMarker() {
const visibleMarkers = timeline1.FindVisibleEvents(); const visibleMarkers = timeline1.VisibleEvents;
if (visibleMarkers.length <= 0) { if (visibleMarkers.length <= 0) {
LogInfo("No visible markers"); LogInfo("No visible markers");
return; return;
@ -246,7 +261,7 @@ function UpdateMarker() {
} }
function DeleteMarker() { function DeleteMarker() {
const visibleMarkers = timeline1.FindVisibleEvents(); const visibleMarkers = timeline1.VisibleEvents;
if (visibleMarkers.length <= 0) { if (visibleMarkers.length <= 0) {
LogInfo("No visible markers"); LogInfo("No visible markers");
return; return;
@ -261,7 +276,7 @@ function DeleteMarker() {
} }
function FindVisibleEvents() { function FindVisibleEvents() {
const visibleMarkers = timeline1.FindVisibleEvents(); const visibleMarkers = timeline1.VisibleEvents;
LogInfo(""); LogInfo("");
LogInfo(JSON.stringify(visibleMarkers)); LogInfo(JSON.stringify(visibleMarkers));