{
const config = {
width: 600,
height: 350,
margin: { top: 20, right: 20, bottom: 60, left: 50 }
};
const svg = d3.create("svg")
.attr("width", config.width)
.attr("height", config.height)
.style("font-family", "Arial, sans-serif");
const xScaleScatter = d3.scaleLinear()
.domain(d3.extent(datosScatter, d => d.x))
.range([config.margin.left, config.width - config.margin.right]);
const yScaleScatter = d3.scaleLinear()
.domain(d3.extent(datosScatter, d => d.y))
.range([config.height - config.margin.bottom, config.margin.top]);
const colorScale = d3.scaleOrdinal()
.domain(["Tecnología", "Salud", "Educación"])
.range(["#66bb6a", "#fdd835", "#42a5f5"]);
const tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("padding", "10px")
.style("background", "rgba(0,0,0,0.8)")
.style("color", "white")
.style("border-radius", "5px")
.style("pointer-events", "none")
.style("opacity", 0);
svg.selectAll(".dot")
.data(datosScatter)
.enter()
.append("circle")
.attr("class", "dot")
.attr("cx", d => xScaleScatter(d.x))
.attr("cy", d => yScaleScatter(d.y))
.attr("r", 0)
.style("fill", d => colorScale(d.categoria))
.style("stroke", "#2c3e50")
.style("stroke-width", 2)
.style("cursor", "pointer")
.transition()
.duration(800)
.delay((d, i) => i * 100)
.attr("r", 10)
.end().then(() => {
svg.selectAll(".dot")
.on("mouseover", function(event, d) {
d3.select(this)
.transition()
.duration(200)
.attr("r", 14)
.style("stroke-width", 3);
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(`
<strong>${d.nombre}</strong><br/>
Categoría: ${d.categoria}<br/>
X: ${d.x}, Y: ${d.y}
`)
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 28) + "px");
})
.on("mouseout", function(event, d) {
d3.select(this)
.transition()
.duration(200)
.attr("r", 10)
.style("stroke-width", 2);
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
});
svg.append("g")
.attr("transform", `translate(0,${config.height - config.margin.bottom})`)
.call(d3.axisBottom(xScaleScatter));
svg.append("g")
.attr("transform", `translate(${config.margin.left},0)`)
.call(d3.axisLeft(yScaleScatter));
svg.append("text")
.attr("transform", `translate(${config.width/2},${config.height - 10})`)
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("Inversión en Marketing");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - config.margin.left)
.attr("x", 0 - (config.height / 2))
.attr("dy", "1em")
.style("text-anchor", "middle")
.style("font-size", "14px")
.text("ROI (%)");
const legend = svg.selectAll(".legend")
.data(colorScale.domain())
.enter().append("g")
.attr("class", "legend")
.attr("transform", (d, i) => `translate(${config.width - 120},${20 + i * 25})`);
legend.append("circle")
.attr("r", 6)
.style("fill", colorScale);
legend.append("text")
.attr("x", 15)
.attr("dy", ".35em")
.style("text-anchor", "start")
.style("font-size", "12px")
.text(d => d);
return svg.node();
}