javascript - 在 svg 元素上 Hook 鼠标事件时,NVD3 图表控件不起作用

标签 javascript svg nvd3.js

我在 nvd3 中有一个面积图:

var chart = nv.models.stackedAreaChart()
    .x(function (d) { return d[0] })
    .y(function (d) { return Math.round(d[1]) })
    .clipEdge(true)
    .showControls(true)
    .useInteractiveGuideline(true);

如您所见,我启用了 showControls,它在图表的左上角显示三个小按钮(Stacked、Stream 和 Expanded)。

由于需要通过拖动鼠标来选择图表的子部分,因此我通过在包含图表的 SVG 元素上连接 mouseup、mousedown 和 mousemove 事件来实现以下解决方案。

    var mouseDown = false;
    var mouseDownCoords;
    var rect = svg.append("rect")
        .attr("x", 0).attr("y", 0)
        .attr("width", 0).attr("height", 0)
        .attr("fill", "rgba(43,48,87,0.3)");

    svg.on('mousedown', function () {
        var height = svg[0][0].height;

        mouseDownCoords = d3.mouse(this);
        mouseDown = true;

        rect.attr("x", mouseDownCoords[0]);
        rect.attr("height", height.animVal.value);

        // Register mousemove when the mouse button is down
        svg.on('mousemove', function () {
            var coords = d3.mouse(this);
            rect.attr("width", Math.max(coords[0] - mouseDownCoords[0], 0));
        });
    });

    svg.on('mouseup', function () {
        if (mouseDown) {
            var coords = d3.mouse(this);
            var width = Math.max(coords[0] - mouseDownCoords[0], 0);

            mouseDown = false;
            rect.attr("width", 0);

            if (width > 0) {
                var totalWidth = svg[0][0].width.animVal.value;
                var totalPeriod = dateTo.getTime() - dateFrom.getTime();
                var newDateFrom = new Date(Math.floor(dateFrom.getTime() + totalPeriod * mouseDownCoords[0] / totalWidth));
                var newDateTo = new Date(Math.floor(newDateFrom.getTime() + totalPeriod * width / totalWidth));
                window.setSearchTimeframe(newDateFrom, newDateTo);
            }
        }

        // Unregister mousemove
        svg.on('mousemove', null);
    });

但是,注册这些事件回调会阻止控制按钮工作。当我点击它们时,什么也没有发生,即使当我将它们悬停在它们上时指针正确地改变。

最佳答案

你是对的,在 NVD3 内置事件系统之外的元素上注册事件似乎确实会破坏内部事物(在我看来,情况不应该如此)。您可以通过在图表中需要自定义行为的部分放置一个不可见元素来解决此问题。

演示

红色矩形是图表中具有自定义行为的部分(单击它)。

var chartElement = d3.select("#chart svg");
var chart;

nv.addGraph(function() {
  chart = nv.models.pieChart()
    .x(function(d) {
      return d.label
    })
    .y(function(d) {
      return d.value
    })
    .showLabels(true);

  var chartData = [{
    label: "Foo",
    value: 67
  }, {
    label: "Bar",
    value: 33
  }];

  chartElement
    .datum(chartData)
    .call(chart);

  $("#customUI").on("mousedown", function() {
    alert("Some custom behaviour...");
  });

  return chart;
});
#wrapper {
  position: relative;
}
#chart {
  position: absolute;
  height: 500px;
}
#customUI {
  position: absolute;
  background: red;
  opacity: 0.2;
  width: 100px;
  height: 100px;
  left: 100px;
  top: 200px;
}
#customUI:hover {
  opacity: 0.5;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/nvd3/1.8.2/nv.d3.min.css" rel="stylesheet" />
<div id="wrapper">
  <div id="chart">
    <svg>
    </svg>
  </div>
  <div id="customUI">
  </div>
</div>

关于javascript - 在 svg 元素上 Hook 鼠标事件时,NVD3 图表控件不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36568073/

相关文章:

javascript - 在移动设备上预加载音频

javascript - 如何实现一个算法来检测一个数字是否有2个连续的数字?

javascript - 如何在超链接单击时使用 javascript 动态更改 SVG 图案图像

javascript - 获取 Rect 元素的屏幕像素坐标

nvd3.js - NVD3 - 更改折线图上的 X 标签轴

javascript - 我的 JavaScript 搜索递归循环出了什么问题?

javascript - 如何设置正文相对于屏幕大小的字体大小

css - 理解 viewBox : how to use the correct size

javascript - 在动态创建的 div 上绘制多个 NVD3.js 图表的问题

angularjs - nvd3 中的事件处理