在 d3js 中绘制线条会导致 d3.v5.min.js:2 错误: <path> 属性 d:预期数量



我有一个双 y 轴图表,我想在其中显示总分的条形图和平均分的线条。 玩完之后,我已经配置了所有内容,除了无法显示的行。

我收到控制台错误d3.v5.min.js:2 Error: <path> attribute d: Expected number, "MNaN,189.02173913…".所以我认为我的lineFunction有问题,但我看不出是什么,它应该返回 x 和 y 值来绘制线条。 我用这个页面作为灵感

我已经在这里和这里检查了类似答案的解决方案,但我的Average变量已经是一个数字,所以在我的情况下这似乎没问题。

我错过了什么?

我的代码:

//// VERTICAL BAR CHART WITH SVG AND NAMES SINGLE X AND DUAL Y AXES
		// Create data array of values to visualize
		var dataArray = [{ "Player": "John Doe", "Points": 23, "Average": 4.5 }, { "Player": "Jane Doe", "Points": 13, "Average": 2.3 }, { "Player": "Mary Jane", "Points": 21, "Average": 1.5 }, { "Player": "Debasis Das", "Points": 14, "Average": 5.7 }, { "Player": "Nishant", "Points": 37, "Average": 5.9 }, { "Player": "Mark", "Points": 15, "Average": 6.2 }, { "Player": "Andrew", "Points": 18, "Average": 1.2 }, { "Player": "Simon", "Points": 34, "Average": 3.1 }, { "Player": "Lisa", "Points": 30, "Average": 9.2 }, { "Player": "Marga", "Points": 20, "Average": 7.8 }];
		// Create variable for the SVG
		var canvas = d3.select(".v5chart").append("g").attr("transform", "translate(20,30)");
		var canvasWidth = 500;
		var maxValue = d3.max(dataArray, function (d) { return d.Points; });
		var maxValue2 = d3.max(dataArray, function (d) { return d.Average; });
		//console.error("maxValue2:" + maxValue2);
		var canvasHeight = maxValue * 10;
		var canvasHeight2 = maxValue2 * 10;
		//make sure y-axes are equal in height
		if (canvasHeight > canvasHeight2) {canvasHeight2 = canvasHeight;}
		else if (canvasHeight < canvasHeight2) {canvasHeight = canvasHeight2;}
		var heightScale = d3.scaleLinear()
			.domain([0, d3.max(dataArray, function (d) { return d.Points; })])
			.range([canvasHeight, 0]); //use max value (37) * 10
		var y_axis = d3.axisLeft()
			.scale(heightScale);
		var heightScale2 = d3.scaleLinear()
			.domain([0, d3.max(dataArray, function (d) { return d.Average; })])
			.range([canvasHeight2, 0]); 
		var y_axis2 = d3.axisRight()
			.scale(heightScale2);
		//band settings x axis
		var xScale = d3.scaleBand()
			.domain(dataArray.map(function (d) { return d.Player; }))
			.range([0, canvasWidth]).padding([0.1]);
		var x_Axis = d3.axisBottom(xScale);
		// create bars
		canvas.selectAll("rect")
			.data(dataArray)
			.enter().append("rect")
			.attr("class", "bar")
			.attr("height", function (d, i) { return (d.Points * 10) })
			.attr("width", xScale.bandwidth())
			.attr("x", function (d, i) { return xScale(d.Player); })
			.attr("y", function (d, i) { return canvasHeight - (d.Points * 10) });
		// text for in vertical bars
		canvas.selectAll("text")
			.data(dataArray)
			.enter().append("text")
			.text(function (d) { return d.Points })
			.attr("text-anchor", "middle")
			.attr("class", "text")
			.attr("x", function (d, i) { return (xScale(d.Player) + xScale.bandwidth() / 2); })
			.attr("y", function (d, i) { return canvasHeight + 20 - (d.Points * 10) });

		var yScale = d3.scaleLinear()
			.domain([0, maxValue2]) // input 
			.range([canvasHeight2, 0]); // output
		var lineFunction = d3.line()
			.x(function (d, i) { return xScale(i); }) // set the x values for the line generator
			.y(function (d, i) { return yScale(d.Average); }) // set the y values for the line generator 
			.curve(d3.curveMonotoneX); // apply smoothing to the line
		
		// 4. Call the y axis in a group tag
		canvas.append("g")
			.attr("class", "y axis")
			.call(d3.axisRight(yScale)) // Create an axis component with d3.axisLeft
			.attr("transform", "translate(" + canvasWidth + ",0)")
			.append("text")
			.attr("fill", "#000")
			.attr("transform", "rotate(-90)")
			.attr("y", 6)
			.attr("dy", "-1em")
			.attr("text-anchor", "end")
			.text("Average");
		canvas.append("path")
			.attr("class", "line")
			.attr("d", lineFunction(dataArray));
canvas.selectAll(".dot")
.data(dataArray)
.enter().append("circle") // Uses the enter().append() method
.attr("class", "dot") // Assign a class for styling
.attr("cx", function (d, i) { return xScale(d.Player) })
.attr("cy", function (d) { return yScale(d.Average) })
.attr("r", 5)
.on("mouseover", function (a, b, c) {
console.log(a)
//this.attr('class', 'focus')
})
.on("mouseout", function () { })
.append("text")
.attr("text-anchor", "middle")
.text(function (d) {
return d.Average;
});
	 
		//y axis 1 settings
		canvas.append("g")
			.attr("transform", "translate(0,0)")
			.call(y_axis)
			.append("text")
			.attr("fill", "#000")
			.attr("transform", "rotate(-90)")
			.attr("y", 6)
			.attr("dy", "0.71em")
			.attr("text-anchor", "end")
			.text("Points");
		//x axis
		canvas.append("g")
			.attr("transform", "translate(0," + canvasHeight + ")")
			.call(x_Axis)
			.selectAll("text")
			.attr("x", 30)
			.attr("transform", function (d) {
				return "rotate(65)"
			});
/*Rectangle bar class styling*/
	.bar {
	  fill: #0080FF
	}
	.bar:hover {
	  fill: #003366
	}
	/*Text class styling*/
	.text {
	  fill: white;
	  font-family: sans-serif
	}
	/* Style the lines by removing the fill and applying a stroke */
	.line {
		fill: none;
		stroke: #ffab00;
		stroke-width: 3;
	}
	  
	.overlay {
	  fill: none;
	  pointer-events: all;
	}
	/* Style the dots by assigning a fill and stroke */
	.dot {
		fill: #ffab00;
		stroke: #fff;
	}
	  
	  .focus circle {
	  fill: none;
	  stroke: steelblue;
	}
<script src="https://d3js.org/d3.v5.min.js"></script>
	<svg class="v5chart" width="960" height="500"></svg>

在 d3 的文档中;

域中的第一个元素将映射到第一个波段,即 第二个域值到第二个波段,依此类推。域值为 内部存储在从字符串化值到索引的映射中;这 然后使用所得指数来确定波段。因此,一个乐队 scale的值必须强制为字符串,并且字符串化 域值的版本唯一标识相应的 乐队。如果未指定域,则此方法返回当前 域。

但是在 xScale 函数中,您将 dataArray 的映射值与 Player 键一起使用。我的意思是,如果您想从xScale函数中获取任何正确的数字,则必须将其与"John Doe","Jane Doe"等播放器键一起使用。

总之,如果将 line 函数更改为此函数,您将看到结果:

var lineFunction = d3.line()
.x(function (d, i) { return xScale(d.Player); /*return xScale(i)*/ })
.y(function (d, i) { return yScale(d.Average); })
.curve(d3.curveMonotoneX);

我想,您想在此之后解决对齐问题。这取决于你。

相关内容

最新更新