Function Repository Resource:

InteractiveGraphics

Source Notebook

Create an interactive version of a graphics expression with zooming, panning and tooltips

Contributed by: Lukas Lang

ResourceFunction["InteractiveGraphics"][graphics]

creates an interactive version of graphics.

ResourceFunction["InteractiveGraphics"][Dynamic[graphics]]

dynamically updates graphics, but preserves the plot range and tooltips.

Details and Options

ResourceFunction["InteractiveGraphics"][graphics] will create a dynamic version of graphics that can be interacted with by zooming, panning and adding tooltip labels to objects in the plot.
The tooltip labels placed by ResourceFunction["InteractiveGraphics"] will always snap to objects, such as points and lines present in the graphic, ensuring that the coordinates are properly read out.
The following interactions are supported by default:
+ dragpan the plot around
/ + drag zoom into the plot
/ + vertical/horizontal dragzoom only along the vertical/horizontal axis
Doubleclickreset plot range to default
Click on point/line/…add a tooltip label/move the active tooltip label
Click on label/anchor select the tooltip label
/ + click on point/line/…add additional tooltip labels
/ + click on labelremove the tooltip label
Drag label anchormove the tooltip around
/ + drag label anchormove the tooltip smoothly along lines
Drag labelmove the tooltip label around
Right-click + "Copy Tooltip Coordinates"copy the list of tooltip coordinates to the clipboard
Right-click + "Convert to Static Graphics"disable interactivity while keeping the current plot range and tooltips
The cursor is changed dynamically to indicate the current action, as indicated by the previous table.
By default, the modifier keys are , and on Windows and Linux, and , and on macOS, as indicated in the previous table.
ResourceFunction["InteractiveGraphics"] accepts the following options:
LabelStyle{}the style to apply to the tooltips
LabelingFunctionIdentitythe function to apply to the tooltips before display
"LabelPosition""Attached"how to position the tooltip labels
"AllowInterpolation"CurrentValue["OptionKey"]whether to allow interpolation between corner points of lines
"AllowedActions"Allwhich types of interactions to allow
"UseLinkHandCursor"Truewhether to use the "LinkHand" cursor for all objects that can be tooltipped
"ModifierKeys"{"OptionKey","ShiftKey","ControlKey","CommandKey"}which modifier key to use for which interaction
"LabelMoveMethod"Automatichow to move tooltips when the plot is updated
"ReplottingMethod"Nonemethod to use to update the plot when zooming and panning
"GroupingStrategy""Color"how to attempt to group the plot elements
The option LabelStyle is effectively applied to all tooltip labels and can be a list of any of the options supported by Framed.
ResourceFunction["InteractiveGraphics"] effectively uses the setting of CoordinatesToolOptions to generate the contents of the labels and the coordinates copied by the "Copy Tooltip Coordinates" context menu option.
The value of LabelingFunction is applied to the "DisplayFunction" setting of the CoordinatesToolOptions of the graphics expression before being displayed.
The "LabelPosition" option controls how the tooltip labels are placed in relation to the anchor points or the graphic.
The "LabelPositon" can be set to the following:
"Attached"label moves with the anchor and is fixed to one of the four corners
"Free"label moves with the anchor, but can be placed anywhere
"FreeScaled"label does not move with the anchor and can be positioned anywhere
posposition the list of labels at the given position
In "LabelPosition"pos, pos can be a pair of numbers (with coordinates from 0 to 1), a symbolic position (Left,Right,Bottom,Top or Center) or a combination of the two.
"AllowInterpolation" controls whether the anchors snap to the corner points of lines and similar objects, or whether any position along the line should be allowed.
With the default setting "AllowInterpolation"CurrentValue["OptionKey"], the snapping behavior can be changed by holding the / key while dragging the anchor around.
The "AllowedActions" option controls which types of interactions are supported. Possible values are:
Allallow all interactions
"Zoom"allow only zooming
"Pan"allow only panning
"Label"allow only the creation of a single tooltip label
"MultiLabel"allow the creation of multiple tooltip labels
{act1,act2,}allow several interactions
The option "ModifierKeys" controls the modifier keys that need to be held down to perform certain interactions.
The option "ModifierKeys" needs to be set to a list of three values, where the values specify the keys necessary for zooming, panning and label creation, respectively.
For each entry in the setting for "ModifierKeys", a CurrentValue argument can be given or a list of multiple alternatives can be specified as opt1,opt2,. In principle, any argument where CurrentValue[arg] returns True or False is supported, but not all cases will work as expected.
The option "LabelMoveMethod" controls how tooltip anchors are moved when the graphic in ResourceFunction["InteractiveGraphics"][Dynamic[graphics]] is dynamically updated.
The following settings can be used for "LabelMoveMethod":
Automaticdetermine the method automatically based on the object type
"Horizontal"allow only horizonal movements
"Vertical"allow only vertical movements
Nearestmove to the nearest point
The setting "LabelMoveMethod"Automatic is equivalent to "Vertical" for labels annotating lines, but tries to follow a given point when it is annotated by determining the index of the annotated point and finding the new point at that index.
For all settings of "LabelMoveMethod", only points along the same object group are considered (determined by index), where the object groups are determined by the "GroupingStrategy" option.
When no suitable position for a label can be found, it is put into an orphaned state, indicated by a red anchor point. The label can be reassigned to an object by making it active and clicking on an object to move it there.
The following settings can be used for "ReplottingMethod":
Nonedo not automatically recreate the plot
Automaticattempt to automatically recreate the plot
funcuse a user-defined function to recreate the plot
For the setting of "ReplottingMethod" to have an effect, the first argument of ResourceFunction["InteractiveGraphics"] must be wrapped in Dynamic since the unevaluated form of the graphics is needed for it to work.
With the setting "ReplottingMethod"Automatic, ResourceFunction["InteractiveGraphics"] attempts to automatically recreate the plot by passing an updated plot range to the plotting function in order to properly sample the plot range that is currently visible.
With the setting "ReplottingMethod"func, the specified function is used to create the updated plot. For ResourceFunction["InteractiveGraphics"][Dynamic[expr],"ReplottingMethod"func], func[expr][plotRange] is evaluated with the current plot range in the form {{xmin,xmax},{ymin,ymax}} whenever necessary.
The "GroupingStrategy" option controls how the contents of a plot are grouped together for the purposes of tooltip label movement.
When dragging a tooltip label anchor interactively, the anchor will only move to points of the same object. The grouping also affects the automatic label movement, as noted previously.
The following settings can be used for "GroupingStrategy":
Automatictry to use an automatic strategy that works for most plots
"Color"group objects based on color
Allput all objects into one group
Annotationuse Annotation[prims,ResourceFunction["InteractiveGraphics"][Annotation]] as a grouping indicator
The grouping strategy effectively examines the structure of the graphics expression from the outer levels inward, and when the first nontrivial structure is found, the items of that structure are grouped. Such structures might, for example, be lists of several elements, items with an explcit color given or Annotation[] wrappers.
Options to control the dynamic updating behavior can be given via ResourceFunction["InteractiveGraphics"][Dynamic[expr,opts]], where the following Dynamic options are supported: TrackedSymbols, UpdateInterval, BaseStyle, Initialization and Deinitialization.
ResourceFunction["InteractiveGraphics"]["FixAfterUndo"] can restore interactive functionality in certain situations involving the "Convert to Static Graphics" action, as explained in Possible Issues.

Examples

Basic Examples (2) 

Create an interactive version of a simple plot:

In[1]:=
ResourceFunction["InteractiveGraphics"][
 Plot[{Sin[x], x^2/10}, {x, 0, 4}, Frame -> True]
 ]
Out[1]=

Add a label by clicking on the curve:

Move the label to the blue curve by clicking on it:

Move the label out of the way of the intersection by dragging it downward:

Zoom into the region around the label by holding and dragging:

Add a second label using +click (+click on macOS) on the orange curve:

Move the plot range slightly to the right by holding and dragging:


Estimate the position of the maximum of a curve by plotting it and adding a label to the highest points:

In[2]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2] - Cos[x] + \[Sqrt]x, {x, 0, 5.5}]
 ]
Out[2]=

Ensure the labels are as close as possible to the peak by holding ( on macOS) and dragging them upward (the further above the cursor is, the more accurate this will be):

Extract the positions by choosing "Copy Tooltip Coordinates" from the context menu and pasting the result:

Scope (3) 

Coordinates with rationals and roots are supported:

In[3]:=
pts = {{0, 1}, {-2/3, -1/3}, {3/4, 0}};
circ = Circumsphere[pts];
{c, r} = {First[circ], Last[circ]};

ResourceFunction["InteractiveGraphics"]@
 Graphics[{circ, LightBlue, Triangle[pts], Red, Point[c], Dashed, Line[{c, c + r*Normalize[{1, 1}]}]}]
Out[3]=

Inspect a two-axis plot created by the resource function CombinePlots:

In[4]:=
ResourceFunction["InteractiveGraphics"][
 ResourceFunction["CombinePlots"][
  Plot[Cos[x^2], {x, 0, 4}, Frame -> True],
  Plot[Exp[x] + Exp[-x], {x, 0, 4}, ScalingFunctions -> "Log", Frame -> True, PlotStyle -> Red, FrameStyle -> Red
   ],
  "AxesSides" -> "TwoY"
  ]
 ]
Out[4]=

Use on other types of plots:

In[5]:=
ResourceFunction["InteractiveGraphics"][
 ContourPlot[Sin[x] Sin[y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}]
 ]

Options (22) 

LabelStyle (2) 

With the default setting LabelStyle{}, the tooltip labels have a white background and a colored border:

In[6]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2], {x, 0, 6}]
 ]
Out[6]=

Add some padding, rounded corners and a semi-transparent background:

In[7]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2], {x, 0, 6}],
 LabelStyle -> {FrameMargins -> 5, RoundingRadius -> 3, Alignment -> Center, Background -> Directive[White, Opacity@0.7]}
 ]
Out[7]=

LabelingFunction (2) 

With the default setting LabelingFunctionIdentity, the value returned by the CoordinatesToolOptions suboption "DisplayFunction" is used:

In[8]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2], {x, 0, 6}]
 ]
Out[8]=

Use NumberForm to display only two decimal digits:

In[9]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2], {x, 0, 6}],
 LabelingFunction -> (NumberForm[#, 2] &)
 ]
Out[9]=

LabelPosition (2) 

With the default setting "LabelPosition" "Attached", the tooltip labels are attached to the anchors at one corner:

In[10]:=
ResourceFunction["InteractiveGraphics"][
 Plot[0.2 x^3 - x^2, {x, 0, 6}, Frame -> True]
 ]
Out[10]=

Allow the labels to be moved freely, but still together with the anchors:

In[11]:=
ResourceFunction["InteractiveGraphics"][
 Plot[0.2 x^3 - x^2, {x, 0, 6}, Frame -> True],
 "LabelPosition" -> "Free"
 ]
Out[11]=

Allow the labels to be moved freely and make them fixed with respect to the plot:

In[12]:=
ResourceFunction["InteractiveGraphics"][
 Plot[0.2 x^3 - x^2, {x, 0, 6}, Frame -> True],
 "LabelPosition" -> "FreeScaled"
 ]
Out[12]=

Put all labels into the top-left corner:

In[13]:=
ResourceFunction["InteractiveGraphics"][
 Plot[{0.2 x^3 - x^2, \[Sqrt]x}, {x, 0, 6}, Frame -> True],
 "LabelPosition" -> {Top, Left}
 ]
Out[13]=

AllowInterpolation (3) 

With the default setting "AllowInterpolation"CurrentValue["OptionKey"], tooltips snap to key points of objects unless the key ( key on macOS) is held while dragging:

In[14]:=
ResourceFunction["InteractiveGraphics"][
 Graphics[
  {
   Red,
   Line@{{0, 0}, {1, 1}, {3, -4}},
   Blue,
   Circle[{2, -2}, {1, 1.5}],
   Darker@Green, PointSize@Large,
   Point@{{0, -1}, {2, 1}, {2, -3}}
   },
  AspectRatio -> 1/2
  ]
 ]
Out[14]=

Always allow any point along lines to be selected:

In[15]:=
ResourceFunction["InteractiveGraphics"][
 Graphics[
  {
   Red,
   Line@{{0, 0}, {1, 1}, {3, -4}},
   Blue,
   Circle[{2, -2}, {1, 1.5}],
   Darker@Green,
   PointSize@Large,
   Point@{{0, -1}, {2, 1}, {2, -3}}
   },
  AspectRatio -> 1/2
  ],
 "AllowInterpolation" -> True
 ]
Out[15]=

Never allow points along lines to be selected:

In[16]:=
ResourceFunction["InteractiveGraphics"][
 Graphics[
  {
   Red,
   Line@{{0, 0}, {1, 1}, {3, -4}},
   Blue,
   Circle[{2, -2}, {1, 1.5}],
   Darker@Green,
   PointSize@Large,
   Point@{{0, -1}, {2, 1}, {2, -3}}
   },
  AspectRatio -> 1/2
  ],
 "AllowInterpolation" -> False
 ]
Out[16]=

AllowedActions (2) 

With the default setting "AllowedActions" All, all types of interactions are enabled:

In[17]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[1/x], {x, 0, 2}, MaxRecursion -> 10, PlotRange -> All, Frame -> True]
 ]
Out[17]=

Only allow zooming and panning:

In[18]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[1/x], {x, 0, 2}, MaxRecursion -> 10, PlotRange -> All, Frame -> True],
 "AllowedActions" -> {"Zoom", "Pan"}
 ]
Out[18]=

UseLinkHandCursor (2) 

With the default setting "UseLinkHandCursor"True, the cursor changes when over any object that is labeled:

In[19]:=
ResourceFunction["InteractiveGraphics"][
 Plot[x^2, {x, 0, 3}]
 ]
Out[19]=

Disable the cursor in case it is distracting or confusing:

In[20]:=
ResourceFunction["InteractiveGraphics"][
 Plot[x^2, {x, 0, 3}],
 "UseLinkHandCursor" -> False
 ]
Out[20]=

ModifierKeys (1) 

Swap the modifier keys for zooming and panning:

In[21]:=
ResourceFunction["InteractiveGraphics"][
 Plot[x^2, {x, 0, 3}],
 "ModifierKeys" -> {"ShiftKey", "OptionKey", "ControlKey" | "CommandKey"}
 ]

LabelMoveMethod (3) 

With the default setting "LabelMoveMethod"Automatic, tooltip labels on lines are moved vertically and tooltips on points are kept at the same point:

In[22]:=
plot[a_] := Show[
  Plot[a x^2, {x, 0, 1}],
  ListPlot[Table[{i a/2, i a}, {i, Subdivide[10]}], PlotStyle -> Red],
  Frame -> True,
  PlotRange -> {{0, 1}, {0, 2}}
  ]

Manipulate[
 ResourceFunction["InteractiveGraphics"][Dynamic@plot[a]],
 {a, 1, 3}
 ]

Move labels to the nearest possible position:

In[23]:=
Manipulate[
 ResourceFunction["InteractiveGraphics"][Dynamic@plot[a], "LabelMoveMethod" -> Nearest],
 {a, 1, 3}
 ]

Move labels only horizontally, which will likely not be possible for labels on points:

In[24]:=
Manipulate[
 ResourceFunction["InteractiveGraphics"][Dynamic@plot[a], "LabelMoveMethod" -> "Horizontal"],
 {a, 1, 3}
 ]

ReplottingMethod (3) 

With the default setting "ReplottingMethod"None, the graphics are never reevaluated by InteracitveGraphics:

In[25]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@ContourPlot[Sin[x] Sin[y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}]
 ]

Automatically attempt to replot the graphics for the appropriate plot range:

In[26]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@ContourPlot[
   Sin[x] Sin[y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}],
 "ReplottingMethod" -> Automatic
 ]

Use a custom function to do the replotting:

In[27]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@ContourPlot[
   Sin[x] Sin[y], {x, 0, 2 \[Pi]}, {y, 0, 2 \[Pi]}],
 "ReplottingMethod" -> Function[{plot},
   Show[plot, PlotLabel -> Row@{"Plot range: ", #}] &
   ]
 ]

GroupingStrategy (2) 

With the default setting "GroupingStrategy""Color", objects in the plot are grouped based on their color:

In[28]:=
ResourceFunction["InteractiveGraphics"][
 Show[
  Plot[{Sin[x], Cos[x]}, {x, 0, 2 \[Pi]}],
  ListPlot[Table[{x, -Cos[x]}, {x, Subdivide[0, 2 \[Pi], 80]}], ColorFunction -> Hue]
  ]
 ]

Group everything together:

In[29]:=
ResourceFunction["InteractiveGraphics"][
 Show[
  Plot[{Sin[x], Cos[x]}, {x, 0, 2 \[Pi]}],
  ListPlot[Table[{x, -Cos[x]}, {x, Subdivide[0, 2 \[Pi], 80]}], ColorFunction -> Hue]
  ],
 "GroupingStrategy" -> All
 ]

Possible Issues (6) 

For Dynamic[] type arguments, a Graphics expression must still be returned:

In[30]:=
ResourceFunction["InteractiveGraphics"][Dynamic["Not a Graphic"]]
Out[30]=

Interactivity might be disabled if the functions can't be reloaded after a kernel restart:

In[31]:=
ResourceFunction["InteractiveGraphics"][Plot[Sin[x], {x, 0, 2 \[Pi]}]]
Out[31]=

Trying to undo the action of "Convert to Static Graphics" does not work properly, and interacting with the resulting object will break future interactive graphics:

In[32]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x], {x, 0, 2 \[Pi]}]
 ]
(* Add callout label *)
(* Right \
click\[ThinSpace]+\[ThinSpace]"Convert to Static Graphics" *)
(* Undo \
(\[ControlKey]/\[CommandKey]\[ThinSpace]+\[ThinSpace]Z) *)
(* Click \
on label *)
(* Errors appear in message window *)
(* Re-evaluate cell \
*)
Out[32]=

Fix the errors by calling InteractiveGraphics["FixAfterUndo"]:

In[33]:=
ResourceFunction["InteractiveGraphics"]["FixAfterUndo"]
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x], {x, 0, 2 \[Pi]}]
 ]
Out[33]=

The axes might move out of the visible area when panning:

In[34]:=
ResourceFunction["InteractiveGraphics"][
 ListPlot[Range[5]]
 ]

This is caused by the setting AxesOrigin{0,0} of the graphics expression:

In[35]:=
Options[ListPlot[Range[5]], AxesOrigin]
Out[35]=

Resetting the setting to Automatic fixes the issue:

In[36]:=
ResourceFunction["InteractiveGraphics"][
 Show[ListPlot[Range[5]], AxesOrigin -> Automatic]
 ]

Alternatively, use a frame instead of axes:

In[37]:=
ResourceFunction["InteractiveGraphics"][
 ListPlot[Range[5], Frame -> True]
 ]

The setting for "ReplottingMethod" only takes effect for Dynamic type arguments:

In[38]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x]^3, {x, 0, 2 \[Pi]}],
 "ReplottingMethod" -> Automatic
 ]

Wrap the first argument in Dynamic to enable replotting:

In[39]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@Plot[Sin[x]^3, {x, 0, 2 \[Pi]}],
 "ReplottingMethod" -> Automatic
 ]

When zooming into a plot with a highly oscillatory function, the original sampling might not be sufficient to properly resolve all details:

In[40]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[1/(x^2 + 0.005)], {x, -2, 2}]
 ]

Use "ReplottingMethod"Automatic to automatically refine the plot:

In[41]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@Plot[Sin[1/(x^2 + 0.005)], {x, -2, 2}],
 "ReplottingMethod" -> Automatic
 ]

Neat Examples (3) 

Customize the label appearance using LabelStyle and LabelingFunction:

In[42]:=
ResourceFunction["InteractiveGraphics"][
 Plot[Sin[x^2], {x, 0, 6}],
 LabelStyle -> {Background -> GrayLevel@0.92, FrameStyle -> None, FrameMargins -> 8, Alignment -> {Center, Center}},
 LabelingFunction -> (Grid[
     {{"X:", NumberForm[#[[1]], 3]}, {"Y:", NumberForm[#[[2]], 3]}},
     ItemStyle -> {{Directive[Bold, RGBColor[0, 0.5, 0.6]], Black}},
     BaseStyle -> 12,
     Alignment -> Left,
     Spacings -> {0.5, 0.6}
     ] &)
 ]
Out[42]=

Create a version of the Mandelbrot set that can be interactively explored:

In[43]:=
ResourceFunction["InteractiveGraphics"][
 Dynamic@MandelbrotSetPlot[],
 "ReplottingMethod" -> Automatic
 ]

Annotate a point on a curve and watch how its position changes as the curve moves:

In[44]:=
Manipulate[
 ResourceFunction["InteractiveGraphics"][
  Dynamic@Plot[
    {Sin[x + t], Cos[x - t]},
    {x, 0, 2 \[Pi]}
    ]
  ],
 {t, 0, 2 \[Pi]}
 ]

Publisher

Lukas Lang

Version History

  • 3.0.0 – 11 December 2020
  • 2.0.0 – 05 November 2020
  • 1.0.0 – 20 October 2020

Source Metadata

Related Resources

Author Notes

Changes from Version 1.1.0 to 1.2.0:

Fixed issues with PlotRange, PlotRangePadding, ImagePadding and ImageSize not being preserved properly for Legended Graphics expressions.
Fixed issues with CoordinatesToolOptions of Legended Graphics not being properly applied to tooltips.
Fixed issues with tooltips unexpectedly detaching from points when using the default setting "LabelMoveMethod"Automatic.
Fixed issues with "ReplottingMethod"Automatic not actually re-plotting anything.

Changes from Version 1.0.0 to 1.1.0:

Added option "ReplottingMethod"
The algorithm behind "LabelMoveMethod" can now reattach orphaned labels if there is a valid destination once again
Fixed issues with primitives of the type Circle[,Offset[]] not being properly ignored
Fixed issues with degenerate GraphicsComplex[pts,opts] type expressions leading to errors

License Information