💥 Update interactive Globe with latest features

It was long and painful but it's finally looking neat!

- place markers on globe following camera world matrix
- show location on marker hover instead of showing label near dot
- make marker easier to select
- make rotation constant no matter the monitor refresh rate by using a delta timed animation
- [wip] lighting the globe with a dark area / todo: how to get current sun lighting from a location?

Merci Julien :)
This commit is contained in:
2022-09-24 23:42:00 +02:00
parent b764b4d1d1
commit 71625dbce0
13 changed files with 394 additions and 422 deletions

View File

@@ -4,46 +4,93 @@
position: relative;
z-index: 10;
user-select: none;
overflow: hidden;
// Inner
&__inner {
// Canvas
&__canvas {
position: relative;
width: var(--width);
z-index: 2;
left: 50%;
transform: translateX(-50%);
transform: translateX(-50%) translateZ(0);
width: var(--width);
// Responsive square padding
&:after {
content: "";
display: block;
padding-bottom: 100%;
}
// Overlay
&:before {
content: "";
display: block;
position: absolute;
z-index: 21;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
pointer-events: none;
border-radius: 100%;
background: $color-primary;
transition: opacity 1.5s var(--ease-quart);
}
:global(canvas) {
position: absolute;
z-index: 10;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: grab;
}
// Is faded under name
&:global(.is-faded:before) {
opacity: 0.65;
}
}
// Canvas
&__canvas {
// Location name
&__location {
position: absolute;
z-index: 2;
top: 0;
left: 50%;
transform: translate3d(-50%, 0, 0);
width: 100%;
height: 100%;
}
:global(canvas) {
position: absolute;
z-index: 10;
top: 0;
z-index: 30;
top: 50%;
left: 0;
width: 100%;
height: 100%;
cursor: grab;
overflow: hidden;
transform: translateY(-50%) translateZ(0);
pointer-events: none;
text-align: center;
:global(.char) {
transition: none;
}
:global(.name) {
font-family: $font-serif;
font-weight: 100;
letter-spacing: -0.035em;
color: $color-secondary;
font-size: clamp(#{rem(88px)}, 20vw, #{rem(320px)});
}
.country {
display: block;
text-transform: uppercase;
font-size: rem(14px);
color: $color-tertiary;
letter-spacing: 0.1em;
font-weight: 500;
}
}
// Markers
&__markers {
position: absolute;
z-index: 2;
top: 0;
left: 0;
position: relative;
z-index: 20;
pointer-events: none;
user-select: none;
@@ -61,178 +108,51 @@
left: 0;
user-select: none;
transform: translate3d(var(--x), var(--y), 0);
transition: opacity 0.4s var(--ease-quart);
a {
position: relative;
top: -10px;
left: -10px;
display: block;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
color: $color-secondary;
pointer-events: auto;
dl > * {
transition: opacity 0.5s;
}
dt {
line-height: 1;
}
dd {
color: $color-gray;
margin-top: 4px;
line-height: 1;
opacity: 0;
}
// Dot
&:before {
content: "";
i {
display: block;
position: absolute;
top: 10px;
left: -16px;
width: 8px;
height: 8px;
border-radius: 100%;
width: 10px;
height: 10px;
border-radius: 32px;
background: $color-secondary;
transition: box-shadow 0.4s var(--ease-quart), transform 0.4s var(--ease-quart);
transform-origin: 50% 50%;
}
}
/*
** States
*/
// Has name
&:global(.is-dot-only) {
dt, dd {
opacity: 0;
// Name
span {
display: none;
}
}
// Has country
&:global(.has-country) {
dd {
opacity: 1;
}
}
}
// Cluster
&__cluster {
position: absolute;
z-index: 10;
top: 300px;
left: 300px;
pointer-events: auto;
button {
width: 32px;
height: 32px;
padding: 0;
border: none;
border-radius: 100%;
background: rgba($color-secondary, 0.2);
transition: box-shadow 0.5s var(--ease-quart), background 0.5s var(--ease-quart);
}
&:hover {
button {
background: rgba($color-secondary, 0.3);
box-shadow: 0 0 0 8px rgba($color-secondary, 0.1);
}
}
}
// Popin
&__popin {
position: absolute;
z-index: 10;
top: 12vw;
left: 50%;
transform: translate3d(-50%, 0, 0);
pointer-events: auto;
width: 546px;
padding: 24px 32px;
border-radius: 16px;
background: #fff;
--shadow-color: #{rgba(45, 4, 88, 0.05)};
box-shadow:
0 6px 6px var(--shadow-color),
0 12px 12px var(--shadow-color),
0 24px 24px var(--shadow-color),
0 40px 40px var(--shadow-color);
ul {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px 16px;
}
li {
display: block;
transform: translateZ(0);
}
a {
display: flex;
align-items: center;
padding: 12px;
border-radius: 6px;
text-decoration: none;
transition: background 0.3s var(--ease-quart);
// Hover: Grow marker outline
&:hover {
background: rgba($color-secondary, 0.1);
i {
box-shadow: 0 0 0 10px rgba($color-tertiary, 0.25);
}
}
}
// Flag
:global(.flag) {
display: block;
width: 28px;
height: 28px;
overflow: hidden;
border-radius: 100%;
transform: translateZ(0);
// State: Is hidden
&:global(.is-hidden) {
opacity: 0;
:global(img) {
display: block;
width: 100%;
height: 100%;
}
}
// Details
dl {
margin-left: 16px;
}
dt {
margin-bottom: 4px;
line-height: 1.2;
}
dd {
color: $color-gray;
line-height: 1;
}
// Close buttom
.close {
position: absolute;
z-index: 2;
top: 12px;
right: 12px;
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
color: $color-primary-darker;
background: rgba($color-secondary, 0.15);
border-radius: 100%;
transition: background 0.3s var(--ease-quart);
svg {
display: block;
width: 9px;
height: 9px;
}
&:hover {
background: rgba($color-secondary, 0.3);
i {
transform: scale(0) translateZ(0);
}
}
}