Why do the following SVG paths produce dramatically different results in webkit? - html

I'm generating pie charts in SVG (using the ruby library svg-graph, but that isn't totally relevant), but there is a strange edge case where the chart is totally blank. This occurs in Chrome and Safari, but not in IE11 or Firefox.
I've narrowed it down to a certain path element whose d attribute varies slightly between the two. One produces a yellow circle while the other does not. My SVG knowledge is limited, so I don't understand why the second snippet isn't outputting anything. Any ideas?
Working:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="M109.0,109.0 L109.0,0.0 A109.0,109.0 0, 1,1, 108.99999000000007 0.0 Z"
transform="translate( -3.216245299353273e-15 10.0 )"
style="fill: #FFDC00" />
</g>
</svg>
Not working:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="M108.5,108.5 L108.5,0.0 A108.5,108.5 0, 1,1, 108.49999000000007 0.0 Z"
transform="translate( -3.216245299353273e-15 10.0 )"
style="fill: #FFDC00" />
</g>
</svg>

This may be a rounding issue. The path is trying to draw a circle using the arc path instruction "A". The beginning and ending points of the arc are very close together (< 0.0000001 units). If the SVG renderer thinks the two points are actually the same then it will draw an empty arc (0% of a circle) instead of a nearly complete (99.9999% of a circle).
You can try separating the beginning and ending points slightly further away (e.g., try 359 degrees instead of 360); as the Z instruction will close the path anyway and hide the tiny wedge left over. Also to see more of what's going on try stroking the path instead of filling it.
Or draw a circle using two half-circle arcs. See Circle drawing with SVG's arc path

Related

SVG line graph curved lines, on peaks and troughs

I am trying to get a line to curve on peaks and troughs, however I am a little confused with SVG path as they dont quite flow right.
I have an image to explain what I mean. As you can see there are 2 lines. One straight (showing correct data, ie turns on the points) and one curved (wrong, turns after the points).
What I need to do is get them to turn on the actual points as such.
The code I have is like this.
<g>
<path
class="line"
stroke-width="1.5px"
d="M50 90, 100 100, T150 190, T200 200, T250 180, T300 150"
fill="none"
stroke="#7aa3e5"
></path>
</g>
<g>
<path
class="line"
stroke-width="1.5px"
d="M50 90, 100 100, 150 190, 200 200, 250 180, 300 150"
fill="none"
stroke="green"
></path>
</g>
Would I need to add extra data points to get better curves, if so, would there be some kind of algorithm that can manage that? Or a better way to do curves that are not so drastic.
Best regards and thanks for taking a look at this.
How about using Bézier Curves?
Bézier Curves is difficult, But, it's useful once you get used to using it.
If you don't know about Bézier Curves, first read the link below. Then you practice at GIMP or some image editor software. Second, Drow what you want to express. Finally, Export it as SVG.
Of curse, SVG Bézier Curves can be used text editor, but it's difficult.
Bézier Curves GIMP
Bézier Curves MDN
I hope this post will help you.

SVG: The blending of semitransparent lines is dependent on the stroke width?

The blending of semitransparent lines on top of each other behaves differently depending on the used stroke width when viewed in Chrome or Firefox.
Example:
<svg xmlns="http://www.w3.org/2000/svg" width="300" height="300" version="1.1">
<path d="M 0 0 L 200 200 L 0 200 L 200 200 L 0 200 L 200 0" fill="none" stroke="#000000" stroke-width="0.80" stroke-opacity="0.75" shape-rendering="geometricPrecision"
</svg>
The line at the bottom is drawn three times on top of each other, therefore it should appear darker when blended. With a stroke width of <= 0.8, it behaves as expected. A width > 0.8 changes all lines to be uniform in color. Note that the behavior is also dependent on the zoom level used in the browser.
stroke-width="0.8"
stroke-width="0.81"
stroke-width="5"
The problem I'm facing is that I have a lot of overlapping semitransparent lines in my application and the resulting image should implicitly highlight which paths have been used more often than others (Example in codepen):
correct with stroke-width="0.8"
wrong with stroke-width="0.81"
Is there any approach for correct blending? shape-rendering does have an influence, but doesn't solve the problem.

How to fix gap between svg elements

The Problem
I noticed a strange gap between a rect and a path that, according to the coordinates, should look like this:
but instead looks like this:
It occurs in Firefox, Edge and IE, in Chrome only in certain zoom levels or when adding Stoke.
I tried to:
remove all white spaces (looks like the very same problem)
add attribute shape-rendering="crispEdges"
move the elements closer together so that they would overlap (jsfiddle)
Improved the problem, but didn't fix it and introduced new ones (like stroke not matching).
Result in Chrome(v64.0.3282.140):
Result in Firefox(v58.0.1):
Thanks for your consideration
Example
<svg>
<g transform="matrix(1,0,0,1,60,10)">
<rect width="60" height="10" x="-30" y="0" rx="5" ry="5"></rect>
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10" ></path>
</g>
</svg>
<style>
g{
stroke: red;
fill: black;
}
</style>
The rects outline seems to be rendered in color different from black.
Couldn't reproduce the behaviour on Chrome 63 (63.0.3239.132) without the style element, not even scanning through the zoom levels.
However, one possible fix is to close the path with the closepath specifier ( Z or z in the path spec; see here for the pertinent portion of the svg specs):
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10"></path>
In case this modification does not suffice, complement the path to paint over the rectangle's outline along the x interval covered by the path-defined shape:
<path d="M15,10 C0,10 15,25 0,25 C-15,25 0,10 -15,10 l0,-1 L15,9 Z"></path>

SVG: how to correct for off-centered markers with bezier curved paths?

Context
I want to get an arrowhead on a path to a node in a graph that I am making. Because I am using bezier curves it is easier to use the center of the points to / from which the path ends / starts respectively.
In the attached JSFiddle (below) we see a simple triangle of points, one of which is the control points for a quadratic bezier curve. In addition the end markers have been offset to make contact with the node rather than being partially behind it; this is due to paths being drawn to the centers of the points rather than the edges.
Aesthetically there are a few things not quite right with this drawing:
the tip of the arrow head is thiner than the path
although the tip is angled correctly for the arrowhead on the bezier curve, the path is not centered at the point the arrow head appears.
These aesthetic flaws occur because:
the point of an arrow head is obviously thiner than a path / the path extends through the node
the arrow head is so large in respect to the curvature of the path, there is no satisfactory solution to the arrow head problem (given the current code)
Now one could jury-rig the second issue by making a tight cubic bezier curve as done in the second SVG of the JSFiddle.
However, as seen in the third SVG, this does not work with extreme curvature either.
Questions
Is there either a simple way to ensure that the angle of the arrow-head's point and positions of the path when the arrow head joins are centered; alternatively a way to simply scale the arrow head to be small enough where one would not notice?
Is there a way to make the path starting at the arrowhead to the end invisible? / alternatively a simple way to get paths to end prior to hitting the node?
# code to meet SO requirements
# look at this code
JSFiddle
SVG Marker Demo
For your specific application, try adding a viewBox to the marker to make it smaller so it looks somewhat aligned with the end of the bezier. (SVG markers do not currently align with curves.) Change refX to 'slide' the arrow a bit forward to the end of the line.
e.g.
<marker id="arrow" viewBox="0 0 25 25" markerWidth="20" markerHeight="10" refX="20" refY="5" orient="auto" markerUnits="strokeWidth">
Why not just make the markers use your coordinate system, instead of strokeweight:
<marker id="arrow" markerWidth="40" markerHeight="30" refX="25" refY="-5"
orient="auto" markerUnits="userSpaceOnUse" overflow="visible">
<!-- path for the arrow head -->
<path d="M-18,10 l 6 -15 l -6 -15 l 40 15 l -40 15 Z"
fill="white"
stroke='black'
stroke-width='3'
opacity='1' />
</marker>
Sorted. If we draw the paths after the "points" so that the arrow heads end up on top:

How to move multiple lines so that they don't layer over each other

I am attempting to draw a number of lines on a map- basically, walking directions to subway stations. Many of these walking directions are the same for 50% or more of the journey (as you'd expect, coming from the same start point), so when I draw them, they draw on top of each other, obscuring each other- like so:
In this example, the red line is partly obscured by the yellow line- I would like to move the yellow e.g. at a 45 degree angle to place it parallel to the red line. I initially tried offsetting the X and Y coordinates by a few pixels, but any lines that aren't on 90 degree angles look wrong. I started playing around with calculating the degrees that a line is travelling on and to be honest I started to get lost- get the programming side of it, just not the geometry/trig/math of it.
Does anyone have some advice of what keywords I should even be looking for, or what paths I should be going down with this? Thanks in advance.
One trick is to stagger the lines when it overlaps. Here's 4 lines overlapping and staggered so that all lines are visible. Human eye is well trained to follow a color.
Example: http://jsbin.com/ovacar/1/edit
<svg>
<path stroke="skyblue" stroke-width="4" stroke-dasharray="5,15" d="M0 20 l215 0" />
<path stroke="cyan" stroke-width="4" stroke-dasharray="0,0,5,15" d="M5 20 l215 0" />
<path stroke="pink" stroke-width="4" stroke-dasharray="0,5,5,10" d="M5 20 l215 0" />
<path stroke="green" stroke-width="4" stroke-dasharray="0,10,5,5" d="M5 20 l215 0" />
</svg>
I would try just moving each corner on line 2 a couple of metre to the North East by adding a small fraction (try .00001 but experiment) to both lat and long values. This should give parallel lines when zoomed in.
You could also try reducing the opacity of the lines so they blend rather than overlay.