如何为Plotly中“下载图表”按钮导出的图片添加文字/水印?
为Plotly下载的图表添加文字/水印的实现方法
可以实现,但Plotly原生的toImageButtonOptions配置项没有直接添加水印的参数,需要通过以下两种方式实现:
方法1:在图表中添加隐藏文本(简单快速)
在图表中添加一个透明度极低的文本注释,平时几乎不可见,但下载图片时会被包含在内,作为水印。
示例代码:
import plotly.express as px df = px.data.iris() fig = px.scatter(df, x="sepal_width", y="sepal_length") # 添加水印注释,设置低透明度放在角落 fig.add_annotation( text="© 2024 自定义水印", xref="paper", yref="paper", x=0.95, y=0.05, # 右下角位置(paper坐标系:0-1) showarrow=False, font=dict(size=14, color="rgba(0,0,0,0.15)"), # 浅灰色半透明 opacity=0.15 ) # 保留你的下载配置 config = { 'toImageButtonOptions': { 'format': 'png', 'filename': 'download_image', } } fig.show(config=config)
方法2:自定义下载逻辑(灵活可控)
如果需要更明显的水印或自定义样式,可以禁用原生下载按钮,通过代码生成带水印的图片后再触发下载(以Dash应用为例,需依赖Pillow库处理图片):
示例代码:
from dash import Dash, dcc, html, Input, Output, State import plotly.express as px from io import BytesIO from PIL import Image, ImageDraw, ImageFont app = Dash(__name__) df = px.data.iris() fig = px.scatter(df, x="sepal_width", y="sepal_length") app.layout = html.Div([ # 隐藏原生工具栏,使用自定义下载按钮 dcc.Graph(id='watermark-graph', figure=fig, config={'displayModeBar': False}), html.Button('下载带水印的图表', id='download-btn', style={'margin-top': 10}), dcc.Download(id='watermark-download') ]) @app.callback( Output('watermark-download', 'data'), Input('download-btn', 'n_clicks'), prevent_initial_call=True ) def generate_watermarked_image(n_clicks): # 将图表转为PNG字节流 img_bytes = fig.to_image(format='png') img = Image.open(BytesIO(img_bytes)) # 初始化绘图对象 draw = ImageDraw.Draw(img) # 加载字体(可替换为本地字体路径,或使用默认字体) try: font = ImageFont.truetype('simhei.ttf', 24) # 中文黑体,需确保字体存在 except IOError: font = ImageFont.load_default() # 添加水印:右下角,半灰色 watermark_text = "© 2024 自定义水印" text_width, text_height = draw.textsize(watermark_text, font=font) draw.text( (img.width - text_width - 20, img.height - text_height - 20), watermark_text, fill=(100, 100, 100, 120), # RGBA,最后一位是透明度 font=font ) # 将处理后的图片转为字节流 buffer = BytesIO() img.save(buffer, format='PNG') buffer.seek(0) return dcc.send_bytes(buffer.getvalue(), 'download_image_with_watermark.png') if __name__ == '__main__': app.run_server(debug=True)
两种方法对比
- 方法1:无需额外依赖,实现简单,但水印样式和透明度受限,适合低调的版权标识。
- 方法2:依赖Pillow库,可完全自定义水印的字体、颜色、位置和透明度,适合需要醒目水印的场景。
内容的提问来源于stack exchange,提问作者Himanshu Joshi
相关产品推荐
相关产品推荐

