Last active
December 24, 2015 20:19
-
-
Save estk/6856958 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Radar chart</title> | |
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> | |
<style> | |
body { | |
font: 10px sans-serif; | |
} | |
.axis + .axis g text { | |
display: none; | |
} | |
.chart { | |
margin: auto; | |
text-align:center; | |
} | |
</style> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="RadarChart.js" charset="utf-8"></script> | |
</head> | |
<body> | |
<div class="chart"></div> | |
<script src="script.js"></script> | |
</body> | |
</html> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Practically all this code comes from https://github.com/alangrafu/radar-chart-d3 | |
//I only made some additions and aesthetic adjustments to make the chart look better | |
//(of course, that is only my point of view) | |
//Such as a better placement of the titles at each line end, | |
//adding numbers that reflect what each circular level stands for | |
//Not placing the last level and slight differences in color | |
// | |
//For a bit of extra information check the blog about it: | |
//http://nbremer.blogspot.nl/2013/09/making-d3-radar-chart-look-bit-better.html | |
// | |
var RadarChart = { | |
draw: function(id, d, options){ | |
var cfg = { | |
radius: 10, | |
w: 600, | |
h: 600, | |
rotate: 0, | |
factor: 1, | |
factorLegend: 0.85, | |
levels: 3, | |
maxValue: 0, | |
radians: 2 * Math.PI, | |
opacityArea: 0.5, | |
opacityFill: 0.7, | |
ToRight: 5, | |
TranslateX: 80, | |
TranslateY: 30, | |
ExtraWidthX: 100, | |
ExtraWidthY: 100, | |
color: d3.scale.category10() | |
}; | |
if('undefined' !== typeof options){ | |
for(var i in options){ | |
if('undefined' !== typeof options[i]){ | |
cfg[i] = options[i]; | |
} | |
} | |
} | |
cfg.maxValue = Math.max(cfg.maxValue, d3.max(d, function(i){return d3.max(i.map(function(o){return o.value;}))})); | |
var allAxis = (d[0].map(function(i, j){return i.axis;})); | |
var total = allAxis.length; | |
var radius = cfg.factor*Math.min(cfg.w/2, cfg.h/2); | |
var Format = d3.format('%'); | |
d3.select(id).select("svg").remove(); | |
function getXCoord(i) { | |
return cfg.w/2*(1-cfg.factor*Math.sin((i*cfg.radians)/total)); | |
} | |
function getYCoord(i) { | |
return cfg.h/2*(1-cfg.factor*Math.cos((i*cfg.radians)/total)); | |
} | |
var g = d3.select(id) | |
.append("svg") | |
.attr("width", cfg.w+cfg.ExtraWidthX) | |
.attr("height", cfg.h+cfg.ExtraWidthY) | |
.append("g") | |
.attr("transform", "translate(" + cfg.TranslateX + "," + cfg.TranslateY + ")"+" rotate("+cfg.rotate +','+(cfg.w/2)+','+cfg.h/2+')'); | |
var tooltip; | |
//Circular segments | |
for(var j=0; j<cfg.levels-1; j++){ | |
var levelFactor = cfg.factor*radius*((j+1)/cfg.levels); | |
g.selectAll(".levels") | |
.data(allAxis) | |
.enter() | |
.append("svg:line") | |
.attr("x1", function(d, i){return levelFactor*(1-cfg.factor*Math.sin(i*cfg.radians/total));}) | |
.attr("y1", function(d, i){return levelFactor*(1-cfg.factor*Math.cos(i*cfg.radians/total));}) | |
.attr("x2", function(d, i){return levelFactor*(1-cfg.factor*Math.sin((i+1)*cfg.radians/total));}) | |
.attr("y2", function(d, i){return levelFactor*(1-cfg.factor*Math.cos((i+1)*cfg.radians/total));}) | |
.attr("class", "line") | |
.style("stroke", "grey") | |
.style("stroke-opacity", "0.75") | |
.style("stroke-width", "0.3px") | |
.attr("transform", "translate(" + (cfg.w/2-levelFactor) + ", " + (cfg.h/2-levelFactor) + ")"); | |
} | |
series = 0; | |
var axis = g.selectAll(".axis") | |
.data(allAxis) | |
.enter() | |
.append("g") | |
.attr("class", "axis"); | |
axis.append("line") | |
.attr("x1", cfg.w/2) | |
.attr("y1", cfg.h/2) | |
.attr("x2", function(d, i){return getXCoord(i);}) | |
.attr("y2", function(d, i){return getYCoord(i);}) | |
.attr("class", "line") | |
.style("stroke", "grey") | |
.style("stroke-width", "1px"); | |
axis.append("text") | |
.attr("class", "legend") | |
.text(function(d){return d}) | |
.style("font-family", "sans-serif") | |
.style("font-size", "11px") | |
.attr("text-anchor", "middle") | |
.attr("dy", "1.5em") | |
.attr("transform", function(d, i){ | |
var x = getXCoord(i)-60*Math.sin(i*cfg.radians/total); | |
var y = getYCoord(i)-20*Math.cos(i*cfg.radians/total); | |
return "translate(0, -10) rotate(" + -cfg.rotate + ',' + x +','+ y +')'; | |
}) | |
.attr("x", function(d, i){return getXCoord(i)-60*Math.sin(i*cfg.radians/total);}) | |
.attr("y", function(d, i){return getYCoord(i)-20*Math.cos(i*cfg.radians/total);}); | |
d.forEach(function(y, x){ | |
dataValues = []; | |
g.selectAll(".nodes") | |
.data(y, function(j, i){ | |
dataValues.push([ | |
cfg.w/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)), | |
cfg.h/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)) | |
]); | |
}); | |
dataValues.push(dataValues[0]); | |
g.selectAll(".area") | |
.data([dataValues]) | |
.enter() | |
.append("polygon") | |
.attr("class", "radar-chart-serie"+series) | |
.style("stroke-width", "2px") | |
.style("stroke", cfg.color(series)) | |
.attr("points",function(d) { | |
var str=""; | |
for(var pti=0;pti<d.length;pti++){ | |
str=str+d[pti][0]+","+d[pti][1]+" "; | |
} | |
return str; | |
}) | |
.style("fill", function(j, i){return cfg.color(series)}) | |
.style("fill-opacity", cfg.opacityArea) | |
.on('mouseover', function (d){ | |
z = "polygon."+d3.select(this).attr("class"); | |
g.selectAll("polygon") | |
.transition(200) | |
.style("fill-opacity", 0.1); | |
g.selectAll(z) | |
.transition(200) | |
.style("fill-opacity", cfg.opacityFill); | |
}) | |
.on('mouseout', function(){ | |
g.selectAll("polygon") | |
.transition(400) | |
.style("fill-opacity", cfg.opacityArea); | |
}); | |
series++; | |
}); | |
series=0; | |
d.forEach(function(y, x){ | |
g.selectAll(".nodes") | |
.data(y).enter() | |
.append("svg:circle") | |
.attr("class", "radar-chart-serie"+series) | |
.attr('r', cfg.radius) | |
.attr("alt", function(j){return Math.max(j.value, 0)}) | |
.attr("cx", function(j, i){ | |
dataValues.push([ | |
cfg.w/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)), | |
cfg.h/2*(1-(parseFloat(Math.max(j.value, 0))/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)) | |
]); | |
return cfg.w/2*(1-(Math.max(j.value, 0)/cfg.maxValue)*cfg.factor*Math.sin(i*cfg.radians/total)); | |
}) | |
.attr("cy", function(j, i){ | |
return cfg.h/2*(1-(Math.max(j.value, 0)/cfg.maxValue)*cfg.factor*Math.cos(i*cfg.radians/total)); | |
}) | |
.attr("data-id", function(j){return j.axis}) | |
.style("fill", cfg.color(series)).style("fill-opacity", cfg.opacityFill) | |
.on('mouseover', function (d, i){ | |
newX = parseFloat(d3.select(this).attr('cx'))-30*Math.sin(i*cfg.radians/total); | |
newY = parseFloat(d3.select(this).attr('cy'))-30*Math.cos(i*cfg.radians/total); | |
tooltip | |
.attr('x', newX) | |
.attr('y', newY) | |
.attr("text-anchor", "middle") | |
.attr("transform", function(d, i){ | |
return "rotate(" + -cfg.rotate + ',' + newX +','+ newY +')'; | |
}) | |
.text(Format(d.value)) | |
.transition(200) | |
.style('opacity', 1); | |
z = "polygon."+d3.select(this).attr("class"); | |
g.selectAll("polygon") | |
.transition(200) | |
.style("fill-opacity", 0.1); | |
g.selectAll(z) | |
.transition(200) | |
.style("fill-opacity", cfg.opacityFill); | |
}) | |
.on('mouseout', function(){ | |
tooltip | |
.transition(200) | |
.style('opacity', 0); | |
g.selectAll("polygon") | |
.transition(200) | |
.style("fill-opacity", cfg.opacityArea); | |
}) | |
.append("svg:title") | |
.text(function(j){return Math.max(j.value, 0)}); | |
series++; | |
}); | |
//Tooltip | |
tooltip = g.append('text') | |
.style('opacity', 0) | |
.style('font-family', 'sans-serif') | |
.style('font-size', '13px'); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d3.select(self.frameElement).style("height", "900px"); | |
var colorscale = d3.scale.category10(); | |
// Data | |
d = [ | |
[{ axis: "Novelty", value: .75}, | |
{ axis:"Originiality", value: .45}, | |
{ axis:"Multidimentionality", value: .3}, | |
{ axis:"Density", value: .2}, | |
{ axis:"Functionality", value: .8}, | |
{ axis:"Abstraction", value: .9}, | |
{ axis:"Redundancy", value: .25}, | |
{ axis:"Familiarity", value: .65}, | |
{ axis:"Unidimensionality", value: .7}, | |
{ axis:"Lightness", value: .8}, | |
{ axis:"Decoration", value: .2}, | |
{ axis:"Figuration", value: .1}] | |
]; | |
//Options for the Radar chart, other than default | |
var config = { | |
w: 600, | |
h: 600, | |
rotate: 75, | |
maxValue: 1, | |
levels: 0, | |
factor: .925, | |
opacityArea: .2, | |
opacityFill: .2, | |
ExtraWidthX: 200 | |
} | |
RadarChart.draw(".chart", d, config); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment