d3可滚动热力图y轴滚动时固定x轴位置的实现问题
核心问题说明
你的实现存在三个核心问题:
- 承载x轴的svg被放在了带滚动属性的
#my_dataviz容器内部,滚动时会跟着内容一起移动 - x轴的svg插入顺序晚于热力图容器,所以默认渲染在热力图下方
- svg内部元素不支持CSS
position: fixed属性,你给x轴文本加这个属性无效,反而会导致文本渲染异常
修改方案
拆分固定x轴区域和滚动内容区域,调整对应样式和渲染逻辑,修改后x轴会固定在顶部,y轴滚动时不会移动,x轴标签文本完整显示,位置正确。
完整可运行代码如下:
HTML
<script src="https://d3js.org/d3.v4.min.js"></script> <div id="container"> <!-- 固定x轴区域 --> <div id="x-axis-container"></div> <!-- 滚动热力图区域 --> <div id="my_dataviz"></div> </div>
CSS
.rect { opacity: 0.8; } #container { width: 610px; } #x-axis-container { width: 100%; height: 70px; overflow: hidden; } #my_dataviz { width: 100%; height: 500px; overflow-y: scroll; }
JS
var width = 500, height = 600, margintop = 0, marginbottom = 50, marginright = 10, marginleft = 50 d3.csv("https://raw.githubusercontent.com/Lea1216/d3/main/heatmap.csv", function(data) { var svg = d3.select("#my_dataviz") .append("div") .classed("chart",true) .append("svg") .attr("width",width +marginleft + marginright) .attr("height",height+margintop + marginbottom) .append("g") .attr("transform", "translate(" + marginleft + "," + margintop + ")"); // x轴渲染到固定容器内 var axis = d3.select("#x-axis-container") .append("svg") .attr("width", width + marginleft +marginright) .attr("height",70) .append("g") .attr("transform", "translate(" + marginleft + ", 20)"); var x_axis = d3.scaleBand() .range([0, width]) .domain(data.map(function(d) { return d.group; })) .padding(0.01); axis.call(d3.axisTop(x_axis)) .selectAll("text") .style("text-anchor", "end") .attr("dx",15) .attr("dy",5) .attr("transform", "rotate(-65)"); var y_axis = d3.scaleBand() .range([height, 0]) .domain(data.map(function(d) { return d.activity; })) .padding(0.01); svg.append("g") .call(d3.axisLeft(y_axis)) .attr("class", "y_axis") .selectAll("text") .on("click", function(d) { window.open(d.url, "_blank") }); var myColor = d3.scaleLinear() .range(["white", "#C37B89"]) .domain([1, 100]) svg.selectAll() .data(data, function(d) { return d.group + ':' + d.activity; }) .enter() .append("rect") .attr("x", function(d) { return x_axis(d.group) }) .attr("y", function(d) { return y_axis(d.activity) }) .attr("width", x_axis.bandwidth()) .attr("height", y_axis.bandwidth()) .style("fill", function(d) { return myColor(d.value) }) .style("stroke-width", 1) .style("stroke", "none") })
内容的提问来源于stack exchange,提问作者Lea
相关产品推荐
相关产品推荐

