Update color palette and styles across components for improved visual consistency

- Changed theme color in index.html to a brighter orange for better aesthetics.
- Introduced a modern color palette in styles.scss for enhanced readability and consistency.
- Updated various components (AppFooter, AppNavigation, DialogWidget, etc.) to utilize new color variables, ensuring a cohesive look throughout the application.
- Adjusted button styles and hover effects for improved user interaction feedback.
- Enhanced background colors and text colors for better contrast and visibility.
This commit is contained in:
Torsten Schulz (local)
2026-01-22 12:22:05 +01:00
parent 41106ae306
commit 78d43e6859
17 changed files with 172 additions and 112 deletions

View File

@@ -21,7 +21,7 @@
<meta name="twitter:title" content="YourPart Community, Chat, Forum, Vokabeltrainer, Falukant & Minispiele" />
<meta name="twitter:description" content="Community, Chat, Forum, soziales Netzwerk, Vokabeltrainer zum Sprachen lernen, das Aufbauspiel Falukant sowie Minispiele jetzt in der Beta testen." />
<meta name="theme-color" content="#F9A22C" />
<meta name="theme-color" content="#FF8C5A" />
<script type="application/ld+json">
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

View File

@@ -1,3 +1,16 @@
:root {
/* Moderne Farbpalette für bessere Lesbarkeit */
--color-primary-orange: #FF8C5A; /* Helleres, freundliches Orange */
--color-primary-orange-hover: #FFA366; /* Noch helleres Orange für Hover */
--color-primary-orange-light: #FFF4F0; /* Sehr helles Orange für Hover-Hintergründe */
--color-primary-green: #4ADE80; /* Helles, freundliches Grün - passt zum Orange */
--color-primary-green-hover: #6EE7B7; /* Noch helleres Grün für Hover */
--color-text-primary: #1F2937; /* Dunkles Grau für Haupttext (bessere Lesbarkeit) */
--color-text-secondary: #5D4037; /* Dunkles Braun für sekundären Text/Hover */
--color-text-on-orange: #000000; /* Schwarz auf Orange */
--color-text-on-green: #000000; /* Schwarz auf Grün */
}
html,
body {
height: 100%;
@@ -8,7 +21,7 @@ body {
margin: 0;
padding: 0;
background-color: #f4f4f4;
color: #333;
color: var(--color-text-primary);
}
a {
@@ -20,18 +33,18 @@ button {
margin-left: 10px;
padding: 5px 12px;
cursor: pointer;
background: #F9A22C;
color: #000000;
border: 1px solid #F9A22C;
background: var(--color-primary-orange);
color: var(--color-text-on-orange);
border: 1px solid var(--color-primary-orange);
border-radius: 4px;
transition: background 0.05s;
border: 1px solid transparent;
}
button:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: var(--color-primary-orange-light);
color: var(--color-text-secondary);
border: 1px solid var(--color-text-secondary);
}
.rc-system {
@@ -49,7 +62,7 @@ button:hover {
}
.link {
color: #F9A22C;
color: var(--color-primary-orange);
cursor: pointer;
}
@@ -67,17 +80,17 @@ h3 {
.multiselect__option--highlight[data-selected],
.multiselect__option--highlight[data-deselect] {
background: none;
background-color: #F9A22C;
color: #000;
background-color: var(--color-primary-orange);
color: var(--color-text-on-orange);
}
span.button {
padding: 2px 2px;
margin-left: 4px;
cursor: pointer;
background: #F9A22C;
color: #000000;
border: 1px solid #F9A22C;
background: var(--color-primary-orange);
color: var(--color-text-on-orange);
border: 1px solid var(--color-primary-orange);
border-radius: 4px;
transition: background 0.05s;
border: 1px solid transparent;
@@ -89,9 +102,9 @@ span.button {
}
span.button:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: var(--color-primary-orange-light);
color: var(--color-text-secondary);
border: 1px solid var(--color-text-secondary);
}
.font-color-gender-male {

View File

@@ -65,10 +65,10 @@ export default {
<style scoped>
footer {
display: flex;
background-color: #7BBE55;
background-color: var(--color-primary-green);
height: 38px;
width: 100%;
color: #7E471B;
color: #1F2937; /* Dunkles Grau für besseren Kontrast auf hellem Grün */
}
.logo,

View File

@@ -295,7 +295,7 @@ nav,
nav > ul {
display: flex;
justify-content: space-between;
background-color: #f9a22c;
background-color: #FF6B35;
color: #000;
padding: 0;
margin: 0;
@@ -317,7 +317,7 @@ nav > ul > li {
}
nav > ul > li:hover {
background-color: #d37c06;
background-color: #FF8C5A;
white-space: nowrap;
}
@@ -345,7 +345,7 @@ a {
.menuitem {
cursor: pointer;
color: #7e471b;
color: #5D4037;
}
.mailbox {
@@ -363,8 +363,8 @@ a {
.submenu1 {
position: absolute;
border: 1px solid #7e471b;
background-color: #f9a22c;
border: 1px solid #5D4037;
background-color: #FF6B35;
left: 0;
top: 2.5em;
max-height: 0;
@@ -388,13 +388,13 @@ a {
.submenu1 > li {
padding: 0.5em;
line-height: 1em;
color: #7e471b;
color: #5D4037;
position: relative;
}
.submenu1 > li:hover {
color: #000;
background-color: #d37c06;
background-color: #FF8C5A;
}
.menu-icon,
@@ -419,10 +419,10 @@ a {
.submenu2 {
position: absolute;
background-color: #f9a22c;
background-color: #FF6B35;
left: 100%;
top: 0;
border: 1px solid #7e471b;
border: 1px solid #5D4037;
max-height: 0;
overflow: hidden;
opacity: 0;
@@ -444,12 +444,12 @@ a {
.submenu2 > li {
padding: 0.5em;
line-height: 1em;
color: #7e471b;
color: #5D4037;
}
.submenu2 > li:hover {
color: #000;
background-color: #d37c06;
background-color: #FF8C5A;
}
.subsubmenu {

View File

@@ -3,6 +3,7 @@
</template>
<script>
import { markRaw } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
@@ -30,7 +31,8 @@ export default {
model: null,
animationId: null,
mixer: null,
clock: new THREE.Clock()
clock: markRaw(new THREE.Clock()),
baseYPosition: 0 // Basis-Y-Position für Animation
};
},
computed: {
@@ -50,8 +52,16 @@ export default {
}
// Zufällige Auswahl beim ersten Mount, dann persistent
if (this.randomAge === null) {
// Zufälliges Alter zwischen 18 und 65 Jahren
this.randomAge = Math.floor(Math.random() * 47) + 18;
// Zufällige Altersgruppe auswählen, damit verschiedene Altersbereiche dargestellt werden
const ageGroups = [
{ min: 0, max: 3 }, // toddler
{ min: 4, max: 7 }, // child
{ min: 8, max: 12 }, // preteen
{ min: 13, max: 17 }, // teen
{ min: 18, max: 65 } // adult
];
const selectedGroup = ageGroups[Math.floor(Math.random() * ageGroups.length)];
this.randomAge = Math.floor(Math.random() * (selectedGroup.max - selectedGroup.min + 1)) + selectedGroup.min;
}
return this.randomAge;
},
@@ -95,39 +105,76 @@ export default {
const container = this.$refs.container;
if (!container) return;
// Scene erstellen
this.scene = new THREE.Scene();
// Scene erstellen - markRaw verwenden, um Vue's Reactivity zu vermeiden
this.scene = markRaw(new THREE.Scene());
// Hintergrund wird später geladen
this.scene.background = new THREE.Color(0xf0f0f0);
// Hintergrundbild laden
this.loadBackground();
// Camera erstellen
const aspect = container.clientWidth / container.clientHeight;
this.camera = new THREE.PerspectiveCamera(50, aspect, 0.1, 1000);
this.camera = markRaw(new THREE.PerspectiveCamera(50, aspect, 0.1, 1000));
this.camera.position.set(0, 1.5, 3);
this.camera.lookAt(0, 1, 0);
// Renderer erstellen
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
this.renderer = markRaw(new THREE.WebGLRenderer({ antialias: true, alpha: true }));
this.renderer.setSize(container.clientWidth, container.clientHeight);
this.renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(this.renderer.domElement);
// Licht hinzufügen
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
// Verbesserte Beleuchtung für hellere Modelle
// Mehr ambient light für gleichmäßigere Ausleuchtung
const ambientLight = new THREE.AmbientLight(0xffffff, 1.0);
this.scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
// Hauptlicht von vorne oben - stärker
const directionalLight = new THREE.DirectionalLight(0xffffff, 1.2);
directionalLight.position.set(5, 10, 5);
this.scene.add(directionalLight);
// Zusätzliches Licht von hinten
const backLight = new THREE.DirectionalLight(0xffffff, 0.3);
backLight.position.set(-5, 0, -5);
// Zusätzliches Licht von hinten - heller
const backLight = new THREE.DirectionalLight(0xffffff, 0.75);
backLight.position.set(-5, 5, -5);
this.scene.add(backLight);
// Zusätzliches Seitenlicht für mehr Tiefe
const sideLight = new THREE.DirectionalLight(0xffffff, 0.5);
sideLight.position.set(-5, 5, 5);
this.scene.add(sideLight);
// Resize Handler
window.addEventListener('resize', this.onWindowResize);
},
loadBackground() {
// Zufällig einen Hintergrund auswählen
const backgrounds = ['bg1.png', 'bg2.png'];
const randomBg = backgrounds[Math.floor(Math.random() * backgrounds.length)];
const bgPath = `/images/falukant/backgrounds/${randomBg}`;
const loader = new THREE.TextureLoader();
loader.load(
bgPath,
(texture) => {
// Hintergrund erfolgreich geladen
if (this.scene) {
this.scene.background = texture;
}
},
undefined,
(error) => {
console.warn('Fehler beim Laden des Hintergrunds:', error);
// Fallback auf Standardfarbe bei Fehler
if (this.scene) {
this.scene.background = new THREE.Color(0xf0f0f0);
}
}
);
},
async loadModel() {
if (!this.scene) return;
@@ -167,51 +214,57 @@ export default {
gltf = await loader.loadAsync(fallbackPath);
}
this.model = gltf.scene;
// Modell als raw markieren, um Vue's Reactivity zu vermeiden
this.model = markRaw(gltf.scene);
// Modell zentrieren und skalieren
const box = new THREE.Box3().setFromObject(this.model);
const center = box.getCenter(new THREE.Vector3());
const size = box.getSize(new THREE.Vector3());
// Initiale Bounding Box für Größenberechnung (vor Skalierung)
const initialBox = new THREE.Box3().setFromObject(this.model);
const initialSize = initialBox.getSize(new THREE.Vector3());
// Skalierung basierend auf Alter
const age = this.actualAge;
let scale = 1;
let ageScale = 1;
if (age <= 3) {
scale = 0.4;
ageScale = 0.4;
} else if (age <= 7) {
scale = 0.6;
ageScale = 0.6;
} else if (age <= 12) {
scale = 0.75;
ageScale = 0.75;
} else if (age <= 17) {
scale = 0.9;
ageScale = 0.9;
} else {
scale = 1.0;
ageScale = 1.0;
}
// Modell skalieren, damit es in die Szene passt
const maxDimension = Math.max(size.x, size.y, size.z);
const maxDimension = Math.max(initialSize.x, initialSize.y, initialSize.z);
const targetHeight = 2; // Zielhöhe in 3D-Einheiten
const modelScale = (targetHeight / maxDimension) * scale;
const modelScale = (targetHeight / maxDimension) * ageScale;
this.model.scale.set(modelScale, modelScale, modelScale);
// Modell zentrieren
this.model.position.sub(center.multiplyScalar(modelScale));
this.model.position.y = 0; // Auf Boden setzen
// Bounding Box NACH dem Skalieren neu berechnen
const scaledBox = new THREE.Box3().setFromObject(this.model);
const scaledCenter = scaledBox.getCenter(new THREE.Vector3());
// Modell zentrieren basierend auf der skalierten Bounding Box
// Position direkt setzen statt zu subtrahieren, um Proxy-Probleme zu vermeiden
const baseY = -scaledBox.min.y; // Auf Boden setzen (y=0 entspricht dem unteren Rand)
this.model.position.set(-scaledCenter.x, baseY, -scaledCenter.z);
this.baseYPosition = baseY; // Basisposition für Animation speichern
this.scene.add(this.model);
// Animationen laden falls vorhanden
if (gltf.animations && gltf.animations.length > 0) {
this.mixer = new THREE.AnimationMixer(this.model);
this.mixer = markRaw(new THREE.AnimationMixer(this.model));
gltf.animations.forEach((clip) => {
this.mixer.clipAction(clip).play();
});
}
// Sanfte Rotation-Animation
// Keine Rotation - Figuren bleiben statisch
if (this.model) {
this.model.rotation.y = Math.random() * Math.PI * 2;
this.model.rotation.y = 0;
}
} catch (error) {
console.error('Error loading 3D model:', error);
@@ -228,13 +281,7 @@ export default {
this.mixer.update(delta);
}
if (this.model) {
// Sanfte Rotation
this.model.rotation.y += 0.005;
// Sanftes Auf und Ab
this.model.position.y = Math.sin(Date.now() * 0.001) * 0.1;
}
// Keine Bewegung - Modelle bleiben statisch
if (this.renderer && this.scene && this.camera) {
this.renderer.render(this.scene, this.camera);

View File

@@ -216,7 +216,7 @@ export default {
justify-content: space-between;
padding: 5px 5px;
border-bottom: 1px solid #ddd;
background-color: #F9A22C;
background-color: #FF6B35;
cursor: move;
}
@@ -258,7 +258,7 @@ dialog-footer {
margin-left: 10px;
padding: 5px 10px;
cursor: pointer;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: none;
border-radius: 4px;
@@ -266,9 +266,9 @@ dialog-footer {
}
.dialog-button:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
.is-active {

View File

@@ -133,7 +133,7 @@ export default {
justify-content: space-between;
padding: 10px 20px;
border-bottom: 1px solid #ddd;
background-color: #F9A22C;
background-color: #FF6B35;
}
.dialog-icon {

View File

@@ -253,9 +253,9 @@ export default {
margin-left: 10px;
padding: 5px 12px;
cursor: pointer;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: 1px solid #F9A22C;
border: 1px solid #FF6B35;
border-radius: 4px;
transition: background 0.05s;
border: 1px solid transparent;
@@ -263,8 +263,8 @@ export default {
}
.contact-button:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
</style>

View File

@@ -57,7 +57,7 @@ export default {
}
.simple-tab.active {
background: #F9A22C;
background: #FF6B35;
color: #000;
}
</style>

View File

@@ -821,7 +821,7 @@ export default {
}
.messages > li .footer {
color: #f9a22c;
color: #FF6B35;
font-size: 0.8em;
margin-top: 0.3em;
display: flex;

View File

@@ -218,11 +218,11 @@
opacity: 0.9;
}
.city-price-green {
background-color: #90EE90;
background-color: var(--color-primary-green);
color: #000;
}
.city-price-orange {
background-color: #FFA500;
background-color: #FF6B35;
color: #000;
}
.city-price-red {

View File

@@ -627,11 +627,11 @@
cursor: help;
}
.city-price-green {
background-color: #90EE90;
background-color: var(--color-primary-green);
color: #000;
}
.city-price-orange {
background-color: #FFA500;
background-color: #FF6B35;
color: #000;
}
.city-price-red {

View File

@@ -174,26 +174,26 @@ export default {
.actions>div {
flex: 1;
background-color: #fdf1db;
background-color: #FFF4F0;
align-items: center;
justify-content: flex-start;
display: flex;
color: #7E471B;
color: #5D4037;
flex-direction: column;
overflow: auto;
padding: 0.5rem;
}
.actions>div>h2 {
color: #F9A22C;
color: #FF6B35;
}
.seo-content {
max-width: 1000px;
margin: 24px auto 0 auto;
padding: 0 16px 40px 16px;
color: #7E471B;
background-color: #fdf1db;
color: #5D4037;
background-color: #FFF4F0;
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 4px;
}

View File

@@ -321,9 +321,9 @@ export default {
.btn-current-lesson {
padding: 12px 24px;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: 1px solid #F9A22C;
border: 1px solid #FF6B35;
border-radius: 4px;
cursor: pointer;
font-size: 1em;
@@ -332,9 +332,9 @@ export default {
}
.btn-current-lesson:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
.lessons-table {
@@ -491,9 +491,9 @@ export default {
.btn-start {
padding: 8px 16px;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: 1px solid #F9A22C;
border: 1px solid #FF6B35;
border-radius: 4px;
cursor: pointer;
font-size: 0.9em;
@@ -502,9 +502,9 @@ export default {
}
.btn-start:hover:not(:disabled) {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
.btn-start:disabled {
@@ -517,9 +517,9 @@ export default {
.btn-edit {
padding: 6px 12px;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: 1px solid #F9A22C;
border: 1px solid #FF6B35;
border-radius: 4px;
cursor: pointer;
font-size: 0.85em;
@@ -527,9 +527,9 @@ export default {
}
.btn-edit:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
.btn-delete {

View File

@@ -1801,9 +1801,9 @@ export default {
.btn-switch-mode {
padding: 8px 16px;
background: #F9A22C;
background: #FF6B35;
color: #000000;
border: 1px solid #F9A22C;
border: 1px solid #FF6B35;
border-radius: 4px;
cursor: pointer;
font-size: 0.9em;
@@ -1812,9 +1812,9 @@ export default {
}
.btn-switch-mode:hover {
background: #fdf1db;
color: #7E471B;
border: 1px solid #7E471B;
background: #FFF4F0;
color: #5D4037;
border: 1px solid #5D4037;
}
.vocab-answer-area.multiple-choice {
@@ -2114,7 +2114,7 @@ export default {
justify-content: space-between;
padding: 10px 20px;
border-bottom: 1px solid #ddd;
background-color: #F9A22C;
background-color: #FF6B35;
}
.dialog-title {