diff --git a/backend/services/memberService.js b/backend/services/memberService.js index d620946..e3f157f 100644 --- a/backend/services/memberService.js +++ b/backend/services/memberService.js @@ -1132,32 +1132,33 @@ class MemberService { } const tileDimension = 200; - const galleryGap = 20; - const maxColumns = Math.max(1, Math.floor((1920 - galleryGap) / (tileDimension + galleryGap))); + // Maximale Breite für die Galerie (Dialog-Breite 900px - 32px Padding = 868px) + const maxGalleryWidth = 868; + // Berechne maximale Anzahl Spalten, die in die Breite passen + // Formel: n * tileDimension <= maxGalleryWidth + const maxColumns = Math.max(1, Math.floor(maxGalleryWidth / tileDimension)); const columns = Math.min(maxColumns, galleryEntries.length); const rows = Math.ceil(galleryEntries.length / columns); - const canvasWidth = Math.max( - 1, - galleryGap + columns * (tileDimension + galleryGap) - ); - const canvasHeight = Math.max( - 1, - galleryGap + rows * (tileDimension + galleryGap) - ); - const gap = galleryGap; + + // Canvas-Breite: columns * tileDimension (kein Abstand zwischen Bildern) + const canvasWidth = columns * tileDimension; + // Canvas-Höhe: rows * tileDimension (kein Abstand zwischen Zeilen) + const canvasHeight = rows * tileDimension; + const backgroundColor = '#101010'; - const grid = this._computeGalleryGrid(galleryEntries.length, canvasWidth, canvasHeight, gap); const composites = []; let index = 0; for (const entry of galleryEntries) { - const row = Math.floor(index / grid.columns); - const col = index % grid.columns; - const left = galleryGap + col * (grid.tileWidth + galleryGap); - const top = galleryGap + row * (grid.tileHeight + galleryGap); + const row = Math.floor(index / columns); + const col = index % columns; + // Linke Position: col * tileDimension (kein Abstand) + const left = col * tileDimension; + // Obere Position: row * tileDimension (kein Abstand, y += 200 für nächste Zeile) + const top = row * tileDimension; - const resizedBuffer = await sharp(entry.filePath) - .resize(200, 200, { fit: 'cover' }) + const resizedBuffer = await sharp(entry.filePath) + .resize(tileDimension, tileDimension, { fit: 'cover' }) .toBuffer(); composites.push({ @@ -1166,11 +1167,11 @@ class MemberService { left }); - const textHeight = Math.max(36, Math.round(grid.tileHeight * 0.18)); - const nameOverlay = this._buildNameOverlay(grid.tileWidth, textHeight, entry.fullName); + const textHeight = Math.max(36, Math.round(tileDimension * 0.18)); + const nameOverlay = this._buildNameOverlay(tileDimension, textHeight, entry.fullName); composites.push({ input: Buffer.from(nameOverlay), - top: top + grid.tileHeight - textHeight, + top: top + tileDimension - textHeight, left }); diff --git a/frontend/src/views/DiaryView.vue b/frontend/src/views/DiaryView.vue index 32296be..d727b45 100644 --- a/frontend/src/views/DiaryView.vue +++ b/frontend/src/views/DiaryView.vue @@ -2476,23 +2476,30 @@ h3 { display: flex; justify-content: flex-start; align-items: flex-start; - padding: 20px; + padding: 0; min-height: 60vh; max-height: 70vh; overflow: auto; } .gallery-image-wrapper { - max-width: none; - max-height: none; + width: 100%; + display: flex; + justify-content: flex-start; + align-items: flex-start; } .gallery-dialog-image { display: block; max-width: 100%; + width: auto; height: auto; border-radius: 8px; box-shadow: 0 4px 18px rgba(0, 0, 0, 0.35); + position: static !important; + left: auto !important; + top: auto !important; + border: none !important; } .gallery-loading,