//- you can change these two values
- let n_rings = 18 /* must be even */, n_sides = 24;
- let n = n_rings*n_sides;
style
- for(let i = 0; i < n_rings; i++)
| .area:nth-child(n + #{n_sides*i + 1}) { --i: #{i} }
- for(let i = 0; i < n_sides; i++)
| .area:nth-child(#{n_sides}n + #{i + 1}) { --j: #{i} }
section.scene
div(class='🌐' style=`--n-rings: ${n_rings}; --n-sides: ${n_sides}`)
while n--
.area
.prompt scroll
View Compiled
$r: 23vmin; // sphere inradius
body { height: 200vh }
section, div { display: grid }
svg[height='0'], .scene { position: fixed }
div {
grid-area: 1/ 1;
place-self: center
}
.scene {
inset: 0;
perspective: 25em;
background:
url(https://assets.codepen.io/2017/night_sky.jpg)
50%/ cover #212121;
background-blend-mode: multiply;
&::before, &::after {
grid-area: 1/ 1;
margin: 0 auto;
padding: .5em;
max-width: 18em;
color: #121212;
font: clamp(.625em, 6.5vmin, 3.25em) neonderthaw, cursive;
text-align: center;
content: 'Dedicated to the person who taught me about Jupiter some 35 years ago. Missing you.'
}
&::after {
align-self: end;
mix-blend-mode: multiply;
content: '1 June 1927 - 18 January 2019'
}
}
.🌐 {
transform-style: preserve-3d;
rotate: x -60deg;
will-change: transform;
animation:
ry 16s linear infinite,
rx 1s linear forwards;
}
@supports (animation-timeline: auto, scroll()) {
.🌐 { animation-timeline: auto, scroll() }
@keyframes rx { to { rotate: x 60deg } }
}
@supports not (animation-timeline: auto, scroll()) {
.prompt { display: none }
}
@keyframes ry { to { transform: rotatey(1turn) } }
.area {
--dif-i: calc(var(--i) - .5*(var(--n-rings) - 1));
--sgn-i: clamp(-1, 2*var(--dif-i), 1);
--rnd-i: round(to-zero, var(--dif-i), 1);
/* get around lack of support for abs() in Firefox */
--abs-i: max(var(--rnd-i), -1*var(--rnd-i));
--bay: calc(360deg/var(--n-sides));
--hay: calc(180deg/var(--n-sides));
--bax: calc(180deg/var(--n-rings));
--hax: calc(90deg/var(--n-rings));
--l: calc(2*#{$r}*tan(var(--hax)));
--f0: cos(var(--abs-i)*var(--bax));
--f1: cos((var(--abs-i) + 1)*var(--bax));
--y0: sin(var(--abs-i)*var(--bax));
--y1: sin((var(--abs-i) + 1)*var(--bax));
--rx: atan2(var(--f0) - var(--f1), var(--y1) - var(--y0));
--oy0: calc((var(--sgn-i) - 1)*-50%);
--oy1: calc((var(--sgn-i) + 1)*50%);
--w: calc(var(--f0)*2*#{$r}*tan(var(--hay)));
width: var(--w);
height: var(--l);
//backface-visibility: hidden;
perspective-origin: 50% var(--oy1);
perspective: calc(max(.1, var(--f1))*var(--l)/(var(--f0) - var(--f1)));
transform-origin: 50% var(--oy0);
transform:
rotatey(calc(var(--j)*var(--bay)))
translate3d(
0,
calc(var(--sgn-i)*(50% + #{$r}*var(--y0))),
calc(var(--f0)*#{$r}))
rotatex(calc(-1*var(--sgn-i)*var(--rx)));
clip-path:
polygon(
calc((1 - var(--f1)/var(--f0))*50%) var(--oy1),
calc((1 + var(--f1)/var(--f0))*50%) var(--oy1),
100% var(--oy0),
0 var(--oy0));
filter:
drop-shadow(0 0 1px wheat)
drop-shadow(0 0 1px peachpuff);
&::after {
transform-origin: inherit;
transform:
matrix3d(1, 0, 0, 0,
0, 1, calc(-1*var(--sgn-i)), 0,
0, 0, 1, 0,
0, 0, 0, 1);
background:
url(https://assets.codepen.io/2017/jupiter_projection.jpg)
calc(-1*var(--j)*var(--w)) calc(-1*var(--i)*var(--l))/
calc(var(--n-sides)*100%) calc(var(--n-rings)*100%);
content: ''
}
}
/* fallback if round() is not supported in Chrome */
@supports not (z-index: Round(to-zero, 8.5, 1)) {
@property --rnd-i {
syntax: '<integer>';
initial-value: 0;
inherits: true
}
.area { --rnd-i: calc(var(--dif-i) - var(--sgn-i)*.5) }
}
.prompt {
grid-auto-flow: column;
align-items: center;
justify-self: end;
padding: .5em;
color: ivory;
font: 1.25em montserrat, sans-serif;
writing-mode: vertical-rl;
text-orientation: upright;
text-transform: uppercase;
&::before, &::after { font-size: 1.5em }
&::before { content: '↑' }
&::after { content: '↓' }
&::selection { background: darkorange }
}
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.