Place text/image on svg path centroid using D3 - javascript

Ive looked and read all i could suck in, but im still having trouble with this Centroid. This is somewhat similar to another question of mine, but this is much more precise.
I need to put text / image on the centroid of these regions:
The svg data is already in my html file in the format like this:
So i need to select a path, and use the centroid function on the d attribute, and then place a dot/text/image etc.
Ive attached a JSFiddle to see all regions, dont mind the class´s/id´s.
<svg id="gamemap">
<g>
<path id='1613' class='Faction2' d='M541.02,336.29L541.71,336.09L543.77,338.27L543.53,338.58L545.92,338.99L546.76,340.12L548.44,340.06L548.55,341.76L549.62,342.38L549.24,343.35L550.58,344.54L551.35,344.98L553.38,344.66L554.17,345.63L555.37,345.08L556.2,346.28L556.8,345.6L557.82,347.73L558.51,347.76L558.17,350.15L560.8,350.12L561.12,349.61L563.89,349.94L562.98,351.84L562.99,353.94L562.06,353.97L560.77,357.72L561.33,357.73L562.06,359L563.49,358.5L563.75,357.85L564.17,358.09L564.64,361.19L565.52,361.68L564.51,362.21L564.67,363.38L565.17,363.21L565.35,364.41L566.19,364.53L566.23,365.29L569.63,364.91L570.56,365.3L571.08,364.96L570.95,363.35L571.8,363.24L572.34,361.72L574.42,361.71L574.42,362.52L575.54,363.71L576.52,363.63L577.12,366.98L576.92,367.48L576.48,367.11L576.07,368.69L575.27,369.28L574.63,368.34L573.95,368.48L572.81,367.73L572.98,367.22L568.79,367.27L569.11,368.9L570.26,368.96L570.47,370.97L569.84,371.57L569.93,372.77L567.97,373.13L567.87,374.18L566.53,374.8L566.23,376.97L567.97,378.31L567.71,378.99L568.26,379.8L569.51,379.48L570.12,379.99L569.89,381.28L570.75,381.42L571.35,380.69L571.68,381.56L572.49,381.6L572.58,384.48L570.45,386.31L571.53,387.37L575.34,387.32L576.48,386.31L577.75,387.06L578.55,386.9L578.72,386.35L579.14,388.12L582.26,388.74L582.26,388.74L581.47,393.15L580.4,393.97L579.82,395.87L579.08,395.35L578.2,396.29L577.28,396.38L577.29,397.52L578.35,397.61L579.28,399.98L577.41,400.34L577.11,401.08L574.8,400.87L573.67,400.08L572.75,400.72L573.27,402.26L572.33,403.02L572.9,403.12L572.9,406.09L571.14,407.62L570.94,409.22L568.54,410.96L567.72,412.46L566.65,412.91L565.57,412.67L565.46,413.7L564.67,413.56L564.03,414.13L564.03,414.13L563.23,413.7L563.3,412.5L561.74,411.47L557.87,411.88L557.23,410.94L555.76,411.18L555.63,410.36L554.66,409.87L554.24,407.54L553.46,408.06L553.18,407.52L552.19,407.79L552.13,406.67L551.61,406.4L549.85,407.78L550.64,408.52L550.35,409.52L548.88,409.93L546.92,411.56L545.91,411.15L545.41,411.64L544.54,410.6L544.91,410.04L544.56,409.77L546.56,408.07L547.67,406.07L544.73,404.27L543.76,404.56L543.09,406.83L542.24,406.82L539.6,408.5L538.88,407.79L538,407.92L538,407.92L537.23,405.88L537.12,402.37L536.06,401.04L535.09,400.83L534.83,399.78L535.59,399.16L534.97,398.75L535.21,397.8L533.26,395.38L533.52,394.35L534.62,394.05L534.62,392.72L537.23,391.28L536.87,390.53L535.54,390.11L534.7,388.6L533.39,389.1L531.94,387.66L530.97,388.6L530.32,387.03L529.52,386.78L528.33,384.83L528.33,384.83L528.41,383.41L529.8,381.78L529.94,380.84L532.2,379.27L533.94,379.57L535.17,379.04L535.49,373.58L534.78,368.75L534.3,368.46L535.34,367.54L533.5,369.09L533.31,368.51L533.16,368.93L532.38,368.65L532,369.91L530.61,370.02L528.8,367.47L527.48,367.8L527.47,367.3L526.14,367.25L526.14,363.27L522.15,361.35L522.76,360.8L522.44,359.18L522.85,358.72L524.05,359.8L525.49,359.83L527.33,359.09L528.25,356.19L527.62,355.4L528.01,353.55L528.68,353.53L528.87,352.71L531.71,352.3L530.81,349.43L531.44,349.31L531.64,347.98L530.57,347.83L531.23,345.53L531.87,345.02L533.86,344.93L534.43,345.96L534.87,345.52L535.88,345.99L536.09,347.44L537.04,348.1L537.23,349.32L538.33,350.45L541.8,348.99L541.87,348.25L543.42,347.42L544.39,347.69L544.48,346.42L542.96,344.27L543.61,341.8L540.93,341.91L540.88,341.21L538.99,340.21L538.31,338.99L538.71,337.22L538.71,337.22L539.3,337.63z'/><path id='1614' class='Faction2' d='M546.46,257.82L545.19,257.69L545.32,258.18L543.54,257.65L541.38,259.38L542.02,260.56L540.61,260.4L538.66,258.32L536.13,258.13L535.82,258.52L535.34,258.01L533.87,259.42L533.2,259.42L532.34,257.98L530.81,258.02L529.74,257.1L529.84,255.69L529,255.13L530.84,254.47L530.2,254L530.15,252.87L528.99,252.2L529.29,251L531.38,249.47L533.13,249.19L533.53,248.49L534.28,249.13L534.78,247.81L535.79,247.12L535.17,245.59L533.4,244.1L533.46,243.33L532.94,243.15L533.23,242.5L535.15,241.24L536.1,241.87L537.59,241.28L539.29,238.42L540,238.94L541.47,238.45L542.04,238.74L540.53,236.05L542.23,236.64L541.97,235.28L543.78,235.25L544.4,233.9L545.04,234.33L544.79,235.26L545.4,236.52L547.05,237.66L548.92,239.98L550.77,239.84L552.86,240.63L555.26,240.44L555.25,240.92L554.36,240.98L554.53,241.89L552.78,241.9L551.46,243.23L551.74,245.25L553.79,247.69L553.79,247.69L553.79,248.62L551.45,250.07L551.45,250.07L548.96,250.95L546.19,250.97L546.21,253.02L547.91,253.88L548.31,254.99L547.66,256.41L547.66,256.41z'/></g>
</svg>
JSFiddle
Hope for a solution to this. Thanks

Related

How do I set presentation attributes of Image tags that can be found within SVGs (Files or Inline)? [duplicate]

This question already has answers here:
How can I change the color of an 'svg' element?
(40 answers)
How to change color of SVG image using CSS (jQuery SVG image replacement)?
(18 answers)
Closed last year.
This post was edited and submitted for review last year and failed to reopen the post:
Original close reason(s) were not resolved
I am writing an SVG editor program. I am trying to implement highlighted feel for when an element (<image>, not <img>) is clicked. I have implemented this for other elements like <circle>, by setting stroke, stroke-width, and stroke-dash-array. But setting the presentation attributes of the <image> tag, either by setting the attributes directly or through CSS styling, is not taking effect. I also tried the border style but it's not working. How can I achieve this?
According to MDN , <image> is meant to have have global attributes, including presentation, which ultimately means this should work. If you also inspect <image> with a browser you will see it will highlight like it follows box model.
<svg viewBox="0 0 1370 1170" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<image width="128" height="128" x="617.9207153320312" href="data:some-valid-link" style="stroke-width: 3px; stroke-dasharray: 7px;" stroke="#3aa2c2"></image>
</svg>
I don't think that you can set stroke on an image.
Usually those attributes are used to 'draw' vector image. Here you're trying to put a stroke on a raster image.
If you want to put lines around a square image you could use a border to achieve it.
If you want to put lines around a complicated shape, I don't think it's possible to do that in CSS. You would need to add that in graphics software.
You cannot restyle an external SVG, if you load it in an <img> tag.
Instead, you could paste the <svg> code directly into your HTML, and apply styles like this (source svg):
svg {
width: 500px;
}
svg path,
svg polygon {
stroke-width: 10px;
stroke-dasharray: 10px;
}
<svg height="210" width="500">
<polygon points="100,10 40,198 190,78 10,78 160,198" style="fill:lime;stroke:purple;stroke-width:5;fill-rule:nonzero;"/>
Sorry, your browser does not support inline SVG.
</svg>
You would need and SVG with a more specific code targeting all the vectors and not just a tag. Then you could make groups of the parts of the image/draw you want to style. You can do this by using illustrator, then after grouping the parts, your code will have a 'g' tag: <g id="group_to_style" > with an ID that you have named when doing the groups. Then using CSS you can target the groups of the SVG and style or even animate. Like gru said, with an you cant style or animate anything.

add custom svg layer on google map (api v3)

Here is the problem,
I try to add a custom layer (svg) on a google map.
The layer I chose is really simple, it is just a "rect" but sooner or later these are gonna be much more complex with paths & so on... but that's not the problem actually.
I finally could add the svg on the map and make it visible,
but, since svg are not like image tags, i cannot find a way to scale/size the svg with the google map like simple images would...
here is a google example, when you scale (mousewheel) the map, the custom overlay size is changing too :
https://developers.google.com/maps/documentation/javascript/examples/overlay-simple
And, here is the svg I tried to add on the map, you will notice that the div (container) is located at specific points (lat/lng), and scales correctly with mousewheel on the map. BUT, the svg layer I tried to add into it, is jut NOT into it at all, and, does not scale on mousewheel... the only point going fine with this svg layer is that it's working with map dragging...
svg layer should be contained in the defined div (with bounds...). Svg is a simple layer :
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" class="svg-editor">
<g>
<rect id="svg_5" height="181" width="311" y="95.25" x="47.75" stroke-width="5" fill="#FF0000"/>
</g>
</svg>
here is the fiddle :
http://jsfiddle.net/7b3byzrf/27/
Thanks for help!
If you want your svg image to be correctly scaled, you need to have
a viewBox (you've put it, this part is OK)
no dimension in the svg element (here's the problem).
Remove those lines :
svg.setAttribute('width','400');
svg.setAttribute('height','400');
Demonstration

D3 Multiple Visualizations Per Page Namespace IRI Conflicts [duplicate]

I've enbedded d3's force directed graph layout into extjs tabs so that each time a new tab gets added a new graph svg gets generated.
No Problemo so far.
Now I intended to turn the graph into a directed one (by adding a marker and tell the lines to use it)
Each generated svg elements is following this pattern:
<svg width="100%" height="100%">
<defs><marker id="end-arrow" viewBox="0 -5 10 10" refX="6" markerWidth="3" markerHeight="3" orient="auto"><path d="M0,-5L10,0L0,5" fill="#ccc"></path></marker>
</defs>
<g transform="translate(4,0) scale(1)"><line class="link" sig="30.84" style="stroke-width: 3;" x1="538" y1="347" x2="409" y2="467" marker-end="url(#end-arrow)"></line>
...
</g>
</svg>
With Crome everything works just fine.
So I arrived at the concusion that the structur and
the way I generate the svgs should be more or less correct.
But with Firefox the Markers will only show for the first svg. (the first tab)
All other svgs won't show any Arrowheads.
"Inspect Elements" tells me the Markers are there and that the lines are refering to them.
And this is where I'm running out of Ideas where or what to look for. :(
You have multiple non-distinct IDs within the same html or svg document. This is invalid, different UAs respond differently but as you're not allowed to do this, it doesn't really matter that they are inconsistent.

Dilate and erode SVG shapes using Javascript

EDIT:
I finally found a way to erode and dilate polygons (offsetting) so that new geometry is created using Clipper library:
https://sourceforge.net/projects/jsclipper/
Live demo of Javascript Clipper:
http://jsclipper.sourceforge.net/5.0.2.1/main_demo.html
The Clipper can only handle polygons or multi-polygons (eg. polygons with holes), so for it to work with other graphical objects of SVG format, they have to be converted to straight lines. At least paths are rather easy to convert to lines using path.getTotalLength() and path.getPointAtLength() (http://whaticode.com/2012/02/01/converting-svg-paths-to-polygons/).
The other possibility is use this like technique (that does not create new geometry):
https://stackoverflow.com/a/12723835/1691517
Is there any way to erode and dilate shapes in SVG via Javascript?
I have the following SVG example:
http://jsfiddle.net/timo2012/2S4Kt/1/
There are three shapes, blue is original, green is eroded (thinned) and red is dilated (bolded). They are made in Illustrator.
I have tested erode and dilate filters, but the effect is not so good:
https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/examples/feMorphology.svg
After few hours searching over internet, I have found only examples about bitmap image eroding and dilating, but nothing about vector shapes.
I have succeeded in dilating and eroding SVG polygons using Shapely ( http://toblerity.github.com/shapely/manual.html ) in Python by sending path points via Ajax call to PHP script which makes system() call to Python script, but this method is slow and requires server to do the work that could be done client side.
This is my code for dilating and eroding in Python (as you see it is quite short):
#!/usr/bin/python26
from shapely.geometry import Polygon
from shapely.geometry import MultiPolygon
import sys
if len(sys.argv)>2:
inset=eval(sys.argv[1])
coords=eval(sys.argv[2])
else:
sys.exit()
bowtie = Polygon(coords)
clean = bowtie.buffer(inset)
clean = clean.simplify(1, preserve_topology=False)
if clean.length>0:
if clean.geom_type=="MultiPolygon":
for n in range(0, len(clean)):
print list(clean[n].exterior.coords)
#print "\n"
elif clean.geom_type=="Polygon":
print list(clean.exterior.coords)
Also find this document, which tries to define dilate and erode in mathematical terms:
http://en.wikipedia.org/wiki/Mathematical_morphology
There is a sentence "The basic idea in binary morphology is to probe an image with a simple, pre-defined shape, drawing conclusions on how this shape fits or misses the shapes in the image. This simple "probe" is called structuring element, and is itself a binary image (i.e., a subset of the space or grid)."
I assume that this method could be used in morphing vector shapes, but how...
EDIT: One comment in a reply raised a possible issue of using filters instead of creating new geometry: if someone wants to add drag handles to polygon points, then drag handles may seem to be in wrong place. This can be acceptable, because then the impression is that the original path data is untouched, which is actually the case in filters, but - after further testing - it proved that the quality is a bigger problem. According to this and this SVG filter uses pixel representation of vector graphic object instead of path data itself, which leads to not so good looking results.
EDIT2: POSSIBLE WORKAROUND: One of the answers in this page led me to use variable-width strokes and mask to achieve a good looking workaround to this issue. I made a few tests and get implemented an Adobe Illustrator -like Offset Path Effect.
You can sort of get what you seem to be after by stroking with different stroke-widths in combination with clip-path or mask. Here's an example, some explanations of how it's constructed see here and here (arrow up or down to see some other slides on that example).
It doesn't give you new geometry though, just something that might look like new geometry.
Have you actually tested SVG's native filters? This looks close enough:
<svg width="612" height="792" viewBox="0 0 612 792" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="erode">
<feMorphology operator="erode" in="SourceGraphic" radius="12" />
</filter>
<filter id="dilate">
<feMorphology operator="dilate" in="SourceGraphic" radius="8" />
</filter>
<path id="original_path" d="M193.193,85c23.44,0.647,45.161,0.774,62,12c1.596,1.064,12,11.505,12,13
c0,2.941,8.191,5.669,3,12c-3.088,3.767-6.01-0.758-11-1c-19.56-0.948-33.241,12.296-33,34c0.163,14.698,8.114,24.492,4,41
c-1.408,5.649-6.571,15.857-10,21c-2.484,3.726-7.898,10.784-12,13c-4.115-11.677,2.686-27.29-6-35c-6.693-5.942-20.021-4.051-26,1
c-13.573,11.466-11.885,41.492-7,58c-5.8,1.772-18.938,7.685-23,12c-6.752-10.805-15.333-17.333-24-26c-3.307-3.307-9.371-12-15-12
c-16.772,0-13.963-15.741-13-28c1.283-16.324,1.727-28.24,4-42c1.276-7.72,8-16.411,8-23c0-7.416,15.945-29,23-29
c4.507,0,17.678-8.701,24-11C164.853,90.76,178.27,88.546,193.193,85"/>
</defs>
<use xlink:href="#original_path" fill="#f00" filter="url(#dilate)"></use>
<use xlink:href="#original_path" fill="blue"></use>
<use xlink:href="#original_path" fill="#1CFF00" filter="url(#erode)"></use>
</svg>
There is some clipping going on the dilate filter that can't seem to be resolved by increasing the filter region, but other than that it's pretty close to your illustrator rendering. Sure beats rendering server-side.
http://jsfiddle.net/5Qv5v/

SVG elements are not shown in a browser

I have faced to a quite strange situation. I have a script which draws some lines using jQuery SVG plugin. It is working in a separate html file. But once I copy that script and insert into another html file it stops showing SVG elements in a browser. It works perfectly, because when I see the source code of the page after running a script I could see that the script is adding SVG elements to the page. Here is SVG code of the page in any case:
<svg version="1.1">
<line x1="492" y1="503" x2="717" y2="576" stroke="#4A4A4A" stroke-width="2"></line>
<line x1="500" y1="400" x2="600" y2="400" stroke="#4A4A4A" stroke-width="2"></line>
<line x1="604.5" y1="539.5" x2="587.5" y2="542.5" stroke="red" stroke-width="2"></line>
<line x1="604.5" y1="539.5" x2="592.5" y2="527.5" stroke="red" stroke-width="2"></line>
</svg>
What could be the problem the those SVG elements are not shown in the browser? Have anybody else faced such a strange situation?
You forgot to add the SVG namespace tag to your page?
Try adding a viewBox attribute to the svg element to ensure that the coordinate system makes the lines appear within the svg viewport. Or make sure that in both documents size of the svg element is the same. My guess is that in one document the svg is quite wide, and in the other it's not as wide (thus clipping away the lines).
The problem is solved. I didn't notice that in the new page where SVG elements were not shown, the DIV element where I was drawing SVG elements had been wrapped by another DIV. And in the CSS file the wrapper DIV had an attribute display: table;. I removed that attribute and now SVG elements are shown. Thanks guys for you help and suggestions.

Categories