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