如何解决如何在 dc.js 饼图中添加图标而不是文本 向 dc.js 馅饼切片添加内容限制
我已经使用 dc.js 一年了。最近我的任务是实现如下饼图:
我想用适当的图像替换饼图切片中的文本标签。
我看到这是在纯 d3.js 中实现的。有人能帮我把实现翻译成 dc.js 吗?
22
解决方法
我拿了 fiddle 并添加了几个我发现的“Meteoicons”here。
(当然,这些图标只是作为例子,我没有许可将它们用于商业)
图标存储在单独的 <svg>
元素中。要呈现图标,只需选择其根 <g>
元素并将其内容复制到您在饼图中创建的另一个 <g>
:
g.append("g")
.attr("transform",d => `translate(${arc.centroid(d)}) scale(0.25)`)
.append('g')
.attr('transform','translate(-256,-256)') // The original icons are 256 x 256
.html(d => d3.select(`#meteo-icon-${... some attribute of d ...} > g`).html())
代码仅用于演示目的,您需要根据需要进行修改。
在下面的片段中查看结果:
var width = 550,height = 550,radius = 250,colors = d3.scale.ordinal()
.range(['#336699 ','#336699 ','#ACD1E9','#ACD1E9']);
var image_width=40,image_height=40;
var piedata = [
{
label: "test",image: "http://placeimg.com/40/40/any",value: 50
},{
label: "",image: "http://placeimg.com/42/42/any",value: 50
},{
label: "Jonathan",image: "http://placeimg.com/44/44/any",{
label: "Lorenzo",image: "http://placeimg.com/46/46/any",{
label: "Hillary",image: "http://placeimg.com/38/38/any",value: 50
}
]
var pie = d3.layout.pie()
.value(function(d) {
return d.value;
})
var arc = d3.svg.arc()
.outerRadius(250)
.innerRadius(100)
var svg = d3.select('body').append('svg')
.attr('width',width)
.attr('height',height)
.append('g')
.attr('transform','translate('+(width-radius)+','+(height-radius)+')');
var g = svg.selectAll(".arc")
.data(pie(piedata))
.enter().append("g")
.attr("class","arc");
g.append("path")
.attr("d",arc)
.style("fill",function(d,i) { return colors(i); });
g.append("g")
.attr("transform",d => `translate(${arc.centroid(d)}) scale(0.25)`)
.append('g')
.attr('transform',-256)')
.html(() => d3.select(`#meteo-icon-${Math.random() < 0.5 ? 1 : 2} > g`).html())
.selectAll('path')
.style('fill','orange');
path {
stroke: #fff;
fill-rule: evenodd;
}
text {
font-family: Arial,sans-serif;
font-size: 12px;
}
.meteo-icon {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<svg id="meteo-icon-1" class="meteo-icon" width="24" height="24" viewBox="0 0 512 512">
<g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#1D1D1B" d="M177.615,288c7.438-36.521,39.688-64,78.396-64
c38.709,70.958,27.479,78.376,64h32c-7.834-54.125-54.084-96-110.376-96c-56.271,0-102.541,41.875-110.375,96H177.615z
M256.011,160c8.833,16-7.167,16-16v-32c0-8.833-7.167-16-16-16c-8.832,0-16,7.167-16,16v32
C240.011,152.833,247.179,160,256.011,160z M403.073,156.917c-6.249-6.25-16.374-6.25-22.625,0l-22.625,22.625
c-6.249,6.25-6.249,16.375,22.625c6.251,6.25,16.376,22.625,0l22.625-22.625
C409.323,173.292,409.323,163.167,403.073,156.917z M154.177,179.542l-22.625-22.625c-6.249-6.25-16.373-6.25-22.625,0
c-6.249,22.625l22.625,22.625c6.252,0
C160.429,195.917,160.429,185.792,154.177,179.542z M352.011,320h-192c-8.832,16s7.168,16,16h192
c8.833,16-16S360.844,320,352.011,320z M320.011,384h-128c-8.832,16h128
c8.833,16-16S328.844,384,320.011,384z"/>
</g>
</svg>
<svg id="meteo-icon-2" class="meteo-icon" width="24" height="24" viewBox="0 0 512 512">
<g>
<path fill="#1D1D1B" d="M349.852,343.15c-49.876,49.916-131.083,49.916-181,0c-49.916-49.917-49.916-131.125,0-181.021
c13.209-13.187,29.312-23.25,47.832-29.812c5.834-2.042,12.293-0.562,16.625,3.792c4.376,4.375,5.855,10.833,3.793,16.625
c-12.542,35.375-4,73.666,22.249,99.917c26.209,26.228,64.501,34.75,99.917,22.25c5.792-2.062,12.271-0.583,3.792
c4.376,4.333,5.834,10.812,3.771,16.625C373.143,313.838,363.06,329.941,349.852,343.15z M191.477,184.754
c-37.438,37.438-37.438,98.354,135.771c40,40.021,108.125,36.417,143-8.167c-35.959,2.25-71.375-10.729-97.75-37.084
c-26.375-26.354-39.333-61.771-37.084-97.729C196.769,179.796,194.039,182.192,191.477,184.754z"/>
</g>
</svg>
首先,为一个不完整的例子道歉,但我没时间了,我认为这表明了原则。
-
我同意@MichaelRovinsky 的观点,即 SVG 图标会比图像更好,但我找不到适合该示例的 SVG 图标 CDN,我认为原理完全相同,因为您也可以将 SVG 嵌入为
image
。 -
为此目的使用 placeimg.com 会导致奇怪的结果,因为相同的 URL 在读取两次时会产生不同的结果,例如两个切片可能会得到相同的图像,并且在图表重绘时图像会发生变化。
幸运的是,这些都与自定义 dc.js 无关!
向 dc.js 馅饼切片添加内容
它 would be nice 如果 dc.js 使用 svg g
组元素来放入文本。然后我们可以添加到它,位置就会正确。
相反,我们必须添加我们的 image
元素并从饼图标签中读取相应的数据以获取展示位置:
chart.on('pretransition',chart => {
let labelg = chart.select('g.pie-label-group');
let data = labelg.selectAll('text.pie-label').data();
console.log('data',data);
然后我们可以在同一层/g中添加image
元素:
let pieImage = labelg.selectAll('image.pie-image');
let arcs = chart._buildArcs();
pieImage.data(data)
.join(
enter => enter.append('image')
.attr('class','pie-image')
.attr('x',-19)
.attr('y',-19))
.attr('href',d => images[d.data.key === 'Others' ? 'Others' : d.data.key.slice(4)])
.attr('transform',d => chart._labelPosition(d,arcs));
});
请注意,只需要设置一次(在进入时)的属性在 join 调用内部,而每次重绘(在更新时)都需要设置的属性在 join 调用之外。
x
和 y
是图像大小的负二分之一以将图像居中。
我使用了一个对象来存储 URL,但您可以使用任何对象。
限制
与饼图的任何自定义一样,这并不能很好地解释动画。图像将在动画完成之前移动。如果您在乎,我想我几年前写了一个答案,该答案正确地处理了这个问题。我可能可以挖掘它,但它非常复杂,恕我直言不值得。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。