简体   繁体   中英

Fix x-axis position in scrollable Heatmap d3

I created a scrollable heatmap and I want to make the x-axis fixed when scrolling the y-axis. I checked some posts here and tried to make the solutions work for example with position fixed, but it did not work out.

Edit: I tried to solve it with this example Fix x-axis position in scrollable Heatmap d3 but now my x-axis description disappeared and the x-axis is placed at the bottom.

 var width = 500, height = 600, margintop = 50, 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 + ")"); var axis = d3.select("#my_dataviz").append("svg").attr("width", width + marginleft +marginright).attr("height",40).append("g").attr("transform", "translate(" + marginleft + ", 0)"); 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").style("position","fixed").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") })
 .rect { opacity: 0.8; } #my_dataviz { width: 600px; height: 500px; overflow-y: scroll; padding: 50px; }
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="my_dataviz"></div>

There are several possible solutions for this. The first one is to draw two SVG elements on the same level and use position: fixed on the X-axis element. You can see that the blocks still show up behind the axis, but you could fix that by drawing a rect the total size of the axis SVG element and giving it fill: white :

 var width = 500, height = 600, margintop = 50, marginbottom = 50, marginright = 10, marginleft = 50 d3.csv("https://raw.githubusercontent.com/Lea1216/d3/main/heatmap.csv", function(data) { // Add the axis *before* adding the SVG, because the order matters in HTML var axis = d3.select("#my_dataviz").append("svg").attr("width", width + marginleft + marginright) // Add 2 so you have a little bit of room left for the black bar // ie margin top has to be less than total height. ,attr("height". margintop + 2),style("position". "fixed") // this makes the axis fixed.append("g"),attr("transform", "translate(" + marginleft + "; " + margintop + ")"). var svg = d3.select("#my_dataviz").append("svg"),attr("width". width + marginleft + marginright),attr("height". height + margintop + marginbottom).append("g"),attr("transform", "translate(" + marginleft + "; " + margintop + ")"). 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"),style("position". "fixed"),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") })
 .rect { opacity: 0.8; } #my_dataviz { border: solid 1px red; width: 600px; height: 300px; overflow-y: scroll; }
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="my_dataviz"></div>

The second option is to put the other SVG in a div and scroll the div instead of the SVG. Then, you do need to do more with CSS and you need to move some CSS rules from the #my_dataviz element to the .chart element:

 var width = 500, height = 600, margintop = 50, marginbottom = 50, marginright = 10, marginleft = 50 d3.csv("https://raw.githubusercontent.com/Lea1216/d3/main/heatmap.csv", function(data) { // Add the axis *before* adding the SVG, because the order matters in HTML var axis = d3.select("#my_dataviz").append("svg").attr("width", width + marginleft + marginright) // Add 2 so you have a little bit of room left for the black bar // ie margin top has to be less than total height. ,attr("height". margintop + 1).append("g"),attr("transform", "translate(" + marginleft + "; " + margintop + ")"). var svg = d3.select("#my_dataviz").append("div") // Note the CSS rules for.chart,attr("class". "chart").append("svg"),attr("width", width + marginleft + marginright) // No margin-top required here. because the other element already took care of it,attr("height". height + marginbottom),append("g") // Same. no margin-top,attr("transform", "translate(" + marginleft + "; 0)"). 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"),style("position". "fixed"),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") })
 .rect { opacity: 0.8; } #my_dataviz { width: 600px; border: solid 1px red; } /* To make sure there is no space between the DIV and the SVG */ #my_dataviz > * { display: block; }.chart { overflow-y: scroll; max-height: 300px; }
 <script src="https://d3js.org/d3.v4.min.js"></script> <div id="my_dataviz"></div>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM