Skip to content

Instantly share code, notes, and snippets.

@tobiasburri
Last active March 15, 2016 21:24
Show Gist options
  • Save tobiasburri/58da90571c7457be97ac to your computer and use it in GitHub Desktop.
Save tobiasburri/58da90571c7457be97ac to your computer and use it in GitHub Desktop.
Spider Charts
<!DOCTYPE html>
<meta charset="utf-8">
<script src="http://underscorejs.org/underscore.js"></script>
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
.wrapper {
position: relative;
width:960px;
height:504px;
margin:auto;
}
.sub-wrapper {
width:305px;
position: relative;
}
.left {
float:left;
}
.right{
float:right;
}
.side-element
{
margin-top:15px;
margin-left: 1px;
width:150px;
height:150px;
float:left;
}
.sub-wrapper-central {
width:342px;
margin-left:2px;
position: relative;
height:502px;
float:left;
}
#centralElement {
height:340px;
width:340px;
margin-top:75px;
float:left;
}
</style>
<body>
<div class='wrapper'>
<div class='sub-wrapper left'>
<div class='side-element chart-container' data-key='3'></div>
<div class='side-element chart-container' data-key='4'></div>
<div class='side-element chart-container' data-key='5'></div>
<div class='side-element chart-container' data-key='6'></div>
<div class='side-element chart-container' data-key='7'></div>
<div class='side-element chart-container' data-key='8'></div>
</div>
<div class='sub-wrapper-central'>
<div id='centralElement' class='chart-container' data-key='15'></div>
</div>
<div class='sub-wrapper right'>
<div class='side-element chart-container' data-key='9'> </div>
<div class='side-element chart-container' data-key='10'></div>
<div class='side-element chart-container' data-key='11'></div>
<div class='side-element chart-container' data-key='12'></div>
<div class='side-element chart-container' data-key='13'></div>
<div class='side-element chart-container' data-key='14'></div>
</div>
</div>
<script type="text/javascript">
var polygonContainer = [];
var createPolygonData = function(edges) {
var polygonData = _.range(edges).map(function(i){
var ranNum = Math.random() * 4;
return {'data': ranNum};
})
return polygonData;
};
d3.selectAll('.chart-container')[0].forEach(function(element) {
var
CIRCLE_COORDINATES_COUNT = 3600,
container = d3.select(element),
sizeArray = container.node().getBoundingClientRect(),
height = sizeArray.height,
width = sizeArray.width,
centreX = width/2,
centreY = height/2,
edges = parseInt(container.node().dataset.key);
var svg = d3.select(element)
.append('svg')
.attr('width',height)
.attr('height', width);
var createCircleCoordinates = function(radius){
var
circleCoordinates = {},
xValues = [centreX],
yValues = [centreY],
steps = CIRCLE_COORDINATES_COUNT;
for (var i = 0; i < steps; i++) {
xValues[i] = (centreX + radius * Math.cos(2 * Math.PI * i / steps));
yValues[i] = (centreY + radius * Math.sin(2 * Math.PI * i / steps));
}
circleCoordinates.x = xValues;
circleCoordinates.y = yValues;
return circleCoordinates;
};
var getIndicesForPolygonCoordinates = function(numberOfEdges) {
var interval = Math.ceil(3600/numberOfEdges);
var indices = _.range(0,3600,interval)
if (numberOfEdges % 2 !== 0) {
indices = indices.map( function(i) {
i = (i + 2700) % 3600;
return i;
})
}
return indices;
}
var createObjects = function(circleCoordinates, indices, getCentre) {
var objectContainer = [];
indices.forEach(function(entry,i) {
var obj = {}
var x1 = circleCoordinates['x'][indices[((i + 1) % edges)]];
var y1 = circleCoordinates['y'][indices[((i + 1) % edges)]];
var x2 = circleCoordinates['x'][indices[i]];
var y2 = circleCoordinates['y'][indices[i]];
if(getCentre === true) {
x1 = centreX;
y1 = centreY;
}
obj.x1 = x1;
obj.y1 = y1;
obj.x2 = x2
obj.y2 = y2
objectContainer.push(obj)
})
return objectContainer;
};
var createYScales = function(axisData) {
var yScales = [];
axisData.forEach(function(obj){
var yScale = d3.scale.linear()
.domain([0, 4])
.range([obj.y1, obj.y2]);
yScales.push(yScale)
})
return yScales;
}
var createXScales = function(axisData) {
var xScales = [];
axisData.forEach(function(obj){
var xScale = d3.scale.linear()
.domain([0, 4])
.range([obj.x1, obj.x2]);
xScales.push(xScale)
})
return xScales;
};
/*
var createPolygonData = function(edges) {
var polygonData = _.range(edges).map(function(i){
var ranNum = Math.random() * 4;
return {'data': ranNum};
})
return polygonData;
};
*/
var renderChart = function() {
svg.selectAll('*').remove()
var
radius = width * (2/5),
subRadius = radius /4,
subRadii = _.range(subRadius, subRadius * 4, subRadius),
indices = getIndicesForPolygonCoordinates(edges),
circleCoordinates = createCircleCoordinates(radius),
axisData = createObjects(circleCoordinates, indices, true),
gridData = [];
xScale = createXScales(axisData);
yScale = createYScales(axisData);
gridData.push(axisData);
gridData.push(createObjects(circleCoordinates, indices));
subRadii.forEach( function(subRadius) {
var subRadiusCoordinates = createCircleCoordinates(subRadius);
gridData.push(createObjects(subRadiusCoordinates, indices));
});
gridData.forEach(function(dataEntry) {
svg.selectAll('linePlaceholder')
.data(dataEntry)
.enter()
.append('line')
.attr('x1', function(d) {return d.x1})
.attr('y1', function(d) {return d.y1})
.attr('x2', function(d) {return d.x2})
.attr('y2', function(d) {return d.y2})
.style('stroke', 'gray')
.style('stroke-width',1);
})
polygonData = createPolygonData(edges);
polygon = svg.selectAll("polygonPlaceholder")
.data([polygonData])
.enter()
.append("polygon")
.attr("points",function(d) {
return d.map(function(d,i) {
return [xScale[i](d.data), yScale[i](d.data)].join(",");
}).join(" ");
})
.attr('class', 'polygon')
.attr("stroke","blue")
.attr('fill', 'blue')
.attr('opacity', 0.3)
.attr('stroke-opacity',0.5)
.attr("stroke-width",2);
polygonContainer.push({'polygon':polygon,'edges': edges, 'xScale':xScale, 'yScale':yScale});
};
renderChart();
})
polygonContainer.forEach(function(obj) {
setInterval(function() {
obj.polygon.data([createPolygonData(obj.edges)])
.transition()
.duration(1000)
.attr('fill', 'blue')
.attr("points",function(d) {
return d.map(function(d,i) {
return [obj.xScale[i](d.data), obj.yScale[i](d.data)].join(",");
}).join(" ");
})
}, (Math.random() * 500) + 1000)
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment