繁体   English   中英

d3.js 图例重叠图表区域

[英]d3.js legend overlapping chart area

我对D3.jsD3.js (我是R程序员)。

我正在尝试创建一个散点图并在右下角放置一个图例。 但是,它与图表区域重叠。

我一直试图在互联网上举一些例子,但没有运气。 当我尝试将其向右移动时,名称和/或符号不可见。

我想将图例放在图表框架之外,这样它就不会重叠。

任何帮助表示赞赏。

这是我到目前为止尝试过的:

 d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) { // CSV section var body = d3.select('body') var selectData = [{ "text": "sepal.length" }, { "text": "sepal.width" }, { "text": "petal.length" }, { "text": "petal.width" }, ] // setup fill color var colors = ['#575757', '#5FB1B9', '#C94257']; var symbol = d3.svg.symbol() .type('circle') .size("160") var cValue = function(d) { return d.variety; }, color = d3.scale.ordinal() .range(colors); // Select Y-axis Variable var span = body.append('span') .text('Select Y-Axis variable: ') var yInput = body.append('select') .attr('id', 'ySelect') .on('change', yChange) .selectAll('option') .data(selectData) .enter() .append('option') .attr('value', function(d) { return d.text }) .text(function(d) { return d.text; }) body.append('br') // Select X-axis Variable var span = body.append('span') .text('Select X-Axis variable: ') var yInput = body.append('select') .attr('id', 'xSelect') .on('change', xChange) .selectAll('option') .data(selectData) .enter() .append('option') .attr('value', function(d) { return d.text }) .text(function(d) { return d.text; }) body.append('br') // Variables var body = d3.select('body') var margin = { top: 50, right: 50, bottom: 50, left: 50 } var h = 500 - margin.top - margin.bottom var w = 500 - margin.left - margin.right // var formatPercent = d3.format('.2%') // Scales // var colorScale = d3.scale.category20() var xScale = d3.scale.linear() .domain([ d3.min([0, d3.min(data, function(d) { return d['sepal.length'] })]), d3.max([0, d3.max(data, function(d) { return d['sepal.length'] })]) ]) .range([0, w]) var yScale = d3.scale.linear() .domain([ d3.min([0, d3.min(data, function(d) { return d['sepal.length'] })]), d3.max([0, d3.max(data, function(d) { return d['sepal.length'] })]) ]) .range([h, 0]) // SVG var svg = body.append('svg') .attr('height', h + margin.top + margin.bottom) .attr('width', w + margin.left + margin.right) .append('g') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') // X-axis var xAxis = d3.svg.axis() .scale(xScale) // .tickFormat(formatPercent) .ticks(6) .outerTickSize(0) .tickSize(0) .orient('bottom') // Y-axis var yAxis = d3.svg.axis() .scale(yScale) // .tickFormat(formatPercent) .ticks(6) .tickSize(-w) .outerTickSize(0) .orient('left') // Circles var circles = svg.selectAll('circle') .data(data) .enter() .append('circle') .attr('cx', function(d) { return xScale(d['sepal.length']) }) .attr('cy', function(d) { return yScale(d['sepal.length']) }) .attr('r', '10') // .attr('stroke', 'black') .attr('stroke-width', 0.2) .attr("fill", function(d) { return color(cValue(d)); }) .attr('fill-opacity', 0.8) // .attr('fill', function(d, i) { // return colorScale(i) // }) .on('mouseover', function() { d3.select(this) .transition() .duration(300) .ease('elastic') .attr('r', 15) .attr('stroke-width', 1) .attr('fill-opacity', 1) }) .on('mouseout', function() { d3.select(this) .transition() .duration(100) .attr('r', 10) .attr('stroke-width', 0.5) }) .append('title') // Tooltip .text(function(d) { return d.variety + '\\nSepal Length: ' + d['sepal.length'] + '\\nSepal Width: ' + d['sepal.width'] + '\\nPetal Length: ' + d['petal.length'] + '\\nPetal Width: ' + d['petal.width'] }) // X-axis svg.append('g') .attr('class', 'axis') .attr('id', 'xAxis') .attr('transform', 'translate(0,' + h + ')') .call(xAxis) .append('text') // X-axis Label .attr('id', 'xAxisLabel') .attr('y', -25) .attr('x', w) .attr('dy', '.71em') .style('text-anchor', 'end') .text('Sepal Length') // labels distance from xaxis svg.selectAll(".axis text") .attr("dy", 15); // Y-axis svg.append('g') .attr('class', 'axis') .attr('id', 'yAxis') .call(yAxis) .append('text') // y-axis Label .attr('id', 'yAxisLabel') .attr('transform', 'rotate(-90)') .attr('x', 0) .attr('y', 5) .attr('dy', '.71em') .style('text-anchor', 'end') .text('Sepal Length') function yChange() { var value = this.value // get the new y value yScale // change the yScale .domain([ d3.min([0, d3.min(data, function(d) { return d[value] })]), d3.max([0, d3.max(data, function(d) { return d[value] })]) ]) yAxis.scale(yScale) // change the yScale d3.select('#yAxis') // redraw the yAxis .transition().duration(500) .call(yAxis) d3.select('#yAxisLabel') // change the yAxisLabel .text(value) d3.selectAll('circle') // move the circles .transition().duration(500) .delay(function(d, i) { return i * 10 }) .attr('cy', function(d) { return yScale(d[value]) }) } function xChange() { var value = this.value // get the new x value xScale // change the xScale .domain([ d3.min([0, d3.min(data, function(d) { return d[value] })]), d3.max([0, d3.max(data, function(d) { return d[value] })]) ]) xAxis.scale(xScale) // change the xScale d3.select('#xAxis') // redraw the xAxis .transition().duration(500) .call(xAxis) d3.select('#xAxisLabel') // change the xAxisLabel .transition().duration(500) .text(value) d3.selectAll('circle') // move the circles .transition().duration(500) .delay(function(d, i) { return i * 10 }) .attr('cx', function(d) { return xScale(d[value]) }) } // create legend var legend = svg.selectAll(".legend") .data(color.domain()) .enter().append("g") .attr("class", "legend") .attr("transform", function(d, i) { return "translate(0," + i * 25 + ")"; }); // draw legend colored rectangles legend.append("path") .attr('d', symbol) .attr("transform", "translate(434, 313)") //much easier approach to position the symbols // .attr("x", w + 34) // .attr("y", h - 97) // .attr("width", 18) // .attr("height", 18) .style("fill", color); // draw legend text legend.append("text") .attr("transform", "translate(422, 311)") // .attr("x", w + 24) // .attr("y", h - 89) .attr("dy", ".35em") .style("text-anchor", "end") .text(function(d) { return d; }) })
 body { font-size: 16px; } /* circle { fill: steelblue; } */ circle:hover { fill: orange; } .axis text { font-size: 13px; /* font-weight: bold; */ } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; stroke-width: 0.02px; } /* .circle { fill: orange; } */ label { position: absolute; top: 10px; right: 10px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script> <body></body>

为什么不将您的图例渲染为 HTML 并使用 CSS 来帮助布局?

 d3.csv('https://gist.githubusercontent.com/netj/8836201/raw/6f9306ad21398ea43cba4f7d537619d0e07d5ae3/iris.csv', function(data) { // CSV section var body = d3.select('body') var selectData = [{ "text": "sepal.length" }, { "text": "sepal.width" }, { "text": "petal.length" }, { "text": "petal.width" }, ] // setup fill color var colors = ['#575757', '#5FB1B9', '#C94257']; var symbol = d3.svg.symbol() .type('circle') .size("160") var cValue = function(d) { return d.variety; }, color = d3.scale.ordinal() .range(colors); var controls = body.append('div').attr('class', 'controls') // Select Y-axis Variable var yControls = controls.append('div') var span = yControls.append('span') .text('Select Y-Axis variable: ') var yInput = yControls.append('select') .attr('id', 'ySelect') .on('change', yChange) .selectAll('option') .data(selectData) .enter() .append('option') .attr('value', function(d) { return d.text }) .text(function(d) { return d.text; }) // Select X-axis Variable var xControls = controls.append('div') var span = xControls.append('span') .text('Select X-Axis variable: ') var yInput = xControls.append('select') .attr('id', 'xSelect') .on('change', xChange) .selectAll('option') .data(selectData) .enter() .append('option') .attr('value', function(d) { return d.text }) .text(function(d) { return d.text; }) // Variables var body = d3.select('body') var margin = { top: 50, right: 50, bottom: 50, left: 50 } var h = 500 - margin.top - margin.bottom var w = 500 - margin.left - margin.right var xScale = d3.scale.linear() .domain([ d3.min([0, d3.min(data, function(d) { return d['sepal.length'] })]), d3.max([0, d3.max(data, function(d) { return d['sepal.length'] })]) ]) .range([0, w]) var yScale = d3.scale.linear() .domain([ d3.min([0, d3.min(data, function(d) { return d['sepal.length'] })]), d3.max([0, d3.max(data, function(d) { return d['sepal.length'] })]) ]) .range([h, 0]) // SVG var svgContainer = body.append('div').attr('class', 'svg-container') var svg = svgContainer.append('svg') .attr('height', h + margin.top + margin.bottom) .attr('width', w + margin.left + margin.right) .append('g') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')') // X-axis var xAxis = d3.svg.axis() .scale(xScale) // .tickFormat(formatPercent) .ticks(6) .outerTickSize(0) .tickSize(0) .orient('bottom') // Y-axis var yAxis = d3.svg.axis() .scale(yScale) // .tickFormat(formatPercent) .ticks(6) .tickSize(-w) .outerTickSize(0) .orient('left') // Circles var circles = svg.selectAll('circle') .data(data) .enter() .append('circle') .attr('cx', function(d) { return xScale(d['sepal.length']) }) .attr('cy', function(d) { return yScale(d['sepal.length']) }) .attr('r', '10') // .attr('stroke', 'black') .attr('stroke-width', 0.2) .attr("fill", function(d) { return color(cValue(d)); }) .attr('fill-opacity', 0.8) // .attr('fill', function(d, i) { // return colorScale(i) // }) .on('mouseover', function() { d3.select(this) .transition() .duration(300) .ease('elastic') .attr('r', 15) .attr('stroke-width', 1) .attr('fill-opacity', 1) }) .on('mouseout', function() { d3.select(this) .transition() .duration(100) .attr('r', 10) .attr('stroke-width', 0.5) }) .append('title') // Tooltip .text(function(d) { return d.variety + '\\nSepal Length: ' + d['sepal.length'] + '\\nSepal Width: ' + d['sepal.width'] + '\\nPetal Length: ' + d['petal.length'] + '\\nPetal Width: ' + d['petal.width'] }) // X-axis svg.append('g') .attr('class', 'axis') .attr('id', 'xAxis') .attr('transform', 'translate(0,' + h + ')') .call(xAxis) .append('text') // X-axis Label .attr('id', 'xAxisLabel') .attr('y', -25) .attr('x', w) .attr('dy', '.71em') .style('text-anchor', 'end') .text('Sepal Length') // labels distance from xaxis svg.selectAll(".axis text") .attr("dy", 15); // Y-axis svg.append('g') .attr('class', 'axis') .attr('id', 'yAxis') .call(yAxis) .append('text') // y-axis Label .attr('id', 'yAxisLabel') .attr('transform', 'rotate(-90)') .attr('x', 0) .attr('y', 5) .attr('dy', '.71em') .style('text-anchor', 'end') .text('Sepal Length') function yChange() { var value = this.value // get the new y value yScale // change the yScale .domain([ d3.min([0, d3.min(data, function(d) { return d[value] })]), d3.max([0, d3.max(data, function(d) { return d[value] })]) ]) yAxis.scale(yScale) // change the yScale d3.select('#yAxis') // redraw the yAxis .transition().duration(500) .call(yAxis) d3.select('#yAxisLabel') // change the yAxisLabel .text(value) d3.selectAll('circle') // move the circles .transition().duration(500) .delay(function(d, i) { return i * 10 }) .attr('cy', function(d) { return yScale(d[value]) }) } function xChange() { var value = this.value // get the new x value xScale // change the xScale .domain([ d3.min([0, d3.min(data, function(d) { return d[value] })]), d3.max([0, d3.max(data, function(d) { return d[value] })]) ]) xAxis.scale(xScale) // change the xScale d3.select('#xAxis') // redraw the xAxis .transition().duration(500) .call(xAxis) d3.select('#xAxisLabel') // change the xAxisLabel .transition().duration(500) .text(value) d3.selectAll('circle') // move the circles .transition().duration(500) .delay(function(d, i) { return i * 10 }) .attr('cx', function(d) { return xScale(d[value]) }) } // create legend var legendContainer = body.append('div') .attr('class', 'legend-container') var legend = legendContainer.selectAll(".legend") .data(color.domain()) .enter().append("div") .attr("class", "legend") // draw legend colored rectangles legend.append("span") .attr("class", "legend-color") .style("background-color", color); // draw legend text legend.append("span") .text(function(d) { return d; }) })
 body { font-size: 16px; display: flex; flex-wrap: wrap; } .controls { flex: 1 1 100%; } .legend-container { align-items: center; flex: 0 1 auto; align-self: center; margin: 0 auto; } circle:hover { fill: orange; } .axis text { font-size: 13px; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; stroke-width: 0.02px; } label { position: absolute; top: 10px; right: 10px; } .legend { margin-bottom: 0.5em; } .legend-color { width: 20px; height: 20px; display: inline-block; border-radius: 50%; vertical-align: middle; margin-right: 1em; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script> <body></body>

使用这种方法,您最终会得到这样的结构:

body
  .controls
  .svg-container
    svg
  .legend-container

这可以使响应式布局特别容易使用 CSS。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM