2017-04-18 75 views
0

雖然相對位置邏輯,選擇和翻譯聲音乍看之下像分開的問題,在我的具體情況下,你會看到它們是如何相互關聯的。D3相對位置邏輯,選擇和翻譯

建立了我dynamic button appending project,我現在要打transition()效果,即可以追加東西以任何順序,以任何順序刪除它們,如果事情是從頂部排出,底部元素將優雅地滑行到頂部填補空白空間。我只有半功能,問題是我無法找到正確的邏輯來選擇僅當前按鈕事件下面的文本。

跳過邏輯,我只是​​簡單地用selectAll('text')成功地使用了轉換。這隻適用於有2個項目的情況,一旦你追加了3件事情就會變得混亂,因爲它沒有正確的邏輯來辨別哪個過渡。

另一個翻譯問題是關於使按鈕移動。文本轉換很好,但按鈕固執地原地踏步,無論使用.attr('top', new_value).attr('transform', 'translate(' + 0+','+new_value+')')

進入到live example與意見,並從下拉菜單中選擇的事情,單擊要刪除的頂一個,你會明白我的意思。

所以總結起來:

  1. 我怎麼能做出比目前的頂級距離更大的任何文字if()邏輯檢查? (即,如果頁面中的文本元素低於當前頁面)

  2. 如何告訴D3僅選擇具有較大相對位置的文本(在垂直方向上,即在頁面上較低)

  3. 我該如何讓D3翻譯或更新按鈕的top?請注意,我使用的示例是selectAll('button'),但理想情況下我需要更挑剔的選擇。

回答

2

您應該使用數據綁定來實現這一點,請參閱我的代碼中的render()函數。

var margins = { 
 
    top: 200, 
 
    right: 80, 
 
    bottom: 30, 
 
    left: 50 
 
}; 
 

 
var width = 500; 
 
var height = 200; 
 
var itemHeight = 30; 
 

 
var totalWidth = width + margins.left + margins.right; 
 
var totalHeight = height + margins.top + margins.bottom; 
 

 
var y = d3.scaleOrdinal(); 
 

 
var options = [ 
 
    'Add Text', 
 
    'A', 
 
    'B', 
 
    'C', 
 
    'D', 
 
    'E', 
 
    'F', 
 
    'G', 
 
    'H', 
 
    'I', 
 
]; 
 

 

 
d3.select('#choose') 
 
    .on('change', addText) 
 
    .selectAll('option') 
 
    .data(options) 
 
    .enter().append('option') 
 
    .attr('value', function(d) { 
 
    return d; 
 
    }) 
 
    .text(function(d) { 
 
    return d; 
 
    }); 
 

 
var svg = d3.select('body') 
 
    .append('svg') 
 
    .attr('width', totalWidth) 
 
    .attr('height', totalHeight); 
 

 
var graphGroup = svg.append('g') 
 
    .attr('transform', 'translate(' + margins.left + ',' + margins.top + ')'); 
 

 
svg.append('text') 
 
    .text('Mix and Match Text') 
 
    .attr('font-weight', 'bold') 
 
    .attr('x', 15) 
 
    .attr('y', 60) 
 
    .attr('font-size', '24px'); 
 

 
var count = 0; 
 
var intCount = 0; 
 
var textItems = []; 
 

 
function addText() { 
 

 
    var chooseSel = document.getElementById('choose'); 
 
    var choice = chooseSel.options[chooseSel.selectedIndex].value; 
 
    textItems.push(choice); 
 
    render(); 
 
} 
 

 
function removeItem(item) { 
 
textItems.splice(textItems.indexOf(item), 1); 
 
render() 
 

 
} 
 

 
function render() { 
 
    y.range(textItems.map((item, i) => i * itemHeight + 10)).domain(textItems); 
 

 
    var items = graphGroup.selectAll('.item').data(textItems, d => d); 
 
    
 

 
    var enteringItems = items.enter() 
 
    .append('g') 
 
    .attr('class', 'item') 
 
    .attr('opacity', 0) 
 

 

 
    items.merge(enteringItems) 
 
    .transition() 
 
    .attr('opacity', 1) 
 
    .attr('transform', d => `translate(0, ${y(d)})`) 
 
    
 
    items.exit() 
 
    .transition() 
 
    .attr('opacity', 0) 
 
    .remove() 
 

 
    enteringItems 
 
    .append('text') 
 
    .text(d => d) 
 
    .style('text-align', 'center') 
 

 
    enteringItems 
 
    .append('text') 
 
    .attr('class', 'close-button') 
 
    .attr('transform', 'translate(20, 0)') 
 
    .text('x') 
 
    .on('click', d => removeItem(d)) 
 

 
}
text { 
 
    font-family: sans-serif, Play; 
 
} 
 

 
form .s1 { 
 
    position: absolute; 
 
    top: 180px; 
 
    left: 55px; 
 
} 
 

 
*:focus { 
 
    outline: none; 
 
} 
 

 

 
select { 
 
    background: #404040; 
 
    color: #ffffff; 
 
} 
 

 
select option:checked:after { 
 
    background: #ffffff; 
 
    color: #404040; 
 
} 
 

 
.item { 
 
    fill: black; 
 
} 
 

 
.close-button { 
 
    fill: darkgray; 
 
    cursor: pointer; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.8.0/d3.min.js"></script> 
 
<form> 
 
    <select id='choose' class='s1'></select> 
 
</form>

+0

看起來非常時尚,我想它。必須下載v4,但不應太難集成。 –

+0

你的方法遠遠超出我自己想象的任何東西,我非常喜歡它。但是,我無法弄清楚幾件事情。例如,如果你追加3件東西,第二件東西也會被移動一點。相反,所有項目在添加後都是靜態的。另外,如果追加3個文本項目,然後刪除中間項目,則第3個項目只會向上移動一點。有沒有辦法讓第三件物品到達中間位置的確切高度? –

+0

@ArashHowaida我已經更新了我的答案,以展示如何去做你在問什麼 – thedude