codecamp

ECharts实例一:拖拽的实现

Echarts 如何实现拖拽

下面描述了一个能够实现拖拽的实例,该实例是在 Echarts 的基础上的扩展,我们可以通过该例子了解到怎么利用 Echarts 提供的 API 实现定制化的富有交互的功能。

Echarts 实现拖拽的例子

点击编辑实例 》》

上述实例达到的功能:您可以使用鼠标拖拽图中曲线上的点,然后就能够改变曲线的形状。

上述实现拖拽的例子还很基础,但是学会上述例子之后我们能够进行更多的操作,比如在图中可视化的编辑。

Echarts 本身没有提供封装好的拖拽改变图表的功能,因为现在这个功能被认为不具备通用性。因此开发者要实现这个功能就要使用 API ,这样做的好处是能够让开发者按自己的需要进行设置。

(一)实现基本的拖拽功能

在这个例子中,基础的图表是一个 折线图 (series-line)。详细配置如下:

var symbolSize = 20;

// 这个 data 变量在这里单独声明,在后面也会用到。
var data = [[15, 0], [-50, 10], [-56.5, 20], [-46.5, 30], [-22.1, 40]];

myChart.setOption({
    xAxis: {
        min: -100,
        max: 80,
        type: 'value',
        axisLine: {onZero: false}
    },
    yAxis: {
        min: -30,
        max: 60,
        type: 'value',
        axisLine: {onZero: false}
    },
    series: [
        {
            id: 'a',
            type: 'line',
            smooth: true,
            symbolSize: symbolSize, // 为了方便拖拽,把 symbolSize 尺寸设大了。
            data: data
        }
    ]
});

折线点原本并没有拖拽功能,需要我们为它加上:使用 graphic 组件,在每个点上面,覆盖一个隐藏的可拖拽的圆点,具体操作如下:

myChart.setOption({
    // 声明一个 graphic component,里面有若干个 type 为 'circle' 的 graphic elements。
    // 这里使用了 echarts.util.map 这个帮助方法,其行为和 Array.prototype.map 一样,但是兼容 es5 以下的环境。
    // 用 map 方法遍历 data 的每项,为每项生成一个圆点。
    graphic: echarts.util.map(data, function (dataItem, dataIndex) {
        return {
            // 'circle' 表示这个 graphic element 的类型是圆点。
            type: 'circle',

            shape: {
                // 圆点的半径。
                r: symbolSize / 2
            },
            // 用 transform 的方式对圆点进行定位。position: [x, y] 表示将圆点平移到 [x, y] 位置。
            // 这里使用了 convertToPixel 这个 API 来得到每个圆点的位置,下面介绍。
            position: myChart.convertToPixel('grid', dataItem),

            // 这个属性让圆点不可见(但是不影响他响应鼠标事件)。
            invisible: true,
            // 这个属性让圆点可以被拖拽。
            draggable: true,
            // 把 z 值设得比较大,表示这个圆点在最上方,能覆盖住已有的折线图的圆点。
            z: 100,
            // 此圆点的拖拽的响应事件,在拖拽过程中会不断被触发。下面介绍详情。
            // 这里使用了 echarts.util.curry 这个帮助方法,意思是生成一个与 onPointDragging
            // 功能一样的新的函数,只不过第一个参数永远为此时传入的 dataIndex 的值。
            ondrag: echarts.util.curry(onPointDragging, dataIndex)
        };
    })
});

我们在上述代码中使用了 convertToPixel 这个 API,进行了从 data 到像素坐标的转换,以确定每个圆点所处的位置,然后进行圆点的绘制。

myChart.convertToPixel('grid', dataItem) 中的第一个参数 ‘grid’ 表示 dataItem 在 grid(即直角坐标系)这个组件中进行的转换。

像素坐标,就是以 Echarts 容器 dom element 的左上角为零点的以像素为单位的坐标系中的坐标。

注意:只有在初始化直角坐标系(grid)后才能够调用 myChart.convertToPixel('grid', dataItem)。

加入上述代码之后,折线上就有了可拖拽的点,接着我们要为每个圆点添加拖拽响应的事件,具体操作如下:

// 拖拽某个圆点的过程中会不断调用此函数。
// 此函数中会根据拖拽后的新位置,改变 data 中的值,并用新的 data 值,重绘折线图,从而使折线图同步于被拖拽的隐藏圆点。
function onPointDragging(dataIndex) {
    // 这里的 data 就是本文最初的代码块中声明的 data,在这里会被更新。
    // 这里的 this 就是被拖拽的圆点。this.position 就是圆点当前的位置。
    data[dataIndex] = myChart.convertFromPixel('grid', this.position);
    // 用更新后的 data,重绘折线图。
    myChart.setOption({
        series: [{
            id: 'a',
            data: data
        }]
    });
}

我们在上面的代码中,使用了 convertFromPixel 这个 API。它是 convertToPixel 的逆向过程。

myChart.convertFromPixel('grid', this.position) :把当前像素坐标转换成 grid 组件中直角坐标系的 dataItem 值。

最后,为了使 dom 尺寸改变时,图中的元素能自适应得变化,加入下述代码:

window.addEventListener('resize', function () {
    // 对每个拖拽圆点重新计算位置,并用 setOption 更新。
    myChart.setOption({
        graphic: echarts.util.map(data, function (item, dataIndex) {
            return {
                position: myChart.convertToPixel('grid', item)
            };
        })
    });
});

到目前为止,我们已经基本实现了拖拽功能。

(二)添加 tooltip 组件

现在,我们开始学习使用 tooltip 组件来实时显示拖拽过程中被拖拽的点的 data 值的变化状况。

注意:虽然 tooltip 有其默认的显示和隐藏的触发规则,但是在我们的拖拽场景中不适用,因此需要手动添加它们。

在上述代码中分别添加如下定义:

myChart.setOption({
    ...,
    tooltip: {
        // 表示不使用默认的『显示』『隐藏』触发规则。
        triggerOn: 'none',
        formatter: function (params) {
            return 'X: ' + params.data[0].toFixed(2) + '<br>Y: ' + params.data[1].toFixed(2);
        }
    }
});
myChart.setOption({
    graphic: echarts.util.map(data, function (item, dataIndex) {
        return {
            type: 'circle',
            ...,
            // 在 mouseover 的时候显示,在 mouseout 的时候隐藏。
            onmousemove: echarts.util.curry(showTooltip, dataIndex),
            onmouseout: echarts.util.curry(hideTooltip, dataIndex),
        };
    })
});

function showTooltip(dataIndex) {
    myChart.dispatchAction({
        type: 'showTip',
        seriesIndex: 0,
        dataIndex: dataIndex
    });
}

function hideTooltip(dataIndex) {
    myChart.dispatchAction({
        type: 'hideTip'
    });
}

这里使用了 dispatchAction 来显示隐藏 tooltip。用到了 showTip、hideTip

(三)Echarts 拖拽实例的全部代码

总结一下,全部的代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <script src="http://echarts.baidu.com/dist/echarts.min.js"></script>
</head>
<body>
    <div id="main" style="width: 600px;height:400px;"></div>
    <script type="text/javascript">

    var symbolSize = 20;
    var data = [[15, 0], [-50, 10], [-56.5, 20], [-46.5, 30], [-22.1, 40]];

    var myChart = echarts.init(document.getElementById('main'));

    myChart.setOption({
        tooltip: {
            triggerOn: 'none',
            formatter: function (params) {
                return 'X: ' + params.data[0].toFixed(2) + '<br>Y: ' + params.data[1].toFixed(2);
            }
        },
        xAxis: {
            min: -100,
            max: 80,
            type: 'value',
            axisLine: {onZero: false}
        },
        yAxis: {
            min: -30,
            max: 60,
            type: 'value',
            axisLine: {onZero: false}
        },
        series: [
            {
                id: 'a',
                type: 'line',
                smooth: true,
                symbolSize: symbolSize,
                data: data
            }
        ],
    });

    myChart.setOption({
        graphic: echarts.util.map(data, function (item, dataIndex) {
            return {
                type: 'circle',
                position: myChart.convertToPixel('grid', item),
                shape: {
                    r: symbolSize / 2
                },
                invisible: true,
                draggable: true,
                ondrag: echarts.util.curry(onPointDragging, dataIndex),
                onmousemove: echarts.util.curry(showTooltip, dataIndex),
                onmouseout: echarts.util.curry(hideTooltip, dataIndex),
                z: 100
            };
        })
    });

    window.addEventListener('resize', function () {
        myChart.setOption({
            graphic: echarts.util.map(data, function (item, dataIndex) {
                return {
                    position: myChart.convertToPixel('grid', item)
                };
            })
        });
    });

    function showTooltip(dataIndex) {
        myChart.dispatchAction({
            type: 'showTip',
            seriesIndex: 0,
            dataIndex: dataIndex
        });
    }

    function hideTooltip(dataIndex) {
        myChart.dispatchAction({
            type: 'hideTip'
        });
    }

    function onPointDragging(dataIndex, dx, dy) {
        data[dataIndex] = myChart.convertFromPixel('grid', this.position);
        myChart.setOption({
            series: [{
                id: 'a',
                data: data
            }]
        });
    }

</script>
</body>
</html>

在这些基础上,我们可以实现更多的功能,例如可以添加 dataZoom 组件、可以制作一个直角坐标系上的绘图板等等。


ECharts 富文本标签
ECharts实例二:实现日历图
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

ECharts配置项.setOption

ECharts图例组件配置项

ECharts图例组件配置 文本样式

ECharts xAxis配置 直角坐标系x轴

ECharts xAxis配置 x坐标轴名称的文本样式

ECharts xAxis配置 设置x坐标轴轴线

ECharts xAxis配置 x坐标轴刻度设置

ECharts xAxis配置 x坐标轴刻度标签设置

xAxis配置x坐标轴分隔线

xAxis配置坐标轴分隔区域设置

xAxis配置类目数据

ECharts xAxis配置 类目标签的文本样式

ECharts极坐标系的径向轴

如何使用dataZoom组件

ECharts工具栏组件(toolbox)

ECharts工具栏的feature属性

ECharts导出图片的操作

ECharts的数据视图工具

ECharts数据区域缩放工具

ECharts动态类型切换工具

ECharts区域选择组件(brush)

ECharts系列列表:平行坐标系

ECharts系列:主题河流图

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }