susielu / d3-legend

A reusable d3 legend component.
http://d3-legend.susielu.com/
Apache License 2.0
727 stars 104 forks source link

Fixed spacing of horizontal color legend when labels are wider than shape #47

Closed sstragier closed 7 years ago

sstragier commented 8 years ago

@susielu I've updated the color legend to correctly space out the legend items based on the the text labels. This is done by determining if the label or shape is wider for each legend item and then adjusting the shape and text based on the labelAlign property.

I did not updated the symbol or size legends because I wanted to see if this is something you'd want to include in the library and if it was applicable to those legends. This was something I needed that currently only applies to the color legend. Let me know if you need/want me to update the other legends.

susielu commented 8 years ago

Thanks! I'll take a look this week.

eliquious commented 7 years ago

@susielu, any chance to get this merged soon? 😄

susielu commented 7 years ago

Thanks for the ping. I'll try to take a look this weekend.

On Tue, Feb 28, 2017 at 2:18 PM, Max Franks notifications@github.com wrote:

@susielu https://github.com/susielu, any chance to get this merged soon? 😄

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/susielu/d3-legend/pull/47#issuecomment-283179464, or mute the thread https://github.com/notifications/unsubscribe-auth/ABYfbXxA11Lv6NqctQxTSvKspme-X-ERks5rhJ1FgaJpZM4Khtwu .

susielu commented 7 years ago

The latest version(2.23.0) of this implements labelWrap which in combination with shapePadding should create the same functionality described in this pull request. See the following examples for reference. Let me know if there are any issues.

http://d3-legend.susielu.com/#size-line http://d3-legend.susielu.com/#symbol-ordinal

sstragier commented 7 years ago

@susielu With horizontal orientation, it looks like the shapePadding is being used to determine the width of the cell. Is there any way to have the cell expand to be the width of the label? My use case is that I have an ordinal scale where I want to show a legend with "rect" where each label is variable length and I'd like the labels to be rendered horizontally on a single line.

Here's a plunker of my use case: http://plnkr.co/edit/DZ56Dbu7KVGxpb1QSGzR

susielu commented 7 years ago

I wouldn't recommend expanding the size of the cell unless that cell is more important than the other ones. If you increase just the width of the cell to the label length you're signaling to your user that the width of the cell has some meaning. What is your overall goal here?

I made a few changes but don't have edit permissions updated the index to use the latest d3.legend:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <svg width="500" height="200"></svg>
  </body>
  <script src="script.js"></script>
</html>

Updated the script to use label wrapping:

var labels = ["Really long label", "sh", "ort", "labels"];
var ordinal = d3.scaleOrdinal(d3.schemeCategory10)
  .domain(labels);

var svg = d3.select("svg");

svg.append("g")
  .attr('transform', 'translate(20,0)')
  .attr("class", "legend")
  .call(d3.legendColor()
    .shape("rect")
    .shapeWidth(25)
    .orient("horizontal")
    .shapePadding(20)
    .scale(ordinal)
    .labelWrap(30)
  );

The example above allows you to have nicely spaced cells with long text.

screenshot 2017-04-21 10 42 28

sstragier commented 7 years ago

Thanks for the quick response, I certainly hadn't though of it that way. In my case, I have plenty of horizontal space and I'm trying to keep my vertical space to a minimum. Since the user can't actually see the cell (other than the extra white space) I feel like the size of the shape conveys the meaning. Granted, in my cases I'm only dealing with ordinal scales where the legend labels are just representing different data series.

I updated the plunk (http://plnkr.co/edit/DZ56Dbu7KVGxpb1QSGzR) with your changes and I adjusted the long label a bit and it looks like if a word is longer than the labelWrap that it will just extend into the other labels. I know this is a somewhat contrived example and I understand the limitations and challenges in trying to address this using a wrap. Unfortunately in my case, the labels are dynamic (i.e. entered by a user), so I won't necessarily know what a good "wrap" value would be to prevent this issue.

DougManuel commented 7 years ago

Just wondering if the text wrap works for histograms (i.e bars with varying width). It looks like you should be able to pass an array of widths to .labelwrap()?

I didn't know about d3-legend when I created this plot below. It follows a basic histogram workflow, but with fixed heights. I wanted the plot to be responsive and pondered the same issues about label wrapping in this thread. I opted to create a rules for starting to drop labels when the the bars got very small. I started with the same Mike B example of text wrapping.

hitsogram