繁体   English   中英

创建在一行上显示 Y 位置的工具提示 (d3.js)

[英]Create a tooltip that displays Y-position on a line (d3.js)

我设法沿着一条线拖着一个滑雪者。 最后一个重要步骤是创建一个工具提示,当我将他拖到线上时,它会计算滑雪者的 Y 位置。 假设线的顶部对应于 100 米,线的底部对应于 0。这可能吗? 如果是这样,我怎样才能做到这一点?

拖放滑雪者

 const height = 500; const width = 960; const skierIconSvg = 'https://image.flaticon.com/icons/svg/94/94150.svg'; const [p1, p2, p3] = [ [width / 3, 213], [(2 * width) / 3, 300], [width / 2, 132], ]; const svg = d3.select('svg'); const line = svg.append('line').attr('stroke', 'black'); const projection = svg .append('circle') .attr('r', 5) .attr('stroke', 'red') .attr('fill', 'none'); const g = svg .append('g') .attr('cursor', 'move') .attr('pointer-events', 'all') .attr('stroke', 'transparent') .attr('stroke-width', 30); const skier = g .append('image') .attr('id', 'skier') .datum(p3) .attr('href', skierIconSvg) .attr('width', 100) .attr('height', 100) .attr('transform', 'translate(-50, 40)') .call( d3 .drag() .subject(([x, y]) => ({ x, y, })) .on('drag', dragged) ); // create a tooltip update(); function dragged(d) { d[0] = d3.event.x; d[1] = d3.event.y; update(); } function update() { const t = (width + height) / distance(p1, p2); const l1 = interpolate(p1, p2, t); const l2 = interpolate(p2, p1, t); const p = interpolate(p1, p2, project(p1, p2, p3)); projection.attr('cx', p[0]).attr('cy', p[1]); line.attr('x1', l1[0]).attr('y1', l1[1]); line.attr('x2', l2[0]).attr('y2', l2[1]); skier.attr('x', (d) => d[0]).attr('y', (d) => d[1]); } function distance([x1, y1], [x2, y2]) { return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); } function interpolate([x1, y1], [x2, y2], t) { return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t]; } function project([x1, y1], [x2, y2], [x3, y3]) { const x21 = x2 - x1, y21 = y2 - y1; const x31 = x3 - x1, y31 = y3 - y1; return (x31 * x21 + y31 * y21) / (x21 * x21 + y21 * y21); }
 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script src="https://d3js.org/d3.v5.js"></script> <script src="https://d3js.org/d3-path.v1.min.js"></script> <script src="https://d3js.org/d3-shape.v1.min.js"></script> <script src="https://d3js.org/d3-scale.v3.min.js"></script> <script src="https://d3js.org/d3-axis.v1.min.js"></script> <script src="https://d3js.org/d3-dispatch.v1.min.js"></script> <script src="https://d3js.org/d3-selection.v1.min.js"></script> <link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@300&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap" rel="stylesheet" /> <style> * { font-family: 'Amatic SC', cursive; text-align: center; } h1 { font-size: 50px; } p { font-size: 20px; } path { fill: none; stroke: #000; stroke-width: 4px; } circle { fill: steelblue; stroke: #fff; stroke-width: 3px; } </style> </head> <body> <h1>Forsøk på å lage en tutorial i JavaScript og D3.js</h1> <svg width="960" height="500"></svg> <script src="main.js"></script> </body> </html>

是的,这是很有可能的,因为当您要更新p (投影)和p2 (右下点)的属性时,您就知道它们的属性,这是显示它的最佳时机。

不过,与您的上一个问题相比,似乎确实删除了其他要点,因此很难将它们用作参考点。 这意味着从技术上讲,滑雪者可以超越 100 米高甚至低于 0 米。

我使用toFixed()来格式化数字,但是如果您愿意,您可以轻松地使用d3-format

 const height = 500; const width = 960; const skierIconSvg = 'https://image.flaticon.com/icons/svg/94/94150.svg'; const [p1, p2, p3] = [ [width / 3, 213], [(2 * width) / 3, 300], [width / 2, 132], ]; const svg = d3.select('svg'); const line = svg.append('line').attr('stroke', 'black'); // Store a reference to the span we're going to update const skierHeight = d3.select("#skier-height"); const projection = svg .append('circle') .attr('r', 5) .attr('stroke', 'red') .attr('fill', 'none'); const g = svg .append('g') .attr('cursor', 'move') .attr('pointer-events', 'all') .attr('stroke', 'transparent') .attr('stroke-width', 30); const skier = g .append('image') .attr('id', 'skier') .datum(p3) .attr('href', skierIconSvg) .attr('width', 100) .attr('height', 100) .attr('transform', 'translate(-50, 40)') .call( d3 .drag() .subject(([x, y]) => ({ x, y, })) .on('drag', dragged) ); // create a tooltip update(); function dragged(d) { d[0] = d3.event.x; d[1] = d3.event.y; update(); } function update() { const t = (width + height) / distance(p1, p2); const l1 = interpolate(p1, p2, t); const l2 = interpolate(p2, p1, t); const p = interpolate(p1, p2, project(p1, p2, p3)); projection.attr('cx', p[0]).attr('cy', p[1]); line.attr('x1', l1[0]).attr('y1', l1[1]); line.attr('x2', l2[0]).attr('y2', l2[1]); skier.attr('x', (d) => d[0]).attr('y', (d) => d[1]); skierHeight.text(`${getHeight(p, p1, p2).toFixed(2)} metres`); } function distance([x1, y1], [x2, y2]) { return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); } function interpolate([x1, y1], [x2, y2], t) { return [x1 + (x2 - x1) * t, y1 + (y2 - y1) * t]; } function project([x1, y1], [x2, y2], [x3, y3]) { const x21 = x2 - x1, y21 = y2 - y1; const x31 = x3 - x1, y31 = y3 - y1; return (x31 * x21 + y31 * y21) / (x21 * x21 + y21 * y21); } function getHeight([xp, yp], [x1, y1], [x2, y2]) { // Note that y is counted from top to bottom, so higher y means // a point is actually lower. // First, the total height is 100 metres. const pxPerMeter = (y2 - y1) / 100; // Calculate the height diff in pixels const heightDiffPx = (y2 - yp); // Now transform it to meters return heightDiffPx / pxPerMeter; }
 * { font-family: 'Amatic SC', cursive; text-align: center; } h1 { font-size: 50px; } p { font-size: 20px; } path { fill: none; stroke: #000; stroke-width: 4px; } circle { fill: steelblue; stroke: #fff; stroke-width: 3px; }
 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <script src="https://d3js.org/d3.v5.js"></script> <script src="https://d3js.org/d3-path.v1.min.js"></script> <script src="https://d3js.org/d3-shape.v1.min.js"></script> <script src="https://d3js.org/d3-scale.v3.min.js"></script> <script src="https://d3js.org/d3-axis.v1.min.js"></script> <script src="https://d3js.org/d3-dispatch.v1.min.js"></script> <script src="https://d3js.org/d3-selection.v1.min.js"></script> <link href="https://fonts.googleapis.com/css2?family=Inconsolata:wght@300&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css2?family=Amatic+SC:wght@700&display=swap" rel="stylesheet" /> </head> <body> <h1>Forsøk på å lage en tutorial i JavaScript og D3.js</h1> <h2>Height: <span id="skier-height"></span></h2> <svg width="960" height="500"></svg> <script src="main.js"></script> </body> </html>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM