# Click and Hover Callbacks

It's possible to create callbacks based on user clicks and hovering. First, you need to specify the `pickingModes` prop in `vtk_view` to be a list of modes you want to capture. The following values are accepted:

- `"click"`
- `"hover"`

Afterwards, you need to create callbacks where the inputs and states include one of the following read-only properties of `vtk_view`.

- `clickInfo`: Called when the user clicks on an object.
- `hoverInfo`: Called when the user hovers over an object.

> The full documentation for `vtk_view` can be found in the API reference.

## Callback structure

You can notice that the `clickInfo` or `hoverInfo` data will be a dictionary with various keys describing the picked object. The keys include:

- `displayPosition`: The x,y,z coordinate with on the user's screen.
- `ray`: A line between two points in 3D space (xyz1, xyz2) that represent the mouse position. It covers the full space under the 2D mouse position.
- `representationId`: The ID assigned to the `vtk_geometryrepresentation` containing your object.
- `worldPosition`: The x, y, z coordinates in the 3D environment that you are rendering where the ray hit the object. It corresponds to the 3D coordinate on the surface of the object under your mouse.

## Output `clickInfo` to `html_pre`

The following example shows you how to concisely display the output of `clickInfo` inside an `html_pre`:

View full code

    using JSON3, DashVtk, DashHtmlComponents, Dash

    filepath = download("https://github.com/plotly/dash-vtk/blob/master/demos/data/cow-nonormals.obj");
    txt_content = read(filepath, String);

    view = vtk_view(
        id="click-info-view",
        pickingModes=["click"],
        children=[
            vtk_geometryrepresentation(id="cow-geometry", children=[
                vtk_reader(
                    vtkClass="vtkOBJReader",
                    parseAsText=txt_content,
                ),
            ]),
        ],
    );

    # Dash setup
    app = dash()

    app.layout = html_div([
        html_div(view, style=Dict("width" => "100%", "height" => "300px")),
        html_b("Output of clickInfo (try clicking on the object above):"),
        html_pre(
            id="click-info-output",
            style=Dict("overflowX" => "scroll")
        )
    ]);

    # Dash setup
    app = dash()

    callback!(
        app,
        Output("click-info-output", "children"),
        Input("click-info-view", "clickInfo")
    ) do click_info
        return JSON3(click_info, indent=2)
    end

    run_server(app, "0.0.0.0", debug = true)

Output of clickInfo (try clicking on the object above):

    null

## Update representation state with `hoverInfo`

You can also construct more complex hover callbacks, which would affect the `actor` and `state` of your geometry representations. In the terrain mesh demo, whenever you hover over the surface, a callback is fired and the output is displayed on your screen:

The full code can be found here, but the following snippet summarizes what is needed to capture hover events in the image above:

    # ...

    vtk_view = vtk_view(
        id="vtk-view",
        pickingModes=["hover"],
        children=[
            vtk_geometryrepresentation(id="vtk-representation", ...),
            vtk_geometryrepresentation(
                id="pick-rep",
                children=[
                    dash_vtk.Algorithm(id="pick-sphere", ...)
                ],
                # ...
            ),
        ],
    )

    app.layout = html_div([
      # ...,
      vtk_view,
      # ...
    ])

    callback!(
        app,
        Output("tooltip", "children"),
        Output("pick-sphere", "state"),
        Output("pick-rep", "actor"),
        Input("vtk-view", "clickInfo"), Input("vtk-view", "hoverInfo"),
    ) do (clickData, hoverData)
        info = hoverData ? hoverData : clickData
        if info
            if (
                "representationId" in info &&
                    info["representationId"] == "vtk-representation"
            )
                return (
                    [JSON3.write(info, indent=2)],
                    Dict("center" => info["worldPosition"]),
                    Dict("visibility" => true),
                )
            end
            return no_update, no_update, no_update
        end
        return [""], Dict(), Dict("visibility" => false)
    end

You can also use `hoverInfo` to update the state of another geometry representation. The image below shows how to update a cone position, orientation and size in order to probe the race car object:

Learn more by reading the Python source code or trying out the Vehicle Geometry app