NVD3图表控件don'在svg元素上挂接鼠标事件时不起作用

NVD3 chart controls don't work when hooking mouse events on svg elements

本文关键字:元素 鼠标 不起作用 事件 svg 控件 don NVD3      更新时间:2024-05-03

我在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,它在图表的左上角显示三个小按钮(堆叠、流和展开)。

由于需要通过拖动鼠标来选择图表的子部分,因此我通过在包含图表的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内置事件系统之外的元素上注册事件似乎真的会破坏内部的东西(在我看来,情况不应该如此)。你可以通过在图表中需要自定义行为的部分放置一个不可见的元素来解决这个问题。

Demo

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

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>