Search code examples
javascriptjqueryd3.jswindow-resize

Unable to make jQuery resize event work as expected


I have this function which draws a chart on several divs, This resize event handler code I came up with make the chart to be responsive, but, only in the following sequence: 1) Resize my browser , 2) Manually reloading the webpage.

when I resize the browser, the whole page becomes totally blank, then if I reload the browser the charts are drawn adjusting perfectly to the new dimensions, but this is not as it should be, as the end user wont be so happy having to reloading the page each time the browser is resized.

The problem is even bigger if the page is visualized in a mobile device, because when first loading the charts will adjust perfectlty to the device's dimensions, but if the user rotate the device and change to 'landscape' mode, as I mentioned the whole screen will get blank until the user make a reload. Can you see my code to give me some clues about what I am doing wrong? Thanks.

$(document).ready(function(){
  draw("chartDivs1");
  draw("chartDivs2");
  draw("chartDivs3");
  draw("chartDivs4");

  $(window).resize(function() {
       $(".chartDivs1,.chartDivs2,.chartDivs3,.chartDivs4,.chartDivs6,").empty();
    draw("chartDivs1");
    draw("chartDivs2");
    draw("chartDivs3");
    draw("chartDivs4");
    });
  })

function draw(chartDiv) {	

  //set width and height in function of the div where my chart will be rendered.
  var width = $("."+chartDiv).width();
  var height = $("."+chartDiv).height()

  //declare the data (I must change this for a parameter).

  var data = [
  { country: "Moon",growth: 40},
  { country: "India", growth: 35},
  {country: "Indonesia",growth: 30},
  {country: "Russia",growth: 25},
  {country: "Mars",growth: 20},
  {country: "Pluton",growth: 15},
  {country: "House",growth: 10},
  {country: "Neptune",growth: 5}
  ];

  //set margins
  var margin = {
  top: 20,
  right: 30,
  bottom: 30,
  left: 40
  };
  var width = width - margin.left - margin.right * 2.5;
  var height = height - margin.top - margin.bottom;

  //set scales & ranges

  var xScale = d3.scaleLinear()
  .range([0, width * 1.1 ])

  var yScale = d3.scaleBand()
  .range([30, height]).padding(.3)

  //draw the svg

  var svg = d3.select("."+chartDiv)
  .append("svg")
  .attr("width", width + margin.left + margin.right * 3)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left *1.4  + "," + margin.top + ")")

  //Add a Title
  svg.append("text")
  .attr("x", (width / 2))             
  .attr("y", 11 )
  .attr("text-anchor", "middle")  
  .style("font-size", "16px") 
  .style("text-decoration", "underline")  
  .text("Title");

  //force data
  data.forEach(function(d) {
  return d.growth = +d.growth;
  });

  //set domains

  yScale.domain(data.map(d => d.country))

  xScale.domain([0, d3.max(data, d => d.growth)])

  //add X & Y axes and append the bars to Y axis

  var xAxis = svg.append("g")
  .attr("class", xAxis)
  .attr("transform", "translate(" + 0 + "," + height + ")")
  .call(d3.axisBottom(xScale))

  var yAxis = svg.append("g")
  .attr("class", yAxis)
  .call(d3.axisLeft(yScale))
  .selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("stroke", "transparent")
  .attr("stroke-width", 4)
  .attr("class", "bar")
  .attr("height", yScale.bandwidth())
  .attr("x", 0.5)
  .attr("y", function(d) {
  return yScale(d.country)
  })
  .attr("width", 0)
  .transition()
  .duration(3800)
  .delay((d, i) => (i + 1) * 200)
  .ease(d3.easeElastic)
  .attr("width", function(d) {
  return xScale(d.growth)
  })
  .style("fill", "#00338D")
  .on('end', function() {
  d3.select(this)
  .on("mouseover", function() {
  d3.select(this)
  .transition().duration(600)
  .attr("stroke", "#6D2077")
  .attr("stroke-width", 3)
  .style("fill", "#6D2077")
  d3.selectAll(".textCircle")
  .transition().duration(600)
  .attr("r", yScale.bandwidth() / 1.9)
  .attr("stroke", "#6D2077")
  .attr("stroke-width", 1)
  })
  .on("mouseout", function() {
  d3.select(this)
  .transition()
  .duration(600)
  .attr("stroke", "transparent")
  .attr("stroke-width", 0)
  .style("fill", "#00338D")
  d3.selectAll(".textCircle")
  .transition().duration(600)
  .attr("r", yScale.bandwidth() / 2)
  .attr("stroke", "transparent")
  })
  })

  var newG = svg.append("g")
  newG.selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("class", "textCircle")
  .attr("cx", d => xScale(d.growth))
  .attr("cy", d => yScale(d.country) + yScale.bandwidth() / 2)
  .attr("r", 0)
  .transition()
  .duration(1200)
  .delay((d, i) => (i + 1) * 450)
  .attr("r", yScale.bandwidth() / 2)
  .attr("opacity", 1)
  .style("fill", "#005EB8")
  .attr("stroke", "transparent")
  .ease(d3.easeElastic)

var newG4text = svg.append("g").attr("class","newG4text")

  newG4text.selectAll(".text").data(data)
  .enter()
  .append("text")
  .attr("x", d => xScale(d.growth))
  .attr("y", d => yScale(d.country) + yScale.bandwidth()/2)
  .attr("dx","-.45em")
  .attr("dy",".4em")
  .style("font-size",".8em")
  .style("fill","#FFF")
  .text(d=>d.growth)
  }	
html{ 
		  height: 98%;
		  margin: 0;
		  padding: 0;
		}

		body{
		  min-height: 98%;
		  margin: 0;
		  padding: 0;
		}

		svg{
		  text-rendering: geometricPrecision;
		  shape-rendering:geometricPrecision;
		}
		
		.chCols{
			border: 1px groove #333333;
		}
			
		.halfVh{
			height: 50vh;
		}
		
		.flex-container{
			display:flex;
			-ms-align-items: ;
			align-items: center;
			justify-content: center;
		}
<!-- CDNs-->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.4/js/tether.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js"></script>

<!-- End of CDNs-->

<div class="container-fluid">
  <div class="row halfVh">
    <div class="col-4 chartDivs1 chCols "></div>
    <div class="col-4 chartDivs2 chCols "></div>
    <div class="col-4 chartDivs3 chCols"></div>
  </div>	
  <div class="row halfVh">
    <div class="col-4 chartDivs4 chCols flex-container"></div>
    <div class="col-4 chartDivs5 chCols flex-container">
       ...coming soon.
    </div>
    <div class="col-4 chartDivs6 chCols flex-container">
        ...coming soon.
    </div>
  </div>
</div>


Solution

  • You have a typo on resize method. Remove the , from last when you are emptying the charts on resize.

    $(".chartDivs1,.chartDivs2,.chartDivs3,.chartDivs4,.chartDivs6").empty();
    

    Worked for me :)