Public
Edited
Mar 23, 2023
Insert cell
Insert cell
Insert cell
margin = ({ top: 0, right: 5, bottom: 10, left: 5 })
Insert cell
width = window.innerWidth - margin.left - margin.right
Insert cell
height = 420 - margin.top - margin.bottom
Insert cell
<style>

body {
margin: 0;
}
.observablehq{
margin: 0px;
}
.observablehq > style:only-child:before {
content: none;
}

h1 {
font-family:'Roboto', sans-serif;
font-weight:700;
font-size:1.5em;
fill:"#333333";
}

h2 {
font-family:'Roboto', sans-serif;
font-weight:400;
font-size:1em;
fill:"#333333";
opacity:0.9;
max-width: 620px;
padding-bottom: 10px;
}
h3 {
font-family:'Roboto', sans-serif;
font-weight:400;
font-size:0.8em;
fill:"#333333";
opacity:0.6;
max-width: 620px;
}

hr.hr_style {
border-top: 1px solid "#333333";
width:24px;
background: none;
margin: 0.3rem 0;
}

hr.hr_style2 {
border-top: 1px solid "#333333";
width:24px;
background: none;
padding: 0rem 0;
margin: 0.3rem;
margin-bottom: 20px;
}

.pa2 {
display: none !important;
}
.links {
stroke: #999;
stroke-opacity: 0.6;
stroke-width: 1px;
}

.text_titulo{
font-weight: 800;
font-size: 13px;
}

text {
pointer-events: none;
fill: #333;
font-size: 10.5px;
font-family: 'Roboto', sans-serif;
letter-spacing: 1px;
text-anchor: middle;
}

svg{
border:none;
}

div.tooltip {
position: absolute;
background-color: white;
max-width: 150px;
height: auto;
padding: 10px;
border-style: solid;
border-radius: 1px;
border-width: 1px;
border-color: "#333333";
pointer-events: none;
font-size: 12px;
font-family: 'Roboto', sans-serif;
letter-spacing: 1px;
}

.leyenda2 {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-size: 14px;
text-align: left;
color: #333333;
display: flex;
opacity:1;
margin-block-start: 0;
}

.leyenda3 {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
font-size: 14px;
text-align: left;
color: #333333;
display: flex;
opacity:1;
margin-bottom:30px;
}

.dot_blue {
height: 10px;
width: 10px;
margin-top:3px;
background-color: #A7C5D8;
border-radius: 50%;
display: inline-block;
}

.dot_red {
height: 10px;
width: 10px;
margin-top:3px;
background-color: #F1BF00;
border-radius: 50%;
display: inline-block;
}

.dot_grey {
height: 10px;
width: 10px;
margin-top:3px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
}
</style>
Insert cell
Insert cell
colorScale = d3
.scaleOrdinal() //=d3.scaleOrdinal(d3.schemeSet2)
.domain(["Salud", "Laboral", "titulo"])
.range(["#A7C5D8", "#F1BF00", "#ffffff"])
Insert cell
strength_function = {
if (width < 400) {
return -110;
} else {
return -200;
}
}
Insert cell
//create a simulation for an array of nodes, and compose the desired forces.
simulation = d3
.forceSimulation()
.force(
"link",
d3
.forceLink() // This force provides links between nodes
.id((d) => d.id) // This sets the node id accessor to the specified function. If not specified, will default to the index of a node.
.distance((d) => {
if (width < 400) {
return width / 2.5;
} else {
return width / 3.5;
}
})
)
.force("charge", d3.forceManyBody().strength(strength_function)) // This adds repulsion (if it's negative) between nodes.
.force("center", d3.forceCenter(width / 2, height / 2 + 10)) // This force attracts nodes to the center of the svg area
Insert cell
<h1>Modelo | Priorización de citas</h1>
<hr class="hr_style">
<h2>Algoritmo que estudia los patrones de comportamiento y fraude de bajas.</h2>
<h2 class="leyenda2"><span class="dot_blue"></span>&nbsp;Variables de salud y genéricas &nbsp;&nbsp;<span class="dot_red"></span>&nbsp;Variables laborales</h2>
<h3><img src="https://static.observableusercontent.com/files/00461af558ef75327362004b905184374dce0f450f16867be532765023590d80b1a4d4ad631291e1272df0cc0ed35792a7b9c5a5bc8b4403813887ee06c8bb8f"
" align="left" style="width: 14px; padding-top: 1px;"> &nbsp;Pase sobre los círculos para más información</h3>
Insert cell
Insert cell
myChart = {
const div = html`<div style='max-width: width; overflow-x: hidden; overflow-y: hidden; padding: 0px; margin: 0px;'></div>`;

var tooltip = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);

const svg = d3
.select(div)
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

//appending little triangles, path object, as arrowhead
//The <defs> element is used to store graphical objects that will be used at a later time
//The <marker> element defines the graphic that is to be used for drawing arrowheads or polymarkers on a given <path>, <line>, <polyline> or <polygon> element.
svg
.append("defs")
.append("marker")
.attr("id", "arrowhead")
.attr("viewBox", "-0 -5 10 10") //the bound of the SVG viewport for the current SVG fragment. defines a coordinate system 10 wide and 10 high starting on (0,-5)
.attr("refX", 50) // x coordinate for the reference point of the marker. If circle is bigger, this need to be bigger.
.attr("refY", 0)
.attr("orient", "center")
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("xoverflow", "visible");

//create some data
const dataset = {
nodes: [
{
id: 1,
name: "MODELO ",
teilbereich: "PRIORIZACIÓN DE CITAS",
label: "MODELO",
group: "titulo",
runtime: 700
},
{
id: 2,
name: "",
teilbereich: "Edad",
label: "Edad trabajador a fecha de la baja",
group: "Salud",
runtime: 0
},
{
id: 3,
name: "",
teilbereich: "Diagnóstico",
label: "Diagnóstico médico de la causa de la baja",
group: "Salud",
runtime: 0
},
{
id: 4,
name: "",
teilbereich: "Sexo",
label: "Indicador del sexo del paciente",
group: "Salud",
runtime: 0
},
{
id: 5,
name: "",
teilbereich: "Lugar de residencia",
label: "Lugar de residencia del trabajador",
group: "Salud",
runtime: 0
},
{
id: 6,
name: "",
teilbereich: "Bajas pasadas",
label: "Total de bajas en periodos pasados",
group: "Laboral",
runtime: 0
}
],
links: [
{ source: 1, target: 2 },
{ source: 1, target: 3 },
{ source: 1, target: 4 },
{ source: 1, target: 5 },
{ source: 1, target: 6 }
]
};

console.log("dataset is ...", dataset);

// Initialize the links
const link = svg
.selectAll(".links")
.data(dataset.links)
.enter()
.append("line")
.attr("class", "links")
.attr("marker-end", "url(#arrowhead)"); //The marker-end attribute defines the arrowhead or polymarker that will be drawn at the final vertex of the given shape.

//The <title> element provides an accessible, short-text description of any SVG container element or graphics element.
//Text in a <title> element is not rendered as part of the graphic, but browsers usually display it as a tooltip.
link.append("title").text((d) => d.type);

const edgepaths = svg
.selectAll(".edgepath") //make path go along with the link provide position for link labels
.data(dataset.links)
.enter()
.append("path")
.attr("class", "edgepath")
.attr("fill-opacity", 0)
.attr("stroke-opacity", 0)
.attr("id", function (d, i) {
return "edgepath" + i;
})
.style("pointer-events", "none");

const edgelabels = svg
.selectAll(".edgelabel")
.data(dataset.links)
.enter()
.append("text")
.style("pointer-events", "none")
.attr("class", "edgelabel")
.attr("id", function (d, i) {
return "edgelabel" + i;
})
.attr("font-size", 10)
.attr("fill", "#aaa");

edgelabels
.append("textPath") //To render text along the shape of a <path>, enclose the text in a <textPath> element that has an href attribute with a reference to the <path> element.
.attr("xlink:href", function (d, i) {
return "#edgepath" + i;
})
.style("text-anchor", "middle")
.style("pointer-events", "none")
.attr("startOffset", "50%")
.text((d) => d.type);

// Initialize the nodes
const node = svg
.selectAll(".nodes")
.data(dataset.nodes)
.enter()
.append("g")
.attr("class", "nodes")
.on("mouseover.tooltip", function (d) {
if (d.id != 1) {
tooltip.transition().duration(300).style("opacity", 0.8);
tooltip
.html(d.label)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + 10 + "px");
}
})
.on("mouseout.tooltip", function (d) {
if (d.id != 1) {
tooltip.transition().duration(100).style("opacity", 0);
}
})
.on("mousemove", function () {
tooltip
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + 10 + "px");
})
.call(
d3
.drag() //sets the event listener for the specified typenames and returns the drag behavior.
.on("start", dragstarted) //start - after a new pointer becomes active (on mousedown or touchstart).
.on("drag", dragged) //drag - after an active pointer moves (on mousemove or touchmove).

//.on("end", dragended) //end - after an active pointer becomes inactive (on mouseup, touchend or touchcancel).
);

node
.append("circle")
.attr("r", (d) => {
if (d.id == 1) {
if (width < 400) {
return 60;
} else {
return 80;
}
}
if (d.id != 1) {
return 20;
}
})
.style("stroke", (d) => {
if (d.id == 1) {
return "grey";
} else {
return colorScale(d.group);
}
})
.style("stroke-opacity", (d) => {
if (d.id == 1) {
return 0.3;
} else {
return 0.5;
}
})
.style("stroke-width", (d) => {
if (d.id == 1) {
return 1;
} else {
return 2;
}
})
.style("fill", (d) => {
return "white";
});

// node.append("title").text((d) => d.id + ": " + d.label + " - " + d.group);

node
.append("text")
.attr("class", "text_titulo")
.attr("dy", (d) => {
if (d.id == 1) {
return 0;
} else {
return 5;
}
})
.attr("dx", (d) => {
if (d.id == 1) {
return 0;
} else {
return 0;
}
})
.text((d) => d.name);

node
.append("text")
.attr("dy", (d) => {
if (d.id == 1) {
return 20;
} else {
return 5;
}
})
.attr("dx", (d) => {
if (d.id == 1) {
return 0;
} else {
return 0;
}
})
.text((d) => d.teilbereich);

//Listen for tick events to render the nodes as they update in your Canvas or SVG.
simulation.nodes(dataset.nodes).on("tick", ticked);

simulation.force("link").links(dataset.links);

// This function is run at each iteration of the force algorithm, updating the nodes position (the nodes data array is directly manipulated).
function ticked() {
link
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);

node.attr("transform", (d) => `translate(${d.x},${d.y})`);

edgepaths.attr(
"d",
(d) =>
"M " +
d.source.x +
" " +
d.source.y +
" L " +
d.target.x +
" " +
d.target.y
);
}

//When the drag gesture starts, the targeted node is fixed to the pointer
//The simulation is temporarily “heated” during interaction by setting the target alpha to a non-zero value.
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart(); //sets the current target alpha to the specified number in the range [0,1].
d.fy = d.y; //fx - the node’s fixed x-position. Original is null.
d.fx = d.x; //fy - the node’s fixed y-position. Original is null.
tooltip.style("left", d.x + "px").style("top", d.y + 10 + "px");
}

//When the drag gesture starts, the targeted node is fixed to the pointer
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
tooltip
.style("left", d3.event.x + "px")
.style("top", d3.event.y + 10 + "px");
}

//the targeted node is released when the gesture ends
// function dragended(d) {
// if (!d3.event.active) simulation.alphaTarget(0);
// d.fx = null;
// d.fy = null;

// console.log("dataset after dragged is ...",dataset);
// }

//drawing the legend
/*const legend_g = svg
.selectAll(".legend")
.data(colorScale.domain())
.enter()
.append("g")
.attr("transform", (d, i) => `translate(${width},${i * 20})`);

legend_g
.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 5)
.attr("fill", colorScale);

legend_g
.append("text")
.attr("x", 10)
.attr("y", 5)
.text((d) => d);*/

return div;
}
Insert cell
tooltip = d3
.select("body")
.append("div")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "white")
.attr("class", "tooltip")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more