SVG 底图

v5.1.0 起,ECharts 支持在 geo 坐标系map 系列 中使用 SVG 作为底图,之前仅支持 GeoJSON

此功能使得 ECharts 能够在 canvas 渲染模式和 svg 渲染模式下显示 SVG,并支持诸如 缩放平移选择强调聚焦模糊标签labelLayouttooltip 等功能,只需少量的 ECharts 配置。可在 geo 坐标系 上使用的系列,如 scattereffectScatterlinescustom,也可以基于 SVG 底图进行定位和显示。

以下是使用 SVG 底图的几个示例: Beef Cuts | Organ Visualization | Flight Seatmap | SVG Map | SVG Scatter | SVG Lines | SVG Traffic

基本用法

SVG 底图的使用方式与 GeoJSON 的使用方式相同。

如果在 geo 坐标系 中使用

$.get('map/organ.svg', function (svg) {
    // Firstly we need to register SVG raw string or parsed SVG DOM
    // to echarts with a name:
    echarts.registerMap('organ_diagram', {svg: svg});

    var chart = echarts.init(document.getElementById('main'));
    chart.setOption({
        geo: {
            // Reference it in echarts option.
            map: 'organ_diagram',
            ...
        }
    });
});

如果在 map 系列 中使用

$.get('map/beef_cuts.svg', function (svg) {
    // Firstly we need to register SVG raw string or parsed SVG DOM
    // to echarts with a name:
    echarts.registerMap('beef_cuts_diagram', {svg: svg});

    var chart = echarts.init(document.getElementById('main'));
    chart.setOption({
        series: {
            type: 'map',
            // Reference it in echarts option.
            map: 'beef_cuts_diagram',
            ...
        }
    });
});

缩放和平移

针对 Geo 坐标系

option = {
    geo: {
        // Enable zoom and pan.
        roam: true,
        ...
    }
};
针对 map 系列
option = {
    series: {
        type: 'map',
        // Enable zoom and pan.
        roam: true,
        ...
    }
};

参见 roam。另请参见示例 SVG Map

具名元素

如果希望与 SVG 的某些元素进行交互,需要先在 SVG 中标记这些元素。这可以通过为目标元素添加 name 属性来简单实现。诸如 selectemphasisfocus‑blurlabellabelLayouttooltip 等交互相关特性都依赖这些具名元素。

例如,只在左侧的 SVG path 上添加属性 name="named_rect"

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="https://w3org.cn/2000/svg" version="1.2" fill-rule="evenodd" xml:space="preserve">
    <path name="named_rect" d="M 0,0 L 0,100 100,100 100,0 Z" fill="#765" />
    <path d="M 150,0 L 150,100 250,100 250,0 Z" fill="#567" />
</svg>
随后将鼠标悬停在左侧矩形上时,它会被高亮,而右侧的矩形则不会。

对某些具名元素的配置可以在 geo.regions 中指定,例如

option = {
    geo: {
        map: 'some_svg',
        regions: [{
            name: 'element_name_1',
            itemStyle: { ... }
        }, {
            name: 'element_name_2',
            itemStyle: { ... }
        }]
    }
};

注意

  • 这些 SVG 元素可以被 ECharts 命名并识别:rectcirclelineellipsepolygonpolylinepathtexttspang
  • 支持为多个元素使用相同的 name,届时它们会一起被高亮/选中。

样式自定义

虽然 SVG 元素的样式(如颜色、字体、线宽等)可以直接在 SVG 文件中定义,但具名元素的样式也可以在 ECharts 配置中定制,这在某些场景下非常方便。

样式可以在 geo.itemStyleseries‑map.itemStyle 中指定(同样支持 emphasis.itemStyleselect.itemStyleblur.itemStyleregions[i].itemStyleregions[i].emphasis.itemStyleregions[i].select.itemStyleregions[i].blur.itemStyle)。这里也可以去除具名元素的默认样式,例如将 emphasis.itemStyle.color: null 设为 null,即可防止鼠标悬停时填充颜色变化。

此外,若使用 series‑map,具名元素还可以通过 visualMap 组件 进行样式映射,详见 Beef Cuts

注意:只有以下具名元素可以在 itemStyle 中被样式化:rectcirclelineellipsepolygonpolylinepath

选择

具名元素可通过将 geo.selectedModeseries‑map.selectedMode 设置为 'single''multiple' 来启用“选择”特性。选中时的样式可在 geo.selectseries‑map.select 中指定。

选中的 name 可以通过 geoselectchanged 事件获取,例如

myChart.on('geoselectchanged', function (params) {
    var selectedNames = params.allSelected[0].name;
    console.log('selected', selectedNames);
});

更多细节请参见 Flight Seatmap

强调与聚焦模糊

emphasis 状态(悬停时高亮)会自动应用到具名元素。

特别是,可将 geo.emphasis.focus 设置为 'self',启用 “focus‑blur” 功能,即在悬停某个具名元素时,其他所有元素都会被模糊。

更多细节请参见 Organ Visualization

提示框

Tooltip 可以在具名元素上开启或关闭。

option = {
    // Need to declare the root tooltip to
    // enable tooltip feature on ECharts.
    tooltip: {},
    geo: {
        map: 'some_svg',
        tooltip: {
            // Use `show` to enable/disable tooltip
            // on geo coordinate system.
            show: true
        },
        regions: [{
            name: 'some_name1',
            // Set named element specified tooltip option if needed.
            tooltip: {
                formatter: 'some special tooltip 1'
            }
        }, {
            name: 'some_name2',
            tooltip: {
                formatter: 'some special tooltip 2'
            }
        }]
    }
};

如果希望在悬停具名元素时关闭 geo 的 tooltip,只需

option = {
    tooltip: {},
    geo: {
        map: 'some_svg',
        tooltip: {
            show: false
        }
    }
};

更多细节请参见 SVG Map

标签

虽然可以直接在 SVG 文件中使用 <text>/<tspan> 声明文字标签,但也可以通过在具名元素上指定 geo.labelseries‑map.label 来使用 ECharts 内置的标签功能。

默认情况下,悬停具名元素时会自动显示标签。若要关闭,只需

option = {
    geo: {
        map: 'some_svg',
        emphasis: {
            label: {
                show: false
            }
        }
    }
};

当多个元素需要共享同一个标签文本时,有两种做法:

  • 将这些元素包裹在具名的 <g> 中(例如 <g name="name_a">),则只显示一个标签,并根据该 <g> 的外接矩形定位。
  • 为这些元素使用相同的 name(例如 <path name="name_b"/><path name="name_b"/>),则会为每个元素各自显示一个标签并分别定位。

示例(悬停可显示标签)

注意:仅以下具名元素可以通过 label 选项进行标注:rectcirclelineellipsepolygonpolylinepathg

另请参见 Organ Visualization 中标签的使用方式。

活动

可以通过以下方式简单监听具名元素的鼠标或触摸事件:

// 'name1' is a name of a SVG element.
myChart.on('click', { geoIndex: 0, name: 'name1' }, function (params) {
    console.log(params);
});

SVG 底图布局

默认情况下,ECharts 会将 SVG 底图居中放置在画布内。如需微调,通常只需修改 layoutCenter / layoutSize,偶尔会配合 <svg viewBox="...">geo.boundingCoords(区别在于是否裁剪)。在大多数情况下,这已足够。

如果需要更精细的定位与缩放控制,可关注下面的几个概念。

geo 坐标系map 系列 的布局规则与选项完全相同。因此以下仅演示 geo 坐标系 的情况。

上面的演示在同一个 ECharts 画布中展示了六个 geo 坐标系,分别使用了三份 SVG 文件。每列的两个 geo 共用同一 SVG 文件。

首先,形状的外观由 SVG 文件本身决定。也就是说,上面演示的形状轮廓取决于 <circle>viewBoxviewBox 对圆形进行裁剪)。我们可以看到每列最终的轮廓是一致的(尽管位置、大小和裁剪方式不同),因为它们使用了相同的 SVG 文件。

其次,用户可以通过以下两组选项之一来确定 geo 坐标系geo 视口 的位置和大小,这些选项均基于整个图表画布(所有数值均以 ECharts 画布像素或百分比计)

在上面的演示中,六个 geo 视口 被显示为六个黑色方块。

第三步,会确定 SVG 的 外接矩形,其获取方式如下(均以 SVG 本地单位计)

  1. 如果指定了 geo.boundingCoords,则直接使用该值作为 外接矩形
  2. 否则若在 <svg width="..." height="..."> 中声明了宽高,则以 [0, 0, width, height] 作为 外接矩形(若只声明了 width 或 height,则分别使用 [0, width][0, height])。
  3. 否则若声明了 svg viewBox="...">,则使用 viewBox 作为 外接矩形
  4. 否则使用所有 SVG 元素的并集外接矩形作为 外接矩形
  5. 如果同时指定了 geo.centergeo.zoom,则在前面 1~4 步得到的 外接矩形 基础上进行相应的平移或缩放变换。

确定了 外接矩形 后,将其放入对应的 geo 视口

在 SVG 底图上放置系列

可以在 scattereffectScatterlinescustom 等可用于 geo 坐标系 的系列,同样在 SVG 底图上进行定位和显示。

需注意的是,在此种用法下系列数据值的单位采用的是 SVG 文件的本地坐标。例如

option = {
    geo: {
        map: 'some_svg'
    },
    series: {
        type: 'effectScatter',
        coordinateSystem: 'geo',
        geoIndex: 0,
        data: [
            // SVG local coords.
            [488.2358421078053, 459.70913833075736],
            [770.3415644319939, 757.9672194986475],
            [1180.0329284196291, 743.6141808346214],
        ]
    }
};

顺便提一下,有一种简便方法可以获取 SVG 本地坐标。

myChart.setOption({
    geo: {
        map: 'some_svg'
    }
});
myChart.getZr().on('click', function (params) {
    var pixelPoint = [params.offsetX, params.offsetY];
    var dataPoint = myChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
    // When click, the data in SVG local coords will be printed,
    // which can be used in `series.data`.
    console.log(dataPoint);
});

另请参考 SVG ScatterSVG LinesSVG Traffic

不支持的 SVG 特性

遗憾的是,实现完整的 SVG 解析器相当困难。虽然常用的 SVG 功能已得到支持,但以下列出的特性仍未支持:

  • 翻转与倾斜(将在 v5.1.2 支持)
    • 不支持 transform: skew(...)(包括包含倾斜的 transform: matrix(...))。
    • 不支持在同时存在 rotate 的情况下,transform: scale(x, y)xy 符号相反的情况(例如 scale: (1, -1), rotate(90))。
  • 不支持独立的 <style> 标签。
    • 但支持行内样式(例如 <path style="color:red" />)。
  • 单位
    • 仅支持 px。其他单位如 width="231.65mm" 不被支持。
    • 不支持百分比值,例如 <svg width="30%" height="40%">
  • <defs> 标签
    • 仅支持 <linearGradient><radialGradient>
    • 其它在 <defs> 中定义的元素(如 <pattern><path> 等)尚未支持。
  • <linearGradient>、<radialGradient>
    • fxfy 未支持。
    • gradientTransform 属性未支持。
  • fill:url(...)stroke:url(...)
    • 仅支持 url(#someId) 这种写法。
    • 其它 URL 形式不被支持,例如:
      • url(https://example.com/images/myImg.jpg);
      • url(data:image/png;base64,iRxVB0…);
      • url(myFont.woff);
  • <switch> 标签
    • 所有位于 <switch> 标签内的内容都会被渲染,switch 功能本身不受支持。
  • <text>:
    <!-- Not supported: -->
    <tspan x="0 4.94 9.89">abc</tspan>
    <!-- Supported: -->
    <tspan x="0">a</tspan>
    <tspan x="4.94">b</tspan>
    <tspan x="9.89">c</tspan>
    

贡献者 在 GitHub 上编辑此页面

100pah 100pah