2

I tried to make a straight line with this:

enter.append('line')
   .attr('class', 'lineClass')
   .style("stroke", "blue")
   .style("stroke-width", "1.5px;")
   .attr('x1', function(d) { return 500; })
   .attr('y1', function(d) { return 50; })
   .attr('x2', function(d) { return 800; })
   .attr('y2', function(d) { return 40; });

The line attrs will be actual functions with data. Look at my image, why is the line crooked? If there is no problem with the code, do you have any ideas as to what could be causing this?enter image description here

altocumulus
  • 21,179
  • 13
  • 61
  • 84
shell
  • 1,867
  • 4
  • 23
  • 39

3 Answers3

4

The reason is you are drawing same line again and again on the same x1/x2/y1/y2 for dataset.

This will make your line crooked:

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

var dataSet = [10,20,30,20,30,20,30,20,30,20,30,20,30,20,30,20,30];//many data 17 times you will draw line.

var myLine = svg.selectAll('line')
    .data(dataSet)
    .enter()
    .append('line')
   .style("stroke", "blue")

   .attr('x1', function(d) { return 100; })
   .attr('y1', function(d) { return 200; })
   .attr('x2', function(d) { return 300; })
   .attr('y2', function(d) { return 40; });

Working example here

Now the crookedness will go coz you are making a single line on the x1/x2/y1/y2

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

var dataSet = [10];//you will draw line ones

var myLine = svg.selectAll('line')
    .data(dataSet)
    .enter()
    .append('line')
   .style("stroke", "blue")

   .attr('x1', function(d) { return 100; })
   .attr('y1', function(d) { return 200; })
   .attr('x2', function(d) { return 300; })
   .attr('y2', function(d) { return 40; });

Working example here

So in short you should not be drawing same line over and over again...

Hope this helps!

Cyril Cherian
  • 32,177
  • 7
  • 46
  • 55
  • I didn't realize I was doing this, but I was. Thanks! – shell Dec 12 '15 at 02:05
  • @Cyril Wow, that is astonishing! At first, I thought this was complete nonsense because it would have never dawned on me that stacking a bunch of identical elements at the exact same positions could possibly affect rendering. I had just posted my own answer focusing on (anti-)aliasing which might also provide an explanation for the effect, when I returned to your post to realize that this is actually true! Do you have any explanation for this? I will add an SVG tag to the question, hoping for some Robert Longson to come to the rescue ;-) – altocumulus Dec 12 '15 at 23:17
2

First of all, this is not to blame on D3 at all. This effect is known as aliasing and is very common to all sorts of computer graphics. There is a vast arsenal of countermeasures against it, which are referred to as anti-aliasing. However, it will always be a trade-off between precision and aesthetics.

For SVGs you are — at least to a certain degree — able to control the way the browser or any other user agent deals with this by setting the shape-rendering attribute. Have a look at this example which demonstrates the effect:

line {
  stroke: blue;
  stroke-width: 1;
}
text { font-family: monospace; }
<svg width="500" height="210" xmlns="http://www.w3.org/2000/svg">
  <text y="25">auto</text>
  <line shape-rendering="auto" x1="150" y1="20" x2="450" y2="30" />

  <text y="75">optimizeSpeed</text>
  <line shape-rendering="optimizeSpeed" x1="150" y1="70" x2="450" y2="80" />

  <text y="125">crispEdges</text>
  <line shape-rendering="crispEdges" x1="150" y1="120" x2="450" y2="130" />

  <text y="175">geometricPrecision</text>
  <line shape-rendering="geometricPrecision" x1="150" y1="170" x2="450" y2="180" />
</svg>

Because line #3 having shape-rendering="crispEdges" closely resembles your screenshot, this is most likely the cause of your problem. For this value the SVG spec states:

To achieve crisp edges, the user agent might turn off anti-aliasing for all lines...

To get a smoother line, try setting another value for this property. Please note, that this property is inherited. There is no need to repeat yourself setting this on every element. You might just as well define this somewhere up the DOM hierarchy or even on the root SVG element itself. Additionally, you may opt for setting this via a CSS rule instead of specifying it as an attribute to an element.

altocumulus
  • 21,179
  • 13
  • 61
  • 84
0

The line in your picture is not crooked - it is straight between the points (500,50) and (800,40).

  • So it is only a coordinate problem? The grooves don't seem to disappear when I pass in different coordinates though. – shell Dec 12 '15 at 01:55
  • If both y-values (the second parameter) are the same, it should be perfectly horizontal. Have you tried that? `(500,50) and (800,50)` – ricky3350 Dec 12 '15 at 01:56
  • Yes in that case it is straight, but with any other y value it is not. I am not using horizontal lines unfortunately. – shell Dec 12 '15 at 01:57