Plotly地图实现悬停/点击弹出视频URL及点位不显示问题排查
问题解决:Plotly地图点位消失+悬停/点击弹出视频
问题背景
用Plotly编写的地图点位脚本,原本可正常显示点位,鼠标悬停能展示pandas DataFrame列信息,但将悬停展示的列替换为包含视频URL的列后,地图点位完全消失。需要解决该问题,并实现鼠标悬停/点击时弹出视频(来自URL)的功能。
问题原因
- 视频URL含
&、=等特殊字符,直接作为悬停文本会导致Plotly模板解析失败,破坏点位渲染逻辑 - 未配置Plotly的自定义悬停模板,默认文本处理规则无法兼容URL格式内容
- 原代码未显式定义悬停相关参数,替换列时未适配Plotly的HTML渲染规则
解决方案
核心修改点
- 使用自定义悬停模板(hovertemplate),嵌入HTML
<video>标签实现悬停框内直接播放视频 - 通过
customdata传递视频URL,避免特殊字符干扰Plotly的文本解析 - 可选添加点击事件逻辑,实现点击点位弹出独立视频窗口
完整修改代码
import plotly.graph_objs as go import plotly import pandas as pd from plotly.offline import plot # 设置Mapbox令牌 mapbox_access_token = 'map_token_here' df = pd.read_csv('cvs_with-data') video_type = list(df['Type'].value_counts().index) data = [] for video in video_type: # 筛选对应类型的数据 filtered_df = df.loc[df['Type'] == video] video_data = dict( lat=filtered_df['Latitude'], lon=filtered_df['Longitude'], name=video, marker=dict(size=14), type='scattermapbox', # 传递视频URL作为自定义数据(替换成你的视频URL列名) customdata=filtered_df['Video_URL'], # 自定义悬停模板:嵌入HTML视频标签 hovertemplate='<b>类型:</b> %{fullData.name}<br>' + '<b>视频:</b><br><video width="200" controls src="%{customdata}"></video><extra></extra>' ) data.append(video_data) layout = dict( height=800, margin=dict(t=0, b=0, l=0, r=0), font=dict(color='#FFFFFF', size=11), paper_bgcolor='#000000', mapbox=dict( accesstoken=mapbox_access_token, bearing=0, center=dict( lat=57, lon=-4 ), pitch=0, zoom=5, style='dark' ), ) updatemenus = list([ # 地图样式下拉菜单 dict( buttons=list([ dict(args=['mapbox.style', 'dark'], label='Dark', method='relayout'), dict(args=['mapbox.style', 'light'], label='Light', method='relayout'), dict(args=['mapbox.style', 'outdoors'], label='Outdoors', method='relayout'), dict(args=['mapbox.style', 'satellite-streets'], label='Satellite with Streets', method='relayout') ]), direction='up', x=0.75, xanchor='left', y=0.05, yanchor='bottom', bgcolor='#000000', bordercolor='#FFFFFF', font=dict(size=11) ), # 视频类型筛选下拉菜单(动态适配类型数量) dict( buttons=list([ dict(label='All Testimonies', method='update', args=[{'visible': [True]*len(video_type)}]), dict(label='Stakeholder', method='update', args=[{'visible': [i==0 for i in range(len(video_type))]}]), dict(label='Scientist', method='update', args=[{'visible': [i==1 for i in range(len(video_type))]}]), dict(label='Member of the public', method='update', args=[{'visible': [i==2 for i in range(len(video_type))]}]) ]), direction='down', x=0.01, xanchor='left', y=0.99, yanchor='bottom', bgcolor='#000000', bordercolor='#FFFFFF', font=dict(size=11) ) ]) layout['updatemenus'] = updatemenus annotations = [dict( text='Video Testimonials across Scotland', font=dict(color='#FFFFFF', size=14), borderpad=10, x=0.05, y=0.05, xref='paper', yref='paper', align='left', showarrow=False, bgcolor='black' )] layout['title'] = 'Video testimonials' layout['annotations'] = annotations # 点击弹出视频的自定义JS(可选功能) custom_js = """ <script> document.addEventListener('DOMContentLoaded', function() { var plotDiv = document.getElementById('myPlot'); plotDiv.on('plotly_click', function(data) { var videoUrl = data.points[0].customdata; var modal = document.createElement('div'); modal.style.position = 'fixed'; modal.style.top = '50%'; modal.style.left = '50%'; modal.style.transform = 'translate(-50%, -50%)'; modal.style.zIndex = '1000'; modal.style.backgroundColor = 'black'; modal.style.padding = '10px'; var video = document.createElement('video'); video.width = '600'; video.controls = true; video.src = videoUrl; modal.appendChild(video); var closeBtn = document.createElement('button'); closeBtn.textContent = 'Close'; closeBtn.style.color = 'white'; closeBtn.style.backgroundColor = '#333'; closeBtn.style.marginTop = '10px'; closeBtn.onclick = function() { document.body.removeChild(modal); }; modal.appendChild(closeBtn); document.body.appendChild(modal); }); }); </script> """ # 生成HTML文件,包含自定义JS逻辑 figure = dict(data=data, layout=layout) plot(figure, filename='Test.html', auto_open=False, include_plotlyjs='cdn', post_script=custom_js, div_id='myPlot')
关键说明
- 悬停视频实现:通过
hovertemplate嵌入HTML视频标签,%{customdata}会自动替换为对应点位的视频URL,实现悬停时直接播放 - 点位消失修复:用
customdata传递URL,避免特殊字符破坏Plotly的文本解析流程,确保点位正常渲染 - 点击弹窗功能:自定义JS监听
plotly_click事件,点击点位后生成独立弹窗播放视频,优化交互体验 - 动态适配:类型筛选按钮的
visible参数通过len(video_type)动态生成,避免硬编码数量导致的错误
内容的提问来源于stack exchange,提问作者Konstantinos Sideris
相关产品推荐
相关产品推荐

