d3绘制柱状图
主要代码实现如下
const sample = [
{
language: 'Rust',
value: 78.9,
color: '#000000'
},
{
language: 'Kotlin',
value: 75.1,
color: '#00a2ee'
},
{
language: 'Python',
value: 68.0,
color: '#fbcb39'
},
{
language: 'TypeScript',
value: 67.0,
color: '#007bc8'
},
{
language: 'Go',
value: 65.6,
color: '#65cedb'
},
{
language: 'Swift',
value: 65.1,
color: '#ff6e52'
},
{
language: 'JavaScript',
value: 61.9,
color: '#f9de3f'
},
{
language: 'C#',
value: 60.4,
color: '#5d2f8e'
},
{
language: 'F#',
value: 59.6,
color: '#008fc9'
},
{
language: 'Clojure',
value: 59.6,
color: '#507dca'
}
];
const margin = 60,
width = 1000,
height = 600,
chartWidth = width - 2 * margin,
chartHeight = height - 2 * margin
const svg = d3.select('body').append('svg').attr('width', width).attr('height', height)
const chart = svg.append('g').attr('transform', `translate(${margin}, ${margin})`)
//创建y轴比例尺
const yScale = d3.scaleLinear().range([chartHeight, 0]).domain([0, 100])
//生成y轴
chart.append('g').call(d3.axisLeft(yScale))
//创建x轴比例尺,并设置填充内间距为0.5
const xScale = d3.scaleBand().range([0, chartWidth]).domain(sample.map(s => s.language)).padding(0.5)
//直接通过axisBottom生成x轴,由于要显示到底部,所以应计算位置坐标
chart.append('g').attr('transform', `translate(0, ${chartHeight})`).call(d3.axisBottom(xScale))
//绘制柱状图矩形上的文字提示信息
const bondGroups = chart.append('g').selectAll().data(sample).enter().append('text').attr('class', 'label').attr('y', d => yScale(d.value) - 10).attr('x', d => xScale(d.language)).text(d => `$${d.value}%`)
//创建鼠标hover时的区域
const hoverBox = chart.append('g').attr('class', 'hover')
//渲染出柱状图
chart.append('g').selectAll().data(sample).enter().append('rect').attr('class', 'bar').attr('x', d => xScale(d.language)).attr('y', d => yScale(d.value))
.attr('height', d => chartHeight - yScale(d.value)).attr('width', xScale.bandwidth())
.on('mouseenter', function (actual, i) {
//鼠标进入时,透明度降低,并且有扩大的效果,即x坐标向左平移一段距离,并且宽度增大扩大距离的2倍
d3.select(this).transition().duration(300).attr('opacity', 0.5).attr('x', d => xScale(d.language) - 5).attr('width', xScale.bandwidth() + 10)
d3.selectAll('.label').attr('opacity', 0)
//拿到当前鼠标悬浮矩形的y轴值
const y = yScale(actual.value)
//划线
chart.append('line').attr('class', 'limit').attr('x1', 0).attr('y1', y).attr('x2', chartWidth).attr('y2', y).attr('stroke', 'red').attr('stroke-dasharray', '3 6')
//鼠标hover时,计算值之间的对比,并显示到柱状图矩形上
hoverBox.selectAll('text').data(sample).enter().append('text').attr('class', 'divergence').attr('x', d => xScale(d.language)).attr('y', d => yScale(d.value) - 10).text((d, idx) => {
const divergence = (d.value - actual.value).toFixed(1)
let text = ''
if (divergence > 0) text += '+'
text += `${divergence}%`
return idx === i ? '' : text
})
}).on('mouseleave', function () {
d3.select(this).transition().duration(300).attr('opacity', 1).attr('x', d => xScale(d.language)).attr('width', xScale.bandwidth())
d3.selectAll('.divergence').remove()
d3.selectAll('.label').attr('opacity', 1)
chart.selectAll('.limit').remove()
})
//绘制平行的坐标系轴线,其实是将刻度线反向延长
chart.append('g').attr('class', 'grid').call(
d3.axisLeft().scale(yScale).tickSize(-chartWidth, 0, 0).tickFormat('')
)
//描述文字
chart.append('text').attr('x', -(chartHeight / 2)).attr('y', -margin / 2).attr('transform', 'rotate(-90)').attr('text-anchor', 'middle').text('Love meter (%)')
chart.append('text').attr('x', chartWidth / 2).attr('y', chartHeight + 40).attr('text-anchor', 'middle').text('Languages')
chart.append('text').attr('x', chartWidth / 2).attr('y', -20).attr('text-anchor', 'middle').text('Most loved programming languages in 2018')
最终实现效果
你可以在这里查看完整代码
See the Pen BOmvKy by Leevare (@leevare) on CodePen.
是不是很炫呢?
代码实现参考自:https://juejin.im/entry/5b9237f4e51d450e877f1419?utm_source=gold_browser_extension
如果您觉得本文对您有用,欢迎捐赠或留言~
- 本博客所有文章除特别声明外,均可转载和分享,转载请注明出处!
- 本文地址:https://www.leevii.com/?p=1391