如何使用匿名函数正确调用D3.js中的其他函数
How to use anonymous functions to call other functions in D3.js correctly
我正在尝试使用一个匿名函数来调用另外两个函数,但实际上无法正常工作。我在 SO: Calling two functions on same click event with d3.js 上关注了这个问题,但仍然无法正确解决。
期望的效果是我的条形图同时改变条形和颜色。这就是我正在尝试的:
我要调用的两个函数:
function selectDataset(d) {
let value = this.value;
if (value == "total") {
change(datasetTotal);
} else if (value == "option1") {
change(datasetOption1);
} else if (value == "option2") {
change(datasetOption2);
}
}
function changeColor(d) {
let value = this.value;
if (value == "total") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'blue')
} else if (value == "option1") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'red')
} else if (value == "option2") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'yellow')
}
}
我的匿名函数:
d3.selectAll("input").on("change", function(d) {
selectDataset.call(this, d);
changeColor.call(this, d);
});
这是我的更改功能:
function change(dataset) {
y.domain(dataset.map(function(d) {
return d.label;
}));
x.domain([0, d3.max(dataset, function(d) {
return d.value;
})]);
svg.select(".y.axis").remove();
svg.select(".x.axis").remove();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(0)")
.attr("x", 50)
.attr("dx", ".1em")
.style("text-anchor", "end")
.text("Option %");
var bar = svg.selectAll(".bar")
.data(dataset, function(d) {
return d.label;
});
var barExit = bar.exit().remove();
var barEnter = bar.enter()
.append("g")
.attr("class", "bar");
var barRects = barEnter.append("rect")
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth());
var barTexts = barEnter.append("text")
.attr("x", function(d) {
return x(d.value) + 10;
})
.attr("y", function(d) {
return y(d.label) + y.bandwidth() / 2;
})
.attr("dy", ".35em")
.text(function(d) {
return d.value;
});
var barRectUpdate = bar.select("rect")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth());
var barTextsUpdate = bar.select("text")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(d.value) + 10;
})
.attr("y", function(d) {
return y(d.label) + y.bandwidth() / 2;
})
.attr("dy", ".35em")
.text(function(d) {
return d.value;
});
};
我的图表
var margin = {
top: (parseInt(d3.select('.area-heat-cool').style('height'), 10) / 20),
right: (parseInt(d3.select('.area-heat-cool').style('width'), 10) / 20),
bottom: (parseInt(d3.select('.area-heat-cool').style('height'), 10) / 20),
left: (parseInt(d3.select('.area-heat-cool').style('width'), 10) / 5)
},
width = parseInt(d3.select('.area-heat-cool').style('width'), 10) - margin.left - margin.right,
height = parseInt(d3.select('.area-heat-cool').style('height'), 10) - margin.top - margin.bottom;
var div = d3.select(".area-heat-cool").append("div").attr("class", "toolTip");
var y = d3.scaleBand()
.rangeRound([height, 0], .2, 0.5)
.paddingInner(0.1);
var x = d3.scaleLinear()
.range([0, width]);
var xAxis = d3.axisBottom()
.scale(x);
var yAxis = d3.axisLeft()
.scale(y);
var svg = d3.select(".area-heat-cool").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
d3.select("input[value=\"total\"]").property("checked", true);
change(datasetTotal);
数据集示例:
data1 = [{label: "example 1", value: 156}
{label: "example 2", value: 189}
{label: "example 3", value: 234}
{label: "example 4", value: 345}
{label: "example 5", value: 346}
{label: "example 6", value: 456}
{label: "example 7", value: 489}
{label: "example 8", value: 567}];
data2 = [{label: "example 1", value: 23}
{label: "example 2", value: 211}
{label: "example 3", value: 45}
{label: "example 4", value: 64}
{label: "example 5", value: 95}
{label: "example 6", value: 32}
{label: "example 7", value: 0}
{label: "example 8", value: 234}];
还有我的单选按钮:
<div class="area-heat-cool">
<form>
<label><input type="radio" name="dataset" id="dataset" value="total" checked> Total</label>
<label><input type="radio" name="dataset" id="dataset" value="option1"> Option 1</label>
<label><input type="radio" name="dataset" id="dataset" value="option2"> Option 2</label>
</form>
</div>
当我这样做时,它以某种方式弄乱了我的数据。颜色发生变化,但条形图不再移动到正确的位置。我没有收到任何错误,但行为不是预期的。
我是否正确使用了这个匿名函数?很感谢任何形式的帮助。非常感谢
触发事件时,您对 rect
元素应用了两个转换。但是,这样做时,第二个转换会覆盖第一个转换。
然后在 change
函数中应用第一个转换,您可以在其中更改 rect
元素的大小。当 change
函数 returns 时,您立即调用 changeColor
函数,该函数 select 包含所有 rect
元素并应用不同的过渡来更改元素的颜色rect
个元素。因此颜色转换会覆盖尺寸转换。
要解决这个问题,您可以在一个地方将所有过渡应用到相同的元素。在我的示例中,我将把 changeColor 函数中的代码放入 change
函数中。
首先,更改 change
函数声明以启用包括无线电 select 值:
function change(dataset, optionSelect) {
// code not shown
}
然后,更新 change
中执行 rect
元素转换的代码:
var barRectUpdate = bar.select("rect")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth())
.style('fill', function () {
if (optionSelect === "total") {
return 'blue'
} else if (optionSelect === "option1") {
return 'red'
} else if (optionSelect === "option2") {
return 'yellow'
}
});
更新 selectDataset
函数以在调用 change
:
时包含无线电 select 值
function selectDataset(d) {
let value = this.value;
if (value === "total") {
change(datasetTotal, value);
} else if (value === "option1") {
change(datasetOption1, value);
} else if (value === "option2") {
change(datasetOption2, value);
}
}
删除对 changeColor
函数的调用:
d3.selectAll("input").on("change", function(d) {
selectDataset.call(this, d);
});
最后,完全删除 changeColor
函数。
需要考虑的其他几件事:
id
属性应该是唯一的。现在所有 input
元素都具有相同的 id。
- 考虑将
selectDataset
和 changeColor
中的字符串值检查更改为 ===
而不是 ==
,以避免在比较值时发生意外类型转换:Difference between == and === in JavaScript
- 当您之后不使用这些变量时,您不需要将所有 D3 操作存储在变量中。例如。
bar.select("rect")
与 var barRectUpdate = bar.select("rect")
一样有效。
希望对您有所帮助!
我正在尝试使用一个匿名函数来调用另外两个函数,但实际上无法正常工作。我在 SO: Calling two functions on same click event with d3.js 上关注了这个问题,但仍然无法正确解决。
期望的效果是我的条形图同时改变条形和颜色。这就是我正在尝试的:
我要调用的两个函数:
function selectDataset(d) {
let value = this.value;
if (value == "total") {
change(datasetTotal);
} else if (value == "option1") {
change(datasetOption1);
} else if (value == "option2") {
change(datasetOption2);
}
}
function changeColor(d) {
let value = this.value;
if (value == "total") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'blue')
} else if (value == "option1") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'red')
} else if (value == "option2") {
d3.selectAll("rect")
.transition()
.duration(2000)
.style("fill", 'yellow')
}
}
我的匿名函数:
d3.selectAll("input").on("change", function(d) {
selectDataset.call(this, d);
changeColor.call(this, d);
});
这是我的更改功能:
function change(dataset) {
y.domain(dataset.map(function(d) {
return d.label;
}));
x.domain([0, d3.max(dataset, function(d) {
return d.value;
})]);
svg.select(".y.axis").remove();
svg.select(".x.axis").remove();
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(0)")
.attr("x", 50)
.attr("dx", ".1em")
.style("text-anchor", "end")
.text("Option %");
var bar = svg.selectAll(".bar")
.data(dataset, function(d) {
return d.label;
});
var barExit = bar.exit().remove();
var barEnter = bar.enter()
.append("g")
.attr("class", "bar");
var barRects = barEnter.append("rect")
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth());
var barTexts = barEnter.append("text")
.attr("x", function(d) {
return x(d.value) + 10;
})
.attr("y", function(d) {
return y(d.label) + y.bandwidth() / 2;
})
.attr("dy", ".35em")
.text(function(d) {
return d.value;
});
var barRectUpdate = bar.select("rect")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth());
var barTextsUpdate = bar.select("text")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(d.value) + 10;
})
.attr("y", function(d) {
return y(d.label) + y.bandwidth() / 2;
})
.attr("dy", ".35em")
.text(function(d) {
return d.value;
});
};
我的图表
var margin = {
top: (parseInt(d3.select('.area-heat-cool').style('height'), 10) / 20),
right: (parseInt(d3.select('.area-heat-cool').style('width'), 10) / 20),
bottom: (parseInt(d3.select('.area-heat-cool').style('height'), 10) / 20),
left: (parseInt(d3.select('.area-heat-cool').style('width'), 10) / 5)
},
width = parseInt(d3.select('.area-heat-cool').style('width'), 10) - margin.left - margin.right,
height = parseInt(d3.select('.area-heat-cool').style('height'), 10) - margin.top - margin.bottom;
var div = d3.select(".area-heat-cool").append("div").attr("class", "toolTip");
var y = d3.scaleBand()
.rangeRound([height, 0], .2, 0.5)
.paddingInner(0.1);
var x = d3.scaleLinear()
.range([0, width]);
var xAxis = d3.axisBottom()
.scale(x);
var yAxis = d3.axisLeft()
.scale(y);
var svg = d3.select(".area-heat-cool").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
d3.select("input[value=\"total\"]").property("checked", true);
change(datasetTotal);
数据集示例:
data1 = [{label: "example 1", value: 156}
{label: "example 2", value: 189}
{label: "example 3", value: 234}
{label: "example 4", value: 345}
{label: "example 5", value: 346}
{label: "example 6", value: 456}
{label: "example 7", value: 489}
{label: "example 8", value: 567}];
data2 = [{label: "example 1", value: 23}
{label: "example 2", value: 211}
{label: "example 3", value: 45}
{label: "example 4", value: 64}
{label: "example 5", value: 95}
{label: "example 6", value: 32}
{label: "example 7", value: 0}
{label: "example 8", value: 234}];
还有我的单选按钮:
<div class="area-heat-cool">
<form>
<label><input type="radio" name="dataset" id="dataset" value="total" checked> Total</label>
<label><input type="radio" name="dataset" id="dataset" value="option1"> Option 1</label>
<label><input type="radio" name="dataset" id="dataset" value="option2"> Option 2</label>
</form>
</div>
当我这样做时,它以某种方式弄乱了我的数据。颜色发生变化,但条形图不再移动到正确的位置。我没有收到任何错误,但行为不是预期的。
我是否正确使用了这个匿名函数?很感谢任何形式的帮助。非常感谢
触发事件时,您对 rect
元素应用了两个转换。但是,这样做时,第二个转换会覆盖第一个转换。
然后在 change
函数中应用第一个转换,您可以在其中更改 rect
元素的大小。当 change
函数 returns 时,您立即调用 changeColor
函数,该函数 select 包含所有 rect
元素并应用不同的过渡来更改元素的颜色rect
个元素。因此颜色转换会覆盖尺寸转换。
要解决这个问题,您可以在一个地方将所有过渡应用到相同的元素。在我的示例中,我将把 changeColor 函数中的代码放入 change
函数中。
首先,更改 change
函数声明以启用包括无线电 select 值:
function change(dataset, optionSelect) {
// code not shown
}
然后,更新 change
中执行 rect
元素转换的代码:
var barRectUpdate = bar.select("rect")
.transition()
.duration(3050)
.attr("x", function(d) {
return x(0);
})
.attr("y", function(d) {
return y(d.label);
})
.attr("width", function(d) {
return x(d.value);
})
.attr("height", y.bandwidth())
.style('fill', function () {
if (optionSelect === "total") {
return 'blue'
} else if (optionSelect === "option1") {
return 'red'
} else if (optionSelect === "option2") {
return 'yellow'
}
});
更新 selectDataset
函数以在调用 change
:
function selectDataset(d) {
let value = this.value;
if (value === "total") {
change(datasetTotal, value);
} else if (value === "option1") {
change(datasetOption1, value);
} else if (value === "option2") {
change(datasetOption2, value);
}
}
删除对 changeColor
函数的调用:
d3.selectAll("input").on("change", function(d) {
selectDataset.call(this, d);
});
最后,完全删除 changeColor
函数。
需要考虑的其他几件事:
id
属性应该是唯一的。现在所有input
元素都具有相同的 id。- 考虑将
selectDataset
和changeColor
中的字符串值检查更改为===
而不是==
,以避免在比较值时发生意外类型转换:Difference between == and === in JavaScript - 当您之后不使用这些变量时,您不需要将所有 D3 操作存储在变量中。例如。
bar.select("rect")
与var barRectUpdate = bar.select("rect")
一样有效。
希望对您有所帮助!