3
$\begingroup$

I have a plots with many lines and would like to be able to highlight lines when clicked (or on mouseover). When the data plotted is small this works well

styles = {Automatic, Automatic};
Dynamic@ListStepPlot[
  MapIndexed[
    EventHandler[#,
      {"MouseClicked" :> 
        (styles[[#2[[1]]]] = 
           styles[[#2[[1]]]] /. {Thick -> Automatic, Automatic -> Thick})}] &,
    {{1, 2, 3}, {2, 3, 5}}],
  PlotStyle -> styles]

Mathematica graphics

But my data is large and including the complete ListStepPlot inside Dynamic makes it very slow.

So I tried this, but it didn't work:

styles = {Automatic, Automatic};
ListStepPlot[
  MapIndexed[
    EventHandler[#,
      {"MouseClicked" :> 
        (styles[[#2[[1]]]] = 
           styles[[#2[[1]]]] /. {Thick -> Automatic, Automatic -> Thick})}] &,
    {{1, 2, 3}, {2, 3, 5}}],
  PlotStyle -> Dynamic[styles]]

I know that Dynamic can be used for some Plot options values but apparently not for PlotStyle. Is there a way to make this work efficiently for large data sets?

$\endgroup$
  • 1
    $\begingroup$ How fast/slow is this for your data: ListStepPlot[{{1, 2, 3}, {2, 3, 5}}, BaseStyle -> Thick] /. {styles__, l_Line} :> {styles, MouseAppearance[Dynamic@Mouseover[{Thin, l}, {Thick, l}], "LinkHand"]}? $\endgroup$ – Kuba Aug 3 '17 at 18:21
  • $\begingroup$ This works very well! I had never seen Dynamic being injected like that inside a graphics object. $\endgroup$ – Gustavo Delfino Aug 3 '17 at 18:29
  • $\begingroup$ Oh @Kuba I see you got to the answer before I did $\endgroup$ – b3m2a1 Aug 3 '17 at 18:31
4
$\begingroup$

Edit: more efficient and more flexible solution:

ListStepPlot[
    {{1, 2, 3}, {2, 3, 5}}, BaseStyle -> Thick
] /. {styles__, l_Line} :> DynamicModule[
    {edge = Thin}
  , {styles
    , Dynamic @ edge
    , MouseAppearance[
          EventHandler[
              l
            , "MouseClicked" :> (edge = edge /. {Thick -> Thin, Thin -> Thick} )
          ]
        , "LinkHand"
      ]
    }
 ]

Here is the old fix. Not the best as it doubles the size of the GraphicsBox:

ListStepPlot[
    {{1, 2, 3}, {2, 3, 5}}, BaseStyle -> Thick
] /. {styles__, l_Line} :> {
    styles
  , MouseAppearance[Dynamic@Mouseover[{Thin, l}, {Thick, l}], "LinkHand"]
}
$\endgroup$
1
$\begingroup$

Here's a way to do it by post-processing the Plot:

styleFloops =
  Map[RandomColor[] &, Range[2]];
styles =
  Map[Directive[ColorData[97][#], Thickness@Medium] &, Range[2]];
ListStepPlot[
  MapIndexed[
   EventHandler[#, {"MouseClicked" :> (styles[[#2[[1]]]] = 
         styles[[#2[[1]]]] /. {Thick -> Thickness@Medium, 
           Thickness@Medium -> Thick})}] &, {{1, 2, 3}, {2, 3, 5}}],
  PlotStyle ->
   styleFloops
  ] /.
 MapIndexed[
  Directive[a___, #, b___] :>
    Dynamic[Directive[a, styles[[First@#2]], b]] &,
  styleFloops
  ]

It works under the assumption that RandomColor will never be the Axes color and will never intersect. I think that's reasonable.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.