Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Extend .interactive() with tooltip and legend #3394

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 69 additions & 5 deletions altair/vegalite/v5/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3022,19 +3022,33 @@ def add_selection(self, *params) -> Self:
return self.add_params(*params)

def interactive(
self, name: Optional[str] = None, bind_x: bool = True, bind_y: bool = True
self,
name: Optional[str] = None,
bind_x: bool = True,
bind_y: bool = True,
tooltip: bool = True,
legend: Union[bool, list] = True,
legend_opacity: tuple = (0.7, 0.1),
) -> Self:
"""Make chart axes scales interactive
"""Add common interactive elements to the chart

Parameters
----------
name : string
The parameter name to use for the axes scales. This name should be
unique among all parameters within the chart.
bind_x : boolean, default True
If true, then bind the interactive scales to the x-axis
Bind the interactive scales to the x-axis
bind_y : boolean, default True
If true, then bind the interactive scales to the y-axis
Bind the interactive scales to the y-axis
tooltip : boolean, default True,
Add a tooltip containing the encodings used in the chart
legend : boolean or list, default True
Make the legend clickable and control the opacity of the marks.
Can be set to a list indicating which encodings the legend
interactivity should include.
legend_opacity : tuple, default (0.7, 0.1)
The default opacity values for the clicked and unclicked marks

Returns
-------
Expand All @@ -3047,7 +3061,57 @@ def interactive(
encodings.append("x")
if bind_y:
encodings.append("y")
return self.add_params(selection_interval(bind="scales", encodings=encodings))
interactive_chart = self.add_params(
selection_interval(bind="scales", encodings=encodings)
).copy()
# We can't simply use configure_mark since configure methods
# are not allowed in layered specs
if tooltip:
if isinstance(interactive_chart.mark, str):
interactive_chart.mark = {
"type": interactive_chart.mark,
"tooltip": tooltip,
}
else:
interactive_chart.mark.tooltip = tooltip
if legend:
if not isinstance(legend, list):
# Set the legend to commonly used encodings by default
legend = [
"angle",
"radius",
"color",
"fill",
"shape",
"size",
"stroke",
]
# Detect common legend encodings used in the spec
# legend = [
# enc
# for enc in interactive_chart.encoding.to_dict(validate=False).keys()
# if enc
# in [
# "angle",
# "radius",
# "color",
# "fill",
# "shape",
# "size",
# "stroke",
# ]
# ]
Comment on lines +3089 to +3103
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking it's more elegant if we set the legend encodings only to encodings that actually exist in the spec. However, to_dict(validate=False) currently does not work for channels as per #3075.

It is possible to do something like this instead, but it seems clunky:

[
    enc for enc in vars(chart.encoding)['_kwds']
    if not isinstance(chart.encoding[enc], alt.utils.schemapi.UndefinedType)
]

It is an order of magnitude faster thought, so maybe that it the way to go:

image

legend_selection = selection_point(bind="legend", encodings=legend)
interactive_chart = interactive_chart.add_params(
legend_selection,
).encode(
opacity=condition(
legend_selection,
value(legend_opacity[0]),
value(legend_opacity[1]),
)
)
return interactive_chart


def _check_if_valid_subspec(spec: Union[dict, core.SchemaBase], classname: str) -> None:
Expand Down