在D3 JS中将div放在图表的左上角

时间:2017-01-23 10:15:05

标签: javascript d3.js svg data-visualization

这里是D3的新手,并使用下面的代码处理图表。当用户将鼠标悬停在其中一个文本标签上时,我有一个名为“tip”的div,它显示(通过改变不透明度)。我无法正确定位。

我想要的是将它放在图表的左上角,让我们说x,y坐标为10,10。但我不知道如何得到那个坐标,因为它是一个div。有人可以帮帮我吗?

var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json";
d3.json(url, function(json) {

  var data = json;

  //Dimensions of the SVG container
  var margin = {
    top: 40,
    right: 100,
    bottom: 60,
    left: 60
  };
  //inner width for the chart, within SVG element
  var w = 1000 - margin.left - margin.right;
  //inner height for the chart, within SVG element
  var h = 800 - margin.top - margin.bottom;
  var padding = 20;

  //create SVG conratiner and append to DOM
  var svg = d3.select("#chart")
    .append("svg")
    .attr("width", w + margin.left + margin.right)
    .attr("height", h + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var maxRank = d3.max(data, function(d) {

    return d.Place;

  });

  var minSeconds = d3.min(data, function(d) {

    return d.Seconds;

  });

  var maxSeconds = d3.max(data, function(d) {

    return d.Seconds;

  });

  var formatTime = d3.timeFormat("%M:%S");
  var formatSeconds = formatMinutes = function(d) {
    return formatTime(new Date(2016, 0, 0, 0, 1, d));
  };

  var xScale = d3.scaleLinear()
    .domain([maxSeconds + 5, minSeconds])
    .range([0, w]);

  var yScale = d3.scaleLinear()
    .domain([0, maxRank + 2])
    .range([0, h]);

  var xAxis = d3.axisBottom()
    .scale(xScale)
    .ticks(10)
    .tickFormat(formatMinutes)

  var yAxis = d3.axisLeft()
    .scale(yScale)
    .ticks(10);

  var tip = d3.select("#chart").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);

  var circles = svg.selectAll("circle")
    .data(data)
    .enter()
    .append("circle");


  var circleAttributes = circles
    .attr("cx", function(d) {

      return xScale(d.Seconds);

    })
    .attr("cy", function(d) {

      return yScale(d.Place);

    })
    .attr("r", 6)
    .attr("class", "circles")
    .attr("fill", function(d) {

      if (d.Doping === "") {

        return "#2c3e50";

      } else {

        return "#e74c3c";

      }

    });

  var labels = svg.selectAll("text")
    .data(data)
    .enter()
    .append("text")
    .text(function(d) {

      return d.Name;

    })
    .attr("x", function(d) {

      return xScale(d.Seconds) + 7;

    })
    .attr("y", function(d) {

      return yScale(d.Place) + 4;

    })
    .attr("class", "labels")
    .attr("font-family", "roboto slab")
    .attr("font-size", "12px")
    .attr("fill", "#2c3e50")
    .on("mouseover", function(d) {

      tip.transition()
        .duration(200)
        .style("opacity", 0.7);
      tip.html("<span><strong>" + d.Name + "</strong><br/><i>Place: </i>" + d.Place + "<br/><i>Time: </i>" + d.Time + "<br/><i>Year: </i>" + d.Year + "<br/><i>Nationality: </i>" + d.Nationality + "<br/><i>Doping: </i>" + d.Doping + "</span>")
        .style("left", (d3.event.pageX + 48) + "px")
        .style("top", (d3.event.pageY + 48) + "px");

    })
    .on("mouseout", function(d) {

      tip.transition()
        .duration(200)
        .style("opacity", 0);

    });

  svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(0," + h + ")")
    .call(xAxis);

  svg.append("g")
    .attr("class", "axis")
    .call(yAxis)

})

1 个答案:

答案 0 :(得分:5)

在我看来,这个问题(几乎)与D3.js无关。相反,这是一个CSS问题。

有一些不同的解决方案,我在这里建议的非常简单:只需设置容器div(带有chart的div)相对位置......

#svgwrapper {
    position: relative;
}

...以及工具提示div中的绝对位置,topleft为零:

.tooltip {
    position: absolute;
    top: 0 px;
    left: 0 px;
}

此外,请不要忘记删除d3.event.pageXd3.event.pageY,因为您的工具提示将始终显示在同一位置。

这是一个演示(悬停在圆圈上):

var tip = d3.select("#svgwrapper").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);
		
d3.select("circle").on("mouseover", function(){
    tip.html("Hello!")
		.style("opacity", 1)
}).on("mouseout", function(){
    tip.style("opacity", 0)
});
#svgwrapper {
	border: 1px solid gray;
	position: relative;
}

.tooltip {
	position: absolute;
	top: 0px;
	left: 0px;
	border: 1px solid gray;
	border-radius: 2px;
	padding: 4px;
	background-color: tan;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</div>
<div id="svgwrapper">
<svg>
	<circle cx="100" cy="100" r="20" fill="teal"></circle>
</svg>
</div>