From 70fdbbfb30da832a083a78b8eead164e82d3cde9 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:38:34 +0100 Subject: [PATCH 1/9] update theme --- resources/assets/js/chart-theme.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/resources/assets/js/chart-theme.js b/resources/assets/js/chart-theme.js index 62b55ef01..ffbbe2510 100644 --- a/resources/assets/js/chart-theme.js +++ b/resources/assets/js/chart-theme.js @@ -213,21 +213,28 @@ export function getAxisThemeConfig(mode) { const config = { light: { x: { - color: "rgba(238,243,245,1)", // theme-secondary-200 + color: "rgba(219, 222, 229, 1)", // theme-secondary-300 }, y: { - color: "rgba(238,243,245,1)", // theme-secondary-200 + color: "rgba(219, 222, 229, 1)", // theme-secondary-300 }, }, dark: { x: { - color: "rgba(60,66,73,1)", // theme-secondary-800 + color: "rgba(61, 68, 77, 1)", // theme-dark-700 }, y: { - color: "rgba(60,66,73,1)", // theme-secondary-800 + color: "rgba(61, 68, 77, 1)", // theme-dark-700 }, }, }; return config[mode]; } + +export function getCrosshairColor(mode) { + return { + light: "rgba(99, 114, 130, 1)", // theme-secondary-700, + dark: "rgba(164, 177, 188, 1)", // theme-dark-200, + }[mode]; +} From 2d8164a2db717ffa0c0d74fea605b4c42d092bc0 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:41:59 +0100 Subject: [PATCH 2/9] add crosshair --- resources/assets/js/chart.js | 91 +++++++++++++++++++++++++-------- resources/views/chart.blade.php | 2 + 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 8bb7665e9..067f5534a 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -3,9 +3,10 @@ import { makeGradient, getFontConfig, getAxisThemeConfig, + getCrosshairColor, } from "./chart-theme"; -import { Chart, registerables } from "chart.js"; +import { Chart, registerables, LineController } from "chart.js"; Chart.register(...registerables); @@ -18,6 +19,7 @@ Chart.register(...registerables); * @param {Array} theme * @param {Number} time * @param {String} currency + * @param {Boolean} showCrosshair * @return {Object} */ const CustomChart = ( @@ -28,8 +30,62 @@ const CustomChart = ( tooltips, theme, time, - currency + currency, + showCrosshair = false, ) => { + const themeMode = () => { + if (theme.mode === "auto") { + return ["light", "dark"].includes(localStorage.theme) + ? localStorage.theme + : "light"; + } + + return theme.mode; + }; + + class LineWithCrosshair extends LineController { + draw() { + super.draw(arguments); + + if (this.chart.tooltip._active && this.chart.tooltip._active.length) { + console.log(this.chart.tooltip._active[0], this.chart.tooltip._active[1]); + const activePoint = this.chart.tooltip._active[0].element; + const ctx = this.chart.ctx; + const x = activePoint.x; + const y = activePoint.y; + const topY = this.chart.legend.bottom; + const bottomY = this.chart.chartArea.bottom; + const left = this.chart.chartArea.left; + const right = this.chart.chartArea.right; + + // Set line opts + ctx.save(); + ctx.lineWidth = 1; + ctx.setLineDash([3, 3]); + ctx.strokeStyle = getCrosshairColor(themeMode()); + + // Draw vertical line + ctx.beginPath(); + ctx.moveTo(x, topY); + ctx.lineTo(x, bottomY); + ctx.stroke(); + + // Draw horizontal line + ctx.beginPath(); + ctx.moveTo(left, y); + ctx.lineTo(right, y); + ctx.stroke(); + + ctx.restore(); + } + } + } + + LineWithCrosshair.id = 'lineWithCrosshair'; + LineWithCrosshair.defaults = LineController.defaults; + + Chart.register(LineWithCrosshair); + return { time: time, chart: null, @@ -71,16 +127,6 @@ const CustomChart = ( this.chart.update(); }, - themeMode() { - if (theme.mode === "auto") { - return ["light", "dark"].includes(localStorage.theme) - ? localStorage.theme - : "light"; - } - - return theme.mode; - }, - loadData() { const datasets = []; @@ -95,7 +141,7 @@ const CustomChart = ( values.forEach((value, key) => { let themeName = value.type === "bar" ? "grey" : theme.name; - let graphic = getInfoFromThemeName(themeName, this.themeMode()); + let graphic = getInfoFromThemeName(themeName, themeMode()); let backgroundColor = graphic.backgroundColor; if (backgroundColor.hasOwnProperty("gradient")) { backgroundColor = makeGradient( @@ -104,12 +150,17 @@ const CustomChart = ( ); } + let chartType = value.type || "line"; + if (showCrosshair && chartType === "line") { + chartType = "lineWithCrosshair"; + } + datasets.push({ fill: true, stack: "combined", label: value.name || "", data: value.data || value, - type: value.type || "line", + type: chartType, backgroundColor: value.type === "bar" ? graphic.borderColor @@ -149,7 +200,7 @@ const CustomChart = ( display: grid && key === 0, type: "linear", ticks: { - ...getFontConfig("axis", this.themeMode()), + ...getFontConfig("axis", themeMode()), padding: 15, display: grid && key === 0, suggestedMax: range.max, @@ -159,7 +210,7 @@ const CustomChart = ( grid: { display: grid && key === 0, drawBorder: false, - color: getAxisThemeConfig(this.themeMode()).y.color, + color: getAxisThemeConfig(themeMode()).y.color, }, }); }); @@ -206,12 +257,12 @@ const CustomChart = ( label: (context) => this.getCurrencyValue(context.raw), labelTextColor: (context) => - getFontConfig("tooltip", this.themeMode()) + getFontConfig("tooltip", themeMode()) .fontColor, }, backgroundColor: getFontConfig( "tooltip", - this.themeMode() + themeMode() ).backgroundColor, }, }, @@ -233,12 +284,12 @@ const CustomChart = ( display: grid, includeBounds: true, padding: 10, - ...getFontConfig("axis", this.themeMode()), + ...getFontConfig("axis", themeMode()), }, grid: { display: grid, drawBorder: false, - color: getAxisThemeConfig(this.themeMode()).x.color, + color: getAxisThemeConfig(themeMode()).x.color, }, }, }, diff --git a/resources/views/chart.blade.php b/resources/views/chart.blade.php index e0c68e093..c23f21ac3 100644 --- a/resources/views/chart.blade.php +++ b/resources/views/chart.blade.php @@ -9,6 +9,7 @@ 'grid' => false, 'tooltips' => false, 'theme' => collect(['name' => 'grey', 'mode' => 'light']), + 'showCrosshair' => false, ])
toArray()) }}, '{{ time() }}', '{{ $currency }}', + {{ $showCrosshair ? 'true' : 'false' }} )" wire:key="{{ $id.time() }}" {{ $attributes->only('class') }} From 00b92c9345f17301753b8307494a4fe4aabf7069 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:42:17 +0100 Subject: [PATCH 3/9] add padding options --- resources/assets/js/chart.js | 8 ++++++-- resources/views/chart.blade.php | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 067f5534a..11e31d6a7 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -19,6 +19,8 @@ Chart.register(...registerables); * @param {Array} theme * @param {Number} time * @param {String} currency + * @param {Number} yPadding + * @param {Number} xPadding * @param {Boolean} showCrosshair * @return {Object} */ @@ -31,6 +33,8 @@ const CustomChart = ( theme, time, currency, + yPadding = 15, + xPadding = 10, showCrosshair = false, ) => { const themeMode = () => { @@ -201,7 +205,7 @@ const CustomChart = ( type: "linear", ticks: { ...getFontConfig("axis", themeMode()), - padding: 15, + padding: yPadding, display: grid && key === 0, suggestedMax: range.max, callback: (value, index, data) => @@ -283,7 +287,7 @@ const CustomChart = ( ticks: { display: grid, includeBounds: true, - padding: 10, + padding: xPadding, ...getFontConfig("axis", themeMode()), }, grid: { diff --git a/resources/views/chart.blade.php b/resources/views/chart.blade.php index c23f21ac3..c9b55a7a8 100644 --- a/resources/views/chart.blade.php +++ b/resources/views/chart.blade.php @@ -9,6 +9,8 @@ 'grid' => false, 'tooltips' => false, 'theme' => collect(['name' => 'grey', 'mode' => 'light']), + 'yPadding' => 15, + 'xPadding' => 10, 'showCrosshair' => false, ]) @@ -22,6 +24,8 @@ {{ json_encode($theme->toArray()) }}, '{{ time() }}', '{{ $currency }}', + {{ $yPadding }}, + {{ $xPadding }}, {{ $showCrosshair ? 'true' : 'false' }} )" wire:key="{{ $id.time() }}" From fcada440637b52fecc3bae3ab49363c1fb279ab3 Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:43:21 +0100 Subject: [PATCH 4/9] tweaks to js --- resources/assets/js/chart.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 11e31d6a7..9ed953328 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -212,8 +212,10 @@ const CustomChart = ( this.getCurrencyValue(value), }, grid: { + drawTicks: false, display: grid && key === 0, drawBorder: false, + borderDash: [3, 3], color: getAxisThemeConfig(themeMode()).y.color, }, }); @@ -291,7 +293,7 @@ const CustomChart = ( ...getFontConfig("axis", themeMode()), }, grid: { - display: grid, + display: false, drawBorder: false, color: getAxisThemeConfig(themeMode()).x.color, }, From b7588c5207510b65821547460c4e20b6758a765f Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:43:29 +0100 Subject: [PATCH 5/9] window resize handler --- resources/assets/js/chart.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 9ed953328..04b4088da 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -232,9 +232,14 @@ const CustomChart = ( } this.$watch("time", () => this.updateChart()); - window.addEventListener("resize", () => - window.livewire.emit("updateChart") - ); + + window.addEventListener('resize', () => { + try { + this.chart.resize(); + } catch (e) { + // Hide resize errors - they don't seem to cause any issues + } + }); const data = { labels: labels, From bc07581bdc5d016188bd09d941cc1dc3e8a5671e Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:43:36 +0100 Subject: [PATCH 6/9] scrub --- resources/views/chart.blade.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/views/chart.blade.php b/resources/views/chart.blade.php index c9b55a7a8..66f03b095 100644 --- a/resources/views/chart.blade.php +++ b/resources/views/chart.blade.php @@ -31,7 +31,10 @@ wire:key="{{ $id.time() }}" {{ $attributes->only('class') }} > -
+
Date: Thu, 28 Sep 2023 23:34:07 +0100 Subject: [PATCH 7/9] scrub --- resources/assets/js/chart.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 04b4088da..e645fb8ae 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -52,7 +52,6 @@ const CustomChart = ( super.draw(arguments); if (this.chart.tooltip._active && this.chart.tooltip._active.length) { - console.log(this.chart.tooltip._active[0], this.chart.tooltip._active[1]); const activePoint = this.chart.tooltip._active[0].element; const ctx = this.chart.ctx; const x = activePoint.x; @@ -62,19 +61,16 @@ const CustomChart = ( const left = this.chart.chartArea.left; const right = this.chart.chartArea.right; - // Set line opts ctx.save(); ctx.lineWidth = 1; ctx.setLineDash([3, 3]); ctx.strokeStyle = getCrosshairColor(themeMode()); - // Draw vertical line ctx.beginPath(); ctx.moveTo(x, topY); ctx.lineTo(x, bottomY); ctx.stroke(); - // Draw horizontal line ctx.beginPath(); ctx.moveTo(left, y); ctx.lineTo(right, y); From 7f5948a1f81b583f3cda4875b3fe813f3b467b8a Mon Sep 17 00:00:00 2001 From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com> Date: Thu, 28 Sep 2023 23:36:07 +0100 Subject: [PATCH 8/9] add credit --- resources/assets/js/chart.js | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index e645fb8ae..7a9e33df2 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -51,6 +51,7 @@ const CustomChart = ( draw() { super.draw(arguments); + // Based on https://stackoverflow.com/a/70245628/3637093 if (this.chart.tooltip._active && this.chart.tooltip._active.length) { const activePoint = this.chart.tooltip._active[0].element; const ctx = this.chart.ctx; From 7927dce7ffe28bfe307461db727f38ca04622d45 Mon Sep 17 00:00:00 2001 From: alexbarnsley Date: Thu, 28 Sep 2023 22:39:15 +0000 Subject: [PATCH 9/9] style: resolve style guide violations --- resources/assets/js/chart.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/assets/js/chart.js b/resources/assets/js/chart.js index 7a9e33df2..5895883a2 100644 --- a/resources/assets/js/chart.js +++ b/resources/assets/js/chart.js @@ -35,7 +35,7 @@ const CustomChart = ( currency, yPadding = 15, xPadding = 10, - showCrosshair = false, + showCrosshair = false ) => { const themeMode = () => { if (theme.mode === "auto") { @@ -52,7 +52,10 @@ const CustomChart = ( super.draw(arguments); // Based on https://stackoverflow.com/a/70245628/3637093 - if (this.chart.tooltip._active && this.chart.tooltip._active.length) { + if ( + this.chart.tooltip._active && + this.chart.tooltip._active.length + ) { const activePoint = this.chart.tooltip._active[0].element; const ctx = this.chart.ctx; const x = activePoint.x; @@ -82,7 +85,7 @@ const CustomChart = ( } } - LineWithCrosshair.id = 'lineWithCrosshair'; + LineWithCrosshair.id = "lineWithCrosshair"; LineWithCrosshair.defaults = LineController.defaults; Chart.register(LineWithCrosshair); @@ -230,7 +233,7 @@ const CustomChart = ( this.$watch("time", () => this.updateChart()); - window.addEventListener('resize', () => { + window.addEventListener("resize", () => { try { this.chart.resize(); } catch (e) { @@ -265,13 +268,10 @@ const CustomChart = ( label: (context) => this.getCurrencyValue(context.raw), labelTextColor: (context) => - getFontConfig("tooltip", themeMode()) - .fontColor, + getFontConfig("tooltip", themeMode()).fontColor, }, - backgroundColor: getFontConfig( - "tooltip", - themeMode() - ).backgroundColor, + backgroundColor: getFontConfig("tooltip", themeMode()) + .backgroundColor, }, }, hover: {