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:
Image + dragImagepan the plot around
Image/Image + dragImage Image Imagezoom into the plot
Image/Image + vertical/horizontal dragImagezoom only along the vertical/horizontal axis
DoubleclickImagereset plot range to default
Click on point/line/…Imageadd a tooltip label/move the active tooltip label
Click on label/anchorImage Imageselect the tooltip label
Image/Image + click on point/line/…Imageadd additional tooltip labels
Image/Image + click on labelImageremove the tooltip label
Drag label anchorImagemove the tooltip around
Image/Image + drag label anchorImagemove the tooltip smoothly along lines
Drag labelImagemove the tooltip label around
Right-click + "Copy Tooltip Coordinates"Imagecopy the list of tooltip coordinates to the clipboard
Right-click + "Convert to Static Graphics"Imagedisable 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 Image, Image and Image on Windows and Linux, and Image, Image and Image 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 Image/Image 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]=
Image

Add a label by clicking on the curve:

Image

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

Image

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

Image

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

Image

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

Image

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

Image

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]=
Image

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

Image

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

Image

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]=
Image

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]=
Image

Use on other types of plots:

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

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]=
Image

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]=
Image

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]=
Image

Use NumberForm to display only two decimal digits:

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

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]=
Image

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]=
Image

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]=
Image

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]=
Image

AllowInterpolation (3) 

With the default setting "AllowInterpolation"CurrentValue["OptionKey"], tooltips snap to key points of objects unless the Image key (Image 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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

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]=
Image

Disable the cursor in case it is distracting or confusing:

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

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"}
 ]
Image

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}
 ]
Image

Move labels to the nearest possible position:

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

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}
 ]
Image

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]}]
 ]
Image

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
 ]
Image

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: ", #}] &
   ]
 ]
Image

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]
  ]
 ]
Image

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
 ]
Image

Possible Issues (6) 

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

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

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]=
Image

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]=
Image

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

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

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

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

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

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

Resetting the setting to Automatic fixes the issue:

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

Alternatively, use a frame instead of axes:

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

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
 ]
Image

Wrap the first argument in Dynamic to enable replotting:

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

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}]
 ]
Image

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
 ]
Image

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]=
Image

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

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

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]}
 ]
Image

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