Is it possible to draw different strokes (I want different line widths) in a subpath of SVG?
I know this can be accomplished using different paths, but it is not possible to use use line-joins on different paths. I want to use a line-join round with different line width.
If it is not possible, what is the best techique to draw two connected lines with different strokes (in the picture below the lines are not connected)?
A path element only has one stroke-width property, so it's not possible at the moment to have different stroke-width per subpath since it's all in one element.
Feel free to explain further on how you need the connected lines join, an illustration might help.
Have a look at the tubefy examples for how to do variable-width stroking and other neat effects with svg and some scripting.
Related
I want to programatically create time lines similar to this:
source
Each event will be at a vertical position determined by its datetime, but it can have arbitrary-length text, and must be positioned vertically so that it doesn't overlap with another event box.
How can I programatically detect overlap of SVG elements so that I can move them up or down as needed? A solution in any programming language or using any library is fine, but ideally I'd like to build this time line without involving a browser; I want this to be a command-line utility.
(I think this is possible because GraphViz Dot can output undirected graphs as SVG and keeps the nodes from overlapping - see the Wikipedia article.)
I'm trying to plot multiple arrows to and from different points. I'm using pyplot.quiver and here's my result.
As can be seen, in many places the arrows between two points are overlapping each other. However, I want something similar to this image below where the arrows instead of overlapping are juxtaposed against each other.
I realise that any two points can be connected by only one straight line so my method of simply passing in the list of x and y lists is probably wrong. I am looking for the best possible method to ensure that the arrows are next to each other instead of on top of each other
Any help would be appreciated.
EDIT (16/06/19): I stumbled upon a Python library called Networkx which allows to analyse, visualise, and do other stuff related to network data and that's what I used to create this. It has nice functions for drawing two juxtaposed arrows between a pair of points and trying other things - curved arrows, changing the arrowhead etc.
I have a (circular) dial. I would like to place text centered at a specific angle on the dial. A simple analogy would be a clock face with text above each hour mark. I can write text along an arc, placing text at the top (12h) position, then rotate that path to place it at a specific angle. The only solution I could think of was to create 1 layer for each text then rotate that layer appropriately (10 deg, 20 deg, 30 deg, etc.). This seems a brute force method, and I have not even been able to get it to work (yet). So, is there a better, standard way to do this?
TIA
ken
Definitely no standard way. But there are scripts that can make that easier. They can be found here (some come with a self-contained doc, go directly to the download page.
dial-marks will generate marks (with round sides if required). It's easy to remove the excess point to keep only arcs. You can have other uses for that one if you are in clocks.
ofn-path-edit (break apart function) is used to make one path per stroke
text-along-path can then be used to add text (centered) on each of these paths.
Results of the three main steps
If you want to script this, plenty of code to borrow from in these scripts.
Assuming a relatively modern, SVG-supporting desktop browser and an SVG consisting of hundreds of similar, simple nodes:
The document could be set up as many individual shape elements (<circle>, <line>, etc.) with their own attributes defined.
The document could be set up as a few <symbol> elements and many individual <use> instances that place them and size them appropriately (W3 spec).
I understand the semantic and code-maintenance reasons to use <symbols>/<use>, but I'm not concerned with those now, I'm strictly trying to optimize rendering, transformation and DOM update performance. I could see <symbol> working similar to reusing sprites in Flash, conserving memory and being generally a good practice. However, I'd be surprised if browser vendors have been thinking this way (and this isn't really the intent of the feature).
Edit: I am not expecting the base symbols to be changed or added to over the life-cycle of the SVG, only the instance locations, sizes, etc
Are there any clear patterns to <symbol>/<use> performance?
How idiosyncratic is it to individual browser implementations?
Are there differences between reusing <symbol> vs <g> vs nested <svg>?
Rohit Kalkur compared rendering speed of the creation of 5000 SVG symbols using use against directly creating the SVG symbol's shapes, see here. It turns out that rendering SVG shapes using use was almost 50% slower. He reasons that:
The use element takes nodes from within the SVG document, and
duplicates them in a non-exposed DOM
Given this, I assume that using SVG symbols is at best as performant as manually creating the symbolss shape.
I would advise you to not nest <use> elements deeply. That is known to cause slowdowns in most browsers, see here and here.
In the general case though it should be fast, at least as long as the template itself isn't changed much (since if you do then each of the instances need to be updated too, and each of them can differ from the rest due to CSS inheritance).
Between <svg> and <symbol> there isn't that big of a difference on a functional level, they both allow you to define a coordinate system (via the 'viewBox' attribute). A <g> element doesn't let you do that. Note that <symbol> elements are invisible unless referenced by a <use>, whereas <svg> and <g> are both visible per default. However, in most cases it's advisable to make the template be a child of a <defs> element.
If you change the contents of a g or svg element then a UI can look at the area the old contents were drawn in and where the update will be drawn to and simply redraw those two areas, even redraw only once if they are the same e.g. changing the colour of a shape.
If you update the contents of a symbol then all the instances must be redrawn. It's harder to do that by calculating for each instance where the old and new parts to redraw are as the areas may be affected by transforms and simpler to just redraw all parts of all instances. Some browsers may do the former and some the latter.
In either case, a UI must at a minimum track the changes in the symbol and propagate those changes to all the instances. That's more than likely to have some overhead.
Of course, if you're just moving individual symbol instances and the contents are static then no tracking is required and performance is likely to be similar.
I have a map that I converted from a raster graphic into an SVG file by converting the differently coloured areas into paths.
I know how to do a basic point-in-polygon check given an array of edges, but the svg:path elements represent multiple polygons as well as masks (to account for seas etc) and extracting that information by parsing the d attribute seems rather heavy-handed.
Is there a JS library that allows me to simplify that check? I basically want to create random points and then check whether they are on land (i.e. inside the polygons) or water (i.e. outside).
As SVG elements seem to allow for mouse event handling, I would think that this shouldn't be much of a problem (i.e. if you can tell whether the mouse pointer is on top of an element, you are already solving the point-in-polygon problem).
EDIT: Complicating the matter a bit, I should mention that the svg:path elements seem to be based on curves rather than lines, so just parsing the d attribute to create an array of edges doesn't seem to be an option.
As the elements can take a fill attribute, a ghetto approach of rendering the SVG on a canvas and then finding the colour value of the pixel at the given point could work, but that seems like a really, really awful way to do it.
The answers on Hit-testing SVG shapes? may help you in this quest. There are issues with missing browser support, but you could perhaps use svgroot.checkIntersection to hit test a small (perhaps even 0 width/height would work?) rectangle within your polygon shape.
The approach I suggested as a last resort seems to be the easiest solution for this problem.
I found a nice JS library that makes it easy to render SVG on a canvas. With the SVG rendered, all it takes is a call to the 2D context's getImageData method for a 1x1 region at the point you want to check. I guess it helps to create a copy of the SVG with colour coding to make the check easier if your SVG is more complex than the one I'm using (you'll have to check the RGBA value byte-by-byte).
This feels terribly hackish as you're actually inspecting the pixels of a raster image, but the performance seems to be decent enough and the colour checks can be written in a way that allows for impurities (e.g. near the edges).
I guess if you want relative coordinates you could try creating a 1-to-1 sized canvas and then divide the pixel coordinates by the canvas dimensions.
If somebody comes up with a better answer, I'll accept it instead. Until then, this one serves as a placeholder in case someone comes here with the same problem looking for an easy solution.