Jump to content

How to determine location of D3 visualization within page

Recommended Posts

Site URL: https://metrosight.com

Hi.

I'm creating a new blog post that includes, about halfway through, a D3 visualization.

The visualization works (I've figured out how to use the D3 script and external data when their placed on S3, need the right CORS settings, and pass-thru settings for Cloudfront... solved!).

However, even though the code block is in the right spot halfway through the page, the visualization shows up *at the top* of the blog post--not where I need it.

The key line in the D3 script is:

var svg = d3.select(".sqs-block-content").append("svg")

What should I use instead of ".sqs-block-content" in the select function to get it to show up in the right spot? 

(Or is there some other solution?)

Thanks in advance,

Issi

Edited by evEriceBriTU
Use my name
Link to comment
  • Replies 4
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Posted Images

It's still a draft and I don't want it public yet, so no link. But here's a screenshot.

Despite what I wrote above, the D3 shows up below the very first text block, but above everything else. There are many paragraphs and charts below, and the D3 code block is located beneath them, yet shows up above them.

image.thumb.jpeg.05e539afa519af22bceb8cae10442f96.jpeg

Link to comment
11 hours ago, tuanphan said:

Hope someone will help you. It's hard to visualize d3's code structure without seeing it.

Here is the D3 code:

<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">

<!-- JavaScript Libraries //-->
<script src="https://d3pgfruru6j1ty.cloudfront.net/paying-for-dirt-where-have-home-values-detached-from-construction-costs/d3.min.js"></script>

<!-- CSS Style //-->
<style>


body {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  position: relative;
  width: 800px;
}

.axis text {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.y.axis path {
  display: none;
}

.tick line {
  opacity: 0.1;
}

</style>

</head>

<body>

<script>
var 
    gross_width = 900, 
    margin = {top: 20, right: 20, bottom: 40, left: 250},
    width = gross_width - margin.left - margin.right,
    height = 700 - margin.top - margin.bottom
;

var axis_format = d3.format("r.0");
var mouseover_format = d3.format(".2f")

var base_opacity = 0.5

var y = d3.scale.ordinal()
    .rangeRoundBands([0,height], .1, 0);

var x = d3.scale.linear()
    .range([0, width/2]);

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("top")
    .tickFormat(axis_format)
    .innerTickSize(-height)
    .outerTickSize(2);

var text_for_Val_to_CC_ratio_2016 = [
  "Home Value to Replacement Cost Ratio:",
  " ",
  "When this ratio is high it indicates a disparity between homes' price",
  "tag and appearance because home values mostly correspond to land.",
  "This is the case in the expensive coastal metros, in which the housing ",
  "supply is restricted (Las Vegas is an exception, due to particularly low",
  "replacement costs).",
  " ",
  "When the ratio is more modest, roughly between 1 and 1.5 as in places",
  "like Atlanta and Houston, it indicates that cities are producing enough",
  "new housing to keep home values loosely tethered to construction cost.",
  "Even in these cities, however, home values incorporate a non-negligible",
  "land component, especially in sought-after locations.",
  " ",
  "When the ratio is low enough for replacement costs to exceed home",
  "values, i.e. it is below one, it most often indicates that the demand for",
  "housing in a city has receded below the peak historic level that",
  "determined the size of the existing housing stock. Under these",
  "circumstances, new residential construction is unlikely to be financially",
  "viable.",
  " ",
  "Note that the ratio of home value to improvement value can be high if",
  "land values are high, or if the housing stock is in poor repair and",
  "hence depreciated. Substituting replacement cost for improvement",
  "value in the ratio avoids the need to tell apart these situations,",
  "which is especially important at the zip code level). Moreover, the",
  "ratio used does not depend on the assumed form of depreciation.",
  " ",
  "See Data and Methodology Section for details."
];

var text_for_Est_Avg_Home_Val_2016 = [
  "Average Home Value:",
  " ",
  "The value of a home reflects the amount for which it can expect to be",
  "sold. This amount does not depend on construction costs directly.",
  "Home values can greatly exceed the cost of construction, as they do in",
  "California, and they can fall below it, as they do in the Rust Belt.",
  "Nevertheless, when opportunities to build homes are abundant, as they",
  "are in Texas for example, construction costs influence the value of",
  "homes.",
  " ",
  "When opportunities to build homes are abundant, competition among",
  "developers drives down the price of new homes, but never below",
  "developers’ costs. Under these circumstances, developers' costs",
  "correspond largely to construction, because abundant opportunities",
  "to build imply that land value per home is modest (though not",
  "necessarily per acre, as opposed to per home).",  
  " ",
  "When enough new homes are produced to keep their prices tethered",
  "to construction costs, this keeps the value of existing homes in check,",
  "too.",
  " ",
  "See Data and Methodology Section for details."
];

var text_for_Est_Avg_Unit_Repl_Cost_2016 = [
  "Average Replacement Cost Per Home:",
  " ",
  "The replacement cost of an existing home is the cost of building it anew",
  "at current quality standards and construction costs. Different than the",
  "improvement value, the replacement cost of a home reflects its value if",
  "it were in mint condition.",
  " ",
  "The average replacement cost per home does not vary greatly across",
  "U.S. metro areas. The highest values, found in coastal California, are",
  "about twice as large as the lowest values, found in the Las Vegas and", 
  "Houston metro areas.",
  " ",
  "The differences in replacement costs correspond to differences in the",
  "cost of constructing identical structures across places - driven mostly",
  "by the cost of labor - but they also reflect differences in the nature of",
  "new homes built in each area. For instance, homes in Houston and",
  "Las Vegas are likelier to be found in subdivisions built en masse with",
  "corresponding economies of scale, whereas homes in the expensive",
  "coastal metros are (relatively) more likely to represent costlier infill",
  "development. The typical size and characteristics of homes may differ",
  "across metros as well, e.g. with respect to the single-family versus",
  "multifamily mix, as well as more nuanced home characteristics.",
  " ",
  "See Data and Methodology Section for details."
];

var text_for_Est_Imp_Val_2016 = [
  "Average Improvement Value Per Home:",
  " ",
  "The improvement value of a home reflects the value of the physical",
  "structure, as well as other improvements to the land such as driveways,",
  "grading and landscaping, that are distinct from the value of the land.",
  "Different than the replacement cost, the improvement value of a home",
  "reflects its current state of repair. In this study, improvement values",
  "are approximated by applying a common depreciation formula.",
  " ",
  "The average improvement value per home does not vary greatly",
  "across U.S. metro areas - even less so than replacement costs. The",
  "highest values, found on the West Coast, are about twice as large",
  "as the lowest values, found in the Philadelphia, Providence and",
  "Hartford metro areas.",
  " ",
  "This study approximates improvement values by depreciating",
  "replacement costs according to the existing housing stock's age",
  "structure. Thus, improvement values are more (less) similar to",
  "replacement costs in metros which have seen more (less) growth in",
  "recent decades, and whose housing stock is therefore younger",
  "(older).",
  " ",
  "See Data and Methodology Section for details."
];

var text_for_Est_Land_Val_2016 = [
  "Average Land Value Per Home:",
  " ",
  "The land value per home is the difference between the full value of a",
  "home and the value of the improvements - essentially the structure.",
  " ",
  "The average land value per home varies drastically across U.S. metros,",
  "ranging from close to a million dollars per home in the San Jose and",
  "San Francisco metro areas, down to near-negligible levels in the",
  "Buffalo and Indianapolis metros.",
  " ",
  "The stark differences in land value per home are driven largely by",
  "land use policy enacted in the expensive coastal metros since the",
  "1970s, which has inhibited these cities' growth. These metro areas",
  "have gradually slowed down their outward expansion, i.e. they have",
  "had success in stemming sprawl, but they have failed to compensate",
  "through densification. As a result, the economic vitality of these",
  "metros has been channeled away from population growth and into",
  "housing price growth. Housing price appreciation in these metros",
  "keeps population proportional to the housing stock by selectively",
  "determining who can and cannot afford to live there.",
  " ",
  "See Data and Methodology Section for details."  
];

var options_list = [
  ["Val_to_CC_ratio_2016", "Home Value to Replacement Cost Ratio", "Ratio", "#898E8C", text_for_Val_to_CC_ratio_2016],
  ["Est_Avg_Home_Val_2016", "Average Home Value", "($'000)", "#005960",
    text_for_Est_Avg_Home_Val_2016],
  ["Est_Avg_Unit_Repl_Cost_2016", "Average Replacement Cost Per Home", "($'000)", "#9C9A40",
    text_for_Est_Avg_Unit_Repl_Cost_2016],
  ["Est_Imp_Val_2016", "Average Improvement Value Per Home", "($'000)", "#4F84C4",
    text_for_Est_Imp_Val_2016],
  ["Est_Land_Val_2016", "Average Land Value Per Home", "($'000)", "#D2691E",
    text_for_Est_Land_Val_2016]
];
// Colors; https://www.w3schools.com/colors/colors_trends.asp

var selected_option = options_list[0];

var svg = d3.select(".sqs-block-content").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })
    .data(options_list)
    .enter().append("g")
      .attr("id", "option"); 

svg.append("text")
  .attr("y", height + 15)
  .attr("x", 0) 
  .style("font", "10px sans-serif")
  .style("text-anchor", "start")
  .style("opacity", 1)     
  .text("Source: BuildZoom.")  
;

svg.append("text")
  .attr("y", height + 30)
  .attr("x", 0) 
  .style("font", "10px sans-serif")
  .style("text-anchor", "start")
  .style("opacity", 1)     
  .text("Notes: All numbers refer to 2016. See Data and Methodology Section for details.")  
;

d3.tsv("https://d3pgfruru6j1ty.cloudfront.net/paying-for-dirt-where-have-home-values-detached-from-construction-costs/CBSAs.tsv", function(error, data) {

  data.forEach(function(d) {
    d.Est_Avg_Home_Val_2016 = +d.Est_Avg_Home_Val_2016; 
    d.Est_Avg_Unit_Repl_Cost_2016 = +d.Est_Avg_Unit_Repl_Cost_2016; 
    d.Est_Imp_Val_2016 = +d.Est_Imp_Val_2016; 
    d.Est_Land_Val_2016 = +d.Est_Land_Val_2016; 
    d.Val_to_CC_ratio_2016 = +d.Val_to_CC_ratio_2016;   
  });

  y.domain(data.map(function(d) { return d.cbsa_name; }));
  x.domain([0, 1.1 * d3.max(data, function(d) { return d.Val_to_CC_ratio_2016; }) ]);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .selectAll("text")
      .attr("x", -10)
      .attr("y", 0)
      .style("text-anchor", "end")
  ;

  svg.append("g")
      .attr("class", "x axis")
      .call(xAxis)
  ;

  svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })    
    .append("text")
      .attr("y", function(d,i) { return 22.5 + i * 25 + "px"; })
      .attr("x", 355 ) 
      .style("font", "10px sans-serif")
      .style("text-anchor", "start")
      .style("opacity", 1)     
      .text(function (d) { return d[1]; })                   
    .on("click", function(d) { change(d); })
  ;      

  svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })
    .append("rect")
      .attr("y", function(d,i) { return 10 + i * 25 + "px"; })
      .attr("height", 20)
      .attr("x",  350)
      .attr("width", 220)
      .attr("rx", 5)
      .style("fill", function(d) { return d[3]; } )
      .style("fill-opacity", base_opacity) 
      .style("stroke", "black")                      
      .style("stroke-width", 2)                            
      .style("stroke-opacity", function(d) { return base_opacity * +Boolean(d===selected_option) ; })
    .on("click", function(d) { change(d); })
    .on("mouseover", function(d) { 
        d3.select(this)
          .transition()
          .duration(100)
          .style("fill-opacity", 0.5*base_opacity);
      })          
      .on("mouseout", function(d) {
        d3.select(this)
          .transition()
          .duration(200)
          .style("fill-opacity", base_opacity);                     
      })    
  ;

  svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })    
    .append("rect")
      .attr("id", "option_commentary")
      .attr("y", 140 + "px")
      .attr("height", height - margin.bottom - 140)
      .attr("x",  240)
      .attr("width", 330)
      .attr("rx", 10)
      .style("fill", function(d) { return d[3]; } )
      .style("fill-opacity", function(d) { return 0.25*base_opacity * +Boolean(d===selected_option) ; })
  ;

  svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })    
    .append("text")
      .attr("id", "option_commentary")
      .attr("y", "150px")
      .style("font", "10px sans-serif")
      .style("text-anchor", "start")
      .style("opacity", function(d) { return +Boolean(d===selected_option) ; })           
      .selectAll("g").filter(function() { return this.id==="option" ? this : null; }) 
        .data(function(d) { return d[4]; })
        .enter()
        .append("tspan").text(function(d,i) { return d; })
          .attr("font-weight", function(d,i) { return i===0 ? 700 : 400; })
          .attr("x",250)
          .attr("dy", "15px")
  ;

  svg.selectAll("text").filter("text#axis_title")
    .data(options_list).enter().append("text")
      .attr("id", "axis_title")
      .attr("x", -10)
      .attr("y", -2)
      .attr("opacity", function (d) { return +Boolean(d[0]==="Val_to_CC_ratio_2016"); })        
      .style("font", "10px sans-serif")
      .style("text-anchor", "end")
      .text(function (d) { return d[2]; })
  ;

  svg.selectAll("g").filter(function(d, i) { return this.id==="bar" ? this : null; })
    .data(data)
    .enter().append("g")
      .attr("id", "bar")
  ;

  svg.selectAll("g").filter(function(d, i) { return this.id==="bar" ? this : null; })
      .append("rect")
        .attr("y", function(d) { return y(d.cbsa_name); })
        .attr("height", y.rangeBand())
        .attr("x", 0)
        .attr("width", function(d) { return x(d.Val_to_CC_ratio_2016); })
        .style("fill", selected_option[3])
        .style("fill-opacity", base_opacity)            
  ;

  svg.selectAll("g").filter(function(d, i) { return this.id==="bar" ? this : null; })        
      .append("text")
        .attr("y", function(d) { return y.rangeBand() + (y.rangeBand()-10)/2 + y(d.cbsa_name) + "px"; })        
        .attr("x", function(d) { return x(d.Val_to_CC_ratio_2016) + 5 + "px"; })  
        .style("font", "10px sans-serif")
        .style("text-anchor", "start")
        .style("opacity", 0)           
        .text(function(d) { return mouseover_format(d.Val_to_CC_ratio_2016); })
  ; 

  svg.selectAll("g").filter(function(d, i) { return this.id==="bar" ? this : null; })       
      .selectAll("rect")
      .on("mouseover", function(d) { 
        d3.select(this)
          .transition()
          .duration(100)
          .style("fill-opacity", 1);   
        d3.select(this.parentNode)
          .select("text")
          .transition()
          .duration(100)
          .style("opacity",1 );              
      })          
      .on("mouseout", function(d) {
        d3.select(this)
          .transition()
          .duration(200)
          .style("fill-opacity", base_opacity);   
        d3.select(this.parentNode)
          .select("text")
          .transition()
          .duration(100)
          .style("opacity",0);                     
      })
  ; 

  var sortTimeout = setTimeout(function() {
    change(selected_option);
  }, 0);

  function change(selected_option) {
    // Copy-on-write since tweens are evaluated after a delay.
    var sort_var = selected_option[0]
    var color = selected_option[3]

    var y0 = y.domain(data.sort(function(a, b) { return b[sort_var] - a[sort_var]; })
        .map(function(d) { return d.cbsa_name; }))
        .copy();

    svg.selectAll(".bar")
        .sort(function(a, b) { return y0(a.cbsa_name) - y0(b.cbsa_name); });

    x.domain([0, 1.1 * d3.max(data, function(d) { return d[sort_var]; }) ]);

    svg.selectAll("text").filter("text#axis_title").each(function(d) {
        d3.select(this).attr("opacity", +Boolean(d[0]===sort_var));
    });

    svg.selectAll("g").filter(function() { return this.id==="option" ? this : null; })
      .selectAll("rect")
        .style("stroke-opacity", function(d) { return base_opacity * +Boolean(d===selected_option) ; })
    ;

    var transition = svg.transition().duration(750),
        delay = function(d, i) { return i * 50; };

    transition.selectAll("g").filter(function() { return this.id==="bar" ? this : null; }) 
        .delay(delay)
        .selectAll("rect")
        .attr("y", function(d) { return y0(d.cbsa_name); })
        .attr("width", function(d) { return x(d[sort_var]); })
        .style("fill", color)
    ;

    transition.selectAll("g").filter(function() { return this.id==="bar" ? this : null; }) 
        .delay(delay)
        .selectAll("text")
        .attr("y", function(d) { return y.rangeBand() + (y.rangeBand()-10)/2 + y(d.cbsa_name) + "px"; })        
        .attr("x", function(d) { return x(d[sort_var]) + 5 + "px"; })  
        .text(function(d) { return mouseover_format(d[sort_var]); })        
    ;

    transition.select(".y.axis")
        .call(yAxis)
      .selectAll("g")
        .delay(delay)
      .selectAll("text")
        .attr("x", -10)
        .attr("y", 0)
        .style("text-anchor", "end")
    ;  

    transition.select(".x.axis")
        .call(xAxis)
      .selectAll("g")
        .delay(delay)
      .selectAll("text")
    ;

    transition.selectAll("g").filter(function() { return this.id==="option" ? this : null; })
      .selectAll("rect").filter(function() { return this.id==="option_commentary" ? this : null; })
        .style("fill-opacity", function(d) { return 0.25*base_opacity * +Boolean(d===selected_option) ; })
    ;

    transition.selectAll("g").filter(function() { return this.id==="option" ? this : null; })
      .selectAll("text").filter(function() { return this.id==="option_commentary" ? this : null; })
        .style("opacity", function(d) { return +Boolean(d===selected_option) ; })
    ;    
  } 
}); 

</script>

</body>
</html>

 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

×
×
  • Create New...

Squarespace Webinars

Free online sessions where you’ll learn the basics and refine your Squarespace skills.

Hire a Designer

Stand out online with the help of an experienced designer or developer.