feat(nds): add 2d css NDS and move 3d nds to NDS3D component
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m21s
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m21s
This commit is contained in:
463
app/components/NDS2D.vue
Normal file
463
app/components/NDS2D.vue
Normal file
@@ -0,0 +1,463 @@
|
||||
<script setup lang="ts">
|
||||
const ndsScale = ref(1);
|
||||
|
||||
const updateScale = () => {
|
||||
const scaleX = (window.innerWidth - 40) / 280;
|
||||
const scaleY = (window.innerHeight - 40) / 431;
|
||||
ndsScale.value = Math.min(scaleX, scaleY);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
updateScale();
|
||||
window.addEventListener("resize", updateScale);
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener("resize", updateScale);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="nds2d-container">
|
||||
<div class="nds2d" :style="{ scale: ndsScale }">
|
||||
<div class="nds2d-top-screen">
|
||||
<div class="nds2d-speaker-hole nds2d-sh1"></div>
|
||||
<div class="nds2d-speaker-hole nds2d-sh2"></div>
|
||||
<div class="nds2d-screen nds2d-screen-top">
|
||||
<slot name="topScreen" />
|
||||
</div>
|
||||
<div class="nds2d-speaker-hole nds2d-sh3"></div>
|
||||
<div class="nds2d-speaker-hole nds2d-sh4"></div>
|
||||
</div>
|
||||
<div class="nds2d-hinge">
|
||||
<div class="nds2d-mic"></div>
|
||||
<div class="nds2d-light"></div>
|
||||
</div>
|
||||
<div class="nds2d-bottom-screen">
|
||||
<div class="nds2d-screen nds2d-screen-bottom">
|
||||
<slot name="bottomScreen" />
|
||||
</div>
|
||||
|
||||
<div class="nds2d-d-pad-shadow"></div>
|
||||
<div class="nds2d-d-pad">
|
||||
<div class="nds2d-d-pad-base"></div>
|
||||
<div class="nds2d-d-pad-light"></div>
|
||||
<div class="nds2d-d-pad-tip nds2d-tip-up"></div>
|
||||
<div class="nds2d-d-pad-tip nds2d-tip-down"></div>
|
||||
<div class="nds2d-d-pad-tip nds2d-tip-left"></div>
|
||||
<div class="nds2d-d-pad-tip nds2d-tip-right"></div>
|
||||
<div class="nds2d-d-pad-marker nds2d-dpm-up"></div>
|
||||
<div class="nds2d-d-pad-marker nds2d-dpm-down"></div>
|
||||
<div class="nds2d-d-pad-marker nds2d-dpm-left"></div>
|
||||
<div class="nds2d-d-pad-marker nds2d-dpm-right"></div>
|
||||
</div>
|
||||
|
||||
<div class="nds2d-button nds2d-btn-x">X</div>
|
||||
<div class="nds2d-button nds2d-btn-a">A</div>
|
||||
<div class="nds2d-button nds2d-btn-b">B</div>
|
||||
<div class="nds2d-button nds2d-btn-y">Y</div>
|
||||
|
||||
<div class="nds2d-small-button nds2d-start"></div>
|
||||
<div class="nds2d-small-button nds2d-select"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="css">
|
||||
.nds2d-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
background: #181818;
|
||||
}
|
||||
|
||||
.nds2d {
|
||||
--primary: #1a1a1a;
|
||||
--shadow: #111;
|
||||
--black: #050505;
|
||||
|
||||
width: 414px;
|
||||
height: 431px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.nds2d-top-screen {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 46.5%;
|
||||
border-radius: 15px 15px 5px 5px;
|
||||
background: var(--primary);
|
||||
box-shadow:
|
||||
inset 10px 10px 12px -2px var(--shadow),
|
||||
inset -2px 5px 3px 1px var(--shadow),
|
||||
inset -5px 5px 5px 2px #444,
|
||||
0px -1px 2px 2px #111;
|
||||
}
|
||||
|
||||
.nds2d-screen {
|
||||
position: absolute;
|
||||
width: 51.5%;
|
||||
height: 83.5%;
|
||||
border-radius: 3px;
|
||||
top: 9.5%;
|
||||
left: 24%;
|
||||
box-shadow: 0px 0px 3px 0px #111;
|
||||
}
|
||||
|
||||
.nds2d-screen :deep(canvas) {
|
||||
position: absolute;
|
||||
width: 91%;
|
||||
height: 87%;
|
||||
left: 4%;
|
||||
top: 6%;
|
||||
box-shadow: 0px 0px 1px 2px rgba(0, 0, 0, 0.5);
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.nds2d-speaker-hole {
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
background: var(--black);
|
||||
border-radius: 2.5px;
|
||||
}
|
||||
|
||||
.nds2d-speaker-hole::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
border-radius: 2.5px;
|
||||
background: var(--black);
|
||||
left: 16px;
|
||||
}
|
||||
|
||||
.nds2d-speaker-hole::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
height: 5px;
|
||||
width: 5px;
|
||||
border-radius: 2.5px;
|
||||
background: var(--black);
|
||||
left: 31px;
|
||||
}
|
||||
|
||||
.nds2d-sh1 {
|
||||
left: 30px;
|
||||
top: 94px;
|
||||
}
|
||||
|
||||
.nds2d-sh2 {
|
||||
left: 30px;
|
||||
top: 110px;
|
||||
}
|
||||
|
||||
.nds2d-sh3 {
|
||||
left: 346px;
|
||||
top: 95px;
|
||||
}
|
||||
|
||||
.nds2d-sh4 {
|
||||
left: 346px;
|
||||
top: 110px;
|
||||
}
|
||||
|
||||
.nds2d-hinge {
|
||||
position: absolute;
|
||||
width: 99.5%;
|
||||
top: 46.5%;
|
||||
height: 28px;
|
||||
border-radius: 25px;
|
||||
z-index: 3;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(8, 8, 8) 0%,
|
||||
rgba(20, 20, 20, 1) 10%,
|
||||
rgba(32, 32, 32, 1) 65%,
|
||||
rgba(20, 20, 20, 1) 100%
|
||||
);
|
||||
box-shadow: 0px 5px 10px -1px #080808;
|
||||
}
|
||||
|
||||
.nds2d-hinge::after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #222;
|
||||
left: 49px;
|
||||
}
|
||||
|
||||
.nds2d-hinge::before {
|
||||
position: absolute;
|
||||
content: "";
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background: #222;
|
||||
left: 364px;
|
||||
}
|
||||
|
||||
.nds2d-mic {
|
||||
position: absolute;
|
||||
width: 4px;
|
||||
height: 10px;
|
||||
border-radius: 2px;
|
||||
background: var(--black);
|
||||
left: 49.5%;
|
||||
top: 8px;
|
||||
}
|
||||
|
||||
.nds2d-light {
|
||||
position: absolute;
|
||||
height: 67%;
|
||||
width: 4px;
|
||||
top: 12%;
|
||||
border-radius: 10px;
|
||||
right: 25px;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(40, 40, 40, 1) 0%,
|
||||
rgba(80, 80, 80, 1) 65%,
|
||||
rgba(40, 40, 40, 1) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.nds2d-light::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 4px;
|
||||
top: 0;
|
||||
border-radius: 10px;
|
||||
left: 8px;
|
||||
background: linear-gradient(
|
||||
0deg,
|
||||
rgba(92, 107, 73, 1) 0%,
|
||||
rgba(211, 212, 183, 1) 65%,
|
||||
rgba(123, 142, 98, 1) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.nds2d-bottom-screen {
|
||||
position: absolute;
|
||||
width: 99.5%;
|
||||
height: 50%;
|
||||
bottom: 0;
|
||||
border-radius: 3px 3px 14px 14px;
|
||||
background: var(--primary);
|
||||
box-shadow: 0px 1px 2px 2px #111;
|
||||
}
|
||||
|
||||
.nds2d-bottom-screen .nds2d-screen {
|
||||
top: 24px;
|
||||
height: 168px;
|
||||
width: 52%;
|
||||
background: var(--primary);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.nds2d-bottom-screen .nds2d-screen::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 102%;
|
||||
height: 109%;
|
||||
left: -1%;
|
||||
top: -7%;
|
||||
z-index: -1;
|
||||
border-radius: 5px;
|
||||
box-shadow:
|
||||
10px 7px 10px 3px #111,
|
||||
-6px 4px 5px 2px var(--primary),
|
||||
-12px 4px 8px 3px #333;
|
||||
}
|
||||
|
||||
.nds2d-d-pad-shadow {
|
||||
position: absolute;
|
||||
left: 19px;
|
||||
top: 61px;
|
||||
width: 57px;
|
||||
height: 57px;
|
||||
background: var(--shadow);
|
||||
filter: drop-shadow(0 3px 2px #111);
|
||||
clip-path: path(
|
||||
"M 22.5 0 Q 19 0 19 3.5 L 19 19 L 3.5 19 Q 0 19 0 22.5 L 0 34.5 Q 0 38 3.5 38 L 19 38 L 19 53.5 Q 19 57 22.5 57 L 34.5 57 Q 38 57 38 53.5 L 38 38 L 53.5 38 Q 57 38 57 34.5 L 57 22.5 Q 57 19 53.5 19 L 38 19 L 38 3.5 Q 38 0 34.5 0 Z"
|
||||
);
|
||||
}
|
||||
|
||||
.nds2d-d-pad {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 62px;
|
||||
width: 55px;
|
||||
height: 55px;
|
||||
clip-path: path(
|
||||
"M 22 0 Q 19 0 19 3 L 19 19 L 3 19 Q 0 19 0 22 L 0 33 Q 0 36 3 36 L 19 36 L 19 52 Q 19 55 22 55 L 33 55 Q 36 55 36 52 L 36 36 L 52 36 Q 55 36 55 33 L 55 22 Q 55 19 52 19 L 36 19 L 36 3 Q 36 0 33 0 Z"
|
||||
);
|
||||
}
|
||||
|
||||
.nds2d-d-pad-base {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.nds2d-d-pad-light {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: inset 2px 2px 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-d-pad-tip {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.nds2d-tip-up {
|
||||
left: 19px;
|
||||
top: 0;
|
||||
width: 17px;
|
||||
height: 19px;
|
||||
box-shadow: inset 0 2px 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-tip-down {
|
||||
left: 19px;
|
||||
bottom: 0;
|
||||
width: 17px;
|
||||
height: 19px;
|
||||
box-shadow: inset 0 -2px 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-tip-left {
|
||||
left: 0;
|
||||
top: 19px;
|
||||
width: 19px;
|
||||
height: 17px;
|
||||
box-shadow: inset 2px 0 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-tip-right {
|
||||
right: 0;
|
||||
top: 19px;
|
||||
width: 19px;
|
||||
height: 17px;
|
||||
box-shadow: inset -2px 0 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-d-pad-marker {
|
||||
position: absolute;
|
||||
background: #999;
|
||||
}
|
||||
|
||||
.nds2d-dpm-up,
|
||||
.nds2d-dpm-down {
|
||||
width: 2px;
|
||||
height: 11px;
|
||||
left: 26px;
|
||||
}
|
||||
|
||||
.nds2d-dpm-up {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.nds2d-dpm-down {
|
||||
bottom: 5px;
|
||||
}
|
||||
|
||||
.nds2d-dpm-left,
|
||||
.nds2d-dpm-right {
|
||||
width: 11px;
|
||||
height: 2px;
|
||||
top: 26px;
|
||||
}
|
||||
|
||||
.nds2d-dpm-left {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.nds2d-dpm-right {
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
|
||||
.nds2d-button {
|
||||
user-select: none;
|
||||
position: absolute;
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
padding-top: 1px;
|
||||
border: 1px solid var(--shadow);
|
||||
border-radius: 50%;
|
||||
z-index: 5;
|
||||
font-size: 0.7rem;
|
||||
font-weight: 400;
|
||||
background: #333;
|
||||
color: #999;
|
||||
box-shadow:
|
||||
3px 2px 3px -2px #111,
|
||||
inset 2px 2px 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-btn-x {
|
||||
right: 35px;
|
||||
top: 45px;
|
||||
}
|
||||
|
||||
.nds2d-btn-a {
|
||||
right: 12px;
|
||||
top: 69px;
|
||||
}
|
||||
|
||||
.nds2d-btn-y {
|
||||
right: 59px;
|
||||
top: 69px;
|
||||
}
|
||||
|
||||
.nds2d-btn-b {
|
||||
right: 35px;
|
||||
top: 92px;
|
||||
}
|
||||
|
||||
.nds2d-small-button {
|
||||
user-select: none;
|
||||
position: absolute;
|
||||
width: 11px;
|
||||
height: 11px;
|
||||
border: 1px solid var(--shadow);
|
||||
border-radius: 50%;
|
||||
bottom: 53px;
|
||||
right: 70px;
|
||||
background: #333;
|
||||
box-shadow:
|
||||
3px 2px 3px -2px #111,
|
||||
inset 2px 2px 3px -1px #444;
|
||||
}
|
||||
|
||||
.nds2d-select {
|
||||
bottom: 29px;
|
||||
right: 70px;
|
||||
}
|
||||
|
||||
.nds2d-start::after {
|
||||
position: absolute;
|
||||
content: "START";
|
||||
font-size: 7px;
|
||||
color: #999;
|
||||
left: 15px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.nds2d-select::after {
|
||||
position: absolute;
|
||||
content: "SELECT";
|
||||
font-size: 7px;
|
||||
color: #999;
|
||||
left: 15px;
|
||||
top: 0px;
|
||||
}
|
||||
</style>
|
||||
@@ -27,19 +27,19 @@ const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
||||
<TresAmbientLight />
|
||||
<TresDirectionalLight />
|
||||
|
||||
<NDS
|
||||
<NDS3D
|
||||
v-if="topScreenCanvas && bottomScreenCanvas"
|
||||
:top-screen-canvas="topScreenCanvas"
|
||||
:bottom-screen-canvas="bottomScreenCanvas"
|
||||
/>
|
||||
</TresCanvas>
|
||||
|
||||
<div
|
||||
<NDS2D
|
||||
:style="{
|
||||
visibility: app.settings.renderingMode === '3d' ? 'hidden' : 'visible',
|
||||
}"
|
||||
>
|
||||
<div>
|
||||
<template #topScreen>
|
||||
<Screen ref="topScreen">
|
||||
<IntroTopScreen v-if="!app.booted" />
|
||||
<HomeTopScreen v-else-if="app.screen === 'home'" />
|
||||
@@ -52,8 +52,8 @@ const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
||||
<AchievementsNotification />
|
||||
<CommonConfetti screen="top" />
|
||||
</Screen>
|
||||
</div>
|
||||
<div>
|
||||
</template>
|
||||
<template #bottomScreen>
|
||||
<Screen ref="bottomScreen">
|
||||
<IntroBottomScreen v-if="!app.booted" />
|
||||
<HomeBottomScreen v-else-if="app.screen === 'home'" />
|
||||
@@ -65,7 +65,7 @@ const bottomScreenCanvas = computed(() => bottomScreen.value?.canvas ?? null);
|
||||
|
||||
<CommonConfetti screen="bottom" />
|
||||
</Screen>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</NDS2D>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user