最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - D3.js Bug in the resize function - Stack Overflow

programmeradmin3浏览0评论

I am in the process of writing a resize function for my chart. So far everything works quite well.

However, I noticed the following bug when using the resize function.

After I have rendered the chart and then resize the window, my heatmap chart extends some "px" to the right. This causes the chart to be cut off on the right side.

Can someone please explain why this bug occurs and how I can fix it?

I would be grateful for any advice.

 //Datasource
            const data1= [
                {id: 1,group:"A",variable:"v1",value: 98},{id: 2,group:"A",variable:"v2",value:95},
                {id: 3,group:"A",variable:"v3",value: 22},{id: 4,group:"A",variable:"v4",value:14},
                {id: 11,group:"B",variable:"v1",value: 37},{id: 12,group:"B",variable:"v2",value:50},
                {id: 13,group:"B",variable:"v3",value: 81},{id: 14,group:"B",variable:"v4",value:79}, 
                {id: 21,group:"C",variable:"v1",value: 96},{id: 22,group:"C",variable:"v2",value:13},
                {id: 23,group:"C",variable:"v3",value: 98},{id: 24,group:"C",variable:"v4",value:10},
                {id: 31,group:"D",variable:"v1",value: 75},{id: 32,group:"D",variable:"v2",value:18},
                {id: 33,group:"D",variable:"v3",value: 92},{id: 34,group:"D",variable:"v4",value:43},
                {id: 41,group:"E",variable:"v1",value: 44},{id: 42,group:"E",variable:"v2",value:29},
                {id: 43,group:"E",variable:"v3",value: 58},{id: 44,group:"E",variable:"v4",value:55},
                {id: 51,group:"F",variable:"v1",value: 35},{id: 52,group:"F",variable:"v2",value:80},
                {id: 53,group:"F",variable:"v3",value: 8},{id: 54,group:"F",variable:"v4",value:46}
            ];

            var i_region_static_id = "heatmap"
            var i_height = 450;
            var margin = {top: 0, right: 50, bottom: 25, left: 70}; 
            var width_client = document.body.clientWidth;
            var height_client = document.body.clientHeight;

            const innerWidth = width_client - margin.left - margin.right;
            const innerHeight = i_height - margin.top - margin.bottom; 

            var colorMidValue = 20;

            const labelGroup = "X-Label"
            const labelVars = "Y-Label"
            const color_start = "#f9f9f9"
            const colorEnd = "#6e69b3"
            const colorMid = "#bd326c"

            // Funktion zum Aufrunden der Y-Axis auf 5
            function updateColorAxis(a,b){
                if(b%5 !== 0){
                    b = b+(5-(b%5)); 
                }
                return [a,b];
            }
        
            // Funktion zum Berechnen der Anzahl der Ticks 
            function setColorAxisTicks(a,b){
                if(b%5 === 0){
                    return b/5;
                }
                return b/10;
            }

            // Returns Black/White depending on node color
            function calculateContrast(values){
                var rgb = values.match(/\d+/g);
                // Wenn rgb leer, dann das erste sonst das zweite
                const brightness = (rgb != undefined) ? Math.round(((parseInt(rgb[0]) * 299) + (parseInt(rgb[1]) * 587) + (parseInt(rgb[2]) * 114)) /1000) : 0;
                return brightness < 150 ? 'white' : 'black'   
            }
                
            
            //-----------------------------------------------------------------------------------
            // Anfügen von svg Elementen zu #heatmap
            const svg = d3.select('#svg_heatmap')
                                // Attribute svg
                                .attr("height", innerHeight)
                                .attr("width", width_client + margin.left + margin.right)

            const g_area = d3.select("#svg_" + i_region_static_id)                           
                                // Anfügen einer Gruppe an das SVG Element
                                .append("g")
                                    .attr("id", i_region_static_id + "_area")
                                    .attr("transform", `translate(${margin.left},${margin.top})`);

            const g_nodes = g_area
                                .append("g")
                                .attr("id", i_region_static_id + "_nodes")
            //-----------------------------------------------------------------------------------
            // X-Skalierung
            const x_scale = d3.scaleBand()
                        .range([0, innerWidth])
                        .padding(0.01);

            const xAxisCall = d3.axisBottom(x_scale)

            // X-Achse erstellen
            const xAxis = g_area
                                .append("g")
                                .attr("id", i_region_static_id + "_x_axis")

                        // Einfügen xAxis Values    
                        xAxis.append("g")
                                .attr("id", i_region_static_id + "_x_axis_value")
                                .attr("class", "x axis")
                                .attr("transform", `translate(0, ${innerHeight})`)

                        // Einfügen xAxis Label
                        xAxis.append("text")
                                .attr("id", i_region_static_id + "_x_axis_label")
                                .attr("class", "x label")
                                .attr("x", innerWidth / 2)
                                .attr("y", innerHeight + 50)
                                .attr("text-anchor", "middle")
                                .text(labelGroup);

            
            //-----------------------------------------------------------------------------------
            // Y-Skalierung
            const y_scale = d3.scaleBand()
                        .range([innerHeight, 0])
                        .padding(0.03);
            
            const yAxisCall = d3.axisLeft(y_scale)
                        
            // Y-Achse erstellen
            const yAxis = g_area
                            .append("g")
                                .attr("id", i_region_static_id + "_y_axis")

                        // Einfügen yAxis Value
                        yAxis.append("g")
                            .attr("id", i_region_static_id + "_y_axis_value")
                            .attr("class", "y axis")

                        // Einfügen yAxis Label
                        yAxis.append("text")
                                .attr("id", i_region_static_id + "_y_axis_label")
                                .attr("class", "y label")
                                .attr("y", - 45)                // Y ist hierbei die horizontale ausrichtung
                                .attr("x", - innerHeight / 2)   // X ist hierbei die vertikale ausrichtung
                                .attr("transform", "rotate(-90)")
                                .attr("text-anchor", "middle")
                                .text(labelVars)

            //-----------------------------------------------------------------------------------     
            // Erstelle yColorscale
            const yColorscale = d3.scaleLinear()
                                    .range([innerHeight - 70, 0]);

            // ColorScale Legend
            const g_colorScale = g_area
                                    .append("g")
                                        .attr("id", i_region_static_id + "_colorLegend")

            // Einfügen der Color Achse
            g_colorScale.append("g")
                            .attr("id" , i_region_static_id + "_colorscale_axis")
                            .attr("transform", `translate(${innerWidth + 27},${35})`)
            
            // Einfügen des Farbbalkens
            g_colorScale.append("rect")
                            .attr("id", i_region_static_id + "_colorScale_legend")
                            .attr("x", innerWidth + 15)
                            .attr("y", 35)
                            .attr("rx", "4px")
                            .attr("width", 12)
                            .attr("height", innerHeight - 70)
                            .attr("stroke", "black")
                            .attr("stroke-width", "0.5px")
                            .attr("text-anchor", "middle")
                            .style("fill", "url(#"+ i_region_static_id + "_grad)");
 
            const g_def = g_colorScale.append("defs")
                                        .append("linearGradient")
                                            .attr("id", i_region_static_id + "_grad")
                                            .attr("x1", "0%")
                                            .attr("x2", "0%")
                                            .attr("y1", "0%")
                                            .attr("y2", "100%");
            
            //-----------------------------------------------------------------------------------               
            // Funktion für das Create, Update or Delete der D3 nodes
            function update_heatmap(data){
                const myId = data.map(function(d){return d.id});
                const myGroups = data.map(function(d){return d.group});
                const myVars = data.map(function(d){return d.variable});
                const value = data.map(function(d){return d.value});
                const extent = d3.extent(data, function(d){;return d.value}); 
                var colorArrayValue = updateColorAxis(extent[0], extent[1]);
                    colorArrayValue.push(colorMidValue);
                    colorArrayValue.sort(function(a, b){return a - b});

                const myColor = d3.scaleLinear()
                                .range([color_start, colorMid, colorEnd])
                                .domain(colorArrayValue)

                const GradColors = [myColor(updateColorAxis(extent[0], extent[1])[1]), myColor(colorMidValue), myColor(updateColorAxis(extent[0], extent[1])[0])];
                

                //----------------------------------------------------------------------------------- 
                // Dynamisches Update der X-Achse
                x_scale.domain(myGroups)
                const xAxisGroup = xAxis.select("#" + i_region_static_id + "_x_axis_value")
                                                .call(xAxisCall);

                //----------------------------------------------------------------------------------- 
                // Dynamisches Update der Y-Achse
                y_scale.domain(myVars)
                const yAxisGroup = yAxis.select("#" + i_region_static_id + "_y_axis_value")
                                                .call(yAxisCall);

                //-----------------------------------------------------------------------------------  
                // ColorScale Legend
                yColorscale.domain(updateColorAxis(extent[0], extent[1]))

                const yAxisColorCall = d3.axisRight(yColorscale)
                                                .ticks(setColorAxisTicks(updateColorAxis(extent[0], extent[1])[0], updateColorAxis(extent[0], extent[1])[1]))
                
                const yAxisColorGroup = g_colorScale.select("#" + i_region_static_id + "_colorscale_axis")
                                                .call(yAxisColorCall);

                g_def.selectAll(i_region_static_id + "stop")
                                                .data(GradColors)
                                                .enter()
                                                .append("stop")
                                                .style("stop-color", function(d){return d;})
                                                .attr("offset", function(d,i){
                                                    return 100 * (i / (GradColors.length - 1)) + "%";
                })

                //-----------------------------------------------------------------------------------  
                // Create, Delete and Update
                const rect_nodes = g_nodes.selectAll("." + i_region_static_id + "_node_grp")
                                                .data(data)

                const rect_node_grp = rect_nodes.enter()
                                                .append("g")
                                                /*each() für Create Sektion*/
                                                /*Mit der Each() wird alles in der gruppe geupdated*/
                                                .each(function(d, i) {
                                                //Append Elemente an g
                                                    d3.select(this).append('rect')   
                                                        .style("fill", function(d) {return myColor(d.value)}) 
                                                    d3.select(this).append('text')
                                                })
                                                .merge(rect_nodes)
                                                .attr("class", i_region_static_id + "_node_grp")
                                                //jedes Rect eine ID zu ordnen
                                                .attr("id", function (d){return i_region_static_id + "_node_grp_" + d.id})
                                                .attr("group", function(d) {return d.group})
                                                .attr("variable", function(d) {return d.variable})
                                                .attr("value", function(d) {return d.value})
                                                /*each() für Update Sektion*/
                                                .each(function(d, i) {
                                                    // Update meine Elemente in g tag
                                                    d3.select(this).select('rect')
                                                        .attr("class", i_region_static_id + "_node")
                                                        .transition()
                                                        .delay(50)
                                                        .attr("x", function(d) {return x_scale(d.group)})
                                                        .attr("y", function(d) {return y_scale(d.variable)})
                                                        .attr("width", x_scale.bandwidth())
                                                        .attr("height", y_scale.bandwidth())
                                                        .style("fill", function(d) {return myColor(d.value)})

                                                    d3.select(this).select('text').attr("class", i_region_static_id + "_label")
                                                        .transition()
                                                        .delay(50)
                                                        .attr("x", function(d) {return x_scale(d.group)})
                                                        .attr("y", function(d) { return y_scale(d.variable)})
                                                        .attr("dx", x_scale.bandwidth() / 2)
                                                        .attr("dy", y_scale.bandwidth() / 2)
                                                        .attr("text-anchor", "middle")
                                                        .attr("dominant-baseline", "central")
                                                        .attr("fill", function(d){return calculateContrast(myColor(d.value))})
                                                        .style("font-size", "14px")
                                                        .style("font-family", "sans-serif")
                                                        .text(function(d) {return (d.value)})
                                                    })

                rect_nodes.exit().remove()
            }

            function resize() {
                var innerWidth = parseInt(d3.select("#svg_" + i_region_static_id).style("width")) - margin.left - margin.right,
                    innerHeight

                if(parseInt(d3.select("#svg_" + i_region_static_id).style("height")) < i_height){
                    innerHeight = parseInt(d3.select("#svg_heatmap").style("height")) + margin.top + margin.bottom;
                }else{
                    innerHeight = i_height - margin.top - margin.bottom;
                }
                
                // SVG Dimension
                svg.attr("height", innerHeight)
                    .attr("width", innerWidth)

                // Aktualisieren der Range vom scale mit neuer breite und Höhe
                x_scale.range([0, innerWidth], 0.1);
                y_scale.range([innerHeight, 0]);

                // Position der X-Achse und X-Label
                xAxis
                    .call(xAxisCall)
                    .select("#" + i_region_static_id + "_x_axis_label")
                            .attr("x", innerWidth / 2)
                            .attr("y", innerHeight + 50);
                
                // Position der Y-Achse und X-Label
                yAxis
                    .call(yAxisCall)
                    .attr("transform", "translate(0," + 0 + ")")
                    .select("#" + i_region_static_id + "_y_axis_label")
                        .attr("y", - 45)
                        .attr("x", - innerHeight / 2)

                // Position ColorSkale Farb-Balken 
                g_colorScale
                        .select("#" + i_region_static_id + "_colorScale_legend")
                            .attr("x", innerWidth + 15)
                            .attr("y", 35)
                            .attr("height", innerHeight - 70)
                    
                // Position ColorSkale Achse 
                g_colorScale
                        .select("#" + i_region_static_id + "_colorscale_axis")
                            .attr("transform", `translate(${innerWidth + 27},${35})`)
    
                // D3 Kästchen dimension wird neu kalkuliert
                g_nodes.selectAll("." + i_region_static_id + "_node")
                        .attr("x", function(d) {return x_scale(d.group)})
                        .attr("y", function(d) {return y_scale(d.variable)})
                        .attr("width", x_scale.bandwidth())
                        .attr("height", y_scale.bandwidth())
                        
                // D3 Kästchen Label wir neu Positioniert
                g_nodes.selectAll("." + i_region_static_id + "_label")
                    .attr("x", function(d) {return x_scale(d.group)})
                    .attr("y", function(d) { return y_scale(d.variable)})
                    .attr("dx", x_scale.bandwidth() / 2)
                    .attr("dy", y_scale.bandwidth() / 2)
            };
            //-----------------------------------------------------------------------------------               
            d3.select(window).on('resize', resize);

            update_heatmap(data1)
        <style>
            .label{
                fill: rgba(0, 0, 0, 0.65);
                font-size: 18px;
                font-weight: bold;
                font-family: sans-serif;
            }

            .axis{
                color: rgba(0, 0, 0, 0.65);
                font-size: 16px;
                font-family: arial;
            }

            #svg_heatmap {
                width: 100%;
                height: 100%;
                position: absolute;
            } 
<html>             
    <head>              
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title> 1.Grundgerüst </title>
    </head>
    <body>             
        <svg id="svg_heatmap"></svg>
        <script src=".v7.js" charset="utf-8"></script>
        <script src="" charset="utf-8"> </script> 
    </body>
</html>
发布评论

评论列表(0)

  1. 暂无评论