D3js mulitline图鼠标悬停 [英] D3js mulitline chart mouseOver

查看:293
本文介绍了D3js mulitline图鼠标悬停的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图适应此内容的D3js线图例如鼠标悬停使用我的多线图

似乎 d3.mouse(本)[0] 鼠标移动函数生成以下错误: 无法读取空的特性sourceEvent的'。

1任何想法,为什么我得到空sourceEvent的错误?

2如何将鼠标移到例如,从一个单一的折线图适应多(N)线图任何提示?

下面是一个的jsfiddle 来证明这个问题。
(和解决方案

  VAR对myApp = angular.module('应用',[]);
myApp.directive(折线图功能(){
  返回{
    限制:'E',
    范围: {
      数据:=,
      ID: '@'
    },
    链接:功能(范围,元素,ATTRS){
      范围。$表(数据,功能(数据){
        d3.select(#+ attrs.id)。选择(SVG),删除()。
        如果(数据){
          VAR利润率= {顶:20,右:20,底部:30,左:40},
              宽度=元素[0] .parentElement.offsetWidth - margin.left - margin.right,
              高度=元素[0] .parentElement.offsetHeight - margin.top - margin.bottom;
          VAR parseDate = d3.time.format(%D-%B-%y)的解析。
          VAR X = d3.time.scale()
              .range([0,宽度]);
          变种Y = d3.scale.linear()
              .range([身高,0]);
          VAR XAXIS = d3.svg.axis()
              .scale(X)
              。东方(底部)
              .innerTickSize(-height)
              .ticks(4)
              .outerTickSize(0)
              .tickPadding(5)
              .tickFormat(函数(D){返回d3.time.format('%D /%M%H:%M')(新日期(D));});
          变种Y轴= d3.svg.axis()
              .scale(Y)
              。东方(左)
              .innerTickSize(-width)
              .outerTickSize(0)
              .tickPadding(10);
          VAR线= d3.svg.line()
              .X(函数(D){返回X(D [0]);})
              .Y(函数(D){返回Y(D [1]);});
          VAR SVG = d3.select(元素[0])。追加(SVG)
              .attr(宽度,100%)
              .attr(高度,100%)
              .attr('视框','0 0'+元素[0] .parentElement.offsetWidth ++元素[0] .parentElement.offsetHeight)
            .append(G)
              .attr(转换,翻译(+ margin.left +,+ margin.top +));
          VAR其minX = d3.min(数据,功能(项){返回d3.min(item.values​​,功能(D){返回D [0];})});
          VAR MAXX = d3.max(数据,功能(项){返回d3.max(item.values​​,功能(D){返回D [0];})});
          VAR MINY = d3.min(数据,功能(项){返回d3.min(item.values​​,功能(D){返回D [1];})});
          VAR MAXY = d3.max(数据,功能(项){返回d3.max(item.values​​,功能(D){返回D [1];})});
          x.domain([疯丫头,MAXX]);
          y.domain([0,MAXY]);
          svg.append(G)
              .attr(类,X轴)
              .attr(转换,翻译(0,+高度+))
              .CALL(X轴);
          svg.append(G)
              .attr(类,Y轴)
              .CALL(Y轴);
          VAR酒庄= svg.selectAll(酒庄)
              的.data(数据)
              。进入()。追加(G)
              .attr(类,酒庄);
          domaine.append(路径)
              .attr(类,线)
              .attr(D功能(D){
                  回线(d.values​​);
              })
              .style(中风,功能(D){
                返回d.color;
              });
          变种聚焦= svg.append(G)
              .attr(类,焦点访谈)
              .style(显示,无);
          focus.append(圆)
              .attr(R,4.5);
          focus.append(文本)
              .attr(×,9)
              .attr(DY,.35em);
          svg.append(矩形)
              .attr(类,叠加)
              .attr(宽宽)
              .attr(高度,高度)
              。对(鼠标悬停功能(){focus.style(显示,NULL);})
              。对(鼠标移开功能(){focus.style(显示,无);})
              。对(鼠标移动,鼠标移动());
          鼠标移动功能(){
            VAR X0 = x.invert(d3.mouse(本)[0]),
                I = bisectDate(数据,X0,1),
                D0 =数据[I - 1]
                D1 =数据[I]; / *
                为适应多线
                ,
                D = X0 - d0.date> d1.date - X0? D1:D0;
            focus.attr(转换,翻译(+ X(d.date)+,+ Y(d.close)+));
            focus.select(文本)文本(formatCurrency(d.close)); * /
          }
        }
      });
    }
  };
});
功能MainCtrl($范围){
$ scope.lineData = [{钥匙:用户,色:#16a085
价值观:[1413814800000,4034.418],[1413815400000,5604.155000000001]},
{关键:用户2,色:#d95600
价值观:[1413814800000,3168.183],[1413815400000,1530.8435]}];
}


解决方案

当你写

 。对(鼠标移动,鼠标移动());

这是马上致电鼠标移动函数,并将其返回值作为的监听功能鼠标移动事件。由于您没有设置正确的这个这就是为什么 d3.mouse(本)收益

解决方法是非常简单:只是通过在你的鼠标移动函数作为参考,不叫它:

 。对(鼠标移动,鼠标移动);

然而,即使此修复程序后,你仍然会得到一个错误在小提琴因为你的 bisectDate 功能缺失......

I'm trying to adapt this D3js line chart example of mouse-over usage to my multi-line chart.

It seems that d3.mouse(this)[0] on the mousemove function generate the following error: "Cannot read property 'sourceEvent' of null".

1 Any idea why I get the null sourceEvent error ?

2 Any tips on how to adapt the mouse over example from a single line chart to a multi (n) line chart ?

Here is a jsfiddle to demonstrate the issue. ( And the solution )

var myApp = angular.module('app', []);
myApp.directive("lineChart", function() {
  return {
    restrict: 'E',
    scope: {
      data: '=',
      id: '@'
    },
    link: function (scope, element, attrs) {
      scope.$watch( 'data', function ( data ) {
        d3.select("#"+attrs.id).select("svg").remove();
        if (data) {
          var margin = {top: 20, right: 20, bottom: 30, left: 40},
              width = element[ 0 ].parentElement.offsetWidth - margin.left - margin.right,
              height = element[ 0 ].parentElement.offsetHeight - margin.top - margin.bottom;
          var parseDate = d3.time.format("%d-%b-%y").parse;
          var x = d3.time.scale()
              .range([0, width]);
          var y = d3.scale.linear()
              .range([height, 0]);
          var xAxis = d3.svg.axis()
              .scale(x)
              .orient("bottom")
              .innerTickSize(-height)
              .ticks(4)
              .outerTickSize(0)
              .tickPadding(5)
              .tickFormat(function(d) { return d3.time.format('%d/%m %H:%M')(new Date(d)); });
          var yAxis = d3.svg.axis()
              .scale(y)
              .orient("left")
              .innerTickSize(-width)
              .outerTickSize(0)
              .tickPadding(10);
          var line = d3.svg.line()
              .x(function(d) { return x(d[0]); })
              .y(function(d) { return y(d[1]); });
          var svg = d3.select(element[0]).append("svg")
              .attr("width", '100%')
              .attr("height", '100%')
              .attr('viewBox','0 0 '+ element[ 0 ].parentElement.offsetWidth +' '+ element[ 0 ].parentElement.offsetHeight )
            .append("g")
              .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
          var minX = d3.min(data, function (item) { return d3.min(item.values, function (d) { return d[0]; }) });
          var maxX = d3.max(data, function (item) { return d3.max(item.values, function (d) { return d[0]; }) });
          var minY = d3.min(data, function (item) { return d3.min(item.values, function (d) { return d[1]; }) });
          var maxY = d3.max(data, function (item) { return d3.max(item.values, function (d) { return d[1]; }) });
          x.domain([minX, maxX]);
          y.domain([0, maxY]);
          svg.append("g")
              .attr("class", "x axis")
              .attr("transform", "translate(0," + height + ")")
              .call(xAxis);
          svg.append("g")
              .attr("class", "y axis")
              .call(yAxis);
          var domaine = svg.selectAll(".domaine")
              .data(data)
              .enter().append("g")
              .attr("class", "domaine");
          domaine.append("path")
              .attr("class", "line")
              .attr("d", function (d) {
                  return line(d.values);
              })
              .style("stroke", function (d) {
                return d.color;
              });
          var focus = svg.append("g")
              .attr("class", "focus")
              .style("display", "none");
          focus.append("circle")
              .attr("r", 4.5);
          focus.append("text")
              .attr("x", 9)
              .attr("dy", ".35em");
          svg.append("rect")
              .attr("class", "overlay")
              .attr("width", width)
              .attr("height", height)
              .on("mouseover", function() { focus.style("display", null); })
              .on("mouseout", function() { focus.style("display", "none"); })
              .on("mousemove", mousemove());
          function mousemove() {              
            var x0 = x.invert(d3.mouse(this)[0]),
                i = bisectDate(data, x0, 1),
                d0 = data[i - 1],
                d1 = data[i];/*
                To adapt for multi line
                ,
                d = x0 - d0.date > d1.date - x0 ? d1 : d0;
            focus.attr("transform", "translate(" + x(d.date) + "," + y(d.close) + ")");
            focus.select("text").text(formatCurrency(d.close));*/
          }
        }
      });
    }
  };
});
function MainCtrl($scope) {
$scope.lineData = [{"key": "users","color": "#16a085",
"values": [[1413814800000,4034.418],[1413815400000,5604.155000000001]]},
{"key": "users 2","color": "#d95600",
"values": [[1413814800000,3168.183],[1413815400000,1530.8435]]}];
}

解决方案

When you write

.on("mousemove", mousemove());

it is immediately call the mousemove function and passes its return value as the listener function to the "mousemove" event. Because you are not setting correctly the this that is why d3.mouse(this) returns null.

The fix is very easy: just pass in your mousemove function as reference and don't call it:

.on("mousemove", mousemove);

However even after this fix you will still get an error in the fiddle because your bisectDate function is missing...

这篇关于D3js mulitline图鼠标悬停的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆