Hi, I’m the guy that made this:
Simple Example - Candlestick Chart From CSV File
After beating my brains out on Plotly docs, I decided to post another example of stuff that should be easy, but just seems there aren’t simple examples of.
Here it is, code first:
## TallTim's Iframe example of how to display text in a defined box, which autoscrolls when contents exceed its dimensions.
## I really wish Plotly would have simple examples like these of how to do things, because it took a newbie like me some time
## to recreate this. Reconsider your documentation, its pretty arcane for someone who is just starting out.
# Import what we need to make things work
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from dash import Dash, html, dcc
# Dash bootstrap for using color themes
import dash_bootstrap_components as dbc # Used to load a bootstrap theme
# Figure template for themes
from dash_bootstrap_templates import load_figure_template
load_figure_template('CYBORG') # Load dark theme
# Using bootstrap themes
app = Dash(__name__, external_stylesheets = [dbc.themes.CYBORG])
## A few functions to show you how I'm making the figures - self contained, so easier to edit properties
def myBlankChart(): # Just puts out empty figure with a text annotation
myFig = go.Figure() # empty chart
# Setting layout parameters
myFig.update_layout(
title="<b> The Endless Void Of Unanswered Forum Posts: </b>", # Bold title, but accurate
xaxis = {"visible":False},
yaxis = {"visible":False},
annotations = [
{
"text": "Showing how to annotate with no figure. (Limited, though.) <br> Here's a new line...",
"xref": "paper",
"yref": "paper",
"showarrow": False,
"font": {"size":18}
}
],
paper_bgcolor='rgb(12,12,12)' # Background color
)
return myFig
# Right pane of our demo page
def myOutputPanel():
# You might question why I had a second row here -- it acts like a spacing buffer for the text box
# There may be other ways to do this, but it worked for me and I'm tired of dealing with Plotly arcane commands
myFig = make_subplots(rows=2, row_heights=[0.70, 0.10], cols=1, vertical_spacing=0.02) # Heights must add up to 1
# Scatter type used as an empty placeholder
myFig.add_trace(go.Scatter(x=[], y=[]), row=1, col=1)
## Adding some other options - just makes it look better, you can change as you wish...
# Remove default rangeslider
myFig.update_layout(xaxis_rangeslider_visible=False)
# Background color
myFig.update_layout(plot_bgcolor='rgb(0,0,0)')
# Axes line color
myFig.update_xaxes(showline=True, linewidth=1, linecolor='dimgray')
myFig.update_yaxes(showline=True, linewidth=1, linecolor='dimgray')
# Tick value display format - yaxis<num> is for subplots
myFig.update_layout(yaxis={"tickformat" : ','}, yaxis2={"tickformat" : '.2f'}) # Displays thousands,hundreds without scientific 'K' notation
# Grid line color
myFig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='dimgray')
myFig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='dimgray')
# Adjusting font sizes - You must have this font on your system or it won't work...
myFig.update_layout(
font=dict(
family="Microsoft Sans Serif", # <-- Only works if you have this font installed
size=12, color='rgb(160,166,184)' # Light Gray
),
margin=dict(l=1, r=70, b=0, t=40, pad=1) # Adjusts margin of the figure, also can change subplot height/width above if needed
)
# Placeholder chart title
myFig.update_layout(title="TallTimTestChart", title_x=0.5, yaxis_title="Price")
# Sets the plot background color - note, 'paper' is not the figure background color! Its the borders and the rest...
myFig.update_layout(paper_bgcolor='rgb(12,12,12)') # Dark grey background
# Fixed axes for no zoom - change values if you want to enable this
myFig.update_xaxes(fixedrange=True)
myFig.update_yaxes(fixedrange=True)
return myFig
# Text for Iframe, obeys CSS/HTML rules, but you need to escape the surrounding quotemarks like I have
test_text = "<span style=\"color:white; background:transparent; font-family:Arial,Helvectica,sans-serif; font-size: 16px;\">HOLY MOLY, a scrollable text box!!!!! <br>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus pulvinar aliquam. Ut aliquet tristique nisl vitae volutpat. Nulla aliquet porttitor venenatis. Donec a dui et dui fringilla consectetur id nec massa. Aliquam erat volutpat. Sed ut dui ut lacus dictum fermentum vel tincidunt neque. Sed sed lacinia lectus. Duis sit amet sodales felis. Duis nunc eros, mattis at dui ac, convallis semper risus. In adipiscing ultrices tellus, in suscipit massa vehicula eu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus *end* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus pulvinar aliquam. Ut aliquet tristique nisl vitae volutpat. Nulla aliquet porttitor venenatis. Donec a dui et dui fringilla consectetur id nec massa. Aliquam erat volutpat. Sed ut dui ut lacus dictum fermentum vel tincidunt neque. Sed sed lacinia lectus. Duis sit amet sodales felis. Duis nunc eros, mattis at dui ac, convallis semper risus. In adipiscing ultrices tellus, in suscipit massa vehicula eu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus *end* Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus pulvinar aliquam. Ut aliquet tristique nisl vitae volutpat. Nulla aliquet porttitor venenatis. Donec a dui et dui fringilla consectetur id nec massa. Aliquam erat volutpat. Sed ut dui ut lacus dictum fermentum vel tincidunt neque. Sed sed lacinia lectus. Duis sit amet sodales felis. Duis nunc eros, mattis at dui ac, convallis semper risus. In adipiscing ultrices tellus, in suscipit massa vehicula eu. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam hendrerit nisi sed sollicitudin pellentesque. Nunc posuere purus rhoncus </span>"
# Setting up a dynamic graph container
# Only way to get graph to fill full height was to add -- style={'height':'100vh'} to the main layout Div container
# Config settings go inside the dcc.Graph, instead of fig.show() for setting scroll/zoom
# This was way more of a pain in the ass to find a solution to than it should've been for both of the above...
# Nothing to scroll/zoom on a blank chart, but including just to show how...
graph_container = html.Div([
dcc.Graph(figure = myBlankChart(), id='chart-placeholder', style={'height':'100vh','width':'50vw'}, config = dict({'scrollZoom' : True}))
])
# Right side pane/block
output_container = html.Div([
dcc.Graph(figure = myOutputPanel(), id='output', style={'height':'70vh','width':'50vw'},
config={'displayModeBar': False} # Removed toolbar and prevent pan/zoom - change if you need it
),
# Iframe gets defined here so it shows under the chart/figure
html.Iframe(srcDoc=test_text, style={'width': '100%','height' : 240, 'scrolling' : 'auto'})
])
content = html.Div(
[
graph_container
]
)
# This creates a stack that places the windows side-by-side -- took a bit to find out how this worked...
myStack = html.Div([
dbc.Stack(
[
content, output_container
],
direction="horizontal" # The key setting that enables side-by-side placement
)
])
# Now we tie it all together in a final structure
page_structure = [
dbc.Row([
myStack
])
]
# This allows for dynamic resizing of this page using our final page_structure
app.layout = dbc.Container(
children=page_structure,
fluid=True
)
# Run the App
if __name__ == '__main__':
app.run_server(debug=True,host='0.0.0.0',port=8060) # Set host argument to allow LAN connections, Port for custom ports
Here’s a screenshot:
Note: Due to browser differences, the textbox text color and background may appear different - refer to CSS styling to change this to what you want. (I tested this in Waterfox, just what I had open. Firefox/Chrome doesn’t like the text styling directives, so the text is on a white background and isn’t very legible.)
Hope it helps someone, was a bear getting all this together.
Some CSS Resources: