Compare commits
10 Commits
f70d02d11d
...
a58058b96c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a58058b96c | ||
|
|
1753af0bfc | ||
|
|
d1c61cb803 | ||
|
|
f06a6c6212 | ||
|
|
709d82bc8b | ||
|
|
446870a94c | ||
|
|
2a8b1157ab | ||
|
|
64614d49e7 | ||
|
|
a7d51b9e17 | ||
|
|
796a568ab3 |
50
index.html
50
index.html
@@ -9,10 +9,10 @@
|
|||||||
<body>
|
<body>
|
||||||
<div id="lottie-bg"></div>
|
<div id="lottie-bg"></div>
|
||||||
<header>
|
<header>
|
||||||
<div style="display:flex;align-items:center;gap:0.6rem;margin-bottom:1.25rem">
|
<a href="" style="display:flex;align-items:center;gap:0.6rem;margin-bottom:1.25rem;text-decoration:none;color:inherit;cursor:pointer">
|
||||||
<div id="lottie-logo" style="width:80px;height:80px;flex-shrink:0"></div>
|
<div id="lottie-logo" style="width:80px;height:80px;flex-shrink:0"></div>
|
||||||
<h1 style="margin-bottom:0">Pigmento</h1>
|
<h1 style="margin-bottom:0">Pigmento</h1>
|
||||||
</div>
|
</a>
|
||||||
<nav id="main-nav">
|
<nav id="main-nav">
|
||||||
<button id="menu-toggle" aria-label="Navigation öffnen">
|
<button id="menu-toggle" aria-label="Navigation öffnen">
|
||||||
<span></span><span></span><span></span>
|
<span></span><span></span><span></span>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<main>
|
<main>
|
||||||
<section id="tab-picker" class="tab-content active">
|
<section id="tab-picker" class="tab-content active">
|
||||||
<h2>Farbe aus Bild</h2>
|
<h2>Welche Farbe ist das? Bild hochladen und draufklicken.</h2>
|
||||||
<div id="picker-dropzone">
|
<div id="picker-dropzone">
|
||||||
<p>Bild hierher ziehen, einfügen (Strg+V) oder</p>
|
<p>Bild hierher ziehen, einfügen (Strg+V) oder</p>
|
||||||
<button class="action-btn" id="picker-file-trigger">Datei wählen</button>
|
<button class="action-btn" id="picker-file-trigger">Datei wählen</button>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="tab-eingabe" class="tab-content">
|
<section id="tab-eingabe" class="tab-content">
|
||||||
<h2>Farbe eingeben</h2>
|
<h2>Farbcode eingeben und alle Formate auf einmal sehen.</h2>
|
||||||
<div id="eingabe-preview" class="color-preview" style="background:#3a8fc1"></div>
|
<div id="eingabe-preview" class="color-preview" style="background:#3a8fc1"></div>
|
||||||
<div class="color-codes">
|
<div class="color-codes">
|
||||||
<div class="color-code-group">
|
<div class="color-code-group">
|
||||||
@@ -81,13 +81,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="tab-harmonien" class="tab-content">
|
<section id="tab-harmonien" class="tab-content">
|
||||||
<h2>Farbharmonien</h2>
|
<h2>Welche Farben passen dazu? Harmonien auf einen Blick.</h2>
|
||||||
<p class="subtitle">Ausgangsfarbe: <span id="harmonien-base-hex">#3a8fc1</span></p>
|
<p class="subtitle">Ausgangsfarbe: <span id="harmonien-base-hex">#3a8fc1</span></p>
|
||||||
<div id="harmonien-base-preview" class="color-preview" style="height:50px"></div>
|
<div id="harmonien-base-preview" class="color-preview" style="height:50px"></div>
|
||||||
<div id="harmonien-grid" style="display:flex;flex-direction:column;gap:1.5rem;margin-top:1rem"></div>
|
<div id="harmonien-grid" style="display:flex;flex-direction:column;gap:1.5rem;margin-top:1rem"></div>
|
||||||
</section>
|
</section>
|
||||||
<section id="tab-sammlung" class="tab-content">
|
<section id="tab-sammlung" class="tab-content">
|
||||||
<h2>Sammlung</h2>
|
<h2>Deine gespeicherten Farben, Verläufe und Schemata.</h2>
|
||||||
|
|
||||||
<div class="btn-row" style="margin-bottom:1.5rem">
|
<div class="btn-row" style="margin-bottom:1.5rem">
|
||||||
<button class="action-btn" id="sammlung-export-btn">Exportieren</button>
|
<button class="action-btn" id="sammlung-export-btn">Exportieren</button>
|
||||||
@@ -178,13 +178,7 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/lottie-web/5.12.2/lottie.min.js"></script>
|
||||||
<script type="module" src="js/app.js"></script>
|
<script type="module" src="js/app.js"></script>
|
||||||
<script>
|
<script>
|
||||||
lottie.loadAnimation({
|
// Hintergrund-Animation
|
||||||
container: document.getElementById('lottie-logo'),
|
|
||||||
renderer: 'svg',
|
|
||||||
loop: true,
|
|
||||||
autoplay: true,
|
|
||||||
path: 'Fluid Loading Animation.json'
|
|
||||||
});
|
|
||||||
lottie.loadAnimation({
|
lottie.loadAnimation({
|
||||||
container: document.getElementById('lottie-bg'),
|
container: document.getElementById('lottie-bg'),
|
||||||
renderer: 'svg',
|
renderer: 'svg',
|
||||||
@@ -192,6 +186,36 @@
|
|||||||
autoplay: true,
|
autoplay: true,
|
||||||
path: 'Background Grey Wave.json'
|
path: 'Background Grey Wave.json'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Logo-Animation
|
||||||
|
lottie.loadAnimation({
|
||||||
|
container: document.getElementById('lottie-logo'),
|
||||||
|
renderer: 'svg',
|
||||||
|
loop: true,
|
||||||
|
autoplay: true,
|
||||||
|
path: 'Fluid Loading Animation.json'
|
||||||
|
});
|
||||||
|
|
||||||
|
function _hslToHex(h, s, l) {
|
||||||
|
s /= 100; l /= 100;
|
||||||
|
const a = s * Math.min(l, 1 - l);
|
||||||
|
const f = n => {
|
||||||
|
const k = (n + h / 30) % 12;
|
||||||
|
return Math.round(255 * (l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1)))
|
||||||
|
.toString(16).padStart(2, '0');
|
||||||
|
};
|
||||||
|
return '#' + f(0) + f(8) + f(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('colorChanged', (e) => {
|
||||||
|
const { h, s, l } = e.detail;
|
||||||
|
// grayscale → sepia (Basis ~38°) → Zielfarbe drehen → Sättigung + Helligkeit
|
||||||
|
const rot = h - 38;
|
||||||
|
const sat = s < 5 ? 0 : 3;
|
||||||
|
const bri = Math.max(0.5, l / 50);
|
||||||
|
document.getElementById('lottie-logo').style.filter =
|
||||||
|
`grayscale(1) sepia(1) hue-rotate(${rot}deg) saturate(${sat}) brightness(${bri})`;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
22
js/app.js
22
js/app.js
@@ -1,7 +1,7 @@
|
|||||||
import { initEingabe } from './eingabe.js';
|
import { initEingabe } from './eingabe.js';
|
||||||
import { initPicker } from './picker.js';
|
import { initPicker } from './picker.js';
|
||||||
import { initHarmonien } from './harmonien.js';
|
import { initHarmonien } from './harmonien.js';
|
||||||
import { addFavorit, addColorToSchema, addToHistory, renderSammlung, exportCollection, importCollection, saveSchema, setEditSchemaHandler } from './collection.js';
|
import { addFavorit, addColorToSchema, addToHistory, renderSammlung, exportCollection, importCollection, saveSchema, setEditSchemaHandler, setSwatchClickHandler } from './collection.js';
|
||||||
import { initSchemaModal, openForEdit } from './schema-modal.js';
|
import { initSchemaModal, openForEdit } from './schema-modal.js';
|
||||||
|
|
||||||
// state.color is read-only from outside — always use setColor() to update,
|
// state.color is read-only from outside — always use setColor() to update,
|
||||||
@@ -15,6 +15,16 @@ export const state = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function switchTab(name) {
|
||||||
|
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||||||
|
document.querySelectorAll('.tab-content').forEach(s => s.classList.remove('active'));
|
||||||
|
const btn = document.querySelector(`.tab-btn[data-tab="${name}"]`);
|
||||||
|
if (btn) { btn.classList.add('active'); document.getElementById('menu-active-label').textContent = btn.textContent; }
|
||||||
|
const section = document.getElementById('tab-' + name);
|
||||||
|
if (section) section.classList.add('active');
|
||||||
|
document.getElementById('menu-dropdown').classList.remove('open');
|
||||||
|
}
|
||||||
|
|
||||||
// Hamburger-Menü
|
// Hamburger-Menü
|
||||||
const menuToggle = document.getElementById('menu-toggle');
|
const menuToggle = document.getElementById('menu-toggle');
|
||||||
const menuDropdown = document.getElementById('menu-dropdown');
|
const menuDropdown = document.getElementById('menu-dropdown');
|
||||||
@@ -44,9 +54,16 @@ document.querySelectorAll('.tab-btn').forEach(btn => {
|
|||||||
// Every color change goes into history
|
// Every color change goes into history
|
||||||
document.addEventListener('colorChanged', (e) => addToHistory(e.detail));
|
document.addEventListener('colorChanged', (e) => addToHistory(e.detail));
|
||||||
|
|
||||||
|
// Hintergrundfarbe als extrem helles Pastell + Logo-Animation synchron einfärben
|
||||||
|
document.addEventListener('colorChanged', (e) => {
|
||||||
|
const { h, s } = e.detail;
|
||||||
|
const pastelS = Math.round(Math.min(s * 0.5, 45));
|
||||||
|
document.body.style.background = `hsl(${h}, ${pastelS}%, 92%)`;
|
||||||
|
});
|
||||||
|
|
||||||
initEingabe(addFavorit, addColorToSchema);
|
initEingabe(addFavorit, addColorToSchema);
|
||||||
initPicker(addFavorit, addColorToSchema);
|
initPicker(addFavorit, addColorToSchema);
|
||||||
initHarmonien(addFavorit, addColorToSchema);
|
initHarmonien(addFavorit, addColorToSchema, (hsl) => state.setColor(hsl));
|
||||||
|
|
||||||
document.getElementById('sammlung-export-btn').addEventListener('click', exportCollection);
|
document.getElementById('sammlung-export-btn').addEventListener('click', exportCollection);
|
||||||
document.getElementById('sammlung-import-btn').addEventListener('click', importCollection);
|
document.getElementById('sammlung-import-btn').addEventListener('click', importCollection);
|
||||||
@@ -54,3 +71,4 @@ document.getElementById('sammlung-import-btn').addEventListener('click', importC
|
|||||||
renderSammlung();
|
renderSammlung();
|
||||||
initSchemaModal(saveSchema);
|
initSchemaModal(saveSchema);
|
||||||
setEditSchemaHandler(openForEdit);
|
setEditSchemaHandler(openForEdit);
|
||||||
|
setSwatchClickHandler((hsl) => { state.setColor(hsl); switchTab('harmonien'); });
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ const STORAGE_KEY = 'pigmento';
|
|||||||
|
|
||||||
let editSchemaHandler = null;
|
let editSchemaHandler = null;
|
||||||
export function setEditSchemaHandler(fn) { editSchemaHandler = fn; }
|
export function setEditSchemaHandler(fn) { editSchemaHandler = fn; }
|
||||||
|
|
||||||
|
let swatchClickHandler = null;
|
||||||
|
export function setSwatchClickHandler(fn) { swatchClickHandler = fn; }
|
||||||
const HISTORY_MAX = 20;
|
const HISTORY_MAX = 20;
|
||||||
|
|
||||||
function load() {
|
function load() {
|
||||||
@@ -325,6 +328,11 @@ function makeSwatch(hsl) {
|
|||||||
swatch.style.background = hex;
|
swatch.style.background = hex;
|
||||||
swatch.title = hex;
|
swatch.title = hex;
|
||||||
|
|
||||||
|
if (swatchClickHandler) {
|
||||||
|
swatch.style.cursor = 'pointer';
|
||||||
|
swatch.addEventListener('click', () => swatchClickHandler(hsl));
|
||||||
|
}
|
||||||
|
|
||||||
const label = document.createElement('span');
|
const label = document.createElement('span');
|
||||||
label.style.cssText = 'font-size:0.75rem;font-family:Poppins,sans-serif';
|
label.style.cssText = 'font-size:0.75rem;font-family:Poppins,sans-serif';
|
||||||
label.textContent = hex;
|
label.textContent = hex;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const DESCRIPTIONS = {
|
|||||||
'Split-Komplementär': 'Die zwei Farben neben der Komplementärfarbe (150°/210°). Weniger Spannung als Komplementär, mehr Vielfalt.',
|
'Split-Komplementär': 'Die zwei Farben neben der Komplementärfarbe (150°/210°). Weniger Spannung als Komplementär, mehr Vielfalt.',
|
||||||
};
|
};
|
||||||
|
|
||||||
function renderHarmony(label, colors, onSaveFavorit, onSaveSchema) {
|
function renderHarmony(label, colors, onSaveFavorit, onSaveSchema, onSetColor) {
|
||||||
const row = document.createElement('div');
|
const row = document.createElement('div');
|
||||||
row.className = 'harmony-row';
|
row.className = 'harmony-row';
|
||||||
|
|
||||||
@@ -48,6 +48,10 @@ function renderHarmony(label, colors, onSaveFavorit, onSaveSchema) {
|
|||||||
swatch.className = 'swatch';
|
swatch.className = 'swatch';
|
||||||
swatch.style.background = hex;
|
swatch.style.background = hex;
|
||||||
swatch.title = hex;
|
swatch.title = hex;
|
||||||
|
if (onSetColor) {
|
||||||
|
swatch.style.cursor = 'pointer';
|
||||||
|
swatch.addEventListener('click', () => onSetColor(hsl));
|
||||||
|
}
|
||||||
|
|
||||||
const hexLabel = document.createElement('span');
|
const hexLabel = document.createElement('span');
|
||||||
hexLabel.textContent = hex;
|
hexLabel.textContent = hex;
|
||||||
@@ -80,7 +84,7 @@ function renderHarmony(label, colors, onSaveFavorit, onSaveSchema) {
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
function render(onSaveFavorit, onSaveSchema) {
|
function render(onSaveFavorit, onSaveSchema, onSetColor) {
|
||||||
const hsl = state.color;
|
const hsl = state.color;
|
||||||
const hex = hslToHex(hsl);
|
const hex = hslToHex(hsl);
|
||||||
|
|
||||||
@@ -91,13 +95,13 @@ function render(onSaveFavorit, onSaveSchema) {
|
|||||||
grid.textContent = '';
|
grid.textContent = '';
|
||||||
|
|
||||||
const h = getHarmonies(hsl);
|
const h = getHarmonies(hsl);
|
||||||
grid.appendChild(renderHarmony('Komplementär', h.komplementaer, onSaveFavorit, onSaveSchema));
|
grid.appendChild(renderHarmony('Komplementär', h.komplementaer, onSaveFavorit, onSaveSchema, onSetColor));
|
||||||
grid.appendChild(renderHarmony('Analog', h.analog, onSaveFavorit, onSaveSchema));
|
grid.appendChild(renderHarmony('Analog', h.analog, onSaveFavorit, onSaveSchema, onSetColor));
|
||||||
grid.appendChild(renderHarmony('Triade', h.triade, onSaveFavorit, onSaveSchema));
|
grid.appendChild(renderHarmony('Triade', h.triade, onSaveFavorit, onSaveSchema, onSetColor));
|
||||||
grid.appendChild(renderHarmony('Split-Komplementär', h.splitKomplementaer, onSaveFavorit, onSaveSchema));
|
grid.appendChild(renderHarmony('Split-Komplementär', h.splitKomplementaer, onSaveFavorit, onSaveSchema, onSetColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initHarmonien(onSaveFavorit, onSaveSchema) {
|
export function initHarmonien(onSaveFavorit, onSaveSchema, onSetColor) {
|
||||||
document.addEventListener('colorChanged', () => render(onSaveFavorit, onSaveSchema));
|
document.addEventListener('colorChanged', () => render(onSaveFavorit, onSaveSchema, onSetColor));
|
||||||
render(onSaveFavorit, onSaveSchema);
|
render(onSaveFavorit, onSaveSchema, onSetColor);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user