I am drawing a map using d3.js and geojson file.
Map is getting generated properly and also map is drawn using many path for each district of that country.
Using the long,lat of a city I am drawing a circle at the projected point because I want to apply transformation like zooming and paning of the map.
The problem is that circle is partially coming below the path.
Below is the layout of HTML page.
The reason I have put circles in g tag is because I am applying zoom and pan to map and the circle should also move accordingly.
svg
g
path d=.....
circle...some attributes
g
path
circle
g
path
g
path
g
path
circle
How can I solve the problem or is there any other solution?
In your layout, the paths of each region are drawn before the circles, but the circles from previous regions could be hidden by paths drawn later. You may want to create a group for the paths, append a group for the circles and a last one for the labels in order to avoid the overlapping.
- g.zoom
- g.paths
- path
- path
- ...
- g.circles
- circle
- ...
- g.labels
- text...
You can bind the zoom behavior to the g.zoom group. Regards,
Related
When I use
layer.findOne('#'+mynode).x()
this gives me the X position of the mynode, but only when mynode is ungrouped. If I group it, then it is not updated when the group is dragged.
When I use
absolutePosition()
method for a node - it works (returning the realtime position of a node), but only to the point when the view is moved or zoomed. Then the layer coordinates are no longer aligned with the absolute coordinates, so when I draw a line between nodes on the layer using those absolute coordinates, the line does not stick to the nodes.
So, how to get the position of an object that is in a group, but measured within its layer - so that I can use them to draw a line between nodes on that layer.
You can use node.getAbsolutePosition(layer). That function will return the absolute position of the node relative to the passed container (layer).
I am currently working on the following d3 example where I'd like to place text inside of the arcs, similar to this example. However, whenever I try to append text to anything, the text just doesn't display. I've looked at the developer console, and it appears to be there, but it won't visually display on the screen. I used all the code provided in the first example, except I tried to add the following the the arc elements:
("the d3 element").enter().append("svg:text").text("???")
("the d3 element").enter().append("text").text("???")
("the d3 element").append("svg:text").text("???")
("the d3 element").append("text").text("???")
Aside from cutting off some of the styling changes, it seems like no matter where I put any of this code, it just doesn't want to work for me. I would appreciate and help!
"whenever I try to append text to anything, the text just doesn't display": Text cannot be appended to most svg elements. You can append text to the svg itself or a g, but you cannot append it to a path, rect, circle, etc.
One of the most common methods of dealing with this is to use g elements to place a shape and text while binding data to the g. Using a transform on theg will translate shape and text - great for things like circles and rectangles.
There are several other approaches you can use to overlay text on svg elements:
Use the positioning attributes of an element to set the x and y attributes of text so that you can place text over top of an element.
Use a path as a text path to place text (as in your example)
Use utility methods such as centroid (for arcs or geopaths for example)
Find the bounding box of elements and place elements using this information.
These options help place, but won't make sure that the text falls within the bounds of a shape - that is different complication.
For arcs, one option is to use a circular path as a text-path where the circle has a radius between that of the inner and outer radius of your arc - then place the text using a text offset that reflects the start angle - or make an arc for each piece of text. The general mechanism is shown below (note it can't use a circle element as svg textPaths must follow paths):
var svg=d3.select("body")
.append("svg")
.attr("height",400)
.attr("width",400)
.attr("transform","translate(200,200)")
var arc = d3.arc()
.innerRadius(50)
.outerRadius(100)
.startAngle(0)
.endAngle(2);
var arcText = d3.arc()
.innerRadius(75)
.outerRadius(75)
.startAngle(0)
.endAngle(2);
var arc = svg.append("path")
.attr("d",arc)
.attr("fill","steelblue")
var textPath = svg.append("path")
.attr("d",arcText)
.attr("id","textpath")
.attr("fill","none")
.attr("stroke","black");
var text = svg.append("text")
.append("textPath")
.attr("xlink:href","#textpath")
.text("title")
.attr("startOffset", "25%") // the bottom of the arc is from 50%-100%, the top from 0 to 50%
.style("text-anchor","middle")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>
The above mechanism is very similar to the example you link to - it appends text using the arcs as text paths. The example you reference uses text paths of the visible arc(donut) segments themselves - and offsets the x,y positions to move the text into the arc itself (as opposed to on the arc).
Note that I've used v4, as opposed to v3 as in the linked example.
I have a shape (a drawn cloud) in a g within a defs tag. Unfortunately, I am not able to use this shape inside a circle using d3.js. Here is my code:
JSFiddle
What I am trying to do is to display that shape which is in defs tag inside the circle shown in the SVG. I have tried many times in different ways but I could not use the shape from the defs tag inside the circle. Could anyone please assist me with this issue? Thank you in advance.
A circle can't contain other shapes. According to the MDN docs it may only contain descriptive elements and animation elements. These categories don't include shapes like circle, or use.
Rather than nesting your shapes, you should create a parent g and append the circle and use to that:
// Create a `g`, rather than a `circle`, for each data point
var groups = svg.selectAll(".group").data(data).enter().append("g")
.attr("class", "group");
// Append a `circle` to the new g
groups.append("circle")
.attr("cx",100).attr("cy",100).attr("r",20);
// Append a `use` to the new g
groups.append("use").attr("xlink:href", "#mySymbol");
JSFiddle
I've been searching the web for tutorials or methods on how to to implement my own point to point navigation system for an SVG-based indoor floor plan map. I have searched the web but the only options work with google maps. However I created my map using Illustrator as an SVG image using paths/vectors. I don't need to implement any navigational instructions for the user, just a simple route from one point to another. There must be a way to use the vectors to plot points on the map that the navigational path can take for turns etc.
Any advice appreciated
Thanks
Yes! You can do this with JavaScript, as well as add event listeners and do other DOM manipulation similar to with a normal HTML page. (See the bottom of this answer for how to draw a line on the SVG given two points.)
I am working on a project that does exactly this. The user is able to enter their starting room number and destination room number, and the route is plotted on the SVG.
It was a bit tedious, but what we did was put circle elements on the SVG. There were elements outside of each doorway, and also at hallway intersections.
A typical element is as follows.
<circle
id="route3287-1"
style="fill:#000000;stroke:none"
cx="2014.0000"
cy="239.6"
r=".05"
data-neighbors="route3296-1,06-07" />
Note that the radius attribute is small enough to where it won't be seen on the SVG (unless the user decides to zoom in alot). We also manually entered into the data-neighbors attribute the ids of adjacent points. This is because our back end parses the SVG file, builds a graph using these points, and uses Dijkstra's algorithm to generate the route. We used the cx and cy attributes to calculate the distance between nodes on the graph.
Here is a close up of what the points look like (when the radius is big enough to see them)
Now, when a route is generated we are simply drawing lines on the SVG between each of the points. We put each of the lines in a group so that we can reference it by id later and remove the entire route when we decide to draw a new one.
Here is an example. Where "svg" is a reference to the SVG element, here is how we draw a line between two points (x1,y1,x2,y2), you could easily iterate through a list of points and draw all the lines in a similar fashion.
var newElement = svg.createElementNS('http://www.w3.org/2000/svg', 'path');
newElement.setAttribute('d', 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2);
newElement.style.stroke = '#000000';
newElement.style.strokeWidth = '15px';
svg.appendChild(newElement);
You can manipulate the SVG with JS and CSS and this way add more interactions with the SVG. SVG is XML an can be traversed with JS as normal DOM tree, so you can create functions to handle your requirements. You can even place the SVG you've created as Layer in Google Maps.
The article uses simple example for FloorMaps. Interface with SVG
You can draw a SVG and with javascript add be interative
https://echarts.apache.org/examples/en/editor.html?c=geo-svg-lines
Svg line not displayed on google charts?
Refering this question i want to find out point at which svg line cuts google chart.
This is fiddle link to http://jsfiddle.net/nc6uf/
i want to find point at which mouse intersects google chart in mouse move event
graph.on('mousemove', function() {
line.attr("y1", d3.event.y - 50);
line.attr("y2", d3.event.y - 50);
});
Each Google Chart is drawn in an SVG that is in its own div. SVG objects can only be drawn within an element, and since you have two SVG canvases in your example (one on top and one on the bottom) your line will only be drawn in the element to which you appended the line. Because you used d3.select() you selected the first element that satisfied your condition "svg".
You can see the second SVG canvas interact with your mousemove by changing this line in your example:
var graph = d3.select('svg');
to:
var graph = d3.selectAll('svg');
If you wanted the line to pass through both charts, you'd need the charts to be drawn on the same SVG canvas.