diff --git a/assets/js/components/Forecast/Co2Chart.vue b/assets/js/components/Forecast/Co2Chart.vue index 438098327..ea688deea 100644 --- a/assets/js/components/Forecast/Co2Chart.vue +++ b/assets/js/components/Forecast/Co2Chart.vue @@ -118,10 +118,3 @@ export default defineComponent({ }, }); - - diff --git a/assets/js/components/Forecast/PriceChart.vue b/assets/js/components/Forecast/PriceChart.vue index 14a99622e..00298fa81 100644 --- a/assets/js/components/Forecast/PriceChart.vue +++ b/assets/js/components/Forecast/PriceChart.vue @@ -131,8 +131,8 @@ export default defineComponent({ ? { opacity: 0.33 } : undefined, })), - barMaxWidth: 4, - barMinWidth: 4, + barMaxWidth: 2, + barMinWidth: 2, itemStyle: { color: priceColor, borderRadius: 2, @@ -164,10 +164,3 @@ export default defineComponent({ }, }); - - diff --git a/assets/js/components/Forecast/SolarChart.vue b/assets/js/components/Forecast/SolarChart.vue index bd13a76d9..528279bef 100644 --- a/assets/js/components/Forecast/SolarChart.vue +++ b/assets/js/components/Forecast/SolarChart.vue @@ -129,10 +129,3 @@ export default defineComponent({ }, }); - - diff --git a/assets/js/components/Forecast/chartMixin.ts b/assets/js/components/Forecast/chartMixin.ts index 4df452935..d8c9cecf3 100644 --- a/assets/js/components/Forecast/chartMixin.ts +++ b/assets/js/components/Forecast/chartMixin.ts @@ -1,5 +1,6 @@ import { defineComponent, markRaw } from "vue"; import { echarts } from "./echarts"; +import "./chartStyles.css"; // chartOption is provided by each consuming component's computed type WithChartOption = { chartOption: Record }; @@ -62,6 +63,12 @@ export default defineComponent({ this.chart.on("hideTip", () => { this.tooltipVisible = false; }); + const resetTouch = () => { + this.chart?.dispatchAction({ type: "hideTip" }); + this.tooltipVisible = false; + }; + el.addEventListener("touchend", resetTouch); + el.addEventListener("touchcancel", resetTouch); }, }, }); diff --git a/assets/js/components/Forecast/chartStyles.css b/assets/js/components/Forecast/chartStyles.css new file mode 100644 index 000000000..5b9f3e23e --- /dev/null +++ b/assets/js/components/Forecast/chartStyles.css @@ -0,0 +1,7 @@ +.forecast-chart-scroll { + overflow-x: auto; + padding-bottom: 4px; + user-select: none; + -webkit-user-select: none; + -webkit-touch-callout: none; +} diff --git a/assets/js/components/Forecast/echarts.ts b/assets/js/components/Forecast/echarts.ts index d8f61a122..d56556b54 100644 --- a/assets/js/components/Forecast/echarts.ts +++ b/assets/js/components/Forecast/echarts.ts @@ -51,7 +51,7 @@ export function markPointLabel( return { animation: true, - clip: false, + clip: true, symbol: "rect", symbolSize: 1, label: { @@ -76,11 +76,12 @@ export function tooltipStyle( getChart?: () => { convertToPixel: echarts.ECharts["convertToPixel"] } | null ) { return { + confine: true, backgroundColor: color, borderColor: color, borderWidth: 0, padding: [5, 10], - extraCssText: "box-shadow: none; border-radius: 4px; text-align: center;", + extraCssText: "box-shadow: none; border-radius: 4px; text-align: center; z-index: 1000;", position( point: [number, number], params: { value: [string, number] }[] | { value: [string, number] }, @@ -110,7 +111,7 @@ export function tooltipStyle( } export function forecastGrid() { - return { top: 36, right: 16, bottom: 4, left: 48, borderWidth: 0 }; + return { top: 36, right: 16, bottom: 4, left: 34, borderWidth: 0 }; } export function forecastXAxes(startDate: Date, endDate: Date, weekdayShort: (d: Date) => string) { @@ -129,7 +130,7 @@ export function forecastXAxes(startDate: Date, endDate: Date, weekdayShort: (d: formatter: (value: number) => { const date = new Date(value); const h = date.getHours(); - if (h % 2 !== 0) return ""; + if (h % 4 !== 0) return ""; if (h === 0) return `${h}\n${weekdayShort(date)}`; return `${h}`; }, @@ -171,7 +172,8 @@ export function forecastYAxis(overrides: Record = {}) { lineStyle: { color: colors.border || "" }, }, axisLabel: { - fontSize: 14, + fontSize: 10, + opacity: 0.5, ...(axisLabel as Record), }, ...rest, @@ -188,7 +190,7 @@ export function filterForecastSlots( endDate: Date ): ForecastSlot[] { if (!Array.isArray(slots)) return []; - return slots.filter((s) => new Date(s.end) >= startDate && new Date(s.start) <= endDate); + return slots.filter((s) => new Date(s.end) > startDate && new Date(s.start) <= endDate); } export function minSlotIndex(slots: ForecastSlot[]): number { diff --git a/assets/js/views/Forecast.vue b/assets/js/views/Forecast.vue index 65d4f6d65..2410839d4 100644 --- a/assets/js/views/Forecast.vue +++ b/assets/js/views/Forecast.vue @@ -157,7 +157,7 @@ import store from "../store"; import { adjustedSolar, ForecastType } from "@/utils/forecast"; import type { ForecastSlot } from "../components/Forecast/types"; -const MIN_HOURS = 38; +const MIN_HOURS = 76; const MAX_HOURS = 96; const SLOTS_PER_HOUR = 4; @@ -219,7 +219,7 @@ export default defineComponent({ chartWidth(): number { const ms = this.chartEndDate.getTime() - this.startDate.getTime(); const slots = Math.ceil(ms / (15 * 60 * 1000)); - return slots * 8 + 56; + return slots * 4 + 56; }, currency() { return store.state?.currency; @@ -242,7 +242,10 @@ export default defineComponent({ : this.forecast.solar; }, solarAdjustText() { - return this.$t("forecast.solarAdjustShort"); + const text = this.$t("forecast.solarAdjustShort"); + const scale = this.forecast.solar?.scale || 1; + const percentDiff = scale * 100 - 100; + return `${text} (${this.fmtPercentage(percentDiff, 0, true)})`; }, solarSubtitle(): string { const s = this.solar;