How to show/hide overlay depending on zoom level

You can build this pretty easily by using a RangeXY stream. A basic example would look something like this:

points = hv.Points(np.random.multivariate_normal((0,0), [[0.1, 0.1], [0.1, 1.0]], (500000,)))


def filter_points(points, x_range, y_range):
    if x_range is None or y_range is None:
        return points
    return points[x_range, y_range]

def hover_points(points, threshold=5000):
    if len(points) > threshold:
        return points.iloc[:0]
    return points

range_stream = hv.streams.RangeXY(source=points)
streams=[range_stream]

filtered = points.apply(filter_points, streams=streams)
shaded = datashade(filtered, width=400, height=400, streams=streams)
hover = filtered.apply(hover_points)

dynamic_hover = (shaded * hover).opts(
    hv.opts.Points(tools=['hover'], alpha=0.1, hover_alpha=0.2, size=10))

zoom_hover

Here we built a little pipeline starting with the set of points, apply the filter_points function which selects only the points in the current view port by taking the x_range and y_range from the RangeXY stream and then finally datashade the result and apply the hover_points function which returns an empty set of points if there are more points than the defined threshold. You can even add a panel widget to control the threshold:

range_stream = hv.streams.RangeXY(source=points)
streams=[range_stream]

threshold = pn.widgets.IntSlider(name='Threshold', start=1000, end=10000, step=100)
filtered = points.apply(filter_points, streams=streams)
hover = filtered.apply(hover_points, threshold=threshold)
shaded = datashade(filtered, width=400, height=400, streams=streams)

dynamic_hover = (shaded * hover).opts(
    hv.opts.Points(tools=['hover'], alpha=0.1, hover_alpha=0.2, size=10))

pn.Column(threshold, dynamic_hover)

5 Likes