我需要单击每一块进行旋转,问题是标签开始未对准。并且它们应该像开始时那样对齐。
var width = 670,
height = 400,
radius = Math.min(width, height) / 2,
raio = 180,
active = !active,
labelr = raio + 30;
const dataStructure = {
data: [{
label: 'Lorem Ipsum 1',
value: 100,
color: 'green'
},
{
label: 'Lorem Ipsum 2',
value: 80,
color: 'red'
},
{
label: 'Lorem Ipsum 3',
value: 45,
color: 'blue'
},
{
label: 'Lorem Ipsum 5',
value: 20,
color: 'yellow'
},
{
label: 'Lorem Ipsum 6',
value: 70,
color: 'orange'
}
]
};
const arc = d3
.arc()
.outerRadius(raio)
.innerRadius(8);
const labelArc = d3
.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
const pie = d3.pie().sort(null).value(100)(dataStructure.data);
const svg = d3
.select('#chart-d3')
.append('svg')
.attr('width', width)
.attr('height', 450)
.attr('class', 'container-svg')
.append('g')
.attr('transform', 'translate(' + width / 2 + ' ,' + height / 2 + ')');
svg.append('g').attr('class', 'labels');
svg.append('g').attr('class', 'slices');
const key = function(d) {
return d.data.label;
};
const slice = svg.select('.slices').selectAll('path.slice').data(pie, key).enter();
// gera os 'pedaços' e coloca efeito
slice
.append('path')
.attr('d', arc)
.attr('stroke', '#F0F1F5')
.attr('stroke-width', '1')
.style('fill', function(d) {
return d.data.color;
})
.on('click', (d, i) => {
var rotate =
110 - ((d.startAngle + d.endAngle) / 2 / Math.PI) * 180;
svg
.transition()
.attr(
'transform',
'translate(' + width / 2 + ' ,' + height / 2 + ') rotate(' + rotate + ')'
)
.duration(1000);
d3.selectAll('text')
.transition()
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return (
'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ') rotate(' + -rotate + ')'
);
})
.attr('text-anchor', function(d) {
return (d.endAngle + d.startAngle) / 2 > Math.PI ? 'end' : 'start';
})
.duration(1000);
});
// label
const text = svg.select('.labels').selectAll('text').data(pie, key).enter();
text
.append('text')
.attr('dy', '.35em')
.text((d) => {
return d.data.label
})
.style('fill', '#47484c')
.attr('font-family', 'Bradesco Sans')
.attr('font-size', '14px')
.attr('font-weight', '500')
.attr('id', function(d, i) {
return 'legend-' + i;
})
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return 'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ')';
})
.attr('text-anchor', function(d) {
// are we past the center?
return (d.endAngle + d.startAngle) / 2 > Math.PI ? 'end' : 'start';
});
// d3.select('#circle-icon-0').dispatch('click');
<script src="http://d3js.org/d3.v5.min.js"></script>
<div id="chart-d3"></div>
代码jsfiddle
答案 0 :(得分:0)
您忘记计算text-anchor
的轮换。但是,当我解决该问题时,您会出现跳动的行为,因为该属性无法设置动画。
我看到一些解决方法:
labelr
并持续使用text-anchor: middle;
,请参见下面的示例;
var width = 670,
height = 400,
radius = Math.min(width, height) / 2,
raio = 180,
active = !active,
labelr = raio + 45;
const dataStructure = {
data: [{
label: 'Lorem Ipsum 1',
value: 100,
color: 'green'
},
{
label: 'Lorem Ipsum 2',
value: 80,
color: 'red'
},
{
label: 'Lorem Ipsum 3',
value: 45,
color: 'blue'
},
{
label: 'Lorem Ipsum 5',
value: 20,
color: 'yellow'
},
{
label: 'Lorem Ipsum 6',
value: 70,
color: 'orange'
}
]
};
const arc = d3
.arc()
.outerRadius(raio)
.innerRadius(8);
const labelArc = d3
.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
const pie = d3.pie().sort(null).value(100)(dataStructure.data);
const svg = d3
.select('#chart-d3')
.append('svg')
.attr('width', width)
.attr('height', 450)
.attr('class', 'container-svg')
.append('g')
.attr('transform', 'translate(' + width / 2 + ' ,' + height / 2 + ')');
svg.append('g').attr('class', 'labels');
svg.append('g').attr('class', 'slices');
const key = function(d) {
return d.data.label;
};
const slice = svg.select('.slices').selectAll('path.slice').data(pie, key).enter();
// gera os 'pedaços' e coloca efeito
slice
.append('path')
.attr('d', arc)
.attr('stroke', '#F0F1F5')
.attr('stroke-width', '1')
.style('fill', function(d) {
return d.data.color;
})
.on('click', (d, i) => {
var rotate = 110 - ((d.startAngle + d.endAngle) / 2 / Math.PI) * 180;
svg
.transition()
.attr(
'transform',
'translate(' + width / 2 + ' ,' + height / 2 + ') rotate(' + rotate + ')'
)
.duration(1000);
d3.selectAll('text')
.transition()
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return (
'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ') rotate(' + -rotate + ')'
);
})
.duration(1000);
});
// label
const text = svg.select('.labels').selectAll('text').data(pie, key).enter();
text
.append('text')
.attr('dy', '.35em')
.text((d) => {
return d.data.label
})
.style('fill', '#47484c')
.attr('font-family', 'Bradesco Sans')
.attr('font-size', '14px')
.attr('font-weight', '500')
.attr('id', function(d, i) {
return 'legend-' + i;
})
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return 'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ')';
})
.attr('text-anchor', 'middle');
// d3.select('#circle-icon-0').dispatch('click');
<script src="http://d3js.org/d3.v5.min.js"></script>
<div id="chart-d3"></div>
dx
。动画完成后,重置dx
并设置正确的text-anchor
值。当然,这更麻烦,但是如果您真的不想使用text-anchor: middle
,则可能是一种解决方法。
var width = 670,
height = 400,
radius = Math.min(width, height) / 2,
raio = 180,
active = !active,
labelr = raio + 30;
const dataStructure = {
data: [{
label: 'Lorem Ipsum 1',
value: 100,
color: 'green'
},
{
label: 'Lorem Ipsum 2',
value: 80,
color: 'red'
},
{
label: 'Lorem Ipsum 3',
value: 45,
color: 'blue'
},
{
label: 'Lorem Ipsum 5',
value: 20,
color: 'yellow'
},
{
label: 'Lorem Ipsum 6',
value: 70,
color: 'orange'
}
]
};
const arc = d3
.arc()
.outerRadius(raio)
.innerRadius(8);
const labelArc = d3
.arc()
.outerRadius(radius - 40)
.innerRadius(radius - 40);
const pie = d3.pie().sort(null).value(100)(dataStructure.data);
const svg = d3
.select('#chart-d3')
.append('svg')
.attr('width', width)
.attr('height', 450)
.attr('class', 'container-svg')
.append('g')
.attr('transform', 'translate(' + width / 2 + ' ,' + height / 2 + ')');
svg.append('g').attr('class', 'labels');
svg.append('g').attr('class', 'slices');
const key = function(d) {
return d.data.label;
};
const slice = svg.select('.slices').selectAll('path.slice').data(pie, key).enter();
// gera os 'pedaços' e coloca efeito
slice
.append('path')
.attr('d', arc)
.attr('stroke', '#F0F1F5')
.attr('stroke-width', '1')
.style('fill', function(d) {
return d.data.color;
})
.on('click', (d, i) => {
var rotate = 110 - ((d.startAngle + d.endAngle) / 2 / Math.PI) * 180;
var rotateRads = rotate / 360 * (Math.PI * 2);
svg
.transition()
.attr(
'transform',
'translate(' + width / 2 + ' ,' + height / 2 + ') rotate(' + rotate + ')'
)
.duration(1000);
d3.selectAll('text')
.attr('dx', 0)
.transition()
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return (
'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ') rotate(' + -rotate + ')'
);
})
.attr('dx', function(d) {
// Will their text-anchor change?
const oldAnchor = d3.select(this).attr('text-anchor');
// + 2*PI to make it always positive, then modulo
const newAngle =
((d.endAngle + d.startAngle) / 2 + rotateRads + 2 * Math.PI) % (Math.PI * 2);
const newAnchor = newAngle > Math.PI ? 'end' : 'start';
if (oldAnchor === newAnchor) {
return 0;
}
if (newAnchor === 'end') {
return -this.getBBox().width;
}
return this.getBBox().width;
})
.duration(1000)
.on('end', function(d, i) {
d3.select(this)
.attr('dx', 0)
.attr('text-anchor', function(d) {
const newAngle =
((d.endAngle + d.startAngle) / 2 + rotateRads + 2 * Math.PI) % (Math.PI * 2);
return newAngle > Math.PI ? 'end' : 'start';
});
});
});
// label
const text = svg.select('.labels').selectAll('text').data(pie, key).enter();
text
.append('text')
.attr('dy', '.35em')
.text((d) => {
return d.data.label
})
.style('fill', '#47484c')
.attr('font-family', 'Bradesco Sans')
.attr('font-size', '14px')
.attr('font-weight', '500')
.attr('id', function(d, i) {
return 'legend-' + i;
})
.attr('transform', function(d) {
var c = labelArc.centroid(d),
x = c[0],
y = c[1],
// pythagorean theorem for hypotenuse
h = Math.sqrt(x * x + y * y);
return 'translate(' + (x / h) * labelr + ',' + (y / h) * labelr + ')';
})
.attr('text-anchor', function(d) {
return (d.endAngle + d.startAngle) / 2 > Math.PI ? 'end' : 'start';
});
// d3.select('#circle-icon-0').dispatch('click');
<script src="http://d3js.org/d3.v5.min.js"></script>
<div id="chart-d3"></div>