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

如何在Plotly.js三元图中随画布尺寸动态调整注释位置?

问题描述

我用Python版Plotly制作的三元散点图,注释能随画布尺寸变化自动调整相对位置,布局始终一致。但改用Plotly.js重构后,调整画布宽高(比如从700改为800)时,注释的相对位置发生偏移,甚至出现内容截断的情况。尝试调整yref参数但未解决问题,附上简化实现代码,求问如何让注释随画布尺寸变化自动保持相对位置?

简化代码

JavaScript代码

// 定义自动生成三元轴的函数
function makeAxis(title, tickangle, gridcolor) {
    return {
        "title": title,
        "titlefont": { "size": 20 },
        "tickangle": tickangle,
        "tickfont": { "size": 15 },
        "tickcolor": '#FFFFFF',
        "ticklen": 8,
        "min": 0,
        "showline": true,
        "showgrid": true,
        "ticks": 'outside',
        "tickmode": 'array',
        "tickvals": [0,10,20,30,40,50,60,70,80,90,100],
        "gridcolor": gridcolor,
        "gridwidth": 1.8,
        "tickcolor": gridcolor,
        "tickwidth": 1.8,
    };
}

// 获取绘图容器元素
const ternary_plot_div = document.getElementById('ternary_soil')

// 设置基础绘图数据
const ternaryBaseData = [{
    // 空的基础散点图
    "a": [],
    "b": [],
    "c": [],
    "type": 'scatterternary',
  },  
    // 绘制Sandy Clay分类的轮廓与填充
    {
    "a": [0.55, 0.35, 0.35, 0.55],
    "b": [0.45, 0.65, 0.45, 0.45],
    "c": [0.00, 0.00, 0.20, 0.00],
    "type": 'scatterternary',
    "mode": 'lines',
    "line": {
        "width":3, 
        "color":'black'
    },
    "showlegend": false,
    "fill": 'toself',
    "fillcolor": 'rgba(1.0, 0.7, 0.7, 0.2)',
    "hoverinfo": 'none'
}
];

// 设置三元图布局
const figH = 700;
const figW = 700; 
const text_bg_color = 'rgba(0,0,0,0.4)'
const annotation_text_color = '#fff'

const layout = {
    // 基础外观配置
    "autosize": false,
    "width": figW,
    "height": figH,
    
    // 三元轴配置
    "ternary": {
        "sum": 100,
        "aaxis": makeAxis('', 0, 'rgba(0, 230, 230, 0.8)'),
        "baxis": makeAxis('', 45, 'rgba(230, 0, 230,0.8)'),
        "caxis": makeAxis('', -45, 'rgba(230, 191, 0, 0.8)')
    }, 
    
    // 注释配置:标题、轴标签、区域标签
    "annotations": [
        // 图标题
        {
            "showarrow": false,
            "text": 'USDA土壤/沉积物<br>质地分类',
            "x": 0.5,
            "y": 1.2,
            "xref": "paper",
            "yref": "paper",
            "font": { "size": 25 }
        },

        // Sand轴标签
        {
            "text":"<b>砂粒 (%)</b>",
            "showarrow": false,
            "x": 0.5,
            "y": -0.15,
            "xref": "paper",
            "yref": "paper",
            "font": {
                "size": 26,
                "color": '#000'
            },
            "align": 'center'
        },

        // Clay轴标签
        {
            "text":"<b>黏粒 (%)</b>",
            "showarrow": false,
            "x": 0.015,
            "y": 0.555,
            "xref": "paper",
            "yref": "paper",
            "font": {
                "size": 26,
                "color": '#000'
            },
            "align": 'center',
            "textangle": -60
        },

        // Silt轴标签
        {
            "text":"<b>粉粒 (%)</b>",
            "showarrow": false,
            "x": 0.965,
            "y": 0.575,
            "xref": "paper",
            "yref": "paper",
            "font": {
                "size": 26,
                "color": '#000'
            },
            "align": 'center',
            "textangle": 60
        },

        // Sandy Clay区域标签
        {
            "text": '<b>砂质<br>黏粒</b>',
            "showarrow": false,
            "xref": "ternary",
            "yref": "ternary",
            "a": 0.45, // 对应三元坐标的a值,取区域中心
            "b": 0.55, // 对应三元坐标的b值
            "c": 0.10, // 对应三元坐标的c值
            "font": {
                "size": 17,
                "color": annotation_text_color,
            },
            "align": 'center',
            "bordercolor": '#000',
            "borderwidth": 2,
            "borderpad": 2,
            "bgcolor": text_bg_color,
            "hovertext": '砂质黏粒土壤组成:<br>黏粒: 35-55%<br>粉粒: 0-20%<br>砂粒: 45-65%'
        }
]};

// 绘制图表
Plotly.newPlot(ternary_plot_div, ternaryBaseData, layout); 

HTML代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- 引入Plotly.js -->
    <script src="https://cdn.plot.ly/plotly-2.18.2.min.js"></script>
    
    <title>土壤三元图</title>
</head>
<body>
    <br><br><br>
    <div id='ternary_soil'><!-- Plotly图表将绘制在此DIV内 --></div>
</body>
<!-- 引入三元图脚本 -->
<script src='./throw_away_ternary.js'></script>
</html>
解决核心要点
  1. 移除错误的注释属性:原代码中给注释添加了"type": 'scatterternary',这是数据系列(trace)的类型,不属于注释配置,会干扰注释的定位逻辑,必须删除。
  2. 正确设置坐标系参考:
    • 全局注释(标题、轴标签):设置xref: "paper"和yref: "paper",使用0-1的比例值定位,这样注释会相对于整个画布的比例保持位置,缩放画布时不会偏移。
    • 三元图内部的区域标签:设置xref: "ternary"和yref: "ternary",并使用a/b/c属性绑定三元坐标(取值对应三元图的比例,总和为1),这样标签会始终固定在三元图的对应区域中心,不受画布尺寸变化影响。
  3. 避免内容截断:确保注释的bgcolor和borderpad设置合理,同时如果开启autosize: true,Plotly会自动调整布局适配容器,也可以通过监听容器尺寸变化,调用Plotly.relayout()动态更新宽高。

内容的提问来源于stack exchange,提问作者eigenVector5

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 23:12:05