You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 16:01:18