Open tomicapretto opened 11 months ago
Hi! I don't know of a similar library in the Python world. The easiest way to connect d3.js and Shiny right now is probably https://anywidget.dev/, which can be used with Shiny via the shinywidgets package.
(Unfortunately, the below example doesn't work with shinylive.io, or I would've linked you to a live demo; something within anywidgets and/or shinywidgets is asking where on disk the Shiny app lives, and shinylive.io doesn't have an answer.)
import anywidget
import traitlets
from shinywidgets import output_widget, render_widget
from shiny import App, render, ui
class D3PlotWidget(anywidget.AnyWidget):
_esm = """
import * as d3 from "https://esm.sh/d3@7";
export function render({ model, el }) {
// Declare the chart dimensions and margins.
const width = 640;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;
// Declare the x (horizontal position) scale.
const x = d3.scaleUtc()
.domain([new Date(model.get("startDate")), new Date(model.get("endDate"))])
.range([marginLeft, width - marginRight]);
// Declare the y (vertical position) scale.
const y = d3.scaleLinear()
.domain([0, 100])
.range([height - marginBottom, marginTop]);
// Create the SVG container.
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
// Add the x-axis.
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(d3.axisBottom(x));
// Add the y-axis.
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(d3.axisLeft(y));
svg.classed("d3-plot-widget", true)
// Return the SVG element.
el.appendChild(svg.node());
}
"""
_css = """
.d3-plot-widget { border: 1px solid #ea580c; }
"""
startDate = traitlets.Unicode("2023-01-01").tag(sync=True)
endDate = traitlets.Unicode("2024-01-01").tag(sync=True)
app_ui = ui.page_fluid(
ui.input_date_range("dates", "Date range", start="2023-01-01", end="2024-01-01"),
output_widget("widget"),
)
def server(input, output, session):
@render_widget
def widget():
d3plot = D3PlotWidget()
d3plot.startDate = input.dates()[0].strftime("%Y-%m-%d")
d3plot.endDate = input.dates()[1].strftime("%Y-%m-%d")
return d3plot
app = App(app_ui, server)
@jcheng5 thank you very much! I think this is already what I needed. I'll try to use it for the app I'm developing (I was working on it using R Shiny and r2d2) and if you want I can report back. In the meantime, feel free to close the issue or leave it open, as you consider. Thanks again!
@tomicapretto Maybe shinyobservable with docs here is also useful for your usecase.
Thank you for the reference @crazycapivara! For my use case, I was trying to do some 3d visualization and discovered d3 is not good for that. I ended up using {rgl} and {shiny} in R. I you're interested I can point you to the app once it's public :). The app is about sampling from 2d distributions using hamiltonian monte carlo.
This is more a question than an issue (sorry if this is the wrong place!). I've been using Shiny in R a lot. In the past I used the package {r2d3} to include D3.js visualizations in my Shiny apps.
Thanks in advance!