From 026e0c0e75d5922cf3cc27ce2b896c12112b7739 Mon Sep 17 00:00:00 2001 From: Ferdinand Date: Wed, 1 Apr 2026 16:28:41 +0200 Subject: [PATCH] feat: Harmonien-Tab mit Komplementar, Analog, Triade, Split-Komplementar --- index.html | 7 +++-- js/app.js | 2 ++ js/harmonien.js | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ style.css | 14 +++++++++ 4 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 js/harmonien.js diff --git a/index.html b/index.html index b3825cb..579a34d 100644 --- a/index.html +++ b/index.html @@ -71,8 +71,11 @@
-

Harmonien kommen hier

-
+

Farbharmonien

+

Ausgangsfarbe: #3a8fc1

+
+
+

Sammlung kommt hier

diff --git a/js/app.js b/js/app.js index b3c40ed..db257ae 100644 --- a/js/app.js +++ b/js/app.js @@ -1,5 +1,6 @@ import { initEingabe } from './eingabe.js'; import { initPicker } from './picker.js'; +import { initHarmonien } from './harmonien.js'; // Globaler State — aktive Farbe als { h, s, l } (HSL, 0-360, 0-100, 0-100) // state.color is read-only from outside — always use setColor() to update, @@ -30,3 +31,4 @@ function addColorToSchema(hsl) { console.log('addColorToSchema', hsl); } initEingabe(addFavorit, addColorToSchema); initPicker(addFavorit, addColorToSchema); +initHarmonien(addFavorit, addColorToSchema); diff --git a/js/harmonien.js b/js/harmonien.js new file mode 100644 index 0000000..0839dbb --- /dev/null +++ b/js/harmonien.js @@ -0,0 +1,77 @@ +import { getHarmonies, hslToHex } from './converter.js'; +import { state } from './app.js'; + +function renderHarmony(label, colors, onSaveFavorit, onSaveSchema) { + const row = document.createElement('div'); + row.className = 'harmony-row'; + + const heading = document.createElement('h3'); + heading.textContent = label; + row.appendChild(heading); + + const swatchesDiv = document.createElement('div'); + swatchesDiv.className = 'harmony-swatches'; + + colors.forEach(hsl => { + const hex = hslToHex(hsl); + + const div = document.createElement('div'); + div.className = 'harmony-swatch'; + + const swatch = document.createElement('div'); + swatch.className = 'swatch'; + swatch.style.background = hex; + swatch.title = hex; + + const hexLabel = document.createElement('span'); + hexLabel.textContent = hex; + + const btnRow = document.createElement('div'); + btnRow.style.cssText = 'display:flex;gap:0.25rem'; + + const favBtn = document.createElement('button'); + favBtn.className = 'action-btn'; + favBtn.textContent = 'Fav'; + favBtn.style.fontSize = '0.7rem'; + favBtn.addEventListener('click', () => onSaveFavorit(hsl)); + + const schemaBtn = document.createElement('button'); + schemaBtn.className = 'action-btn'; + schemaBtn.textContent = '+Schema'; + schemaBtn.style.fontSize = '0.7rem'; + schemaBtn.addEventListener('click', () => onSaveSchema(hsl)); + + btnRow.appendChild(favBtn); + btnRow.appendChild(schemaBtn); + + div.appendChild(swatch); + div.appendChild(hexLabel); + div.appendChild(btnRow); + swatchesDiv.appendChild(div); + }); + + row.appendChild(swatchesDiv); + return row; +} + +function render(onSaveFavorit, onSaveSchema) { + const hsl = state.color; + const hex = hslToHex(hsl); + + document.getElementById('harmonien-base-hex').textContent = hex; + document.getElementById('harmonien-base-preview').style.background = hex; + + const grid = document.getElementById('harmonien-grid'); + grid.textContent = ''; + + const h = getHarmonies(hsl); + grid.appendChild(renderHarmony('Komplementar', h.komplementaer, onSaveFavorit, onSaveSchema)); + grid.appendChild(renderHarmony('Analog', h.analog, onSaveFavorit, onSaveSchema)); + grid.appendChild(renderHarmony('Triade', h.triade, onSaveFavorit, onSaveSchema)); + grid.appendChild(renderHarmony('Split-Komplementar', h.splitKomplementaer, onSaveFavorit, onSaveSchema)); +} + +export function initHarmonien(onSaveFavorit, onSaveSchema) { + document.addEventListener('colorChanged', () => render(onSaveFavorit, onSaveSchema)); + render(onSaveFavorit, onSaveSchema); +} diff --git a/style.css b/style.css index 7e8a4d6..0805036 100644 --- a/style.css +++ b/style.css @@ -103,3 +103,17 @@ button.action-btn:hover { background: #f0f0f0; } } #picker-dropzone p { margin-bottom: 0.75rem; color: #666; font-size: 0.9rem; } + +/* --- Harmonien-Tab --- */ +.subtitle { font-size: 0.85rem; color: #666; margin-bottom: 0.5rem; } + +.harmony-row h3 { font-size: 0.9rem; margin-bottom: 0.5rem; } +.harmony-swatches { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: flex-start; } +.harmony-swatch { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.25rem; +} +.harmony-swatch .swatch { width: 56px; height: 56px; } +.harmony-swatch span { font-size: 0.75rem; font-family: monospace; }