Tableau 可视化项扩展开发指南 —— 以雷达图为例

Tableau可视化项扩展开发指南,以雷达图为例详解.trex扩展的完整开发流程。

作者:**姜斌、喜乐君**
版本:1.0 · 2026-05-01

📌 ➊ Viz Extension 核心价值:Tableau 2024.2 引入的里程碑功能,用 HTML/CSS/JS 创建自定义图表,像原生图表一样响应筛选器、支持工具提示、参与仪表板联动
➋ 三部件架构:.trex 清单文件(XML 编码槽位定义)、HTML/JS 页面(WebView 渲染)、共享库(lib/ 目录),数据流清晰
➌ 完整开发流程:从 .trex 结构解析→编码槽位设计→HTML 页面开发→D3.js 渲染→本地调试→云端部署→Server 发布,全链路覆盖
➍ 云端部署:采用腾讯云 COS + 自定义域名方案,需消除 CDN 依赖、配置 CORS/ACL/HTTPS
➎ Server 安全管理:不需上传 .trex 到 Server,通过正则通配符将 COS 域名加入允许列表,实现安全管控

一、什么是 Tableau Viz Extension(总)

1.1 Overview

Tableau 2024.2 引入了一项里程碑式的功能——可视化项扩展(Viz Extensions)。它允许开发者使用标准的 Web 技术(HTML、CSS、JavaScript)创建自定义图表类型,并将其无缝嵌入到 Tableau 工作表的 Marks 卡片中,与原生图表类型(柱状图、折线图、饼图等)并列使用。

在此之前,Tableau 的图表类型受限于内置的 24 种标记类型。Viz Extension 打破了这一限制——你可以创建桑基图、雷达图、径向图、蜂群图,以及任何你能用 D3.js 或 ECharts 实现的图表。

核心价值:不是"在仪表板中嵌入一个网页",而是让自定义图表像原生 Tableau 图表一样工作——响应筛选器、支持工具提示、参与仪表板联动。

Viz Extension 工作原理架构图
图 1:Viz Extension 工作原理 —— Tableau 加载 .trex 清单 → 解析编码槽位 → WebView 渲染 HTML → Extensions API 获取数据 → D3.js 绘制图表

1.2 工作原理

Viz Extension 由三部分组成:

组件

文件

角色

**清单文件**

`.trex`(XML)

告诉 Tableau "这是什么扩展、有哪些编码槽位、页面在哪"

**Web 页面**

`.html`

扩展的 UI,在 Tableau 内嵌 WebView 中渲染

**脚本逻辑**

`.js`

读取 Tableau 数据、处理用户交互、驱动图表渲染

工作流程:

Tableau Desktop/Server
    │
    ├─ 1. 加载 .trex 清单 → 解析编码槽位定义
    ├─ 2. 用户拖拽字段到槽位 → Tableau 查询数据
    ├─ 3. 加载 .html(WebView 中渲染)
    └─ 4. .js 通过 Extensions API 获取数据 → D3.js 绘制图表

1.3 本文目标

本文以雷达图(Radar Chart / Spider Chart)为完整案例,带你从零开始:

  • 理解 .trex 清单文件的 XML 结构
  • 编写扩展的 HTML/JS 代码
  • 在本地开发环境中调试
  • 将扩展部署到云存储,使其在 Tableau Server 上可用
  • 掌握发布到 Tableau Server 的完整配置

每个部分都遵循"Overview → 分步详解 → 引出下一章"的结构,你可以按顺序阅读,也可以跳到需要的章节。

接下来,我们从扩展的文件结构入手,理解一个 Viz Extension 由哪些文件组成。

二、扩展文件结构(分)

2.1 Overview

一个 Viz Extension 在文件系统上是一个标准的 Web 项目,加上一个特殊的 .trex 清单文件。以雷达图为例,完整的目录结构如下:

tableau-viz-extensions/
├── lib/                           ← 共享库(所有扩展共用)
│   ├── tableau.extensions.1.latest.js    Tableau Extensions API 库
│   └── d3.v7.min.js                      D3.js 可视化库
└── extensions/
    └── radar-chart/
        ├── radar-chart.trex       ← 清单文件(Tableau 读取)
        ├── radar-chart.html       ← 扩展主页面
        ├── radar-chart.js         ← 核心渲染逻辑
        ├── config-dialog.html     ← 配置对话框
        └── config-dialog.js       ← 配置逻辑

关键原则:.trex 文件供 Tableau Desktop 本地加载,HTML/JS 文件需要托管在 Web 服务器上。lib/ 目录存放所有扩展共享的第三方库,避免重复下载和 CDN 依赖。

2.2 .trex 清单文件详解

.trex 是一个 XML 文件,它是 Tableau 认识扩展的"身份证"。以下以雷达图的 radar-chart.trex 为例逐段解析:

<?xml version="1.0" encoding="utf-8"?>
<manifest manifest-version="0.1"
          xmlns="http://www.tableau.com/xml/extension_manifest">

  <!-- 扩展标识 -->
  <worksheet-extension id="com.tableau.extension.radar-chart"
                       extension-version="1.0.0">
    <default-locale>en_US</default-locale>
    <name resource-id="name"/>
    <description>Radar Chart with multi-series support</description>
    <author name="Vizwise" email="contact@vizwise.com"
            organization="Vizwise" website="https://vizwise.com"/>

    <!-- API 版本要求 -->
    <min-api-version>1.4</min-api-version>

    <!-- ⭐ 最关键:扩展页面的 URL -->
    <source-location>
      <url>https://oss.vizwise.online/extensions/radar-chart/radar-chart.html</url>
    </source-location>

    <!-- 编码槽位(见 2.4 节详解) -->
    <encoding id="axis"> ... </encoding>
    <encoding id="value"> ... </encoding>
    <encoding id="series"> ... </encoding>

    <!-- 配置对话框 -->
    <context-menu>
      <configure-context-menu-item />
    </context-menu>
  </worksheet-extension>

  <!-- 多语言资源 -->
  <resources>
    <resource id="name">
      <text locale="en_US">Radar Chart</text>
      <text locale="zh_CN">雷达图</text>
    </resource>
  </resources>
</manifest>

各元素说明:

XML 元素

作用

必填

`<manifest>`

根元素,声明 manifest 版本

✅

`<worksheet-extension id="...">`

扩展唯一标识,建议使用反向域名

✅

`<source-location><url>`

扩展页面的托管地址,**这是 Desktop 和 Server 加载扩展的入口**

✅

`<min-api-version>`

要求的最低 Extensions API 版本

✅

`<encoding>`

定义 Marks 卡上的拖放槽位(维度/度量)

至少1个

`<context-menu>`

右键菜单项,如"格式化"配置对话框

可选

`<resources>`

多语言文本资源

建议

2.3 编码槽位设计

编码槽位(Encoding)是 Viz Extension 与传统 Dashboard Extension 最大的区别——它定义了用户在 Tableau 工作表上可以拖放哪些字段。

雷达图有三个槽位:

<!-- 轴:雷达图的各个轴,如"速度""力量""耐久" -->
<encoding id="axis">
  <display-name>Axis</display-name>
  <role-spec>
    <role-type>discrete-dimension</role-type>
  </role-spec>
  <fields max-count="1"/>
  <tooltip>拖入维度字段定义雷达图的各个轴</tooltip>
</encoding>

<!-- 数值:每个轴上的度量值 -->
<encoding id="value">
  <display-name>Value</display-name>
  <data-spec>
    <data-type>numeric</data-type>
  </data-spec>
  <role-spec>
    <role-type>continuous-measure</role-type>
  </role-spec>
  <fields max-count="1"/>
  <tooltip>拖入度量字段设置轴值</tooltip>
</encoding>

<!-- 系列(可选):多系列对比 -->
<encoding id="series">
  <display-name>Series</display-name>
  <role-spec>
    <role-type>discrete-dimension</role-type>
  </role-spec>
  <fields max-count="1"/>
  <tooltip>可选。拖入维度字段叠加多个系列</tooltip>
</encoding>

属性

说明

`id`

槽位唯一标识,JS 代码中通过此 ID 获取数据

`role-type`

`discrete-dimension`(离散维度)或 `continuous-measure`(连续度量)

`fields max-count`

最多可拖入几个字段

`data-spec`

数据类型约束(仅度量槽位需要)

2.4 HTML 页面结构

radar-chart.html 是一个标准的 HTML5 页面,加载在 Tableau 的内嵌 WebView(基于 Chromium Embedded Framework)中:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <!-- ① Tableau Extensions API -->
    <script src="../../lib/tableau.extensions.1.latest.js"></script>
    <!-- ② D3.js v7(本地副本,不使用 CDN) -->
    <script src="../../lib/d3.v7.min.js"></script>
    <!-- ③ 内联 CSS 样式 -->
    <style> /* ... 雷达图样式 ... */ </style>
  </head>
  <body>
    <div id="app">
      <div id="loading"><!-- 加载中 --></div>
      <div id="empty-state"><!-- 空状态提示 --></div>
      <div id="chart-container">
        <svg id="radar-svg"></svg>    <!-- 图表渲染区 -->
        <div id="legend"></div>       <!-- 图例 -->
        <div id="tooltip"></div>      <!-- 工具提示 -->
      </div>
    </div>
    <!-- ④ 核心脚本 -->
    <script src="./radar-chart.js"></script>
  </body>
</html>

三个关键状态:

  1. Loading:扩展初始化中,显示加载动画

  2. Empty State:用户尚未拖入字段,提示操作指引

  3. Chart:数据就绪,D3.js 渲染雷达图

2.5 JavaScript 核心逻辑

radar-chart.js 是扩展的大脑,主要流程:

初始化 Tableau Extensions API
  → 注册"配置对话框"回调
  → 监听数据变更事件
  → 从 encoding 槽位读取数据
  → 调用 D3.js 绘制雷达图

关键代码骨架:

// 1. 初始化
tableau.extensions.initializeAsync({ configure: openConfigDialog })
  .then(() => {
    // 2. 获取工作表
    const worksheet = tableau.extensions.worksheetContent.worksheet;
    // 3. 监听数据变更
    worksheet.addEventListener(
      tableau.TableauEventType.SummaryDataChanged, renderChart
    );
    renderChart();
  });

// 4. 读取槽位数据
async function renderChart() {
  const worksheets = tableau.extensions.worksheetContent.worksheets;
  const dataTable = worksheets[0].getSummaryDataReader();
  // 遍历数据行,按 encoding id 分别提取 axis、value、series
  for (let row of dataTable) { /* ... */ }
  drawRadar(data);  // 调用 D3.js 渲染
}

// 5. 配置对话框
function openConfigDialog() {
  const popupUrl =
    `${window.location.origin}/extensions/radar-chart/config-dialog.html`;
  tableau.extensions.ui.displayDialogAsync(popupUrl, payload,
    { height: 580, width: 420 });
}

数据读取的核心 API:

API

作用

`tableau.extensions.initializeAsync()`

初始化扩展,注册回调

`worksheet.getSummaryDataReader()`

获取聚合数据(Tableau 已完成的聚合结果)

`dataTable.columns[i].fieldName`

获取列名

`dataTable.columns[i].index`

获取列索引

`tableau.extensions.ui.displayDialogAsync()`

弹出配置对话框

掌握了文件结构,接下来我们进入本地开发实战,在 Desktop 上把雷达图跑起来。

三、本地开发实战(分)

本地开发 vs 服务器部署对比
图 2:本地 localhost 只能在本机生效,发布到 Server 后失效;通过 COS 云端托管让 Desktop 和 Server 统一访问

3.1 Overview

本地开发阶段的目标是:在 Tableau Desktop 上加载扩展,能渲染图表、能交互调试。核心步骤:

  1. 启动本地 Web 服务器托管 HTML/JS
  2. 编写 .trex,URL 指向 localhost
  3. 在 Tableau Desktop 中加载扩展
  4. 拖入数据,验证渲染效果
  5. 使用浏览器 DevTools 调试

3.2 启动本地 Web 服务器

任何静态文件服务器都可以。推荐 Python 或 Node.js:

# 方案 A:Python(macOS 自带)
cd tableau-viz-extensions/
python3 -m http.server 8765

# 方案 B:Node.js(需先安装 http-server)
npx http-server -p 8765 --cors

此时访问 http://localhost:8765/extensions/radar-chart/radar-chart.html 即可看到页面。

3.3 配置 .trex 为本地 URL

<source-location>
  <!-- 本地开发 -->
  <url>http://localhost:8765/extensions/radar-chart/radar-chart.html</url>
</source-location>

注意:本地开发可以使用 HTTP(localhost 例外),但生产环境必须使用 HTTPS。

3.4 在 Tableau Desktop 中加载扩展

  1. 打开 Tableau Desktop 2024.2+
  2. 连接数据源(如 Superstore 示例)
  3. 新建工作表
  4. 在 Marks 卡 上,将标记类型下拉切换为 "扩展"(Extension)
  5. 在弹出的对话框中点击 "访问本地扩展"(Access Local Extensions)
  6. 选择 radar-chart.trex 文件

此时 Marks 卡上会显示雷达图的三个编码槽位。

3.5 拖入数据并验证

槽位

拖入字段

效果

**Axis**

维度字段(如 `Category`)

雷达图的 N 个轴

**Value**

度量字段(如 `Sales`)

每个轴上的数值

**Series**

维度字段(如 `Region`,可选)

多条雷达叠加对比

正确配置后,WebView 中应渲染出雷达图,支持悬停工具提示和图例交互。

3.6 调试技巧

由于扩展运行在 Tableau 的内嵌 WebView 中,无法直接使用浏览器 DevTools。解决方案:

  • Chrome 调试:在扩展 HTML 中加入 <script src="http://localhost:8098"></script>(需安装调试桥接工具)

  • 日志输出:使用 console.log(),在 Tableau 日志中查看

  • 独立测试:先在浏览器中直接打开 HTML,模拟数据渲染逻辑

本地调试通过后,图表在你的 Desktop 上完美运行。但当你把工作簿发给同事或发布到 Tableau Server 时,问题就来了——`localhost` 对别人来说毫无意义。下一章我们解决这个问题。

四、从 localhost 到云端:让服务器也能用(分)

4.1 为什么本地能用,服务器不能用?

这是每个 Viz Extension 开发者都会遇到的第一个"坑"。原因很简单:

场景

谁在加载扩展?

`localhost:8765` 指向谁?

结果

**Desktop 本机开发**

你的电脑

你的电脑 ✅

正常

**发布到 Tableau Server**

远程服务器

服务器自己 ❌(上面没有你的文件)

失败

**同事加载你的 .trex**

同事的电脑

同事的电脑 ❌(也没有文件)

失败

.trex 中的 <url> 就是一把"钥匙",Tableau 用它去获取扩展页面。localhost 这把钥匙只在你的机器上有效。

COS 部署完整流程
图 3:从本地开发到 Server 发布的完整流程 —— 编写代码 → 本地测试 → 上传 COS → 发布 Tableau Server

4.2 Overview:云端部署方案

要让扩展在任何地方都能用,需要把 HTML/JS 文件托管到一个公网可访问的 HTTPS 地址。推荐方案:

方案

优点

缺点

**腾讯云 COS + 自定义域名**

国内访问快、HTTPS 免费、配置简单

需要域名

GitHub Pages

免费、自动 HTTPS

国内访问不稳定

自有服务器 Nginx

完全可控

运维成本高

本文采用 腾讯云 COS 对象存储 + 自定义域名 方案。

4.3 部署前需要修改的文件

改动一:消除 CDN 依赖

<!-- 修改前 -->
<script src="https://d3js.org/d3.v7.min.js"></script>

<!-- 修改后:使用 lib/ 目录下的本地副本 -->
<script src="../../lib/d3.v7.min.js"></script>

原则:所有运行时依赖必须随扩展一起上传到 COS,不依赖任何外部 URL。

改动二:更新 .trex 的生产 URL

<source-location>
  <!-- 本地开发 -->
  <!-- <url>http://localhost:8765/extensions/radar-chart/radar-chart.html</url> -->
  <!-- 生产环境 -->
  <url>https://oss.vizwise.online/extensions/radar-chart/radar-chart.html</url>
</source-location>

改动三:确认 JS 中配置对话框路径

// 使用相对路径,自动适配 server 地址
const popupUrl = `${window.location.origin}/extensions/radar-chart/config-dialog.html`;

4.4 上传到 COS

需要上传的文件清单(不含 .trex,.trex 留在本地供 Desktop 加载):

上传到 COS 桶 (tableaubiportal-1306476856):
├── lib/
│   ├── tableau.extensions.1.latest.js   ← 1.8 MB
│   └── d3.v7.min.js                     ← 280 KB
└── extensions/
    └── radar-chart/
        ├── radar-chart.html             ← 主页面
        ├── radar-chart.js               ← 渲染逻辑
        ├── config-dialog.html           ← 配置页
        └── config-dialog.js             ← 配置逻辑

上传命令(使用腾讯云 COS SDK):

node cos_node.mjs upload \
  --bucket tableaubiportal-1306476856 \
  --region ap-shanghai \
  --acl public-read \
  --file "./radar-chart.html" \
  --key "extensions/radar-chart/radar-chart.html"

4.5 关键配置:CORS、ACL、HTTPS

部署到 COS 后,还需要三个关键配置,否则扩展在 Tableau 中无法加载:

配置

值

为什么需要

**文件 ACL**

`public-read`

允许匿名 HTTPS 访问

**CORS**

`Allow-Origin: *`

Tableau WebView 跨域加载扩展页面

**协议**

**HTTPS(强制)**

Tableau Server 对网络启用扩展要求 HTTPS

CORS 配置示例:

Allowed Origins: *
Allowed Methods: GET, HEAD
Allowed Headers: Content-Type, Accept, Origin
Max Age: 3600

4.6 验证部署

在浏览器中访问生产 URL,确认返回 HTTP 200 且 Content-Type 正确:

curl -sI https://oss.vizwise.online/extensions/radar-chart/radar-chart.html
# HTTP/1.1 200 OK
# Content-Type: text/html
# Access-Control-Allow-Origin: *
云端部署完成后,扩展已具备在 Tableau Server 上运行的条件。接下来看 Server 端需要做哪些配置。

五、发布到 Tableau Server(分)

5.1 Overview

将包含 Viz Extension 的工作簿发布到 Tableau Server 时:

  • 不需要上传 .trex 到 Server

  • 不需要在 Server 上部署任何扩展文件

  • 工作簿中携带的是 .trex 中提取的 URL 引用
  • Server 根据 URL 从 COS 加载扩展页面

Server 端的核心工作是安全管控——决定哪些扩展的 URL 被允许运行。

5.2 Server 管理员配置步骤

  1. 启用扩展功能:Tableau Server → 设置 → 扩展 → 勾选"允许扩展在此站点上运行"

  2. 将扩展加入允许列表:在"启用特定扩展"中,添加扩展 URL:

   https://oss.vizwise.online/.*

使用正则通配符可以一次性允许该域名下所有扩展。

  1. 配置数据访问权限:设置"完全数据访问"为允许或拒绝

  2. 配置用户提示:建议保持"显示提示",让终端用户知情

5.3 发布验证

  1. 在 Tableau Desktop 中,确保 .trex 的 <url> 指向生产地址
  2. 将工作簿发布到 Tableau Server
  3. 在 Server 上打开工作簿,验证扩展正常渲染
  4. 测试筛选器联动、工具提示等交互功能
至此,从本地开发到云端部署再到 Server 发布,完整的 Viz Extension 生命周期就打通了。

六、总结与最佳实践(总)

6.1 回顾

本文以雷达图为例,完整演示了 Tableau Viz Extension 的开发全流程:

开发阶段              部署阶段              发布阶段
─────────           ──────────           ──────────
编写 .trex          上传文件到 COS        发布工作簿
编写 HTML/JS/CSS    配置 ACL/CORS         Server 添加允许列表
本地 localhost 测试  替换 .trex URL       终端用户访问
                     验证 HTTPS 访问

6.2 最佳实践清单

#

实践

说明

1

**所有依赖本地化**

JS 库放到 `lib/`,不走 CDN,随扩展一起部署

2

**HTTPS 强制**

生产环境必须 HTTPS,`localhost` 是唯一例外

3

**CORS 必配**

不配 CORS,Tableau WebView 无法加载扩展

4

**public-read ACL**

匿名可读,无需鉴权即可访问静态资源

5

**URL 用变量管理**

本地 / 生产两套 URL 用注释切换,避免手动改代码

6

**三个状态都要有**

Loading → Empty State → Chart,提升用户体验

7

**编码槽位语义化**

`id` 命名清晰(axis/value/series),用 `<tooltip>` 引导用户

8

**.trex 不进 COS**

清单文件只在 Desktop 端使用,不部署到服务器

9

**Server 端用通配符**

`https://your-domain.com/.*` 一次配置,所有扩展可用

10

**先本地后云端**

本地调通渲染逻辑,再处理部署问题,避免混合调试

参考资源

  • Tableau Extensions API 官方文档

  • Tableau Viz Extensions 入门指南

  • Tableau Server 扩展管理

**唯有知识让我们免于平庸。** —— 喜乐君

*开发者:姜斌、喜乐君 · 2026年5月*

📖 相关文章
● Tableau 雷达图扩展使用指南
● Tableau MCP 深度介绍:让 AI 真正"看懂"你的数据
● Tableau LangChain:VizQL Data Service 集成详解
● Tableau 自定义 SQL 参数化 + Apache Doris 倒排索引:亿级大表的毫秒级实时点查实践
● 《解构Tableau可视化原理》勘误
——————————————————————————————

No comments yet