3D Book Image CSS generator using experimental_get-set_query_params

I saw the 3D Book Image CSS generator and I had some time between meetings, here’s a quickly implemented Streamlit version ahah.

It was also a good opportunity to test the latest st.experimental_(get|set)_query_params to store some of the book parameters in the query and create a bookmark. Careful this works only on streamlit-nightly now, but it should be released soon…

app.py
import streamlit as st
import streamlit.components.v1 as components

app_state = st.experimental_get_query_params()
app_state = {k: v[0] if isinstance(v, list) else v for k, v in app_state.items()} 

image_url = st.sidebar.text_input("Image URL", "https://d2sofvawe08yqg.cloudfront.net/outstanding-developer/hero2x?1595108679")
bg_color = st.sidebar.beta_color_picker("Book color", "#01060f")
app_state['rotate'] = st.sidebar.slider("Rotate (deg)", 0, 45, 30)
app_state['rotate_hover'] = st.sidebar.slider("Rotate (hover) (deg)", 0, 45, 0)
perspective = st.sidebar.slider("Perspective (px)", 300, 1300, 600)
transition_duration = st.sidebar.slider("Animation duration (s)", 0, 5, 1)
radius = st.sidebar.slider("Radius (px)", 0, 5, 2)
thickness = st.sidebar.slider("Thickness (px)", 5, 100, 50)
width = st.sidebar.slider("Width (px)", 50, 300, 200)
height = st.sidebar.slider("Height (px)", 75, 450, 300)
pages_offset = st.sidebar.slider("Pages offset (px)", 0, 10, 3)

st.experimental_set_query_params(**app_state)

st.title("3D Book Image CSS Generator")
st.markdown("Check the original implementation : https://3d-book-css.netlify.app/ or https://github.com/scastiel/3d-book-image-css-generator")

html = f"""
<!DOCTYPE html>
<html>
<head>
<style>
.book-container {{
  margin: 100px;
  display: flex;
  align-items: center;
  perspective: {perspective}px;
}}

.book {{
  width: {width}px;
  height: {height}px;
  position: relative;
  transform-style: preserve-3d;
  transform: rotateY({-app_state['rotate']}deg);
  transition: {transition_duration}s ease;
  animation: 1s ease 0s 1 initAnimation;
}}

.book:hover {{
  transform: rotateY({-app_state['rotate_hover']}deg);
}}

@keyframes initAnimation {{
  0% {{
    transform: rotateY({-app_state['rotate_hover']}deg);
  }}
  100% {{
    transform: rotateY({-app_state['rotate']}deg);
  }}
}}

.book > :first-child {{
  position: absolute;
  top: 0;
  left: 0;
  background-color: red;
  width: {width}px;
  height: {height}px;
  transform: translateZ({thickness / 2}px);
  background-color: {bg_color};
  border-radius: 0 {radius}px {radius}px 0;
  box-shadow: 5px 5px 20px #666;
}}

.book::before {{
  position: absolute;
  content: ' ';
  background-color: blue;
  left: 0;
  top: {pages_offset}px;
  width: {thickness - 2}px;
  height: {height - 2 * pages_offset}px;
  transform: translateX({width - thickness / 2 - pages_offset}px) rotateY(90deg);
  background: linear-gradient(90deg, 
    #fff 0%,
    #f9f9f9 5%,
    #fff 10%,
    #f9f9f9 15%,
    #fff 20%,
    #f9f9f9 25%,
    #fff 30%,
    #f9f9f9 35%,
    #fff 40%,
    #f9f9f9 45%,
    #fff 50%,
    #f9f9f9 55%,
    #fff 60%,
    #f9f9f9 65%,
    #fff 70%,
    #f9f9f9 75%,
    #fff 80%,
    #f9f9f9 85%,
    #fff 90%,
    #f9f9f9 95%,
    #fff 100%
    );
}}

.book::after {{
  position: absolute;
  top: 0;
  left: 0;
  content: ' ';
  width: {width}px;
  height: {height}px;
  transform: translateZ(-{thickness / 2}px);
  background-color: ${bg_color};
  border-radius: 0 {radius}px {radius}px 0;
  box-shadow: -10px 0 50px 10px #666;
}}
</style>
</head>
<body>
<div class="book-container">
  <div class="book">
    <img src="{image_url}"/>
  </div>
</div>
</body>
</html>
"""
components.html(html, height=height + 200)
5 Likes

Great stuff! Did you deploy it yet?

I have to admit I did not intend to deploy it, but the gist should be functional :wink:

Maybe when Streamlit For Teams gets out of beta I’ll deploy it.

Sounds great! Sent you a request via LinkedIn. Maybe we could work on something nice :slight_smile:

What version of streamlit is this? I get the error: AttributeError: module 'streamlit' has no attribute 'experimental_get_query_params'

Try pip install streamlit-nightly first (maybe in another python environment)