Я вижу странное поведение с преобразованиями при использовании ввода d3, шаблона обновления. Я создаю группу (svg: g) элементов текста (svg: text). Когда я сначала создаю группы, использующие .enter.append('g').attr('transform',function(d){...translate...}
элементы относятся к вершине SVG. Однако, когда Я обновляю группы после изменения размера окна по сравнению с их внешним контейнером.
Мои данные - это вложенный набор объектов (d3.nest)
var myData=[{
key:f,
values:[{
group:f,
text:'foo'
}]
},
{
key:b,
values:[{
group:'b',
text:'bar'
},{
group:'b',
text:'baz'
}]
}
.....
]
Моя модель ввода/обновления:
// EDIT Some JS to add shapes first
var shapeCont = d3.select('#shapesAtTheTop');
var shapes = shapeCont.selectAll('rect')
.data([50,50]);
shapes.exit().remove();
shapes.enter().append('rect')
.attr('width',function(d){return window.innerWidth*(d/100)})
.attr('x', function(d,i){return i*window.innerWidth*(d/100)})
.attr('y',0)
.attr('height',95);
// END EDIT
// Now add the text
var textgroupLeft = window.width/50, textGrouptop = 100;
function translateGroup(datum, i){
var x = textGroupLeft * i;
var y = textGroupTop;
return 'translate('+x+' '+y+')';
}
var textContainer = d3.select('g.textContainer');
var txtg = textContainer.selectAll('g').data(myData,function(d){return d.key;});
// UPDATE
txtg.attr('transform',translateGroup);
// REMOVE
txtg.exit().remove();
// NEW
txtg.enter().append('g')
.classed('textGroup',true')
.attr('transform',transelateGroup)
var txt = d3.selectAll('g.textGroup').selectAll('text')
.data(function(d){retrun d.values;},
function(dataum){return JSON.stringify(dataum);})
// REMOVE
.....
// UPDATE
.....
// NEW
.....
Мой HTML/SVG:
<svg>
<g id="shapesAtTop">
..... add polygons with positions in the first 100px high ....
</g>
<g id="textBelow" class="textContainer">
</g>
</svg>
Переключение систем координат? Если так, почему?
Трудно понять, где вы ошибаетесь. Вы можете исправить эту проблему, явно указав перевод в группе #textBelow в вашем SVG либо в HTML, либо программно используя D3. Когда эта группа имеет правильную вертикальную позицию, легче перевести любые вложенные объекты.
Твой код для определения переводов применять трудно. Я бы посоветовал использовать d3 BandScale для обработки отображения из индекса объекта, который вы преобразовываете в значение в пикселях.
В приведенном ниже фрагменте демонстрируется обе эти функции с использованием D3 v4. Если вам нужно использовать предыдущую версию D3, тогда имя шкалы отличается, и вам нужно быть более осторожным с selection.enter(), поскольку вы не получаете метод selection.merge().
var data = [{key:'a'}, {key:'b'}]
var width = 500 //px
update(data,width)
setTimeout(function (){update(data,200)}, 2000)
function update(data, width) {
//create a band scale to assist with layout
var scale = d3
.scaleBand()
.domain(d3.range(data.length))
.range([0, width])
// padding ratio of total width
.padding(0.1);
// append/modify shapes
var shapeCont = d3.select("#shapesAtTop");
var shapes = shapeCont.selectAll("rect").data(data);
// remove any unused nodes
shapes.exit().remove();
// enter
shapes.enter()
// add new rectangles
.append("rect")
// merge selection with any existing nodes
.merge(shapes)
// set all rect attributes
.attr("x", function(d, i) {
return scale(i);
})
.attr("y", 0)
.attr("height", 95)
.attr("width", scale.bandwidth());
//append/modify text group elements
var textContainer = d3.select('#textBelow');
var txtg = textContainer.selectAll('g')
.data(data, function(d) {
return d? d.key : this.id
});
// remove any unused nodes
txtg.exit().remove()
// enter
txtg.enter()
.append('g')
.classed('textGroup', true)
// add some text to new elements
.call( function (g) { g.append('text').text('I am text')})
// merge exisiting and new
.merge(txtg)
.attr('transform', function(d, i) {
return 'translate(' + scale(i) + ')'
})
}
svg {
width: 100%;
height: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
<svg>
<g id="shapesAtTop">
</g>
<g id="textBelow" class="textContainer" transform="translate(0,120)">
</g>
</svg>
g
сработало, но зачем это нужно ? Подумав еще немного об этом. мне кажется, что когда страница загружается, "shapeAtTop" имеет размерность 0x0 (H & W), поэтому страница течет на основе этого 0x0. Затем, когда происходит изменение размера, shapeAtTop имеет ненулевую высоту и таким образом выталкивает группу вниз.