使用d3js创建一个平滑的可拖动条形图

时间:2015-06-11 16:00:52

标签: javascript jquery svg d3.js

我正在尝试创建一个条形图,可以通过拖动条来更新。我已经能够创建这样的图形,但拖动不顺畅。在fiddle

中查看我的尝试

这是我的代码:

var data = [{x:-6.1, y: "I"}, {x:-4.5, y: "H"}, {x: -0.4, y: "G"},{x:0.8, y: "F"}, {x:3.8, y: "E"}, {x: 5.3, y: "D"}];

drawDraggableBarGraph= function(data, drawSmoothCurve, element) {
  var bar, barHeight, datae, h, height, j, len, lineFunc, margin, objects, parsedX, svg, w, width, xAxis, xMax, xMin, xScale;
  $(element).empty();

  svg = d3.select(element).append("svg");

  margin = {
    top: 10,
    bottom: 20,
    left: 30,
    right: 10
  };

  w = $(element).width();
  h = 200;
  width = w - margin.left - margin.right;
  height = h - margin.top - margin.bottom;

  for (j = 0, len = data.length; j < len; j++) {
    datae = data[j];
    parsedX = parseFloat(datae.x);
    datae.x = parsedX;
  }

  svg = svg.attr("width", w).attr("height", h).append("g").attr("transform", "translate(" + margin.left + ", " + margin.top + ")");

  xMin = d3.min(data, function(d) {
    return d.x;
  });
  xMax = d3.max(data, function(d) {
    return d.x;
  });

  xScale = d3.scale.linear().domain([xMin > 0 ? xMin * 0.95 : xMin * 1.05, xMax * 1.05]).range([0, width]);

  barHeight = (height / data.length) * 0.9;

  xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(-height);
  svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis);

  objects = svg.append('svg').attr('width', width).attr('height', height);

  bar = objects.selectAll("g").data(data).enter().append("g").attr("transform",       function(d, i) {
    return "translate(0," + (i * barHeight + height * 0.05) + ")";
  }).attr('fill', function(d, i) {
    return d3.scale.category20().range()[i];
  });

  bar.append('rect').attr("x", 0).attr('width', width).attr('height', barHeight - 1).attr('fill', 'transparent');

  bar.append("rect").attr("x", function(d) {
    if (d.x > 0) {
      return xScale(0);
    } else {
      return xScale(d.x);
    }
  }).attr("width", function(d) {
    if (d.x > 0) {
      return xScale(d.x) - xScale(0);
    } else {
      return xScale(0) - xScale(d.x);
    }
  }).attr("height", barHeight - 1).attr('class', function(d) {
    return "drag-bar-" + d.y;
  });

  bar.on('mouseover', function(d) {
    jQuery("line.default-hidden").hide();
    return $(this).children('line').show();
  }).on('mouseout', function(d) {
    return jQuery("line.default-hidden").hide();
  });

  bar.append("text").attr("dy", ".75em").attr("y", barHeight / 2 - 7).attr("x", function(d) {
    if (d.x > 0) {
      return xScale(0) - 10;
    } else {
      return xScale(0) + 10;
    }
  }).attr("text-anchor", "middle").text(function(d) {
    return d.y;
  });

  if (drawSmoothCurve) {

    // Try commenting out from here 
    lineFunc = d3.svg.line().x(function(d) {
      return xScale(d.x);
    }).y((function(_this) {
      return function(d, i) {
        return i * barHeight + barHeight / 2 + height * 0.05;
      };
    })(this)).interpolate("basis");

    objects.append("path").attr("d", lineFunc(data)).attr("stroke", "#666666").attr("stroke-width", 1).attr("fill", "none");
    // Till here

    bar.append('line').attr('x1', function(d) {
      return xScale(d.x);
    }).attr('x2', function(d) {
      return xScale(d.x);
    }).attr('y1', -1).attr('y2', barHeight).attr('stroke', 'black').attr('stroke-width', '6').attr('class', function(d) {
      return "default-hidden drag-line-" + d.y;
    }).on("mousedown", function(d) {
      return d3.select(this).classed('drag-enabled', true);
    }).on('mousemove', function(d) {
      var newX, p;
      if ($(this).attr('class').indexOf('drag-enabled') < 0) {
        return;
      }
      p = d3.mouse(this);
      newX = p[0];
      return d3.select(this).attr('x1', newX).attr('x2', newX);
    }).on('mouseup', (function(_this) {
      return function(d) {
        var attrY, classList, k, klass, l, len1, len2, newBarX;
        d3.select(this).classed('drag-enabled', false);
        newBarX = d3.mouse(this)[0];
        classList = this.classList;
        attrY = null;
        for (k = 0, len1 = classList.length; k < len1; k++) {
          klass = classList[k];
          if (klass.indexOf('drag-line') >= 0) {
            attrY = klass.slice(klass.lastIndexOf('-') + 1);
          }
        }
        data = data;
        for (l = 0, len2 = data.length; l < len2; l++) {
          datae = data[l];
          if (datae.y === attrY) {
            datae.x = xScale.invert(newBarX).toFixed(2);
          }
        }
        return drawDraggableBarGraph(data, true,".sliding-bar");
      };
    })(this));
  }
}

drawDraggableBarGraph(data, true,".sliding-bar");

我正在努力使更新值的过程用户友好但停止,而拖动以某种方式杀死它。

任何使其顺利的建议

0 个答案:

没有答案