在將轉換方法與事件結合使用時,我無法理解 d3.js/javascript 的操作順序。為了說明我的普遍困惑,我創建了一個 div,單擊它后會改變它的高度,還有一個段落使用它的邊界框來獲取它的文本值的高度:
dataArr = [{data:50, id:'a', val : true}]
function update(){
divs = d3.select('body').selectAll('div')
.data(dataArr)
.join('div')
.text("click me")
.style('background-color','red')
.attr('id', d=> d.id)
.on('click', function(_,d){
let heightVal = 20
if(d.val){
heightVal = 50
d.val = false
}
else{
d.val = true
}
d3.select(this).transition().duration(200).style('height',heightVal 'px').text(heightVal)
update()
})
d3.select('body').selectAll('p').data([true]).join('p').text(function(d){
return 'height: ' d3.select('#a').node().getBoundingClientRect().height
})
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="UTF-8">
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
</body>
根據我的理解,在簡單的點擊后段落的文本應該在過渡完成后具有值,但是值的文本來自過渡開始之前。有人可以幫我理解為什么會發生這種情況以及如何解決這個問題嗎?
uj5u.com熱心網友回復:
您的更新函式會啟動一個轉換,該轉換開始與下一個代碼塊同時(異步)運行,該代碼塊通過測量當時呈現的邊界框來確定 div 的高度。
由于過渡還沒有完成,實際上只是剛剛開始,過渡完成后你得到的不是元素未來的大小,而是剛開始時的大小,也就是原來的大小,或者非常接近原始值。這就是為什么“值的文本來自轉換開始之前” - 您在轉換開始時測量了大小(如果您的計算機非常慢,您可能會在轉換早期而不是開始時看到值)。
如果您希望等到過渡結束來測量尺寸,您可以使用transition.on("end", function() { ... }):
顯示代碼片段
dataArr = [{data:50, id:'a', val : true}]
function update(){
divs = d3.select('body').selectAll('div')
.data(dataArr)
.join('div')
.text("click me")
.style('background-color','red')
.attr('id', d=> d.id)
.on('click', function(_,d){
let heightVal = 20
if(d.val){
heightVal = 50
d.val = false
}
else{
d.val = true
}
d3.select(this).transition().duration(200).style('height',heightVal 'px').text(heightVal)
.on("end", function() {
d3.select('body').selectAll('p').data([true]).join('p').text(function(d){
return 'height: ' d3.select('#a').node().getBoundingClientRect().height
})
})
update()
})
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="UTF-8">
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
</body>
當然,在過渡完成之前,這不會更新文本。如果您想要在轉換完成之前獲得最終值,您可以訪問它的最簡單方法是直接使用提供給轉換的值:heightVal并將文本值設定為此而不是使用 getBoundingClientRect。由于 getBoundingClientRect 在給定時刻測量大小,它不能用于在未來某個時間點測量某物的大小。
為了進行比較,框中的文本會在使用 transition.text() 時立即更新,這將“對于每個選定的元素,在轉換開始時將文本內容設定為指定的目標值 ( docs )。”
您可以讓框中的文本轉換為:
顯示代碼片段
dataArr = [{data:50, id:'a', val : true}]
function update(){
divs = d3.select('body').selectAll('div')
.data(dataArr)
.join('div')
.text("click me")
.style('background-color','red')
.attr('id', d=> d.id)
.on('click', function(_,d){
let heightVal = 20
if(d.val){
heightVal = 50
d.val = false
}
else{
d.val = true
}
d3.select(this).transition().duration(200).style('height',heightVal 'px').textTween(()=>d3.interpolateRound(heightVal == 20 ? 50 : 20, heightVal))
.on("end", function() {
d3.select('body').selectAll('p').data([true]).join('p').text(function(d){
return 'height: ' d3.select('#a').node().getBoundingClientRect().height
})
})
update()
})
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="UTF-8">
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
</body>
您還可以在過渡期間使用 getBoundingClientRect 獲取框外文本的大小:
顯示代碼片段
dataArr = [{data:50, id:'a', val : true}]
function update(){
divs = d3.select('body').selectAll('div')
.data(dataArr)
.join('div')
.text("click me")
.style('background-color','red')
.attr('id', d=> d.id)
.on('click', function(_,d){
let heightVal = 20
if(d.val){
heightVal = 50
d.val = false
}
else{
d.val = true
}
d3.select(this)
.transition()
.duration(200)
.style('height',heightVal 'px')
.attrTween("anything", function() {
return function() {
d3.select('body')
.selectAll('p')
.data([true])
.join('p')
.text(function(d){
return 'height: ' d3.select('#a').node().getBoundingClientRect().height
})
}
})
.duration(2000);
update()
})
}
update()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<!DOCTYPE html>
<meta charset="UTF-8">
<body>
<script src="https://d3js.org/d3.v7.min.js"></script>
</body>
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/478558.html
標籤:javascript d3.js
上一篇:Apache服務的搭建與配置
