Hello there,
What else to change in the code to achieve a simple goal of mine as to recover mouse position to work?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatable" content="ie=edge">
<title>Document</title>
</head>
<div id="container"></div>
<body>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script type="module">
// Curved line declaration
const data = [{xpoint: 10, ypoint: 0.2},
{xpoint: 4, ypoint: 1},
{xpoint: 3, ypoint: 2},
{xpoint: 2, ypoint: 3},
{xpoint: 1, ypoint: 10}];
// Declare the chart dimensions and margins.
const width = 640;
const height = 400;
const marginTop = 20;
const marginRight = 20;
const marginBottom = 30;
const marginLeft = 40;
// Declare the x (horizontal position) scale.
const x = d3.scaleLog()
.domain([0.2, 60])
.range([marginLeft, width - marginRight]);
// Declare the y (vertical position) scale.
const y = d3.scaleLog()
.domain([0.1, 100])
.range([height - marginBottom, marginTop]);
// Declare the line generator.
const line = d3.line()
.x((d) => x(d.xpoint))
.y((d) => y(d.ypoint))
.curve(d3.curveCatmullRom.alpha(0.5));
// Create the SVG container.
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
// Add the x-axis.
svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(d3.axisBottom(x));
// Add the y-axis.
svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(d3.axisLeft(y));
// Append a path for the line.
svg.append("path")
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1.5)
.attr("d", line(data));
// This allows to find the closest X index of the mouse:
const bisect = d3.bisector(function(d) { return d.xpoint; }).left;
// Create the circle that travels along the curve of chart
const focus = svg
.append('g')
.append('circle')
.style("fill", "none")
.attr("stroke", "black")
.attr('r', 8.5)
.style("opacity", 0)
// Create the text that travels along the curve of chart
const focusText = svg
.append('g')
.append('text')
.style("opacity", 0)
.attr("text-anchor", "left")
.attr("alignment-baseline", "middle")
// Create a rect on top of the svg area: this rectangle recovers mouse position
svg.append('rect')
.style("fill", "none")
.style("pointer-events", "all")
.attr('width', width)
.attr('height', height)
.on('mouseover', mouseover)
.on('mousemove', mousemove)
.on('mouseout', mouseout);
// What happens when the mouse move -> show the annotations at the right positions.
function mouseover() {
focus.style("opacity", 1)
focusText.style("opacity",1)
};
function mousemove() {
// recover coordinate we need
const x0 = x.invert(d3.pointer(this)[0]);
const i = bisect(data, x0, 1);
const selectedData = d3.select(data[i])
focus
.attr("cx", x(selectedData.xpoint))
.attr("cy", y(selectedData.ypoint))
focusText
.html("x:" + selectedData.xpoint + " - " + "y:" + selectedData.ypoint)
.attr("x", x(selectedData.xpoint)+15)
.attr("y", y(selectedData.ypoint))
};
function mouseout() {
focus.style("opacity", 0)
focusText.style("opacity", 0)
};
// Append the SVG element.
container.append(svg.node());
</script>
</body>
</html>
function mousemove() {
// recover coordinate we need
const x0 = x.invert(d3.pointer(this)[0]);
const i = bisect(data, x0, 1);
const selectedData = d3.select(data[i]) <<<<<< I tried to define the selected line this way and I did not succeed as there is no error and no rectangle of x y data by a circle
focus
.attr("cx", x(selectedData.xpoint))
.attr("cy", y(selectedData.ypoint))
focusText
.html("x:" + selectedData.xpoint + " - " + "y:" + selectedData.ypoint)
.attr("x", x(selectedData.xpoint)+15)
.attr("y", y(selectedData.ypoint))
};
this way data[i] is undefined
const selectedData = data[i]