介绍一个实现拖拽的小例子。这个例子是在原生 echarts 基础上做了些小小扩展,带有一定的交互性。通过这个例子,我们可以了解到,如何使用 echarts 提供的 API 实现定制化的富有交互的功能。

这个例子主要做到了这样一件事,用鼠标可以拖拽曲线的点,从而改变曲线的形状。例子很简单,但是有了这个基础我们还可以做更多的事情,比如在图中可视化得编辑。所以我们从这个简单的例子开始。

echarts 本身没有提供封装好的『拖拽改变图表』功能,因为现在认为这个功能并不足够有通用性。那么这个功能就留给开发者用 API 实现,这也有助于开发者按自己的需要个性定制。

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

  1. // 声明一个 graphic component,里面有若干个 type 为 'circle' 的 graphic elements。
  2. // 这里使用了 echarts.util.map 这个帮助方法,其行为和 Array.prototype.map 一样,但是兼容 es5 以下的环境。
  3. // 用 map 方法遍历 data 的每项,为每项生成一个圆点。
  4. graphic: echarts.util.map(data, function (dataItem, dataIndex) {
  5. return {
  6. // 'circle' 表示这个 graphic element 的类型是圆点。
  7. type: 'circle',
  8. shape: {
  9. // 圆点的半径。
  10. r: symbolSize / 2
  11. },
  12. // 用 transform 的方式对圆点进行定位。position: [x, y] 表示将圆点平移到 [x, y] 位置。
  13. // 这里使用了 convertToPixel 这个 API 来得到每个圆点的位置,下面介绍。
  14. position: myChart.convertToPixel('grid', dataItem),
  15. // 这个属性让圆点不可见(但是不影响他响应鼠标事件)。
  16. invisible: true,
  17. draggable: true,
  18. // 把 z 值设得比较大,表示这个圆点在最上方,能覆盖住已有的折线图的圆点。
  19. z: 100,
  20. // 这里使用了 echarts.util.curry 这个帮助方法,意思是生成一个与 onPointDragging
  21. // 功能一样的新的函数,只不过第一个参数永远为此时传入的 dataIndex 的值。
  22. ondrag: echarts.util.curry(onPointDragging, dataIndex)
  23. };
  24. })
  25. });

上面的代码中,使用 这个 API,进行了从 data 到『像素坐标』的转换,从而得到了每个圆点应该在的位置,从而能绘制这些圆点。myChart.convertToPixel('grid', dataItem) 这句话中,第一个参数 'grid' 表示 dataItemgrid 这个组件中(即直角坐标系)中进行转换。所谓『像素坐标』,就是以 echarts 容器 dom element 的左上角为零点的以像素为单位的坐标系中的坐标。

注意这件事需要在第一次 setOption 后再进行,也就是说,须在坐标系()初始化后才能调用 myChart.convertToPixel('grid', dataItem)

有了这段代码后,就有了诸个能拖拽的点。接下来要为每个点,加上拖拽响应的事件:

上面的代码中,使用了 convertFromPixel 这个 API。它是 的逆向过程。myChart.convertFromPixel('grid', this.position) 表示把当前像素坐标转换成 grid 组件中直角坐标系的 dataItem 值。

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

到此,拖拽的基本功能就完成了。但是想要更进一步得实时看到拖拽过程中,被拖拽的点的 data 值的变化状况,我们可以使用 组件来实时显示这个值。但是,tooltip 有其默认的『显示』『隐藏』触发规则,在我们拖拽的场景中并不适用,所以我们还要手动定制 tooltip 的『显示』『隐藏』行为。

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

  1. myChart.setOption({
  2. return {
  3. type: 'circle',
  4. ...,
  5. // 在 mouseover 的时候显示,在 mouseout 的时候隐藏。
  6. onmousemove: echarts.util.curry(showTooltip, dataIndex),
  7. onmouseout: echarts.util.curry(hideTooltip, dataIndex),
  8. };
  9. })
  10. });
  11. function showTooltip(dataIndex) {
  12. myChart.dispatchAction({
  13. type: 'showTip',
  14. seriesIndex: 0,
  15. dataIndex: dataIndex
  16. });
  17. }
  18. function hideTooltip(dataIndex) {
  19. myChart.dispatchAction({
  20. type: 'hideTip'

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

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