Something like this:
Normally, on the browser, we append the points to the svg like so:
svg.append("g")
.selectAll("g")
.data(data.features)
.enter()
.append("g")
.attr("transform", function(d) { return "translate(" + projection(d.geometry.coordinates) + ")"; })
.append("circle")
.attr("r", 1)
what would be the react native equivalent of the above snippet?
Related
I'm trying to make a d3 tooltip that can show near my cursor when I hover over a dot. I tried lots of methods available online, but none of them works. The tooltip doesn't show, and there is no error messages in console. Could anyone help me with this? My code is as follows:
I suspect there might be some issue with svg, but not sure how to solve it.
var svg = d3.select("#linechart").append("svg").attr('id','cases')
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var xScale = d3.scaleTime()
.domain(d3.extent(getCovidDate(data,state), function(d){return new Date(d)}))
.range([0, width]);
var yScale = d3.scaleLinear()
.domain(d3.extent(getCases(data,state), function(d){return d}))
.range([height, 0]);
var line = d3.line()
.x(function(d) { return xScale(new Date(d[0])); }) // set the x values for the line generator
.y(function(d) { return yScale(d[1]); }) // set the y values for the line generator
.curve(d3.curveMonotoneX) // apply smoothing to the line
var dataset = d3.zip(getCovidDate(data,state),getCases(data,state))
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft
var div = d3.select("#cases").append("div")
.attr("class", "tooltip")
.style("display", "none");
svg.append("path")
.datum(dataset) // Binds data to the line
.attr("class", "line") // Assign a class for styling
.attr("d", line) // Calls the line generator
.style('fill-opacity', 0)
.style('stroke','cadetblue')
.on('mouseover', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '.55')})
.on('mouseout', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '1')});
svg.selectAll(".dot")
.data(dataset)
.enter().append("circle")
.attr("class", "dot") // Assign a class for styling
.attr("cx", function(d) { return xScale(new Date(d[0])) })
.attr("cy", function(d) { return yScale(d[1]) })
.attr("r", 5)
.style("fill",'cadetblue')
.on('mouseover', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '.55')
div.style("display", "inline");
})
.on('mousemove',function(d){
div.text(d[1])
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 15) + "px")
})
.on('mouseout', function (d, i) {
d3.select(this).transition()
.duration('50')
.attr('opacity', '1')
div.style("display", "none");
});
svg.append("line")
.attr("x1", xScale(new Date(inputValue)))
.attr("y1", 0)
.attr("x2", xScale(new Date(inputValue)))
.attr("y2", height)
.style("stroke-width", 2)
.style("stroke", "red")
.style("fill", "none");
d3.select('#cases').remove()
I am able to get a tooltip to work by defining the text but for the life of me I cannot get the tooltip to print text from a data file. I feel like I am messing up defining d.value even though it is being graphed just fine but I also wonder if there is something with v4 that I don't know about. I've tried moving the var statement all over the place but nothing seems to help. It usually ends up being a "Cannot read property of undefined" error. Any thoughts on what I'm doing wrong? Thanks.
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden")
.text("This works just fine");
/* .text(function(d) { return d.value; }); */
d3.tsv("15.tsv", type, function(error, data) {
if (error) throw error;
x.domain([0, d3.max(data, function(d) { return d.value; })]);
y.domain(data.map(function(d) { return (d.gamedate); }))
.paddingInner(0.1)
.paddingOuter(0.5);
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("transform", "translate(" + width + ",0)")
.attr("y", 15)
.style("text-anchor", "end")
.text("Game Score");
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", 0)
.attr("height", y.bandwidth())
.attr("y", function(d) { return y(d.gamedate); })
.attr("width", function(d) { return x(d.value); })
.on("mouseover", function(d){
return tooltip.style("visibility", "visible");})
.on("mousemove", function(d){return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+400)+"px");})
.on("mouseout", function(d){return tooltip.style("visibility", "hidden");})
I think the main issue is that event variable is not defined in the scope of the mousemove function. You can get the mouse values by doing the following:
.on("mousemove", function(d) {
const [xMouse, yMouse] = d3.mouse(this);
tooltip.style("top", (yMouse) + "px")
.style("left", (xMouse) + "px")
.text(`Gamedate ${d.gamedate} with value ${d.value}`)
})
I made a JSbin in order to show how I got it to work, the data is mocked.
possible duplicates: D3 text on mouseover
D3 donut chart text centering
but unsure what is happening in respect to my problem and quite stuck.
Im building a data visualization with many layouts. I am currently trying to make a piechart with text centered in the middle and whenever someone mouse overs the arcs, it displays the text of it in the center.
function GUP_PieRender() {
var svg = d3.select(targetDOMelement).append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var g = svg.selectAll(".arc")
.data(pie(dataset))
.enter().append("g")
.attr("class", "arc")
.on("mouseover", function(d) { d3.select("text").text(d.data.ResearchArea)}); //Problem area
g.append("path")
.attr("d", arc)
.style("fill", function(d) { return color(d.data.ResearchArea); });
g.append("text")
.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; })
.attr("dy", ".35em")
.style("text-anchor", "middle");
}
What it is doing instead is displaying the text in another D3 barchart layout that has text. So I must be calling the mouseover event too early and appending it to the last text element in that?
Can I get a remedy?
Thanks.
The problem here (inside your "mouseover" handler) is simply this:
d3.select("text")
When you do this, D3 selects the first text element it finds in that page. You don't want that, obviously.
Therefore, just do:
g.select("text")
That way, you only select text elements inside your g selection.
Alternatively, you can also do:
d3.select(this).select("text")
Since this in this context is the group element.
Here is a demo (I'm trying to imitate your code):
var data = ["foo", "bar", "baz"];
data.forEach(function(d) {
render(d);
})
function render(data) {
var svg = d3.select("body")
.append("svg")
.attr("width", 100)
.attr("height", 100);
var g = svg.selectAll(null)
.data([data])
.enter()
.append("g")
.on("mouseover", function(d) {
g.select("text").text(String)
})
.on("mouseout", function(d) {
g.select("text").text(null)
})
g.append("circle")
.attr("cx", 50)
.attr("cy", 50)
.attr("r", 20);
g.append("text")
.attr("x", 25)
.attr("y", 20);
}
svg {
background-color: tan;
border: 1px solid darkgray;
margin-right: 10px;
}
circle {
fill: teal;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
When I render latitude/longitude points (my_coords) on my globe with:
svg.append("path")
.datum({type: "MultiPoint", coordinates: my_coords})
.attr("class", "points")
.attr("d", path);
I get circles. I can change the color with CSS, but how can I change the symbol from circles to triangles? I've tried:
svg.append("path")
.datum({type: "MultiPoint", coordinates: my_coords})
.attr("class", "point")
.attr("d", d3.svg.symbol().type("triangle-up"));
But this doesn't work.
You can try this:
//define triangle
var arc = d3.svg.symbol().type('triangle-up');
// put a triangle on every city
svg.selectAll(".tripath")
.data(topojson.feature(uk, uk.objects.places).features)
.enter().append("path")
.attr('d',arc)
.attr("transform", function(d) {
return "translate(" + projection(d.geometry.coordinates) + ")"; });
Here the working code: http://jsfiddle.net/6d3ansfn/
Here the SVG Shape reference from Mike's github: https://github.com/mbostock/d3/wiki/SVG-Shapes#symbol
Example code is from Mike: http://bost.ocks.org/mike/map/
If you has a .tsv file width coordinates, use this:
svg.selectAll(".tripath")
.data( my_coords)
.enter().append("path")
.attr('d',arc)
.attr("transform", function(d) {
return "translate(" + projection(d) + ")"; });
remember update proyection on drag and/or zoom.
I have a geoJSON of zip code centroid points that I am plotting on a D3.js map. I can get them to display but I am unable to adjust the size of the points. I was assuming that .attr("r", 1) would be doing that but I must be missing something.
d3.json("ZipPoints.json", function (zipPoints) {
svg.selectAll("g")
.data(zipPoints.features)
.enter()
.append("path")
.attr("d", path)
.attr("r", 1)
.style("fill", "red");
});
EDIT:
d3.json("ZipPoints.json", function (zipPoints) {
points.selectAll("circle")
.data(zipPoints.features)
.enter()
.append("circle")
.attr("r", 1.5)
.attr("transform", function(d, i) {
return "translate(" + projection(zipPoints.features[i].geometry.coordinates) + ")";
})
.style("fill", "red")
.classed("point", true);
});
You could try the following.
var pins = svg.append("g");
d3.json("ZipPoints.json", function(zipPoints) {
pins.selectAll("circle")
.data(zipPoints.features)
.enter()
.append("circle")
.attr("r", 5)
.style("fill", "red")
.classed("pin", true);
});
You may need transformation on these points to render them correctly (I guess).
In that case you could use the following bit of code. (The transformation function I used was required to plot data that had lat, long information on a map built using a specific projection).
.attr("transform", function(d) {
/*whatever transformation that needs to be done*/
return "translate(" + projection([ d.lon, d.lat ]) + ")";
})