[Archived] Archived WIP of vielle.dev

add index page - will be added to later

+253 -2
+208
src/components/index/map.astro
··· 1 + --- 2 + import mc_map_contents from "@/assets/mc_map_contents.png"; 3 + import mc_red from "@/assets/mc_red_banner.png"; 4 + import mc_cyan from "@/assets/mc_cyan_banner.png"; 5 + import mc_magenta from "@/assets/mc_magenta_banner.png"; 6 + import mc_blue from "@/assets/mc_blue_banner.png"; 7 + import Arrow from "@/assets/arrow.svg.astro"; 8 + 9 + type colour = "red" | "cyan" | "magenta" | "blue"; 10 + type position = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; 11 + 12 + interface Location { 13 + colour: colour; 14 + name: string; 15 + href?: string; 16 + x: position; 17 + y: position; 18 + } 19 + 20 + interface Props { 21 + locations: Location[]; 22 + } 23 + 24 + const { locations } = Astro.props; 25 + 26 + const getSrc = (colour: colour) => { 27 + switch (colour) { 28 + case "red": 29 + return mc_red.src; 30 + case "cyan": 31 + return mc_cyan.src; 32 + case "magenta": 33 + return mc_magenta.src; 34 + case "blue": 35 + return mc_blue.src; 36 + } 37 + }; 38 + 39 + const getCssColour = (colour: colour) => { 40 + switch (colour) { 41 + case "red": 42 + return "#af2d25"; 43 + case "cyan": 44 + return "#159b9b"; 45 + case "magenta": 46 + return "#c64ebc"; 47 + case "blue": 48 + return "#3c43a9"; 49 + } 50 + }; 51 + 52 + const scale = 4; 53 + --- 54 + 55 + <div style=`--scale: ${scale}px;` class="map"> 56 + <img 57 + src={mc_map_contents.src} 58 + alt="" 59 + width={58 * scale} 60 + height={58 * scale} 61 + class="map-img" 62 + /> 63 + 64 + { 65 + locations.map((l) => { 66 + // calculate size of map region 67 + const mapSize = 64 * scale; 68 + 69 + interface XY { 70 + y: number; 71 + x: number; 72 + } 73 + 74 + // calculate position of banner 75 + const bannerPos: XY = { 76 + x: l.x * 8 * scale, 77 + y: l.y * 8 * scale, 78 + }; 79 + 80 + // calculate position of text 81 + // coords are inverted so that it doesnt overlap the map 82 + // and so that the line is based properly 83 + // const textPos: XY = { 84 + // x: mapSize + 16 + Math.floor(Math.random() * 30), 85 + // y: mapSize - 32 + Math.floor(Math.random() * 30) - 15, 86 + // }; 87 + 88 + const textPos: XY = { 89 + ...(l.x < 4 90 + ? { x: -132 - Math.floor(Math.random() * 50) } 91 + : { x: mapSize + 32 + Math.floor(Math.random() * 50) }), 92 + ...(l.y < 4 93 + ? { y: 16 + Math.floor(Math.random() * 50) - 25 } 94 + : { y: (mapSize / 4) * 3 + Math.floor(Math.random() * 50) - 25 }), 95 + }; 96 + 97 + // calculate coordinates of corners 98 + const bannerCorner: XY = { 99 + x: bannerPos.x < 128 ? bannerPos.x : bannerPos.x + 8 * scale, 100 + y: bannerPos.y < 128 ? bannerPos.y : bannerPos.y + 8 * scale, 101 + }; 102 + 103 + const textCorner: XY = { 104 + ...textPos, 105 + ...(l.x < 4 ? { x: textPos.x + 100 } : {}), 106 + ...{ y: textPos.y + 10 }, 107 + }; 108 + 109 + // calculate length and angle of line 110 + 111 + const lineLength: number = Math.sqrt( 112 + (bannerCorner.x - textCorner.x) ** 2 + 113 + (bannerCorner.y - textCorner.y) ** 2 114 + ); 115 + 116 + const lineAngle: number = Math.atan2( 117 + bannerCorner.y - textCorner.y, 118 + bannerCorner.x - textCorner.x 119 + ); 120 + 121 + return ( 122 + <a class="location" href={l.href ?? ""}> 123 + <img 124 + src={getSrc(l.colour)} 125 + alt="" 126 + width={8 * scale} 127 + height={8 * scale} 128 + class="marker" 129 + style={`--y: ${bannerPos.y}px; 130 + --x: ${bannerPos.x}px; 131 + --colour: ${getCssColour(l.colour)};`} 132 + /> 133 + <div 134 + style={`--y: ${textPos.y}px; 135 + --x: ${textPos.x}px; 136 + --colour: ${getCssColour(l.colour)}; 137 + text-align: ${l.x < 4 ? "right" : "left"};`} 138 + class="text" 139 + > 140 + {l.name} 141 + </div> 142 + <Arrow 143 + class="line" 144 + style={`--width: ${lineLength}px; 145 + --y: ${textCorner.y}px; 146 + --x: ${textCorner.x}px; 147 + --angle: ${lineAngle}rad; 148 + --colour: ${getCssColour(l.colour)}; 149 + --scaleY: ${!(l.x < 4 != l.y < 4) ? -1 : 1};`} 150 + /> 151 + </a> 152 + ); 153 + }) 154 + } 155 + </div> 156 + 157 + <style> 158 + img { 159 + display: block; 160 + position: absolute; 161 + &.map-img { 162 + top: calc(3 * var(--scale)); 163 + left: calc(3 * var(--scale)); 164 + } 165 + &.marker { 166 + top: var(--y); 167 + left: var(--x); 168 + .location:hover & { 169 + filter: drop-shadow(0 0 0.5rem var(--colour)); 170 + scale: 1.1; 171 + } 172 + } 173 + } 174 + 175 + .text { 176 + position: absolute; 177 + 178 + width: 10rem; 179 + height: 2rem; 180 + 181 + top: var(--y); 182 + left: var(--x); 183 + 184 + color: var(--colour); 185 + .location:hover & { 186 + filter: drop-shadow(0 0 0.5rem var(--colour)); 187 + } 188 + } 189 + 190 + .location { 191 + display: block; 192 + --speed: 100ms; 193 + transition: scale var(--speed), filter var(--speed); 194 + & * { 195 + transition: inherit; 196 + } 197 + } 198 + 199 + .map { 200 + box-sizing: border-box; 201 + width: calc(64 * var(--scale)); 202 + height: calc(64 * var(--scale)); 203 + background-image: url("../../assets/mc_map.png"); 204 + background-size: 100%; 205 + image-rendering: pixelated; 206 + position: relative; 207 + } 208 + </style>
+45 -2
src/pages/index.astro
··· 1 1 --- 2 + // import Map from "@/components/map.astro" 2 3 import Base from "@/layouts/base.astro"; 4 + import Map from "@/components/index/map.astro"; 3 5 --- 4 - 5 6 <Base title="home"> 6 - <h1>Homepage</h1> 7 + <style slot="head"> 8 + body { 9 + width: 100vw; 10 + height: 100vh; 11 + display: flex; 12 + align-items: center; 13 + justify-content: center; 14 + margin: 0; 15 + background-color: #011627; 16 + } 17 + </style> 18 + <Map 19 + locations={[ 20 + { 21 + colour: "red", 22 + name: "Blog", 23 + href: "/blog", 24 + x: 6, 25 + y: 2, 26 + }, 27 + { 28 + colour: "magenta", 29 + name: "Projects", 30 + href: "/projects", 31 + x: 6, 32 + y: 5, 33 + }, 34 + { 35 + colour: "blue", 36 + name: "Hobbies", 37 + href: "/hobbies", 38 + x: 1, 39 + y: 4, 40 + }, 41 + { 42 + colour: "cyan", 43 + name: "Linktree", 44 + href: "/linktree", 45 + x: 3, 46 + y: 2, 47 + }, 48 + ]} 49 + /> 7 50 </Base>