%%html
<input id="user-input" type="number" value="2">
<button onclick="calculate()">Compute Square</button>
<p id="calc-result"></p>
<script>
function calculate() {
// 1. Get the number the student typed
let value = document
.getElementById("user-input")
.value;
// 2. Do the math
let result = value * value;
// 3. Show the result
document
.getElementById("calc-result")
.innerText = "Result: " + result;
}
</script>6 Interactive Colab Guide
6.1 HTML + JavaScript
Hyper-Text Markup Language, HTML, is the most common programming paradigm in the world, by sheer volume. Every webpage is built on it.
Colab, even if originally aimed at python, has a feature to build magic cells. Preceed html cells with %%html to tell colab to interpret it as such.
Inside it, you can use Javascript as any webpage would.
6.2 SVG Integration
You can also embed Scalable Vector Graphics (SVG) directly into your Colab notebook using the same %%html magic command.
%%html
<svg width="200" height="200">
<circle cx="100"
cy="100"
r="80"
stroke="red" stroke-width="4"
fill="tomato" />
<text
x="50%" y="50%"
text-anchor="middle"
fill="black" font-size="20px"
dy=".3em">SVG Circle</text>
</svg>7 Animating svg
%%html
<svg width="400" height="400">
<circle id="animated-circle"
cx="50%"
cy="50%"
r="80"
stroke="red" stroke-width="4"
fill="tomato" />
<text
x="50%" y="50%"
text-anchor="middle"
fill="black" font-size="20px"
dy=".3em">SVG Circle</text>
</svg>
<br>
<button onclick="startAnimation()">Animate Circle</button>
<script>
let animating = false;
let r = 80;
let growing = false;
function startAnimation() {
if (animating) return; // Prevent multiple loops
animating = true;
let circle = document.getElementById("animated-circle");
function frame() {
if (growing) {
r += 0.1;
if (r >= 120) growing = false;
} else {
r -= 1;
if (r <= 80) growing = true;
}
circle.setAttribute("r", r);
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
}
</script>%%html
<input type="range" min="0" max="10" value="5" id="my-slider" oninput="updateSlider()">
<p id="slider-display"></p>
<script>
function updateSlider() {
let v = document.getElementById("my-slider").value;
document.getElementById("slider-display").innerText = "Current Value: " + v;
}
</script>%%html
<div style="text-align: center; width: 300px;">
<svg width="200" height="200">
<!-- A rectangle with rx and ry equal to half its width/height is a circle -->
<rect id="morph-shape"
x="10" y="10"
width="180" height="180"
rx="90" ry="90"
fill="tomato"
stroke="red" stroke-width="4" />
</svg>
<br><br>
<input type="range" id="morph-slider" min="0" max="90" value="90" oninput="morphShape()" style="width: 100%;">
<p id="morph-label">Shape: Circle (rx=90)</p>
</div>
<script>
function morphShape() {
let sliderValue = document.getElementById("morph-slider").value;
let shape = document.getElementById("morph-shape");
let label = document.getElementById("morph-label");
// Update the corner radius
shape.setAttribute("rx", sliderValue);
shape.setAttribute("ry", sliderValue);
// Update the label text
if (sliderValue == 0) {
label.innerText = "Shape: Square (rx=0)";
} else if (sliderValue == 90) {
label.innerText = "Shape: Circle (rx=90)";
} else {
label.innerText = "Shape: Squircle (rx=" + sliderValue + ")";
}
}
</script>Shape: Circle (rx=90)
%%html
<canvas id="myChart"></canvas>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
let ctx = document.getElementById('myChart');
let chart = new Chart(ctx, {
type: 'line', // You can change this to 'bar' or 'pie'
data: {
labels: [0, 1, 2, 3, 4], // The X-axis
datasets: [{
label: 'y = x^2',
data: [0, 1, 4, 9, 16] // The Y-axis
}]
}
});
</script>%%html
<input id="answer" type="number">
<button onclick="check()">Submit</button>
<p id="feedback"></p>
<script>
function check() {
// Your grading logic here
}
</script8 Shinny Live
!pip install shinyliveRequirement already satisfied: shinylive in /usr/local/lib/python3.12/dist-packages (0.8.6)
Requirement already satisfied: shiny in /usr/local/lib/python3.12/dist-packages (from shinylive) (1.6.0)
Requirement already satisfied: click>=8.1.7 in /usr/local/lib/python3.12/dist-packages (from shinylive) (8.3.1)
Requirement already satisfied: appdirs>=1.4.4 in /usr/local/lib/python3.12/dist-packages (from shinylive) (1.4.4)
Requirement already satisfied: lzstring>=1.0.4 in /usr/local/lib/python3.12/dist-packages (from shinylive) (1.0.4)
Requirement already satisfied: typing-extensions>=4.0.1 in /usr/local/lib/python3.12/dist-packages (from shinylive) (4.15.0)
Requirement already satisfied: setuptools in /usr/local/lib/python3.12/dist-packages (from shinylive) (75.2.0)
Requirement already satisfied: chevron>=0.14.0 in /usr/local/lib/python3.12/dist-packages (from shinylive) (0.14.0)
Requirement already satisfied: future>=0.14.0 in /usr/local/lib/python3.12/dist-packages (from lzstring>=1.0.4->shinylive) (1.0.0)
Requirement already satisfied: uvicorn>=0.16.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.42.0)
Requirement already satisfied: starlette in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.52.1)
Requirement already satisfied: websockets>=13.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (15.0.1)
Requirement already satisfied: htmltools>=0.6.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.6.0)
Requirement already satisfied: markdown-it-py>=1.1.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (4.0.0)
Requirement already satisfied: mdit-py-plugins>=0.3.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.5.0)
Requirement already satisfied: linkify-it-py>=1.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (2.1.0)
Requirement already satisfied: platformdirs>=2.1.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (4.9.4)
Requirement already satisfied: asgiref>=3.5.2 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (3.11.1)
Requirement already satisfied: packaging>=20.9 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (26.0)
Requirement already satisfied: watchfiles>=0.18.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (1.1.1)
Requirement already satisfied: questionary>=2.0.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (2.1.1)
Requirement already satisfied: prompt-toolkit in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (3.0.52)
Requirement already satisfied: python-multipart>=0.0.7 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.0.22)
Requirement already satisfied: narwhals>=1.10.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (2.18.0)
Requirement already satisfied: orjson>=3.10.7 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (3.11.7)
Requirement already satisfied: shinychat>=0.1.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (0.2.9)
Requirement already satisfied: opentelemetry-api>=1.20.0 in /usr/local/lib/python3.12/dist-packages (from shiny->shinylive) (1.38.0)
Requirement already satisfied: uc-micro-py in /usr/local/lib/python3.12/dist-packages (from linkify-it-py>=1.0->shiny->shinylive) (2.0.0)
Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.12/dist-packages (from markdown-it-py>=1.1.0->shiny->shinylive) (0.1.2)
Requirement already satisfied: importlib-metadata<8.8.0,>=6.0 in /usr/local/lib/python3.12/dist-packages (from opentelemetry-api>=1.20.0->shiny->shinylive) (8.7.1)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.12/dist-packages (from prompt-toolkit->shiny->shinylive) (0.6.0)
Requirement already satisfied: h11>=0.8 in /usr/local/lib/python3.12/dist-packages (from uvicorn>=0.16.0->shiny->shinylive) (0.16.0)
Requirement already satisfied: anyio>=3.0.0 in /usr/local/lib/python3.12/dist-packages (from watchfiles>=0.18.0->shiny->shinylive) (4.12.1)
Requirement already satisfied: idna>=2.8 in /usr/local/lib/python3.12/dist-packages (from anyio>=3.0.0->watchfiles>=0.18.0->shiny->shinylive) (3.11)
Requirement already satisfied: zipp>=3.20 in /usr/local/lib/python3.12/dist-packages (from importlib-metadata<8.8.0,>=6.0->opentelemetry-api>=1.20.0->shiny->shinylive) (3.23.0)
8.1 Integrating with Quarto (GitHub Pages)
If you are building a Quarto book or website and hosting it on a static server like GitHub Pages, you cannot run a live Python server in the background. Instead, you use Shinylive, which runs Python entirely inside the user’s browser using WebAssembly.
To enable this, open your terminal, navigate to your Quarto project folder, and run the following command to install the extension:
from shiny import App, render, ui
import numpy as np
import matplotlib.pyplot as plt
# 1. The User Interface
app_ui = ui.page_fluid(
ui.h3("Explore a Sine Wave"),
ui.input_slider("frequency", "Wave Frequency", min=1, max=10, value=5),
ui.output_plot("wave_plot")
)
# 2. The Logic
def server(input, output, session):
@output
@render.plot
def wave_plot():
# Get the slider value
freq = input.frequency()
# Calculate the math
x = np.linspace(0, 2 * np.pi, 100)
y = np.sin(freq * x)
# Draw the plot
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_ylim(-1.5, 1.5)
return fig
# 3. Create App
app = App(app_ui, server)
# 4. Simply call the app object to render it inline in Colab!
app<shiny._app.App at 0x7e06dda54080>