我希望就如何在我拥有的d3 /传单地图上的同一数据集(但两个不同的属性)上实现多个范围滑块过滤器获得一些建议。
我希望能够使用范围滑块按日期过滤地图上的点,并使用另一个范围滑块按“大小”过滤地图上的点。目前,我进行此设置的方法仅适用于按日期过滤。本质上,当实例化时间滑块时,它会从一个函数传入不透明度值,该函数可以将点的不透明度动态设置为零,从而将其滤除。这是基本代码:
//Build time-slider in HTML
<div id="sliderContainer">
<input id="timeslide-leaflet" type="range" min="0" max="25" value="0" step="1" /><br>
//Define years for time slider
var inputValue = null;
var years = ["1993","1994","","","" ];
//load in data
SFData.forEach(function(d) {
var coords = d.geometry.coordinates
console.log(coords)
d.latLong = new L.LatLng(coords[1],
coords[0]);
})
//draw map circles
var feature = mapG.selectAll("circle")
.data(SFData)
.enter().append("circle")
.attr("class", 'features')
//if time-slider moved, call update function
d3.select("#timeslide-leaflet").on("input", function() {
update(+this.value);
});
//Update function sets feature's opacity and can filter by making invisible
function update(value) {
document.getElementById("range-leaflet").innerHTML=years[value];
inputValue = years[value];
d3.selectAll(".features")
.attr("opacity", dateMatch)
}
function dateMatch(data, value) {
//do some internal calculations based on my data
if (yearInt <= inputValueInt && yearExpirationInt >= inputValueInt) {
return ".7";
} else {
return "0"; //return opacity 0 for data that should be filtered out
};
}
我希望能够以类似的方式在不同的属性(大小)上过滤相同的数据。我可以轻松创建另一个时间滑块-但是如何将另一个返回的不透明度值传递给地图要素.attr(“ opacity”)?本质上,我可以编写与dateMatch()类似的函数,该函数按大小进行过滤,我不确定如何将返回的不透明度值传递回地图要素,因为dateMatch()已经传递了值。
谢谢!
答案 0 :(得分:-1)
使功能链接不透明
d3.selectAll(".features")
.attr("opacity", calcOpacity);
function calcOpacity(d) {
var opacity = dateOpacity(d, 1);
return c2Opacity(d, opacity);
}
function dateOpacity(d, opacity) {
if (opacity === 0.0) return opacity;
// calcs
return (yearInt <= inputValueInt && yearExpirationInt >= inputValueInt) ? 0.7 : 0.0;
}
function c2Opacity(d, opacity) {
if (opacity === 0.0) return opacity;
// calcs
return Math.random() < 0.5 ? 0.7 : 0.0;
}
修改
我已经删除了DiamondJoe12对此答案的编辑,并放置了一个片段,该片段使用2个滑块来过滤图表中的圆圈。
滑块提供所需的year
和size
值,我看不出使用查找数组的原因。
滑块的最低值被用作通过所有特定过滤器的标记。
该片段显示了一个svg,其中包含500个不同大小和不同年份数据的圆圈。
var svgWidth = 500, svgHeight = 500;
var svg = d3.select("body")
.append("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
var color = d3.scaleOrdinal(d3.schemeCategory10);
var x = d3.scaleLinear().domain([-0.1, 1.1]).range([0, svgWidth]);
var y = d3.scaleLinear().domain([-0.1, 1.1]).range([0, svgHeight]);
var data = d3.range(500).map(i => ({x:Math.random(), y:Math.random(),
year: 1993 + Math.floor(Math.random()*26),
size: 4 + Math.floor(Math.random()*7) }));
svg.selectAll(".features")
.data(data)
.enter()
.append("circle")
.attr("class", "features")
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
.attr("r", d => d.size)
.attr("fill", (d, i) => color(i));
//if time-slider moved, call update function
d3.select("#timeslide-leaflet").on("input", function() {
update();
});
d3.select("#sizeslide-leaflet").on("input", function() {
update();
});
update();
//Update function sets feature's opacity and can filter by making invisible
function update() {
var year = +document.getElementById("timeslide-leaflet").value;
year = year === 1992 ? 0 : year;
document.getElementById("time-leaflet").innerHTML = year === 0 ? "All" : year;
var size = +document.getElementById("sizeslide-leaflet").value;
size = size === 3 ? 0 : size;
document.getElementById("size-leaflet").innerHTML = size === 0 ? "All" : size;
svg.selectAll(".features")
.transition()
.duration(200)
.attr("opacity", d => calcOpacity(d, year, size) );
}
function calcOpacity(d, year, size) {
var opacity = dateOpacity(d, year, 1);
return sizeOpacity(d, size, opacity);
}
function dateOpacity(d, year, opacity) {
if (opacity === 0.0) return opacity;
if (year === 0) return opacity; // All pass
return (d.year === year) ? 0.7 : 0.0;
}
function sizeOpacity(d, size, opacity) {
if (opacity === 0.0) return opacity;
if (size === 0) return opacity; // All pass
return d.size === size ? 0.7 : 0.0;
}
.features {
stroke:black;
stroke-width:0.5;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="sliderContainer">
<input id="timeslide-leaflet" type="range" min="1992" max="2018" value="1992" step="1" /><br/>
<input id="sizeslide-leaflet" type="range" min="3" max="10" value="3" step="1" />
</div>
<div>
<div>Year: <span id="time-leaflet"></span></div>
<div>Size: <span id="size-leaflet"></span></div>
</div>