我想为某些给定点绘制带插值的曲线。在这里,这些点表示太阳能电池板可以产生多少太阳能,因此每天每小时有一点阳光。点数可能会根据一年中的月份而有所不同(例如,12月份为10点,6月份为16点,因为这些月份每天的太阳分别为10小时和16小时)。
直到这里一切都很好,但现在我们想要在你看到图形的那一天的小时添加太阳图像。为此,我创建了2行:一行在当前小时之前,一行之后,并将太阳图像放在当前小时位置。 6月看起来像是16点,下午1点:
看起来很好。问题是当点数较少时,当前小时之前和之后的点之间的空间更大,并且图形太大。这是1月9日上午10点(错误的图形渲染):
(在两个图像中,底部的结束/开始时间是静态的)
我希望留给太阳的空白始终是一样的。
我尝试过各种各样的事情:
如果有人知道如何正确地完成这项工作,那就太棒了。此外,我可能已经错过了一些显而易见的事情,或者对这个问题采取了错误的方式,但经过3天的思考,我有点超载哈哈。感谢您阅读
答案 0 :(得分:1)
解决此问题的一个方法是使用svg掩码。
像这里解释的那样:"SVG clipPath to clip the *outer content out",你可以创建一个掩码来创建一个"非显示区域"你应用它的元素。换句话说,我创建了一个带有圆圈的面具,该圆圈一直处于太阳位置,隐藏了圆圈内部的曲线部分。
答案 1 :(得分:1)
听起来你有答案,但我会提出一个不同的方法。使用stroke-dasharray
听起来非常容易解决。这是一个快速演示:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
var line = d3.line()
.curve(d3.curveCardinal)
.x(function(d) {
return d[0];
})
.y(function(d) {
return d[1];
});
var data = [[10,450], [250, 50], [490, 450]];
var p = svg.append("path")
.datum(data)
.attr("d", line)
.style("stroke", "orange")
.style("stroke-width", "5px")
.style("fill", "none");
var l = p.node().getTotalLength(),
sunSpace = l / 12;
function createSpace(){
var sunPos = Math.random() * l;
p.attr("stroke-dasharray", (sunPos - sunSpace/2) + "," + sunSpace + "," + l);
}
createSpace();
setInterval(createSpace, 1000);
</script>
</body>
</html>
&#13;
评论的编辑
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<svg width="500" height="500"></svg>
<script>
var svg = d3.select("svg"),
margin = {
top: 20,
right: 20,
bottom: 30,
left: 50
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var y = d3.scaleLinear()
.rangeRound([height, 0])
.domain([0, 10]);
var x = d3.scaleLinear()
.rangeRound([0, width])
.domain([0, 10]);
var line = d3.line()
.curve(d3.curveCardinal)
.x(function(d) {
return x(d[0]);
})
.y(function(d) {
return y(d[1]);
});
var data = [
[1, 1],
[5, 9],
[9, 1]
];
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
var p = g.append("path")
.datum(data)
.attr("d", line)
.style("stroke", "orange")
.style("stroke-width", "5px")
.style("fill", "none");
var pathLength = p.node().getTotalLength(),
sunSpace = pathLength / 12;
function createSpace() {
var sunPos = x(3);
var beginning = 0,
end = pathLength,
target;
while (true) {
target = Math.floor((beginning + end) / 2);
pos = p.node().getPointAtLength(target);
if ((target === end || target === beginning) && pos.x !== sunPos) {
break;
}
if (pos.x > sunPos) end = target;
else if (pos.x < sunPos) beginning = target;
else break; //position found
}
p.attr("stroke-dasharray", (target - sunSpace/2) + "," + sunSpace + "," + pathLength);
}
createSpace();
</script>
</body>
</html>
&#13;
答案 2 :(得分:-1)
你可能会过度思考它。您是否考虑过绘制整条线并在太阳图标周围加上一个白色圆圈?只要你在线后绘制图标,它就会留下适当的空间。
答案 3 :(得分:-1)
您应该能够将数据与渲染模型分开。您没有包含代码,因此您的具体解决方案会有所不同。但一般的想法是,您将实际数据转换为更适合您的渲染需求的内容。例如:
{{1}}
现在,你可以在第一个段应该结束的路径上有精确的点,应该渲染图标,第二个段应该开始。