简体   繁体   中英

d3 radar chart in v5, cannot render 'path' object

I am trying to create a very simple radar chart with d3. All I want is 10 blank axes, with one of ten values assigned to each axis (same scale for each, 0-100). So far, I have been able to properly render the axes. I also want a line (a 'path' object) connecting all the points. So far I have been unable to get this to appear.

I have been working off of this example ( http://bl.ocks.org/nbremer/21746a9668ffdf6d8242 ). Essentially, I have tried to cut out the unnecessary things for me in the radarChart() fn, and convert the code over the d3v5, which I am using.

This is the data that I pass to the function:

var rand = randData();

//data in format for radarchart func
var d = [
    {axis: "1", value: rand[0]},
    {axis: "2", value: rand[1]},
    {axis: "3", value: rand[2]},
    {axis: "4", value: rand[3]},
    {axis: "5", value: rand[4]},
    {axis: "6", value: rand[5]},
    {axis: "7", value: rand[6]},
    {axis: "8", value: rand[7]},
    {axis: "9", value: rand[8]},
    {axis: "10", value: rand[9]}
];

radar.js:

function radarchart(id, data){
//some vars set here, removed for brevity
var svg = d3.select(id)
var r_scale = d3.scaleLinear()
    .domain([0, max_value])
    .range([0, radius])

var g = svg.append('g')
    .attr("transform", "translate(" + (cfg.w/2 + cfg.margin.left) + "," + 
        (cfg.h/2 + cfg.margin.top) + ")");

//wrapper for axes
var axis_grid = g.append('g').attr('class', 'axisWrapper');

var axis = axis_grid.selectAll('.axis')
    .data(all_axis)
    .enter()
    .append('g')
    .attr('class', 'axis')

//draws actual axes
axis.append('line')
    .attr("x1", 0)
    .attr("y1", 0)
    .attr("x2", function(d, i) {
        return r_scale(max_value) * Math.cos(angle_slice*i - Math.PI/2); 
    })
    .attr("y2", function(d, i) { 
        return r_scale(max_value) * Math.sin(angle_slice*i - Math.PI/2); 
    })
    .attr('class', 'line')
    .style('stroke', 'black')
    .style('stroke-width', 2);


//Problem area is below
//radial line func which should make the bounds of the data area
var radar_line = d3.lineRadial()
    .radius(function(d) { return r_scale(d.value); })
    .angle(function(d,i) {  return i*angle_slice; });

var data_area = g.selectAll('.radarWrapper')
    .data(data)
    .enter().append('g')
    .attr('class', 'radarWrapper');

//the path around the data area
data_area.append('path')
    .attr('class', 'radarStroke')
    .attr('d', function(d) { return radar_line(d); })
    .style('stroke-width', 2)
    .style('stroke', 'black')
    .style('fill', 'none')
}

The above code shows no errors. Ten axes are drawn properly. However, no path appears. When inspecting the website, all the radarWrappers are there, as well as ten radarStroke elements. But the radar stroke elements do not have any attribute 'd', so for some reason, they are not getting the data.

I have not been able to find any solution to this problem. If I can't I am going to try to just use single line objects, instead of a path object, and connect each data point individually to give the appearance of a path, however I would like to get path working here. Thanks for any help.

I used this example to fix that problem. Seems as though it needs datum instead of data since it is just one line connecting all the dots.

const radarLine = d3.lineRadial()
    .curve(d3.curveCardinalClosed)
    .radius(d => rScale(d.value))
    .angle((d, i) => i * angleSlice);

// Problem area
// g.selectAll(".radarArea")
//     .data(radData)
//     .enter().append("path")
//     .attr("class", "radarArea")
//     .attr("d", (d,i) => radarLine(d, i))
//     .style("fill", 'skyblue');

// Fix
g.append("path")
    .datum(radData)
    .attr("fill", 'skyblue')
    .attr("d", radarLine);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM