Built with blockbuilder.org
Last active
April 15, 2020 22:32
-
-
Save JoseJuan81/f56cb3485eb1144f0e91c089e5a0c476 to your computer and use it in GitHub Desktop.
Radar
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
license: mit |
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> | |
<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