我有如下的SVG结构:
<g class="labels"></g>
还有一些d3代码:
// svg is d3 context
var labels = svg.select('.labels');
ca = labels.append('g');
function resize() {
ca
.call(colorAxis) // an instance of d3.svg.axis() using same data as below
.selectAll('text')
.remove();
ca
.selectAll('.tick').select('circle')
.data(data)
.enter().append('circle')
.style('fill', function (datum) {
return '#' + datum.hex;
})
.attr('r', '7.5');
}
结构最终看起来像这样:
<g class="labels">
<!-- from ca.call(colorAxis) -->
<g>
<g class="tick" transform="translate(0,14.285714285714285)" style="opacity: 1;">
<line x2="-6" y2="0"></line>
</g>
<!-- more of these... -->
</g>
<circle r="7.5" style="fill: rgb(44, 149, 210);"></circle>
<!-- as many of these as there are ticks -->
</g>
每次调用调整大小时,它都会添加更多的圆圈(这不是我想要的)。我想要的是这样的结构:
<g class="labels">
<!-- from ca.call(colorAxis) -->
<g>
<g class="tick" transform="translate(0,14.285714285714285)" style="opacity: 1;">
<line x2="-6" y2="0"></line>
<circle r="7.5" style="fill: rgb(44, 149, 210);"></circle>
</g>
<!-- more of these... -->
</g>
</g>
如何修复我的d3代码来实现这一目标?我也尝试将ca.selectAll('.tick').select('circle')
更改为ca.selectAll('.tick')
,这导致圈子根本不会被追加。
编辑我认为这是隐含的,但显然不是。在调整DOM大小时调用resize()
函数,并且必须相应地调整轴以适合分配的空间内的内容。数据本身不是动态的。
答案 0 :(得分:0)
我明白了。我需要将resize()
中的代码更改为:
function resize() {
ca
.call(colorAxis) // an instance of d3.svg.axis() using same data as below
.selectAll('text')
.remove();
ca
.selectAll('.tick')
.data(data)
.append('circle')
.style(function (datum) {
return '#' + datum.hex;
})
.attr('r', '7.5');
}
答案 1 :(得分:0)
正如评论中所提到的那样,只要了解了必须调用轴并且(希望)轴布局改变了所有的标记,在调用{之间',@帕特里克提供的解决方案是很好的。 {1}}。原因是每次调用例程时都不会删除现有的圆圈。
即使在更新之间调用轴 ,如果刻度线的数量没有改变 - 例如,如果只有刻度线的颜色编码发生变化 - 那么圆圈将会与每次更新。
对此用例使用@Patricks方法......
function onZoom(){
gXaxis.call(xAxis);
var update = gXaxis.selectAll('.tick')
.data(x.ticks(xAxis.ticks()[0]))
.insert('circle', "line")
.attr('r', 7.5)
.attr('cy',function(){return 16 + i})
.style( "fill", function () {
return cr();
});
i++;
function cr(){
return d3.scale.category20().range()[Math.round(Math.random()*20)]
}
}
工作演示:
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 30
},
width = 600 - margin.left - margin.right,
height = 50 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([0, 100]),
zoom = d3.behavior.zoom()
.scaleExtent([0.5, 3])
.on("zoom", onZoom);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(10);
var svg = d3.select("#viz").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
gXaxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
var i = 0;
function onZoom() {
gXaxis.call(xAxis);
var update = gXaxis.selectAll('.tick')
.data(x.ticks(xAxis.ticks()[0]))
.insert('circle', "line")
.attr('r', 7.5)
.attr('cy', function() {
return 16 + i
})
.style("fill", function() {
return cr();
});
i++;
function cr() {
return d3.scale.category20().range()[Math.round(Math.random() * 20)]
}
}
onZoom();
&#13;
svg {
outline: 1px solid red;
overflow: visible;
}
.domain,
.tick line {
fill: none;
stroke: black;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="viz">
<div>scroll to update...</div>
</div>
&#13;
然而,解决这个问题并不是那么直截了当,你需要添加更多代码......不要太多:
function onZoom(){
gXaxis.call(xAxis);
var update = gXaxis
.datum(x.ticks(xAxis.ticks()[0]))
.selectAll('.tick')
.data(function(d){
return d
})
.selectAll('circle')
.data(function(d){
return [d]
});
update.enter().insert('circle', "line")
.attr('r', 7.5)
.attr('cy',function(){return 16 + i});
update.style( "fill", function (d, i, j) {
return cr() ;
})
i++;
function cr(){
return d3.scale.category20().range()[Math.round(Math.random()*20)]
}
}
相同用例的工作演示:
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 30
},
width = 600 - margin.left - margin.right,
height = 50 - margin.top - margin.bottom;
var x = d3.scale.linear()
.range([0, width])
.domain([0, 100]),
zoom = d3.behavior.zoom()
.scaleExtent([0.5, 3])
.on("zoom", onZoom);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(10);
var svg = d3.select("#viz").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.call(zoom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"),
gXaxis = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
var i = 0;
function onZoom() {
gXaxis.call(xAxis);
var update = gXaxis
.datum(x.ticks(xAxis.ticks()[0]))
.selectAll('.tick')
.data(function(d) {
return d
})
.selectAll('circle')
.data(function(d) {
return [d]
});
update.enter().insert('circle', "line")
.attr('r', 7.5)
.attr('cy', function() {
return 16 + i
});
update.style("fill", function(d, i, j) {
return cr();
})
i++;
function cr() {
return d3.scale.category20().range()[Math.round(Math.random() * 20)]
}
}
onZoom();
&#13;
svg {
outline: 1px solid red;
overflow: visible;
}
.domain,
.tick line {
fill: none;
stroke: black;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="viz">
<div>scroll to update...</div>
</div>
&#13;