单击按钮时动画线条和圆圈

问题描述 投票:0回答:1

我是 d3.js 的新手,我正在努力修复简单绘图上的错误。我基本上是在尝试创建一个“动画棒棒糖图”,可以通过单击按钮进行更新。这是我写的代码: // !preview r2d3 data = structure(list(Name = c("A", "B", "C", "D"), Posterior = c(0.75, 0.45, 0.25, 0.1), Prior = c(0.5, 0.5, 0.55, 0.01)), class = "data.frame", row.names = c(NA, -3L)), dependencies = "d3-jetpack" // set up constants used throughout script const margin = { top: 80, right: 100, bottom: 40, left: 60 }; const plotWidth = 800 - margin.left - margin.right; const plotHeight = 400 - margin.top - margin.bottom; const lineWidth = 4; const mediumText = 18; const bigText = 28; // set width and height of svg element (plot + margin) svg.attr("width", plotWidth + margin.left + margin.right) .attr("height", plotHeight + margin.top + margin.bottom); // create plot group and move it let plotGroup = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // x-axis // x-axis goes from 0 to width of plot let xAxis = d3.scaleLinear() .domain([0, 1]) .range([0, plotWidth]); // y-axis // y-axis goes from height of plot to 0 let yAxis = d3.scaleBand() .domain(data.map(function(d) { return d.Name; })) .padding(1) .range([plotHeight, 0]); // add x-axis to plot // move x axis to bottom of plot (height) // format tick values as date (no comma in e.g. 2,001) // set stroke width and font size plotGroup.append("g") .attr("transform", "translate(0," + plotHeight + ")") .call(d3.axisBottom(xAxis).tickFormat(d3.format(".0%"))) // Format ticks as percentage .attr("stroke-width", lineWidth) .attr("font-size", mediumText); // add y-axis to plot // set stroke width and font size plotGroup.append("g") .call(d3.axisLeft(yAxis)) .attr("stroke-width", lineWidth) .attr("font-size", mediumText); // Lines plotGroup.selectAll("myline") .data(data) .enter() .append("line") .attr("x1", xAxis(0.5)) .attr("x2", function(d) { return xAxis(d.Prior); }) .attr("y1", function(d) { return yAxis(d.Name); }) .attr("y2", function(d) { return yAxis(d.Name); }) .attr("stroke", "grey"); // Circles -> start at priors plotGroup.selectAll("mycircle") .data(data) .enter() .append("circle") .attr("cx", function(d) { return xAxis(d.Prior); }) .attr("cy", function(d) { return yAxis(d.Name); }) .attr("r", "7") .style("fill", "#69b3a2") .attr("stroke", "black"); // Change the X coordinates of line and circle plotGroup.selectAll("circle") .transition() .duration(2000) .attr("cx", function(d) { return xAxis(d.Posterior); }); plotGroup.selectAll("line") .transition() .duration(2000) .attr("x2", function(d) { return xAxis(d.Posterior); }); // Add a dashed vertical line at x = 0.5 plotGroup.append("line") .attr("x1", xAxis(0.5)) .attr("y1", 0) .attr("x2", xAxis(0.5)) .attr("y2", plotHeight) .attr("stroke", "black") .attr("stroke-dasharray", "4"); // Make the line dashed // Add title starting from the left svg.append("text") .attr("x", margin.left) // Start from the left margin .attr("y", margin.top / 2) .attr("text-anchor", "start") // Align to the start (left) .attr("font-size", bigText) .attr("font-family", "Roboto, sans-serif") .attr("font-weight", "bold") .text("Probability of a positive impact"); // Add a button const buttonWidth = 100; const buttonHeight = 30; let buttonText = "Posterior"; // Initial text const button = svg.append("rect") .attr("x", plotWidth + margin.left - buttonWidth) .attr("y", margin.top / 2 - buttonHeight / 2) .attr("width", buttonWidth) .attr("height", buttonHeight) .attr("rx", 5) // rounded corners .attr("ry", 5) .attr("fill", "blue") // Button color .attr("cursor", "pointer") // Change cursor on hover .on("click", buttonClick); const buttonTextElement = svg.append("text") .attr("x", plotWidth + margin.left - buttonWidth / 2) .attr("y", margin.top / 2) .attr("text-anchor", "middle") .attr("alignment-baseline", "middle") .attr("font-family", "Roboto, sans-serif") .attr("font-size", mediumText) .attr("fill", "white") .attr("cursor", "pointer") .text(buttonText) .on("click", buttonClick); // Click event handler for the button function buttonClick() { // Toggle between "Posterior" and "Prior" buttonText = (buttonText === "Posterior") ? "Prior" : "Posterior"; buttonTextElement.text(buttonText); // Update x-coordinates of circles based on the button text plotGroup.selectAll("circle") .transition() .duration(2000) .attr("cx", function(d) { return xAxis(buttonText === "Posterior" ? d.Posterior : d.Prior); }); // Update x2-coordinates of lines based on the button text plotGroup.selectAll("line") .transition() .duration(2000) .attr("x2", function(d) { return xAxis(buttonText === "Posterior" ? d.Posterior : d.Prior); }); }

如下图所示,圆圈移动正确,但我不知道如何使线条随之移动。

d3.js htmlwidgets r2d3
1个回答
0
投票

const data = [{"Name": "A", "Prior": 0.5, "Posterior": 0.75},{"Name": "B", "Prior":0.5, "Posterior": 0.45},{"Name": "C", "Prior":0.55, "Posterior": 0.25},{"Name": "D", "Prior":0.01, "Posterior": 0.1}] // set up constants used throughout script const margin = { top: 80, right: 100, bottom: 40, left: 60 }; const plotWidth = 800 - margin.left - margin.right; const plotHeight = 400 - margin.top - margin.bottom; const lineWidth = 4; const mediumText = 18; const bigText = 28; // set width and height of svg element (plot + margin) var svg = d3.select("#my_dataviz") .append("svg") .attr("width", plotWidth + margin.left + margin.right) .attr("height", plotHeight + margin.top + margin.bottom); // create plot group and move it let plotGroup = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // x-axis // x-axis goes from 0 to width of plot let xAxis = d3.scaleLinear() .domain([0, 1]) .range([0, plotWidth]); // y-axis // y-axis goes from height of plot to 0 let yAxis = d3.scaleBand() .domain(data.map(function(d) { return d.Name; })) .padding(1) .range([plotHeight, 0]); // add x-axis to plot // move x axis to bottom of plot (height) // format tick values as date (no comma in e.g. 2,001) // set stroke width and font size plotGroup.append("g") .attr("transform", "translate(0," + plotHeight + ")") .call(d3.axisBottom(xAxis).tickFormat(d3.format(".0%"))) // Format ticks as percentage .attr("stroke-width", lineWidth) .attr("font-size", mediumText); // add y-axis to plot // set stroke width and font size plotGroup.append("g") .call(d3.axisLeft(yAxis)) .attr("stroke-width", lineWidth) .attr("font-size", mediumText); // Lines plotGroup.selectAll("myline") .data(data) .enter() .append("line") .attr("class", "line") .attr("x1", xAxis(0.5)) .attr("x2", function(d) { return xAxis(d.Prior); }) .attr("y1", function(d) { return yAxis(d.Name); }) .attr("y2", function(d) { return yAxis(d.Name); }) .attr("stroke", "grey"); // Circles -> start at priors plotGroup.selectAll("mycircle") .data(data) .enter() .append("circle") .attr("cx", function(d) { return xAxis(d.Prior); }) .attr("cy", function(d) { return yAxis(d.Name); }) .attr("r", "7") .style("fill", "#69b3a2") .attr("stroke", "black"); // Change the X coordinates of line and circle plotGroup.selectAll("circle") .transition() .duration(2000) .attr("cx", function(d) { return xAxis(d.Posterior); }); plotGroup.selectAll("line") .transition() .duration(2000) .attr("x2", function(d) { return xAxis(d.Posterior); }); // Add a dashed vertical line at x = 0.5 plotGroup.append("line") .attr("x1", xAxis(0.5)) .attr("y1", 0) .attr("x2", xAxis(0.5)) .attr("y2", plotHeight) .attr("stroke", "black") .attr("stroke-dasharray", "4"); // Make the line dashed // Add title starting from the left svg.append("text") .attr("x", margin.left) // Start from the left margin .attr("y", margin.top / 2) .attr("text-anchor", "start") // Align to the start (left) .attr("font-size", bigText) .attr("font-family", "Roboto, sans-serif") .attr("font-weight", "bold") .text("Probability of a positive impact"); // Add a button const buttonWidth = 100; const buttonHeight = 30; let buttonText = "Posterior"; // Initial text const button = svg.append("rect") .attr("x", plotWidth + margin.left - buttonWidth) .attr("y", margin.top / 2 - buttonHeight / 2) .attr("width", buttonWidth) .attr("height", buttonHeight) .attr("rx", 5) // rounded corners .attr("ry", 5) .attr("fill", "blue") // Button color .attr("cursor", "pointer") // Change cursor on hover .on("click", buttonClick); const buttonTextElement = svg.append("text") .attr("x", plotWidth + margin.left - buttonWidth / 2) .attr("y", margin.top / 2) .attr("text-anchor", "middle") .attr("alignment-baseline", "middle") .attr("font-family", "Roboto, sans-serif") .attr("font-size", mediumText) .attr("fill", "white") .attr("cursor", "pointer") .text(buttonText) .on("click", buttonClick); // Click event handler for the button function buttonClick() { // Toggle between "Posterior" and "Prior" buttonText = (buttonText === "Posterior") ? "Prior" : "Posterior"; buttonTextElement.text(buttonText); // Update x-coordinates of circles based on the button text plotGroup.selectAll("circle") .transition() .duration(2000) .attr("cx", function(d) {return buttonText === "Posterior" ? xAxis(d.Posterior) : xAxis(d.Prior); }); // Update x2-coordinates of lines based on the button text plotGroup.selectAll("line.line") .transition() .duration(2000) .attr("x2", function(d) {return buttonText === "Posterior" ? xAxis(d.Posterior) : xAxis(d.Prior); }); }
<script src="https://d3js.org/d3.v7.min.js"></script>

<div id="my_dataviz"></div>

© www.soinside.com 2019 - 2024. All rights reserved.