Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <div class="crumbs">
  <!-- Crumbs dynamically appended -->
</div>

<div class="container">
  <div class="chart"></div>
</div>


              
            
!

CSS

              
                @import url(https://fonts.googleapis.com/css?family=Montserrat);

.crumbs {
  width:100%;
  height:50px;
  font:16px Montserrat, sans-serif;
  align-self:flex-start;
  background:lightgrey;
  
  .crumb {
    position:relative;
    display:inline-block;
    padding:1em;
    
    &:not(:last-of-type) { 
      &:before {
        content:'';
        display:block;
        position:absolute;
        border-top:5px solid transparent;
        border-left:10px solid #658ed0;
        border-bottom: 5px solid transparent;
        top:21px;
        right:-5px;
      }
    }
  }
}

.container {
  width:100%;
  height: 100vh;
  display:flex;
  justify-content:center;
  background:whitesmoke;
  
  .chart {
    width:500px;
    height:500px;
    align-self:center;
  }
}

/*********************
 SVG Elements styling 
*********************/
svg text {
  text-anchor:middle;
}

.ark {
  fill-rule: evenodd;
  cursor:pointer;
  
  &.-depth-0 { fill:white; }
}


              
            
!

JS

              
                // RAW DATA

var text = "website,7\n\
WebPage,1\n\
schema.orgBreadcrumbList-schema.orgListItem-schema.orgWebPage,1\n\
product.group,2\n\
Product-website,2\n\
Organization-website,1\n\
Organization-WebPage,1\n\
Organization-SearchAction-WebSite,1\n\
Organization-product.group,1\n\
Organization,1\n\
ListItem,1\n\
ItemList-Offer-Product-website,1\n\
ContactPoint-Organization-Product-WebSite,1\n\
BreadcrumbList-ListItem-website,4\n\
BreadcrumbList-ListItem-WebSite,1\n\
BreadcrumbList-ListItem-WebPage,1\n\
BreadcrumbList-ListItem-rating-Review-aggregate,1\n\
BreadcrumbList-ListItem-product,2\n\
BreadcrumbList-ListItem-Organization-SearchAction-Service-SiteNavigationElement-WebSite,1\n\
BreadcrumbList-ListItem-Organization,1\n\
BreadcrumbList-ListItem-Offer-Product-WebPage-WebPageElement,1\n\
BreadcrumbList-ListItem-Offer-Product-SiteNavigationElement-WebPage,1\n\
BreadcrumbList-ListItem-Offer-Product-SiteNavigationElement-sport,1\n\
BreadcrumbList-ListItem-Offer-Product-SearchAction-WebPage-WebSite,1\n\
BreadcrumbList-ListItem-Offer-Organization-Product-Store,1\n\
BreadcrumbList-ListItem-Offer-Organization-Product-site-Thing,1\n\
BreadcrumbList-ListItem-Offer-Organization-Product,1\n\
BreadcrumbList-ClothingStore-ListItem-Offer-og:product-PostalAddress-Product-WebSite,1\n\
Breadcrumb-SearchAction-WebSite,1\n\
Breadcrumb-Organization-WebPage,1\n\
Breadcrumb-Offer-Organization-PostalAddress-Product-website,1\n\
Breadcrumb-BreadcrumbList-ClothingStore-ListItem-OfferCatalog-PostalAddress-Product-WebPage-WebSite,1\n\
Breadcrumb-BreadcrumbList-ClothingStore-ItemList-ListItem-PostalAddress-Product-WebPage-WebSite,1\n\
Breadcrumb,2\n\
Brand-BreadcrumbList-ListItem-Offer-Product,1\n\
Brand-BreadcrumbList-ListItem-offer-Organization-Product-PropertyValueSpecification-SearchAction-website,1\n\
article-Organization-Person,1\n\
article-Offer-Organization-Product,1\n\
article-BreadcrumbList-ImageObject-InteractionCounter-ListItem-NewsArticle-Organization-Person-WebPage,1\n\
article-Breadcrumb-ImageObject-NewsArticle-Organization,1\n\
article-Breadcrumb-ContactPoint-Organization-SearchAction,1\n\
article-Breadcrumb,1\n\
article,2\n\
AggregateRating-Organization,1\n\
AggregateRating-BreadcrumbList-ListItem-Product-SiteNavigationElement-WebPage-website,1\n\
AggregateRating-BreadcrumbList-ListItem-Offer-Organization-Product,1\n\
AggregateRating-article-BreadcrumbList-ContactPoint-ListItem-OpeningHoursSpecification-Organization-Place-PostalAddress-SearchAction,1\n";


// BEGIN DATA MANIPULATION
var csv = d3.csv.parseRows(text);
var data = buildHierarchy(csv);

// Take a 2-column CSV and transform it into a hierarchical structure suitable
 // for a partition layout. The first column is a sequence of step names, from
 // root to leaf, separated by hyphens. The second column is a count of how 
 // often that sequence occurred.
 function buildHierarchy(csv) {
   var root = {"name": "root", "children": [], id: 'ROOT'};
   
   for (var i = 0; i < csv.length; i++) {
     var sequence = csv[i][0];
     var size = +csv[i][1];
     
     if (isNaN(size)) { // e.g. if this is a header row
       continue;
     }
     
     var parts = sequence.split("-");
     var currentNode = root;
     for (var j = 0; j < parts.length; j++) {
       var children = currentNode["children"];
       var nodeName = parts[j];
       var childNode;
       console.log(childNode)
       if (j + 1 < parts.length) {
         // Not yet at the end of the sequence; move down the tree.
         var foundChild = false;

         for (var k = 0; k < children.length; k++) {
           if (children[k]["name"] == nodeName) {
             childNode = children[k];
             foundChild = true;
             break;
           }
         }
         
         // If we don't already have a child node for this branch, create it.
         if (!foundChild) {
           childNode = { "name": nodeName, "children": [], id: create_id() };
           children.push(childNode);
         }

         currentNode = childNode;

       } else {
         // Reached the end of the sequence; create a leaf node.
         childNode = {"name": nodeName, "value": size, id: create_id() };
         children.push(childNode);
       }
     }
   }
     
   return root;
 };

// Retrieved from https://gist.github.com/gordonbrander/2230317
function create_id() {
  return '_' + Math.random().toString(36).substr(2, 9);
};


// END DATA MANIPULATION

// log out deep clone of data for review
//console.debug(JSON.parse(JSON.stringify(data)));








/*********************
 BEGIN BUILDING CHART
 ********************/


// Size/state related variables
var width = 500,
    height = 500,
    outer_radius = width/2.5,
    arc_transition; // save current arc transition

// Create scales
var x = d3.scale.linear()
      .range([0, 2 * Math.PI]),
    
    y = d3.scale.sqrt()
      .range([0, width/2]),
    
    color = d3.scale.category20c();

// Partition layout
var partition = d3.layout.partition(),
    nodes = partition.nodes(data);

// Arc generator
var arc_generator = d3.svg.arc()
      .startAngle(function(d) { 
        return Math.max(0, Math.min(2 * Math.PI, x(d.x))); 
      })
      .endAngle(function(d) { 
        return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); 
      })
      .innerRadius(function(d) { 
        return Math.max(0, y(d.y)); 
      })
      .outerRadius(function(d) { 
        return Math.max(0, y(d.y + d.dy)); 
      });

// Append a centered group for the burst to be added to
var burst_group = d3.select('.chart')
                   .append('svg')
                   .attr({
                     width: width,
                     height: height
                   })
                   .append('g')
                   .attr('transform', 'translate(' + width/2 + ',' + height/2 + ')');

// Append Arcs
var arcs = burst_group.selectAll("path.ark")
    .data( nodes )
    .enter().append("path")
    .attr({
      d: arc_generator,
      class: function(d) { return 'ark -depth-' + d.depth; }
    })
    .style("fill", function(d,i) { 
      if (d.depth > 0) return color(i); 
    })
    .on("click", click)
    .on('mouseover', function(d) {
      if (d.depth > 0) {
        var ids = getIDArray(d);
        fade(arcs, 0.1, ids, 'id'); 
        update_crumbs(d);
      }
    })
    .on('mouseout', function(d) {
      fade(arcs, 1);
      remove_crumbs();
    });

// Updates breadcrumbs
function update_crumbs(d) {
  var crumb_container = d3.select('.crumbs'),
      sections = getNameArray(d);
  
  // Remove existing crumbs
  remove_crumbs();
  
  // Append new crumbs
  sections.reverse().forEach(function(name) {
    crumb_container.append('span')
      .classed('crumb', true)
      .text(name);
  });
};

// Removes all crumb spans
function remove_crumbs() {
  d3.select('.crumbs').selectAll('.crumb').remove();
};

// Handle Clicks
function click(d) {
  arc_transition = arcs.transition('arc_tween')
    .duration(750)
    .attrTween("d", arcTween(d));
};

// Retrieve arc name and parent names
function getNameArray(d, array) {
  array = array || [];

  // Push the current objects name to the array
  array.push(d.name);

  // Recurse to retrieve parent names
  if (d.parent) getNameArray(d.parent, array);

  return array;
};

// Retrieve arc name and parent names
function getIDArray(d, array) {
  array = array || [];

  // Push the current objects name to the array
  array.push(d.id);

  // Recurse to retrieve parent names
  if (d.parent) getIDArray(d.parent, array);

  return array;
};

// Interpolate the scales!
function arcTween(d) {
  var xd = d3.interpolate( x.domain(), [d.x, d.x + d.dx] ),
      yd = d3.interpolate( y.domain(), [d.y, 1] ),
      yr = d3.interpolate( y.range(), [d.y ? 20 : 0, outer_radius] );

  return function(d, i) {
    return i
        ? function(t) { return arc_generator(d); }
        : function(t) { 
            x.domain( xd(t) ); 
            y.domain( yd(t) ).range( yr(t) ); 
      
            return arc_generator(d); 
        };
  };
};

// Fade a selection filtering out the comparator(s)
function fade(selection, opacity, comparators, comparatee) {
  var type = typeof comparators,
      key = comparatee ? comparatee : 'value';

  selection.filter(function(d, i) {
                // Remove elements based on a string or number
                if (type === "string" || type === "number") {
                  return d[key] !== comparators;

                // Remove elements based on an array
                } else if (type === 'object' && typeof comparators.slice === 'function') {
                  return comparators.indexOf(d[key]) === -1;

                // If there is no comparator keep everything 
                } else return true;
            })
            .transition('fade')
            .duration(250)
            .style('opacity', opacity);
};


              
            
!
999px

Console