img

html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<style>
.MyText {
font-size: 18px;
width: 60px;
padding-left: 5px;
}
.MyText div {
display: inline-block;
}
.MyText div:first-child {
color: #fcfc00;
}
.MyText div:last-child {
color: blue;
}
.MyText div:first-child::after {
content: '个';
font-size: 12px;
}
.MyText div:last-child::after {
content: '%';
font-size: 12px;
}
</style>
<body>
<div>
<svg width="230" height="205"></svg>
</div>
</body>
</html>
<script>
var epidemicData = [
{ name: '五级', amount: 30, percent: '60' },
{ name: '六级', amount: 20, percent: '30' },
{ name: '七级', amount: 5, percent: '10' },
]
function maxHeight() {
return epidemicData.reduce((total, curVal) => {
return total > curVal.amount ? total : curVal.amount
}, 0)
}
const rectWidth = 20
const yLength = 180
const rectHeight = d3
.scaleLinear()
.domain([0, maxHeight() + 10])
.range([0, yLength])
const interval = 55
const xLength = (rectWidth + interval) * epidemicData.length
const baseLine = 190
let svg = d3.select('svg')
let g = svg.append('g')
let xScale = addX()
let yScale = addY()
let rect = g
.attr('transform', 'translate(' + 30 + ', ' + 0 + ')')
.selectAll('rect')
.data(epidemicData)
.enter()
.append('rect')
.attr('x', (d, i) => i * (rectWidth + interval))
.attr('y', d => baseLine - rectHeight(d.amount))
.attr('width', rectWidth)
.attr('height', d => rectHeight(d.amount))
.attr('stroke', d => {
return '#1A6A9030'
})
.attr('fill', d => {
return getLinearColor()
})
svg
.selectAll('.MyText')
.data(epidemicData)
.enter()
.append('foreignObject')
.attr('class', 'MyText')
.attr('x', function (d, i) {
return xScale(d.name) + 30 + rectWidth
})
.attr('y', function (d) {
return yScale(d.amount)
})
.html(function (d) {
return `<div>${d.amount}</div><div>${d.percent}</div>`
})
function getLinearColor() {
var defs = svg.append('defs')
var linearGradient = defs
.append('linearGradient')
.attr('id', 'linearColor')
.attr('x1', '0%')
.attr('y1', '0%')
.attr('x2', '0%')
.attr('y2', '100%')
var stop1 = linearGradient.append('stop').attr('offset', '0%').style('stop-color', '#50F0FB')
var stop2 = linearGradient.append('stop').attr('offset', '100%').style('stop-color', '#07AAFC')
return 'url(#' + linearGradient.attr('id') + ')'
}
function _address() {
return epidemicData.reduce((total, curVal) => {
total.push(curVal.name)
return total
}, [])
}
function addX() {
const xTick = epidemicData.length
let xScale = d3.scaleBand().domain(_address()).range([0, xLength])
let xAxis = d3.axisBottom(xScale).ticks(xTick).tickPadding(10)
let gx = g
.append('g')
.call(xAxis)
.attr('transform', 'translate(' + -30 + ', ' + 180 + ')')
gx.selectAll('text').style('color', '#bebebe')
gx.selectAll('line').attr('stroke', '')
gx.selectAll('path').attr('stroke', '')
return xScale
}
function addY() {
const yTick = 5
let gy = g.append('g')
let yScale = d3
.scaleLinear()
.domain([0, maxHeight() + 10])
.range([yLength, 0])
const rectHeight = d3
.scaleLinear()
.domain([0, maxHeight() + 10])
.range([0, yLength])
let yAxis = d3.axisLeft(yScale).ticks(yTick)
gy.call(yAxis).attr('transform', 'translate(' + -10 + ', ' + (baseLine - yLength) + ')')
gy.selectAll('line').attr('stroke', '#0D194B20').attr('x2', xLength).attr('stroke-width', 0.5)
gy.selectAll('path').attr('stroke', '')
gy.selectAll('text').style('color', '#01B2E2')
return yScale
}
</script>