Skip to content

Instantly share code, notes, and snippets.

@JoseJuan81
Last active April 15, 2020 22:32
Show Gist options
  • Save JoseJuan81/f56cb3485eb1144f0e91c089e5a0c476 to your computer and use it in GitHub Desktop.
Save JoseJuan81/f56cb3485eb1144f0e91c089e5a0c476 to your computer and use it in GitHub Desktop.
Radar
license: mit
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=Baloo+Paaji+2:wght@500&display=swap" rel="stylesheet">
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
div { align-items:center;display:flex;justify-content:flex-start;height:100%;width:100%; padding-left:20px }
.intense:hover {
opacity: 0.8;
}
</style>
</head>
<body>
<div>
<svg>
</svg>
</div>
<script>
const width = 400;
const height = 400;
const scale = [25, 50, 75, 100];
const data = [
{ sala:50, cocina:80, cuarto:100, patio: 65, bano: 16 },
]
const margin = { top:30, left:30, bottom:30, right:30 };
const angle = 270;
class Geometry {
constructor(data, offset) {
this.x = null;
this.y = null;
this.data = data;
this.axisNames = Object.keys(data[0]);
this.axisNumber = this.axisNames.length;
this.theta = 360 / this.axisNumber;
this.maxRadius = null;
this.radarValues = Object.values(data[0]);
this.graphicRadius = null;
this.startTheta = 0;
this.offset = offset;
}
get axis() {
return this.axisNames;
}
get center() {
return { x: this.x / 2, y: this.y / 2 };
}
get radius() {
return this.graphicRadius;
}
get axisLabels() {
return this.axisNames;
}
selectedItem(index) {
const values = Object.values(this.data[index]);
return (i) => values[i];
}
rad(index) {
return this.deg(index) * (Math.PI / 180);
}
deg(index) {
return (index * this.theta + this.startTheta);
}
init(x, y, angle) {
this.x = x;
this.y = y;
this.maxRadius = y / 2;
this.graphicRadius = y / 2 - this.offset;
this.startTheta = angle;
}
}
const radar = new Geometry(data, margin.left + margin.right);
radar.init(width, height, angle);
// crear svg
const svg = d3.select('svg')
.attr('width', width)
.attr('height', height);
// crear instancias
let circle = svg.append('g');
let axis = svg.append('g');
let majorCircle = svg.append('g')
let axisNames = svg.append('g')
let poligon = svg.append('g')
// crear círculos del radar o campo del radar
circle = circle.selectAll('circle')
.data(scale.reverse())
.enter().append('circle')
.attr('cx', radar.center.x)
.attr('cy', radar.center.y)
.attr('r', function (d) {
const noPercentage = (d / 100);
return radar.radius* noPercentage;
})
.attr('fill', 'lightgray')
.attr('stroke', 'gray')
.attr('opacity', 0.25);
// Ejes
axis = axis.selectAll('line')
.data(radar.axis)
.enter().append('line')
.attr('x1', radar.center.x)
.attr('x2', function (d, index) {
const rad = radar.rad(index);
const x = radar.radius * Math.cos(rad);
return x + radar.center.x;
})
.attr('y1', radar.center.y)
.attr('y2', function (d, index) {
const rad = radar.rad(index);
const y = radar.radius * Math.sin(rad);
return y + radar.center.y;
})
.attr('stroke', 'gray')
.attr('stroke-width', 1);
// Circulo para nombre de ejes
majorCircle = majorCircle.append('circle')
.attr('cx', radar.center.x)
.attr('cy', radar.center.y)
.attr('r', radar.maxRadius - margin.top)
.attr('fill', 'transparent')
.attr('id', 'circle-path');
// ejes
radar.axis.map((a, index) => {
const rad = radar.rad(index);
const deg = radar.deg(index) + 90;
const x = (radar.maxRadius - margin.left) * Math.cos(rad);
const y = (radar.maxRadius - margin.bottom) * Math.sin(rad);
const coox = x + radar.center.x;
const cooy = y + radar.center.y;
const text = axisNames.append('text')
.attr('x', coox)
.attr('y', cooy)
.attr('font-family', 'Verdana')
.attr('text-anchor', 'middle')
.attr('transform', 'rotate(' + deg + ')')
.attr('transform-origin', `${coox} ${cooy}`)
.text(radar.axisLabels[index]);
});
// crear polígonos
poligon = poligon.selectAll('polygon')
.data(data)
.enter().append('polygon')
.attr('fill', d => d3.schemePaired[Math.ceil(Math.random() * 12)])
.attr('opacity', 0.45)
.attr('class', 'intense')
.attr('points', function (d, index) {
const points = [];
const values = radar.selectedItem(index);
for (let i = 0; i < radar.axisNumber; i += 1) {
const rad = radar.rad(i);
const val = values(i);
const r = radar.radius;
const x = r * val / 100 * Math.cos(rad) + radar.center.x;
const y = r * val / 100 * Math.sin(rad) + radar.center.y;
points.push(x, y)
}
return points;
})
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment