Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 120 additions & 122 deletions src/radar-chart.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
var RadarChart = {
const d3 = require('d3');

export const RadarChart = {
defaultConfig: {
containerClass: 'radar-chart',
w: 600,
Expand All @@ -16,7 +18,6 @@ var RadarChart = {
axisText: true,
circles: true,
radius: 5,
open: false,
backgroundTooltipColor: "#555",
backgroundTooltipOpacity: "0.7",
tooltipColor: "white",
Expand All @@ -35,7 +36,7 @@ var RadarChart = {
// default config
var cfg = Object.create(RadarChart.defaultConfig);
function setTooltip(tooltip, msg){
if(msg === false || msg == undefined){
if(msg == false || msg == undefined){
tooltip.classed("visible", 0);
tooltip.select("rect").classed("visible", 0);
}else{
Expand Down Expand Up @@ -63,11 +64,11 @@ var RadarChart = {
selection.each(function(data) {
var container = d3.select(this);
var tooltip = container.selectAll('g.tooltip').data([data[0]]);

var tt = tooltip.enter()
.append('g')
.classed('tooltip', true)

.append('g')
.classed('tooltip', true)
tt.append('rect').classed("tooltip", true);
tt.append('text').classed("tooltip", true);

Expand All @@ -83,7 +84,7 @@ var RadarChart = {
return d3.max(d.axes, function(o){ return o.value; });
}));
maxValue -= cfg.minValue;

var allAxis = data[0].axes.map(function(i, j){ return {name: i.axis, xOffset: (i.xOffset)?i.xOffset:0, yOffset: (i.yOffset)?i.yOffset:0}; });
var total = allAxis.length;
var radius = cfg.factor * Math.min(cfg.w / 2, cfg.h / 2);
Expand Down Expand Up @@ -186,27 +187,27 @@ var RadarChart = {

if(cfg.axisLine) {
axis.select('line')
.attr('x1', cfg.w/2)
.attr('y1', cfg.h/2)
.attr('x2', function(d, i) { return (cfg.w/2-radius2)+getHorizontalPosition(i, radius2, cfg.factor); })
.attr('y2', function(d, i) { return (cfg.h/2-radius2)+getVerticalPosition(i, radius2, cfg.factor); });
.attr('x1', cfg.w/2)
.attr('y1', cfg.h/2)
.attr('x2', function(d, i) { return (cfg.w/2-radius2)+getHorizontalPosition(i, radius2, cfg.factor); })
.attr('y2', function(d, i) { return (cfg.h/2-radius2)+getVerticalPosition(i, radius2, cfg.factor); });
}

if(cfg.axisText) {
axis.select('text')
.attr('class', function(d, i){
var p = getHorizontalPosition(i, 0.5);

return 'legend ' +
((p < 0.4) ? 'left' : ((p > 0.6) ? 'right' : 'middle'));
})
.attr('dy', function(d, i) {
var p = getVerticalPosition(i, 0.5);
return ((p < 0.1) ? '1em' : ((p > 0.9) ? '0' : '0.5em'));
})
.text(function(d) { return d.name; })
.attr('x', function(d, i){ return d.xOffset+ (cfg.w/2-radius2)+getHorizontalPosition(i, radius2, cfg.factorLegend); })
.attr('y', function(d, i){ return d.yOffset+ (cfg.h/2-radius2)+getVerticalPosition(i, radius2, cfg.factorLegend); });
.attr('class', function(d, i){
var p = getHorizontalPosition(i, 0.5);

return 'legend ' +
((p < 0.4) ? 'left' : ((p > 0.6) ? 'right' : 'middle'));
})
.attr('dy', function(d, i) {
var p = getVerticalPosition(i, 0.5);
return ((p < 0.1) ? '1em' : ((p > 0.9) ? '0' : '0.5em'));
})
.text(function(d) { return d.name; })
.attr('x', function(d, i){ return d.xOffset+ (cfg.w/2-radius2)+getHorizontalPosition(i, radius2, cfg.factorLegend); })
.attr('y', function(d, i){ return d.yOffset+ (cfg.h/2-radius2)+getVerticalPosition(i, radius2, cfg.factorLegend); });
}
}

Expand All @@ -219,121 +220,116 @@ var RadarChart = {
});
var polygon = container.selectAll(".area").data(data, cfg.axisJoin);

var polygonType = 'polygon';
if (cfg.open) {
polygonType = 'polyline';
}

polygon.enter().append(polygonType)
.classed({area: 1, 'd3-enter': 1})
.on('mouseover', function (dd){
d3.event.stopPropagation();
container.classed('focus', 1);
d3.select(this).classed('focused', 1);
setTooltip(tooltip, cfg.tooltipFormatClass(dd.className));
})
.on('mouseout', function(){
d3.event.stopPropagation();
container.classed('focus', 0);
d3.select(this).classed('focused', 0);
setTooltip(tooltip, false);
});
polygon.enter().append('polygon')
.classed({area: 1, 'd3-enter': 1})
.on('mouseover', function (dd){
d3.event.stopPropagation();
container.classed('focus', 1);
d3.select(this).classed('focused', 1);
setTooltip(tooltip, cfg.tooltipFormatClass(dd.className));
})
.on('mouseout', function(){
d3.event.stopPropagation();
container.classed('focus', 0);
d3.select(this).classed('focused', 0);
setTooltip(tooltip, false);
});

polygon.exit()
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration)
.remove();
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration)
.remove();

polygon
.each(function(d, i) {
var classed = {'d3-exit': 0}; // if exiting element is being reused
classed['radar-chart-serie' + i] = 1;
if(d.className) {
classed[d.className] = 1;
}
d3.select(this).classed(classed);
})
// styles should only be transitioned with css
.style('stroke', function(d, i) { return cfg.color(i); })
.style('fill', function(d, i) { return cfg.color(i); })
.transition().duration(cfg.transitionDuration)
// svg attrs with js
.attr('points',function(d) {
return d.axes.map(function(p) {
return [p.x, p.y].join(',');
}).join(' ');
})
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});
.each(function(d, i) {
var classed = {'d3-exit': 0}; // if exiting element is being reused
classed['radar-chart-serie' + i] = 1;
if(d.className) {
classed[d.className] = 1;
}
d3.select(this).classed(classed);
})
// styles should only be transitioned with css
.style('stroke', function(d, i) { return cfg.color(i); })
.style('fill', function(d, i) { return cfg.color(i); })
.transition().duration(cfg.transitionDuration)
// svg attrs with js
.attr('points',function(d) {
return d.axes.map(function(p) {
return [p.x, p.y].join(',');
}).join(' ');
})
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});

if(cfg.circles && cfg.radius) {

var circleGroups = container.selectAll('g.circle-group').data(data, cfg.axisJoin);

circleGroups.enter().append('g').classed({'circle-group': 1, 'd3-enter': 1});
circleGroups.exit()
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration).remove();
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration).remove();

circleGroups
.each(function(d) {
var classed = {'d3-exit': 0}; // if exiting element is being reused
if(d.className) {
classed[d.className] = 1;
}
d3.select(this).classed(classed);
})
.transition().duration(cfg.transitionDuration)
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});
.each(function(d) {
var classed = {'d3-exit': 0}; // if exiting element is being reused
if(d.className) {
classed[d.className] = 1;
}
d3.select(this).classed(classed);
})
.transition().duration(cfg.transitionDuration)
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});

var circle = circleGroups.selectAll('.circle').data(function(datum, i) {
return datum.axes.map(function(d) { return [d, i]; });
});

circle.enter().append('circle')
.classed({circle: 1, 'd3-enter': 1})
.on('mouseover', function(dd){
d3.event.stopPropagation();
setTooltip(tooltip, cfg.tooltipFormatValue(dd[0].value));
//container.classed('focus', 1);
//container.select('.area.radar-chart-serie'+dd[1]).classed('focused', 1);
})
.on('mouseout', function(dd){
d3.event.stopPropagation();
setTooltip(tooltip, false);
container.classed('focus', 0);
//container.select('.area.radar-chart-serie'+dd[1]).classed('focused', 0);
//No idea why previous line breaks tooltip hovering area after hoverin point.
});
.classed({circle: 1, 'd3-enter': 1})
.on('mouseover', function(dd){
d3.event.stopPropagation();
setTooltip(tooltip, cfg.tooltipFormatValue(dd[0].value));
//container.classed('focus', 1);
//container.select('.area.radar-chart-serie'+dd[1]).classed('focused', 1);
})
.on('mouseout', function(dd){
d3.event.stopPropagation();
setTooltip(tooltip, false);
container.classed('focus', 0);
//container.select('.area.radar-chart-serie'+dd[1]).classed('focused', 0);
//No idea why previous line breaks tooltip hovering area after hoverin point.
});

circle.exit()
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration).remove();
.classed('d3-exit', 1) // trigger css transition
.transition().duration(cfg.transitionDuration).remove();

circle
.each(function(d) {
var classed = {'d3-exit': 0}; // if exit element reused
classed['radar-chart-serie'+d[1]] = 1;
d3.select(this).classed(classed);
})
// styles should only be transitioned with css
.style('fill', function(d) { return cfg.color(d[1]); })
.transition().duration(cfg.transitionDuration)
// svg attrs with js
.attr('r', cfg.radius)
.attr('cx', function(d) {
return d[0].x;
})
.attr('cy', function(d) {
return d[0].y;
})
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});

.each(function(d) {
var classed = {'d3-exit': 0}; // if exit element reused
classed['radar-chart-serie'+d[1]] = 1;
d3.select(this).classed(classed);
})
// styles should only be transitioned with css
.style('fill', function(d) { return cfg.color(d[1]); })
.transition().duration(cfg.transitionDuration)
// svg attrs with js
.attr('r', cfg.radius)
.attr('cx', function(d) {
return d[0].x;
})
.attr('cy', function(d) {
return d[0].y;
})
.each('start', function() {
d3.select(this).classed('d3-enter', 0); // trigger css transition
});
//Make sure layer order is correct
var poly_node = polygon.node();
poly_node.parentNode.appendChild(poly_node);
Expand Down Expand Up @@ -371,10 +367,12 @@ var RadarChart = {

d3.select(id).select('svg').remove();
d3.select(id)
.append("svg")
.attr("width", cfg.w)
.attr("height", cfg.h)
.datum(d)
.call(chart);
.append("svg")
.attr("width", cfg.w)
.attr("height", cfg.h)
.datum(d)
.call(chart);
}
};
var module = { exports: RadarChart };