D3图表上的缩放和刷牙问题

时间:2018-04-27 04:59:04

标签: javascript jquery d3.js

我在下面的代码中使用 d3.area()而不是 d3.line()。共有2组“焦点”“上下文”焦点是主要图表,而上下文是使用 brushed() zoom()来选择范围。< / p>

问题是焦点组的圆圈正在根据上下文组中的选定范围正确移动,而区域正在消失。

我假设 area()没有返回正确的值。 JSFiddle

  var data = [
  {xLabel: "02:01:00", LastMonday: 200, Today: 500},
  {xLabel: "03:02:00", LastMonday: 620, Today: 600},
  {xLabel: "10:03:20", LastMonday: 300, Today: 800},
  {xLabel: "10:04:00", LastMonday: 440, Today: 700},
  {xLabel: "10:05:00", LastMonday: 900, Today: 900},
  {xLabel: "10:06:30", LastMonday: 300, Today: 500},
  {xLabel: "10:07:00", LastMonday: 50, Today: 300},
  {xLabel: "11:08:00", LastMonday: 350, Today: 70},
  {xLabel: "12:09:50", LastMonday: 750, Today: 200}
];
var textRotation = true;
var righttoleft = false;
var category = ['LastMonday', 'Today'];

var drawLine = ['Today'],
  drawArea = ['LastMonday'];

function initLineChart(data, id) {
  var	mainwidth = $(id).innerWidth(),
  mainheight = $(id).innerHeight();

  function getPercent(actualval, perval)	
  {
    return Math.round((actualval / 100) * perval);
  }

  var margin = {
      top: getPercent(mainheight,4), 
      bottom: getPercent(mainheight,45), 

      },

  margin2 = {
      top: getPercent(mainheight,76), 
      bottom: getPercent(mainheight,16), 

      };

  if(righttoleft)
  {
    margin.left = getPercent(mainwidth,4); 
    margin.right = getPercent(mainwidth,8);
    margin2.left = getPercent(mainwidth,4);
    margin2.right = getPercent(mainwidth,8);
  }else
  {
    margin.left = getPercent(mainwidth,8);
    margin.right = getPercent(mainwidth,4); 
    margin2.left = getPercent(mainwidth,8);
    margin2.right = getPercent(mainwidth,4); 
  }	

  var width = $(id).innerWidth() - margin.left - margin.right,
    height = $(id).innerHeight() - margin.bottom,
    height2 = $(id).innerHeight() - margin2.top - margin2.bottom ;

    var parseDate = d3.timeParse("%H:%M:%S"); 

    var legendSize = 10,
      legendColor = {'LastMonday': 'rgba(255, 160, 233, 0.6)', 'Today': 'rgba(0, 160, 233, 0.2)'};

    var x = d3.scaleTime().range([0, width]),
      x2 = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0]),
      y2 = d3.scaleLinear().range([height2, 0]);

    var xAxis = d3.axisBottom(x).tickFormat(d3.timeFormat("%H:%M:%S"))
              .tickPadding([6]).tickSize(-height),
      xAxis2 = d3.axisBottom(x2).tickFormat(d3.timeFormat("%H:%M:%S")),
      yAxis;
      if(righttoleft){
        yAxis = d3.axisRight(y).ticks(10).tickSize(-width);
      }else
      {
        yAxis = d3.axisLeft(y).ticks(10).tickSize(-width);
      }


    var brush = d3.brushX()
      .extent([[0, 0], [width, height2]])
      .on("brush end", brushed);

    var zoom = d3.zoom()
      .scaleExtent([1, Infinity])
      .translateExtent([[0, 0], [width, height]])
      .extent([[0, 0], [width, height]])
      .on("zoom", zoomed);


    var ddata = (function() {
      var temp = {}, seriesArr = [];
      category.forEach(function (name) {
        temp[name] = {category: name, values:[]};
        seriesArr.push(temp[name]);
      });
      data.forEach(function (d) {
        category.map(function (name) {
          temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
        });
      });

      return seriesArr;
    })();

    var ldata = (function() {
      var temp = {}, seriesArr = [];

      temp[drawLine[0]] = {category: drawLine[0], values:[]};
      seriesArr.push(temp[drawLine]);

      data.forEach(function (d) {
        drawLine.map(function (name) {
          temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
        });
      });

      return seriesArr;
    })();

    var adata = (function() {
      var temp = {}, seriesArr = [];

      temp[drawArea[0]] = {category: drawArea[0], values:[]};
      seriesArr.push(temp[drawArea]);

      data.forEach(function (d) {
        drawArea.map(function (name) {
          temp[name].values.push({'category': name, 'xLabel': parseDate(d.xLabel), 'num': d[name]});
        });
      });

      return seriesArr;
    })();

    x.domain( d3.extent(data, function(d) { return parseDate(d.xLabel); }) );

    y.domain([
      0,
      d3.max(ddata, function(c) { return d3.max(c.values, function(v) { return v['num']; }); })+100
    ]);

    x2.domain(x.domain());
    y2.domain(y.domain());

    var area = d3.area().curve(d3.curveLinear)
        .x(function(d) { return x(d.xLabel); })
        .y0(height)
        .y1(function(d) { return y(d['num']); });

    var area2 = d3.area().curve(d3.curveLinear)
        .x(function(d) { return x2(d.xLabel); })
        .y0(height2)
        .y1(function(d) { return y2(d['num']); });

    d3.select('#svg-disk').remove();

    var svg = d3.select(id).append("svg")
        .attr("id", "svg-disk")
        .attr("viewBox", "0 1 " + mainwidth + " " + mainheight)
        .attr("preserveAspectRatio", "xMinYMin");

    svg.append("defs").append("clipPath")
      .attr("id", "clip")
      .append("rect")
      .attr("width", width)
      .attr("height", height);


    svg.append("rect")
      .attr("class", "zoom")
      .attr("width", width)
      .attr("height", height)
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
      .call(zoom);

    var focus = svg.append("g")
        .attr("class", "focus")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var context = svg.append("g")
        .attr("class", "context")
        .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");

    focus.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    context.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height2 + ")")
        .call(xAxis2);		

    context.append("g")
      .attr("class", "brush")
      .call(brush)
      .call(brush.move, x.range());

    focus.selectAll('.x .tick text').each(function(){ 
      var dd = d3.select(this);
      if(textRotation)
      {
        dd.attr("dx", "-1em")
        .style("text-anchor", "end")
        .attr("transform", "rotate(-65)")
        .attr("dy", "1em");
      }else
      {
        dd.attr("dx", "0em")
        .style("text-anchor", "middle");
      }
    });

    focus.append("g")
        .attr("class", "y axis")
        .call(yAxis);

    var path = focus.selectAll(".gPath")
        .data(adata)
        .enter().append("g")
        .attr("class", "gPath");

    var path2 = context.selectAll(".gPath")
        .data(adata)
        .enter().append("g")
        .attr("class", "gPath");	

    path.append("path")
        .attr("d", function(d) { return area(d['values']); })
        .attr("class", 'areaR');

    path2.append("path")
        .attr("d", function(d) { return area2(d['values']); })
        .attr("class", 'areaR');	

    var lpath = focus.selectAll(".lpath")
        .data(ldata)
        .enter().append("g")
        .attr("class", "lpath");

    var lpath2 = context.selectAll(".lpath")
        .data(ldata)
        .enter().append("g")
        .attr("class", "lpath");	

    lpath.append("path")
        .attr("d", function(d) { return area(d['values']); })
        .attr("class", "areaW");

    lpath2.append("path")
        .attr("d", function(d) { return area2(d['values']); })
        .attr("class", "areaW");		

    var points = focus.selectAll(".seriesPoints")
        .data(ddata)
        .enter().append("g")
        .attr("class", "seriesPoints");

    points.selectAll(".tipPoints")
        .data(function (d) { return d['values']; })
        .enter().append("circle")
        .attr("class", "tipPoints")
        .attr("cx", function (d) { return x(d.xLabel); })
        .attr("cy", function (d) { return y(d['num']); })
        .text(function (d) { return d['num']; })
        .attr("r", "6px")
        .style("fill",function (d) { return legendColor[d['category']]; })
        .style("stroke", "green")
        .on("mouseover", function (d) {
          var currentX = $(this)[0]['cx']['animVal']['value'],
              currentY = $(this)[0]['cy']['animVal']['value'];

          d3.select(this).transition().duration(100).style("opacity", 1);

          var ret = $('circle').filter(function(index) {
            return ($(this)[0]['cx']['animVal']['value'] === currentX && $(this)[0]['cy']['animVal']['value'] !== currentY);
          });

          var jud = ret.length;

          var mainCate = (function() {
            if (jud === 0)
              return 'LastMonday/Today';
            else
              return d['category'];
          })();

          var viceCate = (function() {
            if (category[0] === d['category'])
              return category[1];
            else
              return category[0];
          })();

          $.each(ret, function(index, val) {
            $(val).animate({
              opacity: "1"
            }, 100);

            $(val).tooltip({
              'container': 'body',
              'placement': 'left',
              'title': viceCate + ' | ' + $(this)[0]['textContent'],
              'trigger': 'hover'
            }).tooltip('show');
          });

          focus.append("g")
              .attr("class", "tipDot")
              .append("line")
              .attr("class", "tipDot")
              .transition()
              .duration(50)
              .attr("x1", x(d.xLabel))
              .attr("x2", x(d.xLabel))
              .attr("y2", height);

          focus.append("polyline")
              .attr("class", "tipDot")
              .style("fill", "black")
              .attr("points", (x(d.xLabel)-3.5)+","+(0-2.5)+","+x(d.xLabel)+","+(0+6)+","+(x(d.xLabel)+3.5)+","+(0-2.5));

          focus.append("polyline")
              .attr("class", "tipDot")
              .style("fill", "black")
              .attr("points", (x(d.xLabel)-3.5)+","+(y(0)+2.5)+","+x(d.xLabel)+","+(y(0)-6)+","+(x(d.xLabel)+3.5)+","+(y(0)+2.5));

          try{
            $(this).tooltip({
              'container': 'body',
              'placement': 'left',
              'title': mainCate + ' | ' + d['num'],
              'trigger': 'hover'
            }).tooltip('show');
          }catch(e){}
        })
        .on("mouseout",  function (d) {
          var currentX = $(this)[0]['cx']['animVal']['value'];
          d3.select(this).transition().duration(100).style("opacity", 0);
          var ret = $('circle').filter(function(index) {
            return ($(this)[0]['cx']['animVal']['value'] === currentX);
          });

          $.each(ret, function(index, val) {
            $(val).animate({
              opacity: "0"
            }, 100);
            try{
              $(val).tooltip('destroy');
            }catch(e){}
          });

          d3.selectAll('.tipDot').transition().duration(100).remove();
          try{
            $(this).tooltip('destroy');
          }catch(e){}
        });

      function brushed() {
        if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
        var s = d3.event.selection || x2.range();
        x.domain(s.map(x2.invert, x2));

        focus.select(".x").call(xAxis);

        focus.selectAll('.x .tick text').each(function(){ 
          var dd = d3.select(this);
          if(textRotation)
          {
            dd.attr("dx", "-1em")
            .style("text-anchor", "end")
            .attr("transform", "rotate(-65)")
            .attr("dy", "1em");
          }else
          {
            dd.attr("dx", "0em")
            .style("text-anchor", "middle");
          }
        });

        focus.select(".areaR").attr("d", area);
        focus.select(".areaW").attr("d", area);

        focus.selectAll('.tipPoints')
        .attr("cx", function (d) { return x(d.xLabel); })
        .attr("cy", function (d) { return y(d['num']); });

        svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
          .scale(width / (s[1] - s[0]))
          .translate(-s[0], 0));

      }

      function zoomed() {
          if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
          var t = d3.event.transform;
          x.domain(t.rescaleX(x2).domain());

          focus.select(".x").call(xAxis);

          focus.selectAll('.x .tick text').each(function(){ 
          var dd = d3.select(this);
          if(textRotation)
          {
            dd.attr("dx", "-1em")
            .style("text-anchor", "end")
            .attr("transform", "rotate(-65)")
            .attr("dy", "1em");
          }else
          {
            dd.attr("dx", "0em")
            .style("text-anchor", "middle");
          }
          });


          focus.select(".areaR").attr("d", area);
          focus.select(".areaW").attr("d", area);	

          focus.selectAll('.tipPoints')
          .attr("cx", function (d) { return x(d.xLabel); })
          .attr("cy", function (d) { return y(d['num']); });

          context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
        }				
  return this;	
}
var sca = new initLineChart(data, "#linechart");
		html,body { width:100%; height:100%; margin:none; padding:none; }
		#linechart { width:99%; height:99%; margin:none; padding:none; background-color:#e3ecf3;}

		.axis path,
		.axis line {
			fill: none;
			stroke: #f3f3f3;
			shape-rendering: crispEdges;
		}

		.axis text {
			font-size: .7em;
			color: #a0a0a0;
		}

		.legendRect {
			stroke: #aaabb1;
			stroke-width: 1px;
			fill: none;
		}
		.focus .tipPoints {
		  clip-path: url(#clip);
		}
		/*
		.tipPoints {
			stroke: white;
			stroke-width: 2px;
			opacity: 0;
		}

		.tipNetPoints {
			stroke: white;
			stroke-width: 2px;
			opacity: 0;
		}

		.tipDot {
			stroke: black;
			stroke-width: 0.5px;
		} */

		.areaR {
			fill: rgba(255, 160, 233, 0.6);
		}

		.areaW {
			fill: rgba(0, 160, 233, 0.2);
			stroke-width: 2px;
		}

		.tick {
			font-family: serif;
			font-size: 18px;
		}
		
		.zoom {
		  cursor: move;
		  fill: none;
		  pointer-events: all;
		}

		rect.selection
		{
			fill:green;
			opacity: 0.4;
		}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div id="linechart" ></div>

1 个答案:

答案 0 :(得分:0)

让它工作,通过替换

focus.select(".areaR").attr("d", area);
focus.select(".areaW").attr("d", area);

focus.select(".areaR").attr("d", function(d) { return area(d['values']); });
focus.select(".areaW").attr("d", function(d) { return area(d['values']); });