需求:d3 平时我们看到的要么就是x y 轴都是number 要么就是其中一个是 number
那么 如何画 x y 轴都是非数值的气泡图?
要实现下图的样子:
使用的是 vue + d3 v4 版本,代码如下:
其中,颜色用比例尺去渲染,半径因为原数据太小,在图上根本显示不出来,所以也有线性比例尺去渲染~
let self = this
var initWidth = 800
var initHeight = 800
var padding = {
left: 300,
top: 20,
right: 20,
bottom: 20
}
var height = initWidth - padding.top - padding.bottom
var width = initHeight - padding.left - padding.right
var svg = d3.select(".container")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("padding-left", padding.left)
.style("padding-right", padding.right)
.style("padding-top", padding.top)
.style("padding-bottom", padding.bottom)
//添加y轴坐标轴
//y轴比例尺
let ydata = self.yData
let yScale = d3.scaleBand().rangeRound([height, 0]).padding(1)
.domain(ydata.map(function(d) {
return d;
}))
//定义y轴
let yAxis = d3.axisLeft(yScale)
//添加y轴
svg.append("g")
.attr("class", "xaxis")
.attr("transform", "translate(" + 0 + "," + 0 + ")")
.call(yAxis);
//添加x轴坐标轴
//x轴比例尺
let xData = self.xData
let xScale = d3.scaleBand().rangeRound([0, width]).padding(1)
.domain(xData.map(function(d) {
return d;
}))
//定义x轴
let xAxis = d3.axisBottom(xScale)
//添加x轴
svg.append("g")
.attr("class", "yaxis")
.attr("transform", "translate(" + "0 ," + height + ")")
.call(xAxis);
d3.selectAll('.domain').remove() // 删除多余的两端刻度线
//添加网格-----------
// gridlines in x axis function
function make_x_gridlines() {
return d3.axisBottom(xScale)
.ticks(4)
}
// gridlines in y axis function
function make_y_gridlines() {
return d3.axisLeft(yScale)
.ticks(4)
}
// add the X gridlines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_gridlines()
.tickSize(-height)
.tickFormat("")
)
// add the Y gridlines
svg.append("g")
.attr("class", "grid")
.call(make_y_gridlines()
.tickSize(-width)
.tickFormat("")
)
var colorLinear = d3.scaleLinear()
.domain([d3.min(self.tableValue , function (d) {
return Number(d.p_value); } ),
d3.max(self.tableValue , function (d) {
return Number(d.p_value); })])
.range(["red", "blue"]);
var radiusLinear = d3.scaleLinear()
.domain([d3.min(self.tableValue , function (d) {
return d.gene_ratio; } ),
d3.max(self.tableValue , function (d) {
return d.gene_ratio; })])
.range([10, 20]);
//添加circle包裹层,有几种类型添加几个
var cover = svg.append("g")
//添加circle
cover.selectAll("circle")
.data(self.tableValue)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.x)
})
.attr("cy", function(d) {
return yScale(d.y)
})
.attr("r", function(d) {
return radiusLinear(d.gene_ratio)
})
.attr("fill", function(d) {
return colorLinear(Number(d.p_value))
})
.on("mouseover", function(d) {
let self = this;
d3.select(this)
.transition()
.duration(100)
.attr("r", d3.select(this).attr("r") * 1.6)
showtext.attr("x", function() {
return xScale(d.x)
})
.attr("y", function() {
return yScale(d.y) - d3.select(self).attr("r") * 1.6 - 5
})
.text(function() {
return d.id
})
.attr("text-anchor", "middle")
.attr("fill", "#666")
})
.on("mouseout", function() {
d3.select(this)
.transition()
.duration(100)
.attr("r", d3.select(this).attr("r") / 1.6)
showtext.text("")
})
//添加左侧提示部分包裹层
let detail = cover.append("g")
let showtext = svg.append("text")
.text("")
.attr("font-size", '14px')
复制代码
最终实现效果:
嘿嘿嘿~还不错吧~大功告成!