Сюжетно интерактивная всплывающая подсказка / текст при наведении / всплывающее окно

Подсказки фигуры отображаются только при наведении курсора на точку данных: https://plotly.com/python/hover-text-and-formatting

Я хотел бы иметь простой способ настроить продолжительность отображения всплывающей подсказки после наведения на нее или, возможно, постоянно отображать всплывающую подсказку при нажатии на точку данных.

Это позволит мне включить кликабельные ссылки в подсказку.

Для таблиц данных вы можете настроить продолжительность отображения всплывающей подсказки, но я не вижу аналогичной опции для рисунков: https://dash.plotly.com/datatable/tooltips

Я думаю, вы можете добавить свои собственные всплывающие подсказки через систему событий или, возможно, каким-то образом изменить стиль CSS результирующего HTML, но это кажется излишним. Я бы все равно принял ответ с рабочим примером.

Обходной путь, когда вам нужна только одна ссылка, — использовать свойство text временной шкалы в качестве ссылки, например: "<a href='https://en.wikipedia.org/wiki/"+df['topic']+"' target='_blank'>"+df['topic']+"</a>". Это не решит первоначальную проблему, но позволит кликнуть хотя бы по тексту внутри ноды.

phobic 07.01.2023 08:27

Кажется, предпринимаются некоторые усилия по устранению этой проблемы. Я не совсем понял, возможно ли это решение или как его применить: github.com/plotly/plotly.js/pull/1265 Это открытая проблема, которая, надеюсь, в конечном итоге добавит эту функцию: github .com/plotly/plotly.js/issues/998

phobic 29.01.2023 19:25
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это решение css, которое отключает обычные всплывающие подсказки и вместо этого использует обратный вызов для отображения информации в элементе div. Когда мышь отходит от узла, мы используем css, чтобы сделать div невидимым за несколько секунд.

Ни в коем случае не отличное решение, но оно работает.

Я также попробовал решение, основанное на анимации атрибутов css, которое работает, но немного сложнее.

Я попытался изменить имя класса div вместо стиля и остановить переход при наведении курсора мыши на div, добавив к переходу условие css :not:hover, но не смог заставить его работать полностью.

from dash import Dash, dcc, html, Input, Output, no_update
import plotly.express as px 

df = px.data.tips()

fig = px.scatter(df, x = "total_bill", y = "tip")

# Turn off native plotly.js hover effects - make sure to use
# hoverinfo='none' rather than 'skip' which also halts events.
fig.update_traces(hoverinfo='none', hovertemplate=None)

# Hover distance defaults to 20 and means call hover event if mouse pointer is within x units close to the node.
fig.update_layout(hoverdistance=5)

app = Dash(__name__)

# Clear on unhover means the hover callback is called with hoverDate=None when moving away from the point.log_queue
app.layout = html.Div(
    [
        dcc.Graph(id='graph', figure=fig, clear_on_unhover=True),
        html.Div(id='graph-tooltip'),
    ],
)

# Store previous style globally.
previous_style = None


@app.callback(
    Output('graph-tooltip', 'style'),
    Output('graph-tooltip', 'children'),
    Input('graph', 'hoverData'),
    prevent_initial_call=True,
)
def display_hover(hoverData):
    '''When hovering over a node, show a HTML div element with some Node info and two links. When moving the mouse away from the node the div fades out slowly.'''
    global previous_style
    if hoverData is None:
        # When the mouse moves a way from the node hoverData is None and we hide the element with opacity=0.
        # The transition to hide the element happens over 4 seconds as defined below via the css attribute transition.
        previous_style['opacity'] = 0
        return previous_style, no_update

    # Get attribute NAME from dataframe to display it.
    # And get the x/y coordinates of the current node the mouse is hovering over.
    pt = hoverData['points'][0]
    box = pt['bbox']
    num = pt['pointNumber']

    df_row = df.iloc[num]
    df_value = df_row['time']

    children = [
        html.P(f'{df_value}'),
        html.A('Link to external site 1', href='https://plot.ly', target='_blank'),
        html.Br(),
        html.A('Link to external site 2', href='https://plot.ly', target='_blank'),
    ]
    previous_style = {
        'position': 'absolute',
        'left': f'{box["x1"] + 20}px',  # Display the div next to the node.
        'top': f'{box["y1"] + 20}px',
        'background-color': 'rgba(100, 100, 100, 0.8)',
        'transition': 'opacity 4s  ease-out',  # Fade in / Fade out the div element gradually.

    }
    return previous_style, children


app.run_server()
Ответ принят как подходящий

Вот более сложное решение, которое предотвращает исчезновение всплывающей подсказки при наведении на нее курсора. Для этого вам нужен внешний файл css с анимацией css.

См. https://stackoverflow.com/a/75277310/2474025 для более простого решения.

активы/my.css:


.hideclass:not(:hover) {
  animation: hideanimation 5s ease-in;
  animation-fill-mode: forwards;
}
.showclass {
  animation: showanimation 5s ease-out;
  animation-fill-mode: forwards;
}


@keyframes showanimation {
  0% {
    opacity: 0;
  }
  25% {
    opacity: 0.4;
  }
  50% {
    opacity: 0.7;
  }

  75% {
    opacity: 0.8;
  }
  100% {
    opacity: 1;
  }
}


@keyframes hideanimation {
  0% {
    opacity: 1;
  }
  25% {
    opacity: 0.5;
  }
  50% {
    opacity: 0;
  }

  75% {
    opacity: 0;
    max-width: 0;
    max-height: 0;
    overflow: hidden;
  }
  100% {
    opacity: 0;
    max-width: 0;
    max-height: 0;
    overflow: hidden;
  }
}

Блокнот Python со следующим кодом должен находиться в том же каталоге, что и папка ресурсов:


from dash import Dash, dcc, html, Input, Output, no_update
import plotly.express as px

df = px.data.tips()

fig = px.scatter(df, x='total_bill', y='tip')

# Turn off native plotly.js hover effects - make sure to use
# hoverinfo='none' rather than 'skip' which also halts events.
fig.update_traces(hoverinfo='none', hovertemplate=None)

# Hover distance defaults to 20 and means call hover event if mouse pointer is within x units close to the node.
fig.update_layout(hoverdistance=5)

app = Dash(__name__)

app.layout = html.Div(
    [
        html.Link(rel='stylesheet', href='/assets/my.css'),
        # clear on unhover means the hover callback is called with hoverDate=None when moving away from the point.log_queue
        dcc.Graph(
            id='graph-basic-2',
            figure=fig,
            clear_on_unhover=True,
        ),
        html.Div(
            id='graph-tooltip',
            className='dash-bootstrap',
        ),
    ],
    className='dash-bootrstrap',
)

previous_style = None


@app.callback(
    Output('graph-tooltip', 'style'),
    Output('graph-tooltip', 'className'),
    Output('graph-tooltip', 'children'),
    Input('graph-basic-2', 'hoverData'),
    prevent_initial_call=True,
)
def display_hover(hoverData):
    global previous_style
    if hoverData is None:
        return no_update, 'hideclass', no_update

    print('display')

    # demo only shows the first point, but other points may also be available
    pt = hoverData['points'][0]
    bbox = pt['bbox']

    children = [
        html.A('Link to external site 1', href='https://plot.ly', target='_blank'),
        html.Br(),
        html.A('Link to external site 2', href='https://plot.ly', target='_blank'),
    ]
    previous_style = {
        'position': 'absolute',
        'left': f'{bbox["x1"] + 20}px',
        'top': f'{bbox["y1"] + 20}px',
        'background-color': 'rgba(100, 100, 100, 0.8)',
        'padding': '1em',
    }
    return previous_style, 'showclass', children


# if __name__ == '__main__':
app.run_server(
    dev_tools_hot_reload=True,
)

Другие вопросы по теме