title: Plotly-Dash: How to improve plot responsiveness to slider changes
body: <p>I'm developing a tool to visualize the effects of a set of parameters on a mathematical function by modifying those parameters via Dash sliders. I'm using the approach from a few of the Dash tutorial examples which use a callback to replace the figure.</p>
  <p>This works, but the plot isn't as responsive to slider changes as built-in operations such as rotating the plot via dragging. This is especially the case when there are many elements in the figure.</p>
  <p><strong>Is there a different approach that will improve responsiveness? For example, is there a way to target only the plot elements that changed rather than replacing the entire figure?</strong></p>
  <p>Here's a minimal working example consisting of a static circle (with many samples) and a line segment that we rotate via a slider. Rotation of the line segment is quite choppy.</p>
  <pre class="lang-py prettyprint-override"><code>import dash
  import dash_core_components as dcc
  import dash_html_components as html
  import plotly.graph_objects as go
  from dash.dependencies import Input, Output, State
  import numpy as np
  
  app = dash.Dash(__name__)
  
  # plot a circle
  t = np.linspace(0, 2*np.pi, 10000)  # intentionally use many points to exaggerate the issue
  x = np.cos(t)
  y = np.sin(t)
  z = np.zeros_like(t)
  marker_size = 4
  fig = go.Figure()
  fig.add_trace(go.Scatter3d(x=x, y=y, z=z, mode='lines'))
  fig.add_trace(go.Scatter3d(
      x=[0.0, 0.0], y=[0.0, 0.0], z=[0.0, 0.0],
      marker=go.scatter3d.Marker(size=marker_size),
      line=dict(width=3.0),
      showlegend=False,
  ))
  
  fig.update_layout(
      uirevision='constant',
      autosize=False,
      width=900,
      height=900,
      scene=dict(
          xaxis=dict(range=[-1, 1]),
          yaxis=dict(range=[-1, 1]),
          zaxis=dict(range=[-1, 1.0]),
          aspectratio=dict(x=2, y=2, z=2),
      ),
  )
  
  app.layout = html.Div(children=[
      dcc.Graph(
          id='example-graph',
          figure=fig
      ),
      html.Div(
          [
              dcc.Slider(
                  id='slider-phi',
                  min=0.0,
                  max=360.0,
                  step=1.0,
                  value=0.0,
                  marks={0: '0', 180: '180', 360: '360'},
                  updatemode='drag',
              ),
          ],
          style=dict(width='50%'),
      ),
      html.Div(children='', id='output-box'),
  ])
  
  @app.callback(
      Output('example-graph', 'figure'),
      [Input('slider-phi', 'value')],
      [State('example-graph', 'figure')]
  )
  def display_structure(phi, myfig):
      myfig['data'][1]['x'][1] = np.cos(np.radians(phi))
      myfig['data'][1]['y'][1] = np.sin(np.radians(phi))
      myfig['data'][1]['z'][1] = 0
  
      return myfig
  
  if __name__ == '__main__':
      app.run_server(debug=True)
  </code></pre>