intersection point of google chart and svg line - javascript

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.

Related

In D3, how does one place text inside shapes that already have text attached to them?

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.

Vertical line in D3 plot move on zoom/pan

I am trying to draw a vertical line marker in my graph in D3. It is modeled off of this example: https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172
My issue is that after I draw my line, it doesn't move as I zoom/scroll the graph. An example is shown below:
Currently, I have it calculated as a d3.area().
this.pastDateArea = d3.area()
.x(function(d) { return this.x(this.props.pastDate.toDate()) }.bind(this))
.y0(0)
.y1(function(d) { return this.height }.bind(this))
It is appended as
var pastDateData = [{x:this.props.pastDate.toDate(), y:150}]
this.focus.append("path")
.datum(pastDateData)
.attr("class", "area")
.attr("d", this.pastDateArea)
and zoomed/brushed using
//zoom
var t = d3.event.transform;
this.x.domain(t.rescaleX(this.x2).domain());
//brush
this.svg.select(".zoom").call(this.zoom.transform, d3.zoomIdentity
.scale(this.width / (s[1] - s[0]))
.translate(-s[0], 0));
I know there are similar questions to this one (namely, Draw a vertical line representing the current date in d3 gantt chart) but none of them include the zooming/panning features I have in my graph.
Please let me know if you need more information and thanks!
The issue is that you are not updating the vertical bar with each zoom event. Using the code of the example you show, several things are done when the chart is zoomed, including as you note:
x.domain(t.rescaleX(x2).domain()); // update x scale
focus.select(".area").attr("d", area); // redraw chart area
While you do give the new area the class of area, d3.select will only pick the first matching element. So, on zoom, only one .area element is updated (the first encountered, generally the first appended). But, replacing this with d3.selectAll(".area") will not generate the intended results as the area function referenced (.attr("d",area) ) is only used for the first area (that of the graph, not of the vertical bar).
A solution is to select each area (the chart and the bar) independently and update the area with their respective area generators. To do so, append the vertical bar with a unique class name, or an id and use that to select it later. Then when updating the graph on zoom or brush you can use:
x.domain(s.map(x2.invert, x2)); // update x scale
focus.select(".area").attr("d", area); // redraw chart area
focus.select(".bar").attr("d", pastDateArea);// redraw vertical bar
Remember that this needs to be done for both zoom and brush. Also, in the given example, a clip path is assigned in the css for .area, so you need to keep that in mind as well.
Here's a modified example.

How to create line chart, with custom data points and line style in javascript

I was wondering if I could use some javascript library like Google Charts, gRaphaeljs, flotcharts, or d3js to create a chart like the following:
It has custom circle in more of like a donut shape and the line style I want it to be like connecting dots on a picture. As you can see in the image, the lines have a small margin between each point.
You can use Google Chart for this. I admit I tried it just out of curiosity but it does work. All you have to do is draw chart with standard round points and then when chart is finished (on ready event) add shapes of your own:
google.visualization.events.addListener(chart, 'ready', function(){
// Looping thru every standard point
$('circle').each(function() {
var $c = $(this);
// addinng outer circle
var circles = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circles.setAttribute("cx",$c.attr('cx'));
circles.setAttribute("cy",$c.attr('cy'));
circles.setAttribute("r",$c.attr('r'));
circles.setAttribute("fill",$c.attr('fill'));
circles.setAttribute("stroke",'white');
circles.setAttribute("stroke-width",'3');
this.parentElement.appendChild(circles);
// addinng inner circle
circles = document.createElementNS("http://www.w3.org/2000/svg", "circle");
circles.setAttribute("cx",$c.attr('cx'));
circles.setAttribute("cy",$c.attr('cy'));
circles.setAttribute("r", "4");
circles.setAttribute("fill","white");
this.parentElement.appendChild(circles);
})
});
Demo: http://jsfiddle.net/focnsyu9/1/
Check out charts.js line charts. http://www.chartjs.org/docs/#line-chart

How do I make specific elements appear on top of others in D3.js?

I have a plot in D3 where I draw some circles and then some ellipses afterwards to show the median. I have a 1.5 second delay on my median, to try and draw it after the circles have appeared, but I still run into problems.
Here is a screenshot of an example: http://puu.sh/8csEK.png
The circle to the far right are behind it's median, the rest of the circles are all in front. When areas are crowded you cannot see the median anymore.
I have even tried using the following on transitions of my circles, but it's no use:
.each("end", <call function to draw ellipses>)
So my question is, how do i make sure that my ellipses are drawn on top of my circles?
I have a function that draws my ellipses and a function that draws my circles right now.
I'm assuming that you're using SVG to render your elements. In SVG, the display order is the order of drawing/appending to the DOM. That is, the element you append first is drawn at the back, the element you append last at the front. Child elements (e.g. something underneath a g) are drawn when their parent elements are drawn.
To make sure that groups of elements have the right order, it's usually easiest to add them to different SVG groups that are drawn in the right order. In code, this looks something like this.
var circles = svg.append("g");
var ellipses = svg.append("g");
// ...
ellipses.append(...); // this element appears in the front although it is drawn
// earlier because it is appended to the group appended last
circles.append(...); // this element appears behind the one appended to ellipses

SVG element coming partially below another SVG element

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,

Categories