当其他图表类型正确定位时,为什么我的圆环图表位于容器外部?

时间:2017-09-13 15:15:32

标签: javascript jquery css d3.js

我有一堆图表,用户点击链接在同一个div中绘制(每次点击都会删除之前的svg,然后绘制新的svg)。除甜甜圈图表外,所有图表都按预期位于div的中心。有什么原因吗?我已经创建了一个JS小提琴来帮助说明这一点。

JS Fiddle

基本上,我有三个功能。通用drawChart()函数,它接受已被单击的按钮的索引,并包含一个switch语句,用于选择要绘制的图表。然后是chartTwo(),它只是两行来说明该图表如何定位在中心。 chartOne()是一个圆环图,位于左上角之外。 谢谢你的帮助。

通用图表构建器功能

function drawChart(int){

  var $chartarea = $('#chartarea'),
      ca_w = $chartarea.innerWidth(),
      ca_h = $chartarea.innerHeight();


  if ($chartarea.find('svg').length > 0) {
    $chartarea.find('svg').remove();
  }

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

  var width = ca_w - margin.left - margin.right,
      height = ca_h - margin.top - margin.bottom;

  var g = d3.select('#chartarea').append('svg')
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append('g')
      .style('position', 'relative')
      .style('left', '0')
      .attr('height', height)
      .attr('width', width)
      .attr('transform', 'translate('+margin.left+', '+margin.top+')');

  switch (int) {
    case 0:
      chartOne(g, width, height);
      break;
    case 1:
      chartTwo(g, width, height);
      break;
    default:
      chartOne(g, width, height);
  }

}

甜甜圈图表功能

function chartOne(g, width, height) {

  var data = [
    {name: "USA", value: 40},
    {name: "UK", value: 20},
    {name: "Canada", value: 30},
    {name: "Maxico", value: 10},
  ];

  var text = "";

  var thickness = 40;

  var radius = Math.min(width, height) / 2;
  var color = d3.scaleOrdinal(d3.schemeCategory10);

  var arc = d3.arc()
  .innerRadius(radius - thickness)
  .outerRadius(radius);

  var pie = d3.pie()
  .value(function(d) { return d.value; })
  .sort(null);

  g.selectAll('path')
  .data(pie(data))
  .enter()
  .append("g")
  .on("mouseover", function(d) {
        let g = d3.select(this)
          .style("cursor", "pointer")
          .style("fill", "black")
          .append("g")
          .attr("class", "text-group");

        g.append("text")
          .attr("class", "name-text")
          .text(d.data.name)
          .attr('text-anchor', 'middle')
          .attr('dy', '-1.2em');

        g.append("text")
          .attr("class", "value-text")
          .text(d.data.value)
          .attr('text-anchor', 'middle')
          .attr('dy', '.6em');
      })
    .on("mouseout", function() {
        d3.select(this)
          .style("cursor", "none")
          .style("fill", color(this._current))
          .select(".text-group").remove();
      })
    .append('path')
    .attr('d', arc)
    .attr('fill', (d,i) => color(i))
    .on("mouseover", function() {
        d3.select(this)
          .style("cursor", "pointer")
          .style("fill", "black");
      })
    .on("mouseout", function() {
        d3.select(this)
          .style("cursor", "none")
          .style("fill", color(this._current));
      })
    .each(function(d, i) { this._current = i; });


  g.append('text')
    .attr('text-anchor', 'middle')
    .attr('dy', '.35em')
    .text(text);
}

2 个答案:

答案 0 :(得分:1)

您的饼图/圆环图的中心位于[0,0],而您的x由带有此端点的线组成:

.attr('x1', 0)
.attr('y1', 0)
.attr('x2', width)
.attr('y2', height)

您的线条在可视化的角落处开始和结束,您的饼图/圆环图表位于角落的中心位置。

解决此问题的最简单方法是创建一个g来保存饼图,该饼图具有与g不同的转换以保存其余图表。这个新的g将翻译[width/2,height/2],并将饼图的中心放在可视化的中心。请参阅此fiddle

答案 1 :(得分:1)

添加翻译以调整widthheight可添加到chartOne()功能:

g.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

现在你可以添加边距并完成我猜。见下面的演示:

$(function() {

  // on load
  $('li').eq(0).addClass('active');
  drawChart(0);

  $('li').on('click', function() {
    var index = $(this).index();
    $('li').removeClass('active');
    $(this).addClass('active');

    drawChart(index);
  });
});

function drawChart(int) {

  var $chartarea = $('#chartarea'),
    ca_w = $chartarea.innerWidth(),
    ca_h = $chartarea.innerHeight();


  if ($chartarea.find('svg').length > 0) {
    $chartarea.find('svg').remove();
  }

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

  var width = ca_w - margin.left - margin.right,
    height = ca_h - margin.top - margin.bottom;

  var g = d3.select('#chartarea').append('svg')
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append('g')
    .style('position', 'relative')
    .style('left', '0')
    .attr('height', height)
    .attr('width', width)
    .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');

  switch (int) {
    case 0:
      chartOne(g, width, height, margin);// edited
      break;
    case 1:
      chartTwo(g, width, height);
      break;
    default:
      chartOne(g, width, height, margin);// edited
  }

}

function chartTwo(g, width, height) {
  g.append('line')
    .attr('x1', 0)
    .attr('y1', 0)
    .attr('x2', width)
    .attr('y2', height)
    .attr('stroke', 'grey')
    .attr('stroke-width', '10px');
  g.append('line')
    .attr('x1', width)
    .attr('y1', 0)
    .attr('x2', 0)
    .attr('y2', height)
    .attr('stroke', 'grey')
    .attr('stroke-width', '10px');
}


function chartOne(g, width, height, margin) { // edited
  // ADDED THIS
  g.attr("transform", "translate(" + (width / 2 + margin.left) + "," + (height / 2 + margin.top) + ")");

  var data = [{
      name: "USA",
      value: 40
    },
    {
      name: "UK",
      value: 20
    },
    {
      name: "Canada",
      value: 30
    },
    {
      name: "Maxico",
      value: 10
    },
  ];

  var text = "";

  var thickness = 40;

  var radius = Math.min(width, height) / 2;
  var color = d3.scaleOrdinal(d3.schemeCategory10);

  var arc = d3.arc()
    .innerRadius(radius - thickness)
    .outerRadius(radius);

  var pie = d3.pie()
    .value(function(d) {
      return d.value;
    })
    .sort(null);

  g.selectAll('path')
    .data(pie(data))
    .enter()
    .append("g")
    .on("mouseover", function(d) {
      let g = d3.select(this)
        .style("cursor", "pointer")
        .style("fill", "black")
        .append("g")
        .attr("class", "text-group");

      g.append("text")
        .attr("class", "name-text")
        .text(d.data.name)
        .attr('text-anchor', 'middle')
        .attr('dy', '-1.2em');

      g.append("text")
        .attr("class", "value-text")
        .text(d.data.value)
        .attr('text-anchor', 'middle')
        .attr('dy', '.6em');
    })
    .on("mouseout", function() {
      d3.select(this)
        .style("cursor", "none")
        .style("fill", color(this._current))
        .select(".text-group").remove();
    })
    .append('path')
    .attr('d', arc)
    .attr('fill', (d, i) => color(i))
    .on("mouseover", function() {
      d3.select(this)
        .style("cursor", "pointer")
        .style("fill", "black");
    })
    .on("mouseout", function() {
      d3.select(this)
        .style("cursor", "none")
        .style("fill", color(this._current));
    })
    .each(function(d, i) {
      this._current = i;
    });


  g.append('text')
    .attr('text-anchor', 'middle')
    .attr('dy', '.35em')
    .text(text);
}
* {
  margin: 0;
  padding: 0;
}

#chartarea {
  margin: 20px;
  border: solid 1px black;
  height: 300px;
  width: 500px;
}

ul {
  display: flex;
  width: 500px;
  margin: 20px;
  list-style: none;
  text-align: center;
}

li {
  margin: 0 20px;
  padding: 5px;
  border-radius: 10px;
  flex: 1;
  background: grey;
  cursor: pointer;
}

li.active {
  background: #60cafe
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>

<div id="chartarea" class="charts--item"></div>

<ul>
  <li>Chart One</li>
  <li>Chart Two</li>
</ul>