Skip to content

my love is like a fire tornado¤

jump to demo

%%
some sound to play for some extra texture, the element is resizable so you can stifle extra stimuli.

<section id="sound">
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen="" frameborder="0" height="315" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/qBAPsQkS8QI?si=CkA51qfeJeLb9Mfw" title="YouTube video player" width="560"></iframe>
</section>

    from nbconvert_a11y.table import new
    bs4.Tag._repr_html_ = bs4.Tag.prettify    
    words = \
last 🌃 my wife and i had a sweet date drinking boba, playing pinball, seeing 🌪twisters🌪 with the likable glen powell, and eating 🍔. i 🫶 her a lot. also, 🔥 tornado!

    df = DataFrame(index=pandas.RangeIndex(len(words)), columns=["θ", "x", "y", "z", "letter"])
    df.θ = df.index * numpy.pi / 28
    df.x = (df.index * numpy.pi / 180).map(numpy.cos)
    df.y = df.index / 10
    df.z = (df.index * numpy.pi / 180).map(numpy.sin)
    df.letter = list(new("td", x) for x in words)
    section = df.table(dict(max_rows=1000, figcaption=-1), caption=words, id="twisters")
hide the table because its content is repeated in the figure caption

    section.html.table.attrs.update({"aria-hidden": "true"})    
    display(section); display\
```css
@property --r {
    syntax: "<angle>";
    initial-value: 0deg;
    inherits: true;
}
#twisters {
    --w: 480px;
    --h: 600px;
    --d: 600px;
    --r: 0deg;
    --t: 15s;
    thead, tfoot {display: none;}
    tbody {
        display: block;
        width: var(--w);
        height: var(--h);
        animation: var(--t) infinite linear spin;
        transform: rotateY(var(--r));
        transform-style: preserve-3d;
        tr {
            background: unset !important;
            transform-style: preserve-3d;
            position: absolute;
            --wiggle: calc(sin(var(--0) * 10rad) * -1px);
            th, td {display: none;}
            td:last-child {
                display: block; font-weight: bold; font-size: 1.5rem;
            }
            transform: 
                translate3d(
                    calc((var(--1) - var(--1-min)) / var(--1-diff) * var(--w) / 3 + var(--wiggle) / 2),
                    calc((var(--2) - var(--2-min)) / var(--2-diff) * var(--h) ),
                    calc((var(--3) - var(--3-min)) / var(--3-diff) * var(--d) - var(--d) / 3 + var(--wiggle) / 2)
                )
                translateX(calc(var(--w) / 2))
                translate(-50%, -50%)
                rotateY(calc(var(--0) * 1rad))
                ;
        }
    }
}
#sound {resize: both; overflow: auto; filter: grayscale(100%);}
@supports (background: -moz-element(#twisters)) {
    [href="#twisters"] {
        display: block; width: 100%; height: 400px;
        font-weight: 1000;
        font-size: 5rem;
        background: -moz-element(#twisters); 
        background-size: contain; 
        filter: grayscale(100%);}}
/** i think keyframes need to go last **/
@keyframes spin { 0% { --r: 0deg; } 100% { --r: 360deg; } }
```
last 🌃 my wife and i had a sweet date drinking boba, playing pinball, seeing 🌪twisters🌪 with the likable glen powell, and eating 🍔. i 🫶 her a lot. also, 🔥 tornado!

some sound to play for some extra texture, the element is resizable so you can stifle extra stimuli.

from nbconvert_a11y.table import new
bs4.Tag._repr_html_ = bs4.Tag.prettify    
words = \

last 🌃 my wife and i had a sweet date drinking boba, playing pinball, seeing 🌪twisters🌪 with the likable glen powell, and eating 🍔. i 🫶 her a lot. also, 🔥 tornado!

df = DataFrame(index=pandas.RangeIndex(len(words)), columns=["θ", "x", "y", "z", "letter"])
df.θ = df.index * numpy.pi / 28
df.x = (df.index * numpy.pi / 180).map(numpy.cos)
df.y = df.index / 10
df.z = (df.index * numpy.pi / 180).map(numpy.sin)
df.letter = list(new("td", x) for x in words)
section = df.table(dict(max_rows=1000, figcaption=-1), caption=words, id="twisters")

hide the table because its content is repeated in the figure caption

section.html.table.attrs.update({"aria-hidden": "true"})    
display(section); display\
@property --r {
    syntax: "<angle>";
    initial-value: 0deg;
    inherits: true;
}
#twisters {
    --w: 480px;
    --h: 600px;
    --d: 600px;
    --r: 0deg;
    --t: 15s;
    thead, tfoot {display: none;}
    tbody {
        display: block;
        width: var(--w);
        height: var(--h);
        animation: var(--t) infinite linear spin;
        transform: rotateY(var(--r));
        transform-style: preserve-3d;
        tr {
            background: unset !important;
            transform-style: preserve-3d;
            position: absolute;
            --wiggle: calc(sin(var(--0) * 10rad) * -1px);
            th, td {display: none;}
            td:last-child {
                display: block; font-weight: bold; font-size: 1.5rem;
            }
            transform: 
                translate3d(
                    calc((var(--1) - var(--1-min)) / var(--1-diff) * var(--w) / 3 + var(--wiggle) / 2),
                    calc((var(--2) - var(--2-min)) / var(--2-diff) * var(--h) ),
                    calc((var(--3) - var(--3-min)) / var(--3-diff) * var(--d) - var(--d) / 3 + var(--wiggle) / 2)
                )
                translateX(calc(var(--w) / 2))
                translate(-50%, -50%)
                rotateY(calc(var(--0) * 1rad))
                ;
        }
    }
}
#sound {resize: both; overflow: auto; filter: grayscale(100%);}
@supports (background: -moz-element(#twisters)) {
    [href="#twisters"] {
        display: block; width: 100%; height: 400px;
        font-weight: 1000;
        font-size: 5rem;
        background: -moz-element(#twisters); 
        background-size: contain; 
        filter: grayscale(100%);}}
/** i think keyframes need to go last **/
@keyframes spin { 0% { --r: 0deg; } 100% { --r: 360deg; } }