mirror of
https://github.com/liyunze-coding/RythonDev.git
synced 2026-09-22 15:53:57 +00:00
updated projects component
This commit is contained in:
parent
09c4c24d77
commit
abbed1d6b4
4 changed files with 146 additions and 139 deletions
|
|
@ -26,6 +26,35 @@ const {
|
||||||
} = Astro.props;
|
} = Astro.props;
|
||||||
|
|
||||||
const leftProject = position == "left";
|
const leftProject = position == "left";
|
||||||
|
const side = leftProject ? "left" : "right";
|
||||||
|
const layers = ["background", "frontfacing"] as const;
|
||||||
|
|
||||||
|
const renderLayer = (
|
||||||
|
src: ImageMetadata,
|
||||||
|
theme: "dark" | "light",
|
||||||
|
layer: (typeof layers)[number],
|
||||||
|
) => {
|
||||||
|
const isBackground = layer === "background";
|
||||||
|
const isLight = theme === "light";
|
||||||
|
|
||||||
|
return {
|
||||||
|
src,
|
||||||
|
class: [
|
||||||
|
"absolute top-1/2 left-1/2 aspect-video max-w-full rounded-xl border-2 border-solid",
|
||||||
|
isLight
|
||||||
|
? "project-image-light hidden border-gray-300"
|
||||||
|
: "project-image-dark border-gray-800",
|
||||||
|
isBackground ? "background-img opacity-40" : "frontfacing-img opacity-100",
|
||||||
|
isBackground && isLight ? "brightness-75" : "",
|
||||||
|
side,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(" "),
|
||||||
|
classList: {
|
||||||
|
"has-light-image": !isLight && Boolean(image_light),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
---
|
---
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
@ -37,48 +66,34 @@ const leftProject = position == "left";
|
||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
{
|
{
|
||||||
image && alt && (
|
image &&
|
||||||
<>
|
layers.map((layer) => {
|
||||||
|
const layerProps = renderLayer(image, "dark", layer);
|
||||||
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={image}
|
src={layerProps.src}
|
||||||
alt={alt}
|
alt={alt ?? ""}
|
||||||
class="project-image-dark background-img absolute top-1/2 left-1/2 aspect-video max-w-full rounded-xl border-2 border-solid border-gray-800 opacity-40"
|
|
||||||
class:list={[
|
|
||||||
leftProject ? "left" : "right",
|
|
||||||
{ "has-light-image": Boolean(image_light) },
|
|
||||||
]}
|
|
||||||
width={700}
|
width={700}
|
||||||
|
class={layerProps.class}
|
||||||
|
class:list={layerProps.classList}
|
||||||
/>
|
/>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
{
|
||||||
|
image_light &&
|
||||||
|
layers.map((layer) => {
|
||||||
|
const layerProps = renderLayer(image_light, "light", layer);
|
||||||
|
return (
|
||||||
<Image
|
<Image
|
||||||
src={image}
|
src={layerProps.src}
|
||||||
alt={alt}
|
alt={alt ?? ""}
|
||||||
width={700}
|
width={700}
|
||||||
class="project-image-dark frontfacing-img absolute top-1/2 left-1/2 aspect-video max-w-full rounded-xl border-2 border-solid border-gray-800 opacity-100"
|
class={layerProps.class}
|
||||||
class:list={[
|
class:list={layerProps.classList}
|
||||||
leftProject ? "left" : "right",
|
|
||||||
{ "has-light-image": Boolean(image_light) },
|
|
||||||
]}
|
|
||||||
/>
|
/>
|
||||||
{image_light && (
|
);
|
||||||
<>
|
})
|
||||||
<Image
|
|
||||||
src={image_light}
|
|
||||||
alt={alt}
|
|
||||||
class="project-image-light background-img absolute top-1/2 left-1/2 hidden aspect-video max-w-full rounded-xl border-2 border-solid border-gray-300 opacity-40"
|
|
||||||
class:list={leftProject ? "left" : "right"}
|
|
||||||
width={700}
|
|
||||||
/>
|
|
||||||
<Image
|
|
||||||
src={image_light}
|
|
||||||
alt={alt}
|
|
||||||
width={700}
|
|
||||||
class="project-image-light frontfacing-img absolute top-1/2 left-1/2 hidden aspect-video max-w-full rounded-xl border-2 border-solid border-gray-300 opacity-100"
|
|
||||||
class:list={leftProject ? "left" : "right"}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
|
|
@ -62,26 +62,7 @@ import Project from "./Project.astro";
|
||||||
endless!`}
|
endless!`}
|
||||||
tags={["HTML", "CSS", "Javascript", "C#"]}
|
tags={["HTML", "CSS", "Javascript", "C#"]}
|
||||||
>
|
>
|
||||||
<TaskWidget
|
<TaskWidget position="right" client:visible />
|
||||||
classList={`
|
|
||||||
widget h-full
|
|
||||||
[perspective:200px] absolute
|
|
||||||
w-full
|
|
||||||
opacity-10
|
|
||||||
top-1/2 left-1/2
|
|
||||||
background-widget right
|
|
||||||
`}
|
|
||||||
client:visible
|
|
||||||
/>
|
|
||||||
<TaskWidget
|
|
||||||
classList={`
|
|
||||||
widget h-full
|
|
||||||
[perspective:200px] absolute
|
|
||||||
frontfacing-widget right
|
|
||||||
top-1/2 left-1/2
|
|
||||||
w-full`}
|
|
||||||
client:visible
|
|
||||||
/>
|
|
||||||
</Project>
|
</Project>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -135,15 +135,20 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
classList: string;
|
position?: "left" | "right";
|
||||||
}
|
}
|
||||||
|
|
||||||
let { classList }: Props = $props();
|
let { position = "right" }: Props = $props();
|
||||||
|
const side = $derived(position === "left" ? "left" : "right");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class={`${classList} overflow-hidden`}>
|
{#snippet widgetLayer(layerClass: string, extraClass: string)}
|
||||||
<!-- task bot -->
|
<div
|
||||||
<div class="task-widget absolute flex h-full min-h-[50vh] w-full flex-col">
|
class={`widget absolute top-1/2 left-1/2 h-full w-full overflow-hidden [perspective:200px] ${layerClass} ${side} ${extraClass}`}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="task-widget absolute flex h-full min-h-[50vh] w-full flex-col"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="task-widget-header flex w-full flex-row items-center justify-between
|
class="task-widget-header flex w-full flex-row items-center justify-between
|
||||||
rounded-md
|
rounded-md
|
||||||
|
|
@ -202,7 +207,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render widgetLayer("background-widget", "opacity-40 brightness-75")}
|
||||||
|
{@render widgetLayer("frontfacing-widget", "opacity-100")}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(html[data-theme="light"]) .task-widget-header {
|
:global(html[data-theme="light"]) .task-widget-header {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@
|
||||||
tags = [],
|
tags = [],
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
const positionLeft: boolean = (() => position == "left")();
|
const positionLeft = $derived(position === "left");
|
||||||
|
const side = $derived(positionLeft ? "left" : "right");
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
|
const videos = document.querySelectorAll<HTMLVideoElement>(".playable");
|
||||||
|
|
@ -63,30 +64,31 @@
|
||||||
<div
|
<div
|
||||||
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
class="image-container relative mb-5 flex aspect-video w-full [perspective:200px] lg:mr-5 lg:mb-0 lg:ml-auto lg:w-1/2"
|
||||||
>
|
>
|
||||||
|
{#snippet renderLayer(
|
||||||
|
kind: "image" | "video",
|
||||||
|
layerClass: string,
|
||||||
|
extraClass: string,
|
||||||
|
)}
|
||||||
|
{#if kind === "image"}
|
||||||
<img
|
<img
|
||||||
src={image_src}
|
src={image_src}
|
||||||
alt={image_alt}
|
alt={image_alt}
|
||||||
class="project-media background-img absolute
|
class="project-media absolute top-1/2 left-1/2 max-w-full rounded-xl border-2 border-solid border-gray-800 {layerClass} {extraClass} {side}"
|
||||||
top-1/2
|
|
||||||
left-1/2 max-w-full rounded-xl border-2
|
|
||||||
border-solid border-gray-800
|
|
||||||
opacity-40
|
|
||||||
{positionLeft ? 'left' : 'right'}"
|
|
||||||
width="700"
|
width="700"
|
||||||
/>
|
/>
|
||||||
|
{:else}
|
||||||
<!-- svelte-ignore a11y_media_has_caption -->
|
<!-- svelte-ignore a11y_media_has_caption -->
|
||||||
<video
|
<video
|
||||||
width="700"
|
width="700"
|
||||||
class="project-media playable frontfacing-vid absolute
|
class="project-media playable absolute top-1/2 left-1/2 max-w-full rounded-xl border-2 border-solid border-gray-800 {layerClass} {extraClass} {side}"
|
||||||
top-1/2 left-1/2 max-w-full rounded-xl
|
|
||||||
border-2
|
|
||||||
border-solid border-gray-800
|
|
||||||
opacity-100
|
|
||||||
{positionLeft ? 'left' : 'right'}"
|
|
||||||
>
|
>
|
||||||
<source src={video_src} type="video/webm" />
|
<source src={video_src} type="video/webm" />
|
||||||
</video>
|
</video>
|
||||||
|
{/if}
|
||||||
|
{/snippet}
|
||||||
|
|
||||||
|
{@render renderLayer("image", "background-img", "opacity-40 brightness-75")}
|
||||||
|
{@render renderLayer("video", "frontfacing-vid", "opacity-100")}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:px-10
|
class="flex h-fit w-full flex-col items-center justify-center lg:h-[340px] lg:w-1/2 lg:px-10
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue