Art frame final polish: four mitered wood rails (grain turns at corners) + brushed metals
- Woods are now built from four real mitered rails clipped to 45° joints, each showing the grain along its length — horizontal on top/bottom (rotated texture wood-grain-h.jpg), vertical on the sides — so the grain TURNS at every corner like real cut moulding. Each rail carries a directional bevel (lit top-left) for a rounded profile; per-species recolor moved onto the rails. Rendered via a Svelte snippet in both page + full-screen frames. - Gold/Silver gain fine brushed-metal striations over the existing sheen. - New asset: wood-grain-h.jpg (the CC0 texture rotated 90°), credited in textures/CREDITS.txt. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,8 @@
|
||||
let who = $derived(
|
||||
art ? [art.artist || 'Unknown artist', art.date_text].filter(Boolean) : []
|
||||
);
|
||||
// Woods are built from four real mitered rails (grain turns at the corners); metals/none aren't.
|
||||
let isWood = $derived(['walnut', 'oak', 'mahogany'].includes(frame));
|
||||
|
||||
onMount(async () => {
|
||||
try {
|
||||
@@ -53,6 +55,13 @@
|
||||
<meta name="description" content="A masterwork a day from the world's open museum collections — one piece, beautifully framed, on upbeatBytes." />
|
||||
</svelte:head>
|
||||
|
||||
{#snippet woodRails()}
|
||||
<span class="rail rail--t"></span>
|
||||
<span class="rail rail--r"></span>
|
||||
<span class="rail rail--b"></span>
|
||||
<span class="rail rail--l"></span>
|
||||
{/snippet}
|
||||
|
||||
<div class="room">
|
||||
<header class="bar">
|
||||
<a class="brand" href="/" aria-label="upbeatBytes home">
|
||||
@@ -83,6 +92,7 @@
|
||||
<figure class="piece">
|
||||
<button class="frame frame--{frame}" style="--frame-scale:{thickness}"
|
||||
onclick={() => (zoom = true)} aria-label="Expand artwork">
|
||||
{#if isWood}{@render woodRails()}{/if}
|
||||
<span class="mat">
|
||||
<img src={art.image_url} alt={art.title} />
|
||||
<span class="hint">
|
||||
@@ -137,6 +147,7 @@
|
||||
{#if zoom && art}
|
||||
<button class="lightbox" onclick={() => (zoom = false)} aria-label="Close artwork">
|
||||
<span class="frame frame--{frame} lb-frame" style="--frame-scale:{thickness}">
|
||||
{#if isWood}{@render woodRails()}{/if}
|
||||
<span class="mat"><img src={art.image_url_large || art.image_url} alt={art.title} /></span>
|
||||
</span>
|
||||
<span class="lb-cap">{art.title}{#if art.artist}<span class="sep">·</span>{art.artist}{/if}</span>
|
||||
@@ -220,25 +231,46 @@
|
||||
.frame--walnut, .frame--oak, .frame--mahogany {
|
||||
background: linear-gradient(135deg, #5a3a24, #34210f); /* fallback if texture misses */
|
||||
}
|
||||
.frame--walnut::before, .frame--oak::before, .frame--mahogany::before {
|
||||
content: ""; position: absolute; inset: 0; z-index: 0; border-radius: inherit; pointer-events: none;
|
||||
background:
|
||||
linear-gradient(158deg, rgba(255, 250, 240, 0.14), rgba(0, 0, 0, 0.24) 80%),
|
||||
url("/textures/wood-grain.jpg") center / cover;
|
||||
}
|
||||
.frame--walnut::before { filter: brightness(1.08) saturate(1.05); }
|
||||
.frame--oak::before { filter: brightness(1.72) contrast(0.92) saturate(1.12) sepia(0.22) hue-rotate(-6deg); }
|
||||
.frame--mahogany::before { filter: brightness(0.98) contrast(1.06) saturate(1.55) sepia(0.4) hue-rotate(-16deg); }
|
||||
|
||||
/* Four real mitered rails: the grain TURNS at every corner — horizontal moulding on the
|
||||
top/bottom rails (rotated texture), vertical on the sides — like four cut lengths of
|
||||
wood. Each rail is a trapezoid clipped to 45° at the joints; --rail drives size + cut.
|
||||
A directional bevel per rail (lit top-left) gives the moulding a rounded profile. */
|
||||
.rail {
|
||||
position: absolute; z-index: 0; pointer-events: none;
|
||||
background-position: center; background-size: cover; background-repeat: no-repeat;
|
||||
}
|
||||
.rail--t { top: 0; left: 0; right: 0; height: var(--rail);
|
||||
clip-path: polygon(0 0, 100% 0, calc(100% - var(--rail)) 100%, var(--rail) 100%);
|
||||
background-image: linear-gradient(to bottom, rgba(255,255,255,0.22), rgba(0,0,0,0.22)), url("/textures/wood-grain-h.jpg"); }
|
||||
.rail--b { bottom: 0; left: 0; right: 0; height: var(--rail);
|
||||
clip-path: polygon(var(--rail) 0, calc(100% - var(--rail)) 0, 100% 100%, 0 100%);
|
||||
background-image: linear-gradient(to top, rgba(255,255,255,0.05), rgba(0,0,0,0.36)), url("/textures/wood-grain-h.jpg"); }
|
||||
.rail--l { top: 0; bottom: 0; left: 0; width: var(--rail);
|
||||
clip-path: polygon(0 0, 100% var(--rail), 100% calc(100% - var(--rail)), 0 100%);
|
||||
background-image: linear-gradient(to right, rgba(255,255,255,0.20), rgba(0,0,0,0.22)), url("/textures/wood-grain.jpg"); }
|
||||
.rail--r { top: 0; bottom: 0; right: 0; width: var(--rail);
|
||||
clip-path: polygon(0 var(--rail), 100% 0, 100% 100%, 0 calc(100% - var(--rail)));
|
||||
background-image: linear-gradient(to left, rgba(255,255,255,0.05), rgba(0,0,0,0.36)), url("/textures/wood-grain.jpg"); }
|
||||
/* per-species recolor, now applied to the rails */
|
||||
.frame--walnut .rail { filter: brightness(1.08) saturate(1.05); }
|
||||
.frame--oak .rail { filter: brightness(1.72) contrast(0.92) saturate(1.12) sepia(0.22) hue-rotate(-6deg); }
|
||||
.frame--mahogany .rail { filter: brightness(0.98) contrast(1.06) saturate(1.55) sepia(0.4) hue-rotate(-16deg); }
|
||||
|
||||
/* Metals: fine brushed striations over an anisotropic sheen. */
|
||||
.frame--gold {
|
||||
background: linear-gradient(135deg, #b88c3d, #ecd293 42%, #a9772f 60%, #dcbd71);
|
||||
background:
|
||||
repeating-linear-gradient(180deg, rgba(255,255,255,0.08) 0 1px, rgba(120,80,10,0.07) 1px 2px),
|
||||
linear-gradient(135deg, #b88c3d, #ecd293 42%, #a9772f 60%, #dcbd71);
|
||||
box-shadow: 0 24px 58px rgba(20, 30, 45, 0.20),
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.30),
|
||||
inset 0 2px 3px rgba(255, 249, 226, 0.60),
|
||||
inset 0 -3px 9px rgba(92, 62, 12, 0.48);
|
||||
}
|
||||
.frame--silver {
|
||||
background: linear-gradient(135deg, #a9b0ba, #edf0f3 45%, #98a0ab 62%, #d2d7de);
|
||||
background:
|
||||
repeating-linear-gradient(180deg, rgba(255,255,255,0.11) 0 1px, rgba(40,50,60,0.07) 1px 2px),
|
||||
linear-gradient(135deg, #a9b0ba, #edf0f3 45%, #98a0ab 62%, #d2d7de);
|
||||
box-shadow: 0 24px 58px rgba(20, 30, 45, 0.18),
|
||||
inset 0 0 0 1px rgba(255, 255, 255, 0.50),
|
||||
inset 0 2px 3px rgba(255, 255, 255, 0.75),
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
wood-grain.jpg — "Fine Grained Wood" by Rob Tuytel, Poly Haven (https://polyhaven.com/a/fine_grained_wood)
|
||||
License: CC0 (Public Domain). Free to use, no attribution required. Recolored in CSS for frame variants.
|
||||
License: CC0 (Public Domain). Free to use, no attribution required. Recolored in CSS per frame species.
|
||||
wood-grain-h.jpg — the same texture rotated 90° (horizontal grain), for the top/bottom rails so the grain
|
||||
turns at each mitered corner. Same CC0 source/license.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 171 KiB |
Reference in New Issue
Block a user