虽然相对位置逻辑,选择和翻译声音乍看之下单独的问题,但在我的特殊情况下,您将看到它们如何相互关联。
构建我的动态按钮附加项目,我现在想制定transition()
效果,您可以在任何顺序上附加事物,按任何顺序删除它们,如果从顶部删除某些东西,底部元素将优雅地滑动到顶部以填补空白空间。我只有半功能,问题是我找不到正确的逻辑来仅选择当前按钮事件下方的文本。
跳过逻辑,我确实通过简单地使用selectAll('text')
成功地使用了过渡。这仅在您有2个项目的情况下才起作用,一旦您附加了3件事,它就会变得凌乱,因为它没有正确的逻辑来辨别哪个要过渡。
另一个翻译问题与使按钮移动有关。文本过渡正常,但是按钮固执地保持不变,无论使用.attr('top', new_value)
或.attr('transform', 'translate(' + 0+','+new_value+')')
转到带有评论的实时示例,然后从下拉菜单中选择事物,单击以删除顶部,您将看到我的意思。
总结:
-
如何使
if ()
逻辑检查任何大于当前最高距离的文本?(即,如果页面上的文本元素高于当前的元素( -
我如何告诉D3仅选择具有更大相对位置的文本(在垂直意义上,即页面上的较低(
-
如何使D3翻译或更新按钮的
top
?请注意,在示例中,我正在使用selectAll('button')
,但理想情况下,我需要一个更敏感的选择。
您应该使用数据绑定来实现此目标,请参阅我的代码中的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>