diff --git a/package.json b/package.json index 997e1f1..2929af8 100644 --- a/package.json +++ b/package.json @@ -78,4 +78,4 @@ "import-lang": "node scripts/generate-lang-imports.js", "local-copy": "cp dist/lunar-phase-card.js /Volumes/config/www/dashboard-resources/lunar-phase-card.js" } -} \ No newline at end of file +} diff --git a/src/components/moon-horizon.ts b/src/components/moon-horizon.ts index 68ee2f1..e08cfd2 100644 --- a/src/components/moon-horizon.ts +++ b/src/components/moon-horizon.ts @@ -1,7 +1,6 @@ import { formatDateTime, HomeAssistant, formatDateTimeWithSeconds } from 'custom-card-helpers'; -import { LitElement, html, CSSResultGroup, TemplateResult, css } from 'lit'; +import { LitElement, html, CSSResultGroup, TemplateResult, css, PropertyValues } from 'lit'; import { customElement, state, property } from 'lit/decorators.js'; -import { styleMap } from 'lit/directives/style-map.js'; import type { ChartDataset } from 'chart.js/auto'; @@ -15,8 +14,8 @@ import { Plugin, ScaleChartOptions, } from 'chart.js/auto'; -import annotationPlugin from 'chartjs-plugin-annotation'; -Chart.register(annotationPlugin); +// import annotationPlugin from 'chartjs-plugin-annotation'; +// Chart.register(annotationPlugin); import { LunarPhaseCard } from '../lunar-phase-card'; // Local imports @@ -35,58 +34,71 @@ export class MoonHorizon extends LitElement { @property({ attribute: false }) moon!: Moon; @property({ attribute: false }) card!: LunarPhaseCard; - @state() _chart!: Chart; + @property({ type: Object }) private _chart: Chart | null = null; @state() moreInfo = false; @state() hoverOnChart = false; @state() hoverTimeout: number | null = null; - private _timeAnimationFrame: number | null = null; - private _lastTime: string | null = null; - @state() private cardWidth = 0; - @state() private _resizeEntry?: ResizeObserverEntry; + @state() private _timeAnimationFrame: number | null = null; + @state() private _lastTime: string | null = null; + @state() _resizeInitiated = false; + @state() _chartWidth = 0; + @state() _resizeObserver: ResizeObserver | null = null; connectedCallback(): void { super.connectedCallback(); - console.log('MoonCard connected'); - window.MoonCard = this; - window.Chart = this._chart; + if (!this._resizeInitiated && !this._resizeObserver) { + this.delayedAttachResizeObserver(); + } } disconnectedCallback(): void { - console.log('MoonCard disconnected'); this.cancelTimeAnimationFrame(); + this.detachResizeObserver(); + this._resizeInitiated = false; super.disconnectedCallback(); } - protected firstUpdated(): void { - // Create a new ResizeObserver - const ro = new ResizeObserver((entries: ResizeObserverEntry[]) => { - entries.forEach((entry) => { - // Immediately compute the rect and measure the card on resize - this.measureCard(); - this._resizeEntry = entry; - }); + delayedAttachResizeObserver(): void { + setTimeout(() => { + this.attachResizeObserver(); + this._resizeInitiated = true; + }, 0); + } + + attachResizeObserver(): void { + if (this._resizeObserver) { + return; + } + this._resizeObserver = new ResizeObserver(() => { + this.measureCard(); }); - // Observe the 'ha-card' directly if available - const card = this.parentElement; + const card = this.offsetParent as HTMLElement; if (card) { - ro.observe(card); - } else { - console.warn('ha-card element not found for observation.'); + this._resizeObserver.observe(card); } + } - this.setupChart(); + detachResizeObserver(): void { + if (this._resizeObserver) { + this._resizeObserver.disconnect(); + this._resizeObserver = null; + } } - measureCard(): void { - const card = this.parentElement; - if (!card) { - console.warn('measureCard: ha-card element not found.'); - return; + private measureCard(): void { + const card = this.offsetParent as HTMLElement; + if (card) { + this._chartWidth = card.offsetWidth; } - // Log card width for debugging - this.cardWidth = card.offsetWidth; + } + + protected async firstUpdated(changedProps: PropertyValues): Promise { + super.firstUpdated(changedProps); + + await new Promise((resolve) => setTimeout(resolve, 50)); + this.setupChart(); } static get styles(): CSSResultGroup { @@ -99,13 +111,14 @@ export class MoonHorizon extends LitElement { width: 100%; height: 100%; /* box-shadow: 0 0 6px #e1e0dd30; */ - max-width: 500px; + max-width: 900px; backdrop-filter: blur(4px); border-radius: 0; /* border: 1px solid var(--divider-color); */ box-sizing: border-box; padding: 0 2px; } + .moon-horizon canvas { width: 100%; height: 100%; @@ -164,8 +177,16 @@ export class MoonHorizon extends LitElement { return [moonMarkerPlugin, timeMarkerPlugin, fillTopPlugin]; } - private get cssColors(): ChartColors { - const cssColors = getComputedStyle(this); + private get chartData(): ChartData { + return this._getChartData(); + } + + private get chartOptions(): ChartOptions { + return this._chartOptions(); + } + + private cssColors(): ChartColors { + const cssColors = getComputedStyle(this) as CSSStyleDeclaration; return { primaryTextColor: cssColors.getPropertyValue('--lunar-card-label-font-color'), secondaryTextColor: cssColors.getPropertyValue('--secondary-text-color'), @@ -176,27 +197,32 @@ export class MoonHorizon extends LitElement { } private setupChart(): void { + if (this._chart) { + this._chart.destroy(); + } + // Data - const data = this._getChartData(); - const options = this._chartOptions(); + const data = this.chartData; + const options = this.chartOptions; // Plugins const customPlugins = this.plugins; - - // Create the chart - const ctx = this.shadowRoot?.getElementById('moonPositionChart') as HTMLCanvasElement; + const ctx = this.shadowRoot?.querySelector('canvas') as HTMLCanvasElement; if (ctx) { this._chart = new Chart(ctx, { type: 'line', data: data, options: { ...options, + resizeDelay: 1000, aspectRatio: 2, scales: { ...options.scales, x: { ...options.scales?.x, + // reverse: true, ticks: { ...options.scales?.x?.ticks, + callback: function (value, index) { return (index + 1) % 2 === 0 ? this.getLabelForValue(Number(value)) : ''; }, @@ -221,7 +247,7 @@ export class MoonHorizon extends LitElement { const xTimeNum = element.element.getProps(['raw'], true).raw.x; this.handlePointHover(xTimeNum); - this._chart?.update(); + this._chart?.update('default'); } }, onClick: (_event, elements) => { @@ -232,12 +258,13 @@ export class MoonHorizon extends LitElement { } }, onResize: (_chart, size) => { - if (this.cardWidth !== size.width) { + if (this._chartWidth !== size.width) { _chart.resize(); _chart.update('none'); } }, }, + plugins: [...customPlugins], }); // Add event listeners @@ -257,7 +284,7 @@ export class MoonHorizon extends LitElement { protected render(): TemplateResult { return html`
- +
@@ -288,7 +315,6 @@ export class MoonHorizon extends LitElement { // Only re-render if the seconds have changed if (currentTime !== this._lastTime) { this._lastTime = currentTime; - this.requestUpdate(); // Trigger a re-render } }; this._timeAnimationFrame = requestAnimationFrame(updateFrame); @@ -334,7 +360,7 @@ export class MoonHorizon extends LitElement { this.card.selectedDate = time; } - cancelTimeAnimationFrame(): void { + private cancelTimeAnimationFrame(): void { // Cancel the animation frame when the component is disconnected if (this._timeAnimationFrame) { cancelAnimationFrame(this._timeAnimationFrame); @@ -345,9 +371,10 @@ export class MoonHorizon extends LitElement { /* -------------------------------- DATASETS -------------------------------- */ private _getChartData = (): ChartData => { - const { primaryTextColor, secondaryTextColor, fillColor, fillBelowColor, fillBelowLineColor } = this.cssColors; + const { primaryTextColor, secondaryTextColor, fillColor, fillBelowColor, fillBelowLineColor } = this.cssColors(); const todayData = this.todayData; const timeLabels = todayData.timeLabels; + const altitudeData = todayData.altitude; const { set, rise } = todayData.lang; const langAltitude = this.card.localize('card.altitude'); @@ -363,11 +390,12 @@ export class MoonHorizon extends LitElement { below: fillBelowColor, }, cubicInterpolationMode: 'monotone', - tension: 0.2, + tension: 1, segment: { borderColor: (ctx: ScriptableLineSegmentContext) => - ctx.p0.parsed.y >= 0 && ctx.p1.parsed.y >= 0 ? primaryTextColor : fillBelowLineColor, - borderWidth: (ctx: ScriptableLineSegmentContext) => (ctx.p0.parsed.y <= 0 ? 1 : 1.2), + ctx.p0.parsed.y >= -0.001 && ctx.p1.parsed.y >= -0.001 ? primaryTextColor : fillBelowLineColor, + borderWidth: (ctx: ScriptableLineSegmentContext) => + ctx.p0.parsed.y >= -0.001 && ctx.p1.parsed.y >= -0.001 ? 1.2 : 1, }, radius: () => (this.hoverOnChart ? 1.1 : 0), pointHoverRadius: 3, @@ -394,7 +422,7 @@ export class MoonHorizon extends LitElement { }; private _chartOptions = (): ChartOptions => { - const { secondaryTextColor } = this.cssColors; + const { secondaryTextColor } = this.cssColors(); const { sugestedYMax, sugestedYMin } = this.todayData.minMaxY; const graphConfig = this.card.config?.graph_config; const currentMoon = this.moon._fetchtCurrentMoon(); @@ -405,13 +433,14 @@ export class MoonHorizon extends LitElement { // Scales const scales = {} as ScaleOptions; scales['y'] = { - suggestedMax: 60 + sugestedYMax, + suggestedMax: sugestedYMax + 30, suggestedMin: sugestedYMin > -60 ? -60 : sugestedYMin, ticks: { ...ticksOptions, display: graphConfig?.y_ticks || false, stepSize: graphConfig?.y_ticks_step_size || 30, }, + bounds: 'data', border: { display: false, }, @@ -439,7 +468,7 @@ export class MoonHorizon extends LitElement { const plugins: ChartOptions['plugins'] = {}; plugins['legend'] = { - display: true, + display: graphConfig?.show_legend ?? true, align: graphConfig?.legend_align || 'center', position: graphConfig?.legend_position || 'bottom', labels: { @@ -454,41 +483,26 @@ export class MoonHorizon extends LitElement { }, }; - plugins['annotation'] = { - annotations: { - line1: { - type: 'line', - borderColor: secondaryTextColor, - borderWidth: 0.4, - scaleID: 'y', - value: 0, - }, - }, - }; - plugins['tooltip'] = { - backgroundColor: 'rgba(0, 0, 0, 0.8)', + backgroundColor: (ctx) => { + const index = ctx?.tooltipItems?.[0]?.dataIndex; + return index === currentMoon.currentHourIndex ? 'black' : 'rgba(0, 0, 0, 0.8)'; + }, + titleColor: (ctx) => { + const index = ctx?.tooltipItems?.[0]?.dataIndex; + return index === currentMoon.currentHourIndex ? 'red' : secondaryTextColor; + }, + callbacks: { + title: (ctx) => (ctx[0].dataIndex === currentMoon.currentHourIndex ? currentMoon.title : ctx[0].label), + label: (ctx) => (ctx.dataIndex === currentMoon.currentHourIndex ? currentMoon.body : `${ctx.formattedValue}°`), + }, bodyFont: { size: 14, }, titleAlign: 'right', bodyAlign: 'right', displayColors: false, - callbacks: { - title: (context) => { - if (context[0].dataIndex === currentMoon.currentHourIndex) { - return `${currentMoon.title}`; - } else { - return context[0].label; - } - }, - label: (context) => { - if (context.dataIndex === currentMoon.currentHourIndex) { - return currentMoon.body; - } - return `${context.formattedValue}°`; - }, - }, + padding: 10, }; const layout: ChartOptions['layout'] = { @@ -518,21 +532,26 @@ export class MoonHorizon extends LitElement { /* --------------------------------- PLUGINS -------------------------------- */ private moonMarkerPlugin = (): Plugin => { const emoji = this.todayData.moonPhase.phase.emoji; - const currentHourIndex = this.moon._currentMoonIndex(); - + const { currentHourIndex, altitudeDegrees } = this.moon._fetchtCurrentMoon(); + const showCurrent = this.card.config?.graph_config?.show_current ?? true; + if (!showCurrent) return { id: 'moonMarkerPlugin' }; return { id: 'moonMarkerPlugin', afterDatasetsDraw(chart: Chart) { const dataSet = chart.getDatasetMeta(0); if (dataSet.hidden) return; + const { + ctx, + scales: { x, y }, + } = chart; - const ctx = chart.ctx; - const { x, y } = dataSet.data[currentHourIndex].getProps(['x', 'y']); + const xPosition = x.getPixelForValue(currentHourIndex); + const yPosition = y.getPixelForValue(altitudeDegrees) + 6; if (emoji) { // Draw the emoji ctx.save(); ctx.font = '24px serif'; - ctx.fillText(emoji, x - 12, y); + ctx.fillText(emoji, xPosition, yPosition); ctx.restore(); } }, @@ -540,13 +559,13 @@ export class MoonHorizon extends LitElement { }; private fillTopPlugin = (): Plugin => { - const { fillColor } = this.cssColors; + const { fillColor, secondaryTextColor } = this.cssColors(); return { id: 'fillTopPlugin', beforeDraw(chart: Chart) { const { ctx, - chartArea: { top, right }, + chartArea: { top, right, left }, scales: { x, y }, } = chart as Chart; const midX = x.getPixelForValue(0); @@ -559,14 +578,20 @@ export class MoonHorizon extends LitElement { ctx.fillStyle = gradient; ctx.fillRect(midX, top, right - midX, fillTop - top); ctx.restore(); + ctx.beginPath(); + ctx.fillStyle = secondaryTextColor; + ctx.strokeStyle = secondaryTextColor; + ctx.lineWidth = 0.5; + ctx.moveTo(left, fillTop); + ctx.lineTo(right, fillTop); + ctx.stroke(); }, }; }; private timeMarkerPlugin = (): Plugin => { const timeMarkers = this.todayData.timeMarkers; - const { secondaryTextColor, fillColor } = this.cssColors; - const { sugestedYMax, sugestedYMin } = this.todayData.minMaxY; + const { secondaryTextColor, fillColor } = this.cssColors(); // Pre-load SVG images as Image objects const moonUpSvg = new Image(); @@ -630,12 +655,12 @@ export class MoonHorizon extends LitElement { ctx.fillStyle = secondaryTextColor; ctx.textAlign = textAlign; - ctx.textAlign = textAlign; - + ctx.font = '12px Arial'; + ctx.filter = this.hoverOnChart ? 'opacity(0.2)' : 'opacity(1)'; // Load and draw the SVG based on `isUp` const imgToDraw = isUp ? moonUpSvg : moonDownSvg; const timeWidth = ctx.measureText(formatedTime).width; - let iconOffset; + let iconOffset: number = 0; // Determine `iconOffset` based on `textAlign` if (textAlign === 'start') { @@ -643,18 +668,17 @@ export class MoonHorizon extends LitElement { } else if (textAlign === 'end') { iconOffset = xOffset - timeWidth - 22; // Icon placed to the left of the text (accounting for the icon width) } - // Draw the icon - ctx.drawImage(imgToDraw, iconOffset, isUp ? y - lineOffset - 35 : y + lineOffset, 18, 18); // Draw the time and direction text if (isUp) { ctx.fillText(direction, xOffset, y - lineOffset - 10); - ctx.fillText(formatedTime, xOffset, y - lineOffset - 25); + ctx.fillText(formatedTime, xOffset, y - lineOffset - 27); } else { - ctx.fillText(direction, xOffset, y + lineOffset + 25); + ctx.fillText(direction, xOffset, y + lineOffset + 27); ctx.fillText(formatedTime, xOffset, y + lineOffset + 10); } - + // Draw the icon + ctx.drawImage(imgToDraw, iconOffset, isUp ? y - lineOffset - 37 : y + lineOffset - 5, 18, 18); ctx.restore(); }; @@ -665,7 +689,7 @@ export class MoonHorizon extends LitElement { if (timeDataSet.type === null || timeDataSet.hidden) return; const { ctx, - chartArea: { left, right, bottom }, + chartArea: { left, right, bottom, top }, scales: { x, y }, } = chart; // Iterate over each time marker and draw if necessary @@ -678,7 +702,7 @@ export class MoonHorizon extends LitElement { const xPosition = x.getPixelForValue(index); const yPosition = y.getPixelForValue(0); - const lineOffset = isUp ? Math.abs(sugestedYMax) + 10 : Math.round((bottom - yPosition) / 2); + const lineOffset = isUp ? Math.round((yPosition - top) / 2) : Math.round((bottom - yPosition) / 2); const maxTextWidth = getMaxValueText(ctx, isUp ? 'Rise' : 'Set', formatedTime, direction); let textAlign: CanvasTextAlign = 'start'; @@ -709,6 +733,5 @@ declare global { } interface Window { MoonCard: MoonHorizon; - Chart: Chart; } } diff --git a/src/css/style.css b/src/css/style.css index 4ea0e69..40ba213 100644 --- a/src/css/style.css +++ b/src/css/style.css @@ -149,7 +149,7 @@ h1 { display: block; width: 100%; max-width: 27%; - transition: transform 0.5s; + /* transition: transform 0.5s; */ -webkit-user-select: none; -moz-user-select: none; user-select: none; @@ -162,12 +162,17 @@ h1 { max-width: 35%; } +.moon-image img[southern] { + transform: scaleX(-1) scaleY(-1); + transition: none; +} + .moon-image>img { width: 100%; height: 100%; transform: rotate(0deg); /* Initial state */ - filter: grayscale(1) brightness(1.2) drop-shadow(2px 2px 6px rgba(0, 0, 0, 0.45)) + filter: grayscale(1) brightness(1) drop-shadow(2px 2px 6px rgba(255, 255, 255, 0.2)) } .moon-image img.rotatable { diff --git a/src/editor.ts b/src/editor.ts index 1b8d6e2..f5cbcdf 100644 --- a/src/editor.ts +++ b/src/editor.ts @@ -139,8 +139,16 @@ export class LunarPhaseCardEditor extends LitElement implements LovelaceCardEdit `; }); + const southern = html` + + `; + const contentWrapp = html` -
${radios}
+
${radios} ${southern}
${this._config?.use_default ? this._renderUseDefault() @@ -312,6 +320,8 @@ export class LunarPhaseCardEditor extends LitElement implements LovelaceCardEdit { label: 'yTicks', configValue: 'y_ticks' }, { label: 'xTicks', configValue: 'x_ticks' }, { label: 'showTime', configValue: 'show_time' }, + { label: 'showCurrent', configValue: 'show_current' }, + { label: 'showLegend', configValue: 'show_legend' }, ]; const checkBoxes = html` @@ -579,7 +589,10 @@ export class LunarPhaseCardEditor extends LitElement implements LovelaceCardEdit /* ----------------------------- HANDLER METHODS ---------------------------- */ - private _handleValueChange(ev) { + private _handleValueChange(event: any): void { + event.stopPropagation(); + const ev = event as CustomEvent; + console.log('ev', ev); if (!this._config || !this.hass) { return; } @@ -587,8 +600,8 @@ export class LunarPhaseCardEditor extends LitElement implements LovelaceCardEdit const target = ev.target as any; const configValue = target?.configValue; const configKey = target?.configKey; - // Safely access the value, add a fallback to an empty string if undefined - const value = target?.checked !== undefined ? target.checked : ev.detail.value; + + let value: any = target.checked !== undefined ? target.checked : ev.detail.value; console.log('configKey', configKey, 'configValue', configValue, 'value', value); const updates: Partial = {}; @@ -607,7 +620,6 @@ export class LunarPhaseCardEditor extends LitElement implements LovelaceCardEdit // Check if the configValue is a key of FontCustomStyles if (configKey === 'font_customize') { const key = configValue as keyof FontCustomStyles; - // If the current value is undefined, use the default value const updatedValue = value !== undefined ? value : defaultFontCustomStyles[key]; diff --git a/src/languages/ca.json b/src/languages/ca.json index 5c5755b..fc8e296 100644 --- a/src/languages/ca.json +++ b/src/languages/ca.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Marcadors de temps de sortida/posta", + "showCurrent": "Posició actual de la Lluna", + "showLegend": "Mostra la llegenda", "placeHolder": { "latitude": "Entra la latitud", "longitude": "Entra la longitud", diff --git a/src/languages/cs.json b/src/languages/cs.json index b81705e..b00e158 100644 --- a/src/languages/cs.json +++ b/src/languages/cs.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Značky času východu/západu", + "showCurrent": "Aktuální poloha Měsíce", + "showLegend": "Zobrazit legendu", "placeHolder": { "latitude": "Zadejte zeměpisnou šířku", "longitude": "Zadejte zeměpisnou délku", diff --git a/src/languages/da.json b/src/languages/da.json index e02fc99..0d020f6 100644 --- a/src/languages/da.json +++ b/src/languages/da.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Markører for opgang/nedgang", + "showCurrent": "Nuværende måneposition", + "showLegend": "Vis legend", "placeHolder": { "latitude": "Indtast breddegrad", "longitude": "Indtast længdegrad", diff --git a/src/languages/de.json b/src/languages/de.json index de46db8..d4ee504 100644 --- a/src/languages/de.json +++ b/src/languages/de.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Markierungen für Auf-/Untergangszeiten", + "showCurrent": "Aktuelle Mondposition", + "showLegend": "Legende anzeigen", "placeHolder": { "latitude": "Breitengrad eingeben", "longitude": "Längengrad eingeben", diff --git a/src/languages/en.json b/src/languages/en.json index e8d125e..de9d5ef 100644 --- a/src/languages/en.json +++ b/src/languages/en.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Set/Rise time markers", + "showCurrent": "Current Moon position", + "showLegend": "Display legend", "placeHolder": { "latitude": "Enter latitude", "longitude": "Enter longitude", diff --git a/src/languages/es.json b/src/languages/es.json index 8dd6489..b002d7c 100644 --- a/src/languages/es.json +++ b/src/languages/es.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Marcadores de tiempo de salida/puesta", + "showCurrent": "Posición actual de la Luna", + "showLegend": "Mostrar leyenda", "placeHolder": { "latitude": "Ingresar latitud", "longitude": "Ingresar longitud", diff --git a/src/languages/fr.json b/src/languages/fr.json index cb63d97..f5ece12 100644 --- a/src/languages/fr.json +++ b/src/languages/fr.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Marqueurs de temps de lever/coucher", + "showCurrent": "Position actuelle de la Lune", + "showLegend": "Afficher la légende", "placeHolder": { "latitude": "Entrer latitude", "longitude": "Entrer longitude", diff --git a/src/languages/id.json b/src/languages/id.json index 0f85f44..082bc83 100644 --- a/src/languages/id.json +++ b/src/languages/id.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Penanda waktu terbit/terbenam", + "showCurrent": "Posisi Bulan Saat Ini", + "showLegend": "Tampilkan legenda", "placeHolder": { "latitude": "Masukkan garis lintang", "longitude": "Masukkan garis bujur", diff --git a/src/languages/it.json b/src/languages/it.json index 85f1eac..4290f24 100644 --- a/src/languages/it.json +++ b/src/languages/it.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Indicatori di tempo di alba/tramonto", + "showCurrent": "Posizione attuale della Luna", + "showLegend": "Mostra leggenda", "placeHolder": { "latitude": "Inserisci Latitudine", "longitude": "Inserisci Longitudine", diff --git a/src/languages/nl.json b/src/languages/nl.json index a551497..c2f37b3 100644 --- a/src/languages/nl.json +++ b/src/languages/nl.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Tijdmarkeringen van opkomst/ondergang", + "showCurrent": "Huidige positie van de Maan", + "showLegend": "Toon legenda", "placeHolder": { "latitude": "Enter breedtegraad", "longitude": "Enter lengtegraad", diff --git a/src/languages/pt.json b/src/languages/pt.json index ef86f02..566787d 100644 --- a/src/languages/pt.json +++ b/src/languages/pt.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Marcadores de tempo de nascer/pôr do sol", + "showCurrent": "Posição atual da Lua", + "showLegend": "Mostrar legenda", "placeHolder": { "latitude": "Inserir latitude", "longitude": "Inserir longitude", diff --git a/src/languages/ru.json b/src/languages/ru.json index 1dd5f82..9cbeac6 100644 --- a/src/languages/ru.json +++ b/src/languages/ru.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Маркеры времени восхода/заката", + "showCurrent": "Текущее положение Луны", + "showLegend": "Показать легенду", "placeHolder": { "latitude": "Введите широту", "longitude": "Введите долготу", diff --git a/src/languages/sk.json b/src/languages/sk.json index d3f6dee..7b177f6 100644 --- a/src/languages/sk.json +++ b/src/languages/sk.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Značky času východu/západu", + "showCurrent": "Aktuálna poloha Mesiaca", + "showLegend": "Zobraziť legendu", "placeHolder": { "latitude": "Zadajte zemepisnú šírku", "longitude": "Zadajte zemepisnú dĺžku", diff --git a/src/localize/string.json b/src/localize/string.json index e8d125e..de9d5ef 100644 --- a/src/localize/string.json +++ b/src/localize/string.json @@ -101,6 +101,8 @@ "yTicks": "Y-axis ticks", "xTicks": "X-axis ticks", "showTime": "Set/Rise time markers", + "showCurrent": "Current Moon position", + "showLegend": "Display legend", "placeHolder": { "latitude": "Enter latitude", "longitude": "Enter longitude", diff --git a/src/lunar-phase-card.ts b/src/lunar-phase-card.ts index 012a9cc..5f4bb30 100644 --- a/src/lunar-phase-card.ts +++ b/src/lunar-phase-card.ts @@ -2,6 +2,7 @@ import { LovelaceCardEditor, formatDate, FrontendLocaleData, TimeFormat } from ' import { LitElement, html, TemplateResult, PropertyValues, CSSResultGroup, nothing } from 'lit'; import { customElement, property, query, state } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; + // Local types import { HomeAssistantExtended as HomeAssistant, LunarPhaseCardConfig, defaultConfig } from './types'; @@ -46,7 +47,6 @@ export class LunarPhaseCard extends LitElement { @state() _calendarPopup: boolean = false; @state() _state: MoonState = MoonState.READY; - @query('lunar-base-data') _data!: LunarBaseData; @query('moon-horizon') _moonHorizon!: MoonHorizon; @@ -85,7 +85,7 @@ export class LunarPhaseCard extends LitElement { window.Moon = this.moon; } this.startRefreshInterval(); - document.addEventListener('lunar-card-event', (ev) => this._handleEditorEvent(ev)); + document.addEventListener('lunar-card-event', (ev) => this._handleEditorEvent(ev as CustomEvent)); } disconnectedCallback(): void { @@ -93,7 +93,7 @@ export class LunarPhaseCard extends LitElement { super.disconnectedCallback(); } - private _handleEditorEvent(ev: any): void { + private _handleEditorEvent(ev: CustomEvent) { ev.stopPropagation(); if (!this.isEditorPreview) return; console.log('editor event', ev.detail); @@ -108,8 +108,6 @@ export class LunarPhaseCard extends LitElement { protected firstUpdated(_changedProperties: PropertyValues): void { super.firstUpdated(_changedProperties); - - // Initial style computation and first render handling this._computeStyles(); this._handleFirstRender(); } @@ -187,6 +185,7 @@ export class LunarPhaseCard extends LitElement { } else { this._activeCard = this._defaultCard; } + this.requestUpdate(); } private startRefreshInterval() { @@ -297,9 +296,10 @@ export class LunarPhaseCard extends LitElement { private renderMoonImage(): TemplateResult | void { if (!this.moon) return; const { moonPic } = this.moon.moonImage; - const animate = !this.isEditorPreview ? 'moon-image animate' : 'moon-image'; - return html`
- + const animateClass = !this.isEditorPreview ? 'moon-image animate' : 'moon-image'; + const southernHemisphere = this.config.southern_hemisphere || false; + return html`
+
`; } diff --git a/src/types.ts b/src/types.ts index a1daf63..2044594 100644 --- a/src/types.ts +++ b/src/types.ts @@ -51,6 +51,8 @@ export interface HorizonGraphConfig { y_ticks?: boolean; x_ticks?: boolean; show_time?: boolean; + show_current?: boolean; + show_legend?: boolean; y_ticks_position?: 'left' | 'right'; y_ticks_step_size?: number; legend_position?: 'top' | 'bottom'; @@ -71,6 +73,7 @@ export interface LunarPhaseCardConfig extends LovelaceCardConfig { default_card?: PageType.BASE | PageType.CALENDAR | PageType.HORIZON; selected_language: string; moon_position?: 'left' | 'right'; + southern_hemisphere?: boolean; latitude: number; longitude: number; font_customize: FontCustomStyles; @@ -90,11 +93,13 @@ export const defaultConfig: Partial = { mile_unit: false, default_card: PageType.BASE, moon_position: 'left', + southern_hemisphere: false, number_decimals: 2, graph_config: { y_ticks: false, x_ticks: true, show_time: true, + show_current: true, y_ticks_position: 'left', y_ticks_step_size: 30, legend_position: 'top', diff --git a/src/utils/moon.ts b/src/utils/moon.ts index ede0715..d079adf 100644 --- a/src/utils/moon.ts +++ b/src/utils/moon.ts @@ -172,6 +172,8 @@ export class Moon { altitude: this._getDataAltitude(startTime), timeLabels: Object.keys(_altitudeData), altitudeData: Object.values(_altitudeData), + reverseLabels: Object.keys(_altitudeData).reverse(), + reverseAltitudeData: Object.values(_altitudeData).reverse(), minMaxY: { sugestedYMax: Math.round(Math.max(...Object.values(_altitudeData)) + 10), sugestedYMin: Math.round(Math.min(...Object.values(_altitudeData)) - 10), @@ -266,7 +268,7 @@ export class Moon { contentBody.push(altitude); contentBody.push(direction); - return { currentHourIndex: index, body: contentBody, title: formatedTime }; + return { currentHourIndex: index, body: contentBody, title: formatedTime, altitudeDegrees }; }; convertCardinal = (degrees: number): string => {