function my(){

    // Use the data passed into the .data() accessor.
    if(data){

      // Set properties that may have been reconfigured via accessors.
      chord.padAngle(padAngle);
      color.range(colors);

      // Compute things that depend on width and height.
      var side = Math.min(width, height),
          outerRadius = side / 2 - outerPadding,
          innerRadius = outerRadius - arcThickness;
      ribbonsG
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
      chordGroupsG
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
      ribbon.radius(innerRadius);
      arc
        .innerRadius(innerRadius)
        .outerRadius(outerRadius);
      backgroundRect
        .attr("width", width)
        .attr("height", height);

      // Pre-process the data and calculate the Chord Diagram layout.
      var matrix = generateMatrix(data),
          chords = chord(matrix);

      // Use alphanumerically sorted source and destination names
      // for the color scale domain for consistent colors across refreshes.
      color.domain(matrix.names.slice().sort());

      // Render the ribbons of the Chord Diagram (the connecting fibers inside the circle).
      var ribbons = ribbonsG
        .selectAll("path")
          .data(chords);
      ribbons = ribbons.enter().append("path").merge(ribbons);
      ribbons
        .attr("d", ribbon)
        .style("fill", function(d) {
          return color(matrix.names[d.source.index]);
        })
        .style("stroke", "black")
        .style("stroke-opacity", 0.2)
        .style("cursor", onSelectedRibbonChangeCallback ? "pointer" : "")
        .call(setRibbonOpacity)
        .on("mousedown", function (d){
          my.selectedRibbon(ribbonData(d));
        })
        .on("mouseover", function (d){
          if(onChordHover) onChordHover(ribbonData(d));
        })
        .on("mouseout", function (d){
          if(onChordHover) onChordHover(null);
        });
      ribbons.exit().remove();

      function ribbonData(d) {
        return {
          sourceIndex: d.source.index,
          targetIndex: d.target.index,
          source: matrix.names[d.source.index],
          destination: matrix.names[d.target.index],
          sourceValue: d.source.value,
          destinationValue: d.target.value
        };
      }

      // Scaffold the chord groups.
      var chordGroups = chordGroupsG.selectAll("g").data(chords.groups);
      var chordGroupsEnter = chordGroups.enter().append("g");
      chordGroupsEnter.append("text");
      chordGroupsEnter.append("path");
      chordGroups.exit().remove();
      chordGroups = chordGroups.merge(chordGroupsEnter);

      // Compute locals.
      chordGroups
        .each(function(group) {

          angle.set(this, (group.startAngle + group.endAngle) / 2);

          flip.set(this, angle.get(this) > Math.PI);

          selected.set(this, selectedRibbon &&
            (
              (selectedRibbon.sourceIndex === group.index) ||
              (selectedRibbon.targetIndex === group.index)
            )
          );
        })

      // Add labels
      chordGroups
        .select("text")
          .attr("transform", function() {
            return [
              "rotate(" + (angle.get(this) / Math.PI * 180 - 90) + ")",
              "translate(" + (outerRadius + labelPadding) + ")",
              flip.get(this) ? "rotate(180)" : ""
            ].join("");
          })
          .attr("text-anchor", function() {
            return flip.get(this) ? "end" : "start";
          })
          .attr("alignment-baseline", "central")
          .text(function(group) {
            return matrix.names[group.index];
          })
          .style("cursor", "default")
          .style("font-weight", function(group){
            return selected.get(this.parentNode) ? "bold" : "normal";
          })
          .call(chordGroupHover)
          .call(setChordGroupOpacity);

      // Render the chord group arcs.
      chordGroups
        .select("path")
          .attr("d", arc)
          .style("fill", function(group) {
            return color(matrix.names[group.index]);
          })
          .call(chordGroupHover)
          .call(setChordGroupOpacity);

      function setChordGroupOpacity(selection){
        selection.transition().duration(transitionDuration)
          .style("opacity", function(group){
            if(selectedRibbon){
              return selected.get(this.parentNode) ? defaultOpacity : fadedOpacity;
            } else {
              return defaultOpacity;
            }
          });
      }


      // Sets up hover interaction to highlight a chord group.
      // Used for both the arcs and the text labels.
      function chordGroupHover(selection){
        selection
          .on("mouseover", function (group){
            hoveredChordGroup = group;
            my();
          })
          .on("mouseout", function (){
            hoveredChordGroup = null;
            my();
          });
      }

      // Sets the opacity values for all ribbons.
      function setRibbonOpacity(selection){
        selection
          .transition().duration(transitionDuration)
          .style("opacity", function (d){

            // If there is a currently selected ribbon,
            if(selectedRibbon){

              // show the selected chord in full color,
              if(
                (selectedRibbon.sourceIndex === d.source.index) &&
                (selectedRibbon.targetIndex === d.target.index)
              ){
                return defaultOpacity;
              } else {

                // and show all others faded out.
                return fadedOpacity;
              }
            } else {

              // If there is no currently selected ribbon,
              // then if there is a hovered chord group,
              if(hoveredChordGroup){

                // show the ribbons connected to the hovered chord group in full color,
                if(
                  (d.source.index === hoveredChordGroup.index) ||
                  (d.target.index === hoveredChordGroup.index)
                ){
                  return defaultOpacity;
                } else {

                  // and show all others faded out.
                  return fadedOpacity;
                }
              } else {

                // Otherwise show all ribbons with slight transparency.
                return defaultOpacity;
              }
            }
          });
      }
    }
  }
// Renders the given data as a chord diagram.
Renders the given data as a chord diagram.
Renders the given data as a chord diagram .
function my(){
    if(data){
      chord.padAngle(padAngle);
      color.range(colors);
      var side = Math.min(width, height),
          outerRadius = side / 2 - outerPadding,
          innerRadius = outerRadius - arcThickness;
      ribbonsG
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
      chordGroupsG
        .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
      ribbon.radius(innerRadius);
      arc
        .innerRadius(innerRadius)
        .outerRadius(outerRadius);
      backgroundRect
        .attr("width", width)
        .attr("height", height);
      var matrix = generateMatrix(data),
          chords = chord(matrix);
      color.domain(matrix.names.slice().sort());
      var ribbons = ribbonsG
        .selectAll("path")
          .data(chords);
      ribbons = ribbons.enter().append("path").merge(ribbons);
      ribbons
        .attr("d", ribbon)
        .style("fill", function(d) {
          return color(matrix.names[d.source.index]);
        })
        .style("stroke", "black")
        .style("stroke-opacity", 0.2)
        .style("cursor", onSelectedRibbonChangeCallback ? "pointer" : "")
        .call(setRibbonOpacity)
        .on("mousedown", function (d){
          my.selectedRibbon(ribbonData(d));
        })
        .on("mouseover", function (d){
          if(onChordHover) onChordHover(ribbonData(d));
        })
        .on("mouseout", function (d){
          if(onChordHover) onChordHover(null);
        });
      ribbons.exit().remove();
      function ribbonData(d) {
        return {
          sourceIndex: d.source.index,
          targetIndex: d.target.index,
          source: matrix.names[d.source.index],
          destination: matrix.names[d.target.index],
          sourceValue: d.source.value,
          destinationValue: d.target.value
        };
      }
      var chordGroups = chordGroupsG.selectAll("g").data(chords.groups);
      var chordGroupsEnter = chordGroups.enter().append("g");
      chordGroupsEnter.append("text");
      chordGroupsEnter.append("path");
      chordGroups.exit().remove();
      chordGroups = chordGroups.merge(chordGroupsEnter);
      chordGroups
        .each(function(group) {
          angle.set(this, (group.startAngle + group.endAngle) / 2);
          flip.set(this, angle.get(this) > Math.PI);
          selected.set(this, selectedRibbon &&
            (
              (selectedRibbon.sourceIndex === group.index) ||
              (selectedRibbon.targetIndex === group.index)
            )
          );
        })
      chordGroups
        .select("text")
          .attr("transform", function() {
            return [
              "rotate(" + (angle.get(this) / Math.PI * 180 - 90) + ")",
              "translate(" + (outerRadius + labelPadding) + ")",
              flip.get(this) ? "rotate(180)" : ""
            ].join("");
          })
          .attr("text-anchor", function() {
            return flip.get(this) ? "end" : "start";
          })
          .attr("alignment-baseline", "central")
          .text(function(group) {
            return matrix.names[group.index];
          })
          .style("cursor", "default")
          .style("font-weight", function(group){
            return selected.get(this.parentNode) ? "bold" : "normal";
          })
          .call(chordGroupHover)
          .call(setChordGroupOpacity);
      chordGroups
        .select("path")
          .attr("d", arc)
          .style("fill", function(group) {
            return color(matrix.names[group.index]);
          })
          .call(chordGroupHover)
          .call(setChordGroupOpacity);
      function setChordGroupOpacity(selection){
        selection.transition().duration(transitionDuration)
          .style("opacity", function(group){
            if(selectedRibbon){
              return selected.get(this.parentNode) ? defaultOpacity : fadedOpacity;
            } else {
              return defaultOpacity;
            }
          });
      }
      function chordGroupHover(selection){
        selection
          .on("mouseover", function (group){
            hoveredChordGroup = group;
            my();
          })
          .on("mouseout", function (){
            hoveredChordGroup = null;
            my();
          });
      }
      function setRibbonOpacity(selection){
        selection
          .transition().duration(transitionDuration)
          .style("opacity", function (d){
            if(selectedRibbon){
              if(
                (selectedRibbon.sourceIndex === d.source.index) &&
                (selectedRibbon.targetIndex === d.target.index)
              ){
                return defaultOpacity;
              } else {
                return fadedOpacity;
              }
            } else {
              if(hoveredChordGroup){
                if(
                  (d.source.index === hoveredChordGroup.index) ||
                  (d.target.index === hoveredChordGroup.index)
                ){
                  return defaultOpacity;
                } else {
                  return fadedOpacity;
                }
              } else {
                return defaultOpacity;
              }
            }
          });
      }
    }
  }
function my ( ) { if ( data ) { chord . padAngle ( padAngle ) ; color . range ( colors ) ; var side = Math . min ( width , height ) , outerRadius = side / 2 - outerPadding , innerRadius = outerRadius - arcThickness ; ribbonsG . attr ( "transform" , "translate(" + width / 2 + "," + height / 2 + ")" ) ; chordGroupsG . attr ( "transform" , "translate(" + width / 2 + "," + height / 2 + ")" ) ; ribbon . radius ( innerRadius ) ; arc . innerRadius ( innerRadius ) . outerRadius ( outerRadius ) ; backgroundRect . attr ( "width" , width ) . attr ( "height" , height ) ; var matrix = generateMatrix ( data ) , chords = chord ( matrix ) ; color . domain ( matrix . names . slice ( ) . sort ( ) ) ; var ribbons = ribbonsG . selectAll ( "path" ) . data ( chords ) ; ribbons = ribbons . enter ( ) . append ( "path" ) . merge ( ribbons ) ; ribbons . attr ( "d" , ribbon ) . style ( "fill" , function ( d ) { return color ( matrix . names [ d . source . index ] ) ; } ) . style ( "stroke" , "black" ) . style ( "stroke-opacity" , 0.2 ) . style ( "cursor" , onSelectedRibbonChangeCallback ? "pointer" : "" ) . call ( setRibbonOpacity ) . on ( "mousedown" , function ( d ) { my . selectedRibbon ( ribbonData ( d ) ) ; } ) . on ( "mouseover" , function ( d ) { if ( onChordHover ) onChordHover ( ribbonData ( d ) ) ; } ) . on ( "mouseout" , function ( d ) { if ( onChordHover ) onChordHover ( null ) ; } ) ; ribbons . exit ( ) . remove ( ) ; function ribbonData ( d ) { return { sourceIndex : d . source . index , targetIndex : d . target . index , source : matrix . names [ d . source . index ] , destination : matrix . names [ d . target . index ] , sourceValue : d . source . value , destinationValue : d . target . value } ; } var chordGroups = chordGroupsG . selectAll ( "g" ) . data ( chords . groups ) ; var chordGroupsEnter = chordGroups . enter ( ) . append ( "g" ) ; chordGroupsEnter . append ( "text" ) ; chordGroupsEnter . append ( "path" ) ; chordGroups . exit ( ) . remove ( ) ; chordGroups = chordGroups . merge ( chordGroupsEnter ) ; chordGroups . each ( function ( group ) { angle . set ( this , ( group . startAngle + group . endAngle ) / 2 ) ; flip . set ( this , angle . get ( this ) > Math . PI ) ; selected . set ( this , selectedRibbon && ( ( selectedRibbon . sourceIndex === group . index ) || ( selectedRibbon . targetIndex === group . index ) ) ) ; } ) chordGroups . select ( "text" ) . attr ( "transform" , function ( ) { return [ "rotate(" + ( angle . get ( this ) / Math . PI * 180 - 90 ) + ")" , "translate(" + ( outerRadius + labelPadding ) + ")" , flip . get ( this ) ? "rotate(180)" : "" ] . join ( "" ) ; } ) . attr ( "text-anchor" , function ( ) { return flip . get ( this ) ? "end" : "start" ; } ) . attr ( "alignment-baseline" , "central" ) . text ( function ( group ) { return matrix . names [ group . index ] ; } ) . style ( "cursor" , "default" ) . style ( "font-weight" , function ( group ) { return selected . get ( this . parentNode ) ? "bold" : "normal" ; } ) . call ( chordGroupHover ) . call ( setChordGroupOpacity ) ; chordGroups . select ( "path" ) . attr ( "d" , arc ) . style ( "fill" , function ( group ) { return color ( matrix . names [ group . index ] ) ; } ) . call ( chordGroupHover ) . call ( setChordGroupOpacity ) ; function setChordGroupOpacity ( selection ) { selection . transition ( ) . duration ( transitionDuration ) . style ( "opacity" , function ( group ) { if ( selectedRibbon ) { return selected . get ( this . parentNode ) ? defaultOpacity : fadedOpacity ; } else { return defaultOpacity ; } } ) ; } function chordGroupHover ( selection ) { selection . on ( "mouseover" , function ( group ) { hoveredChordGroup = group ; my ( ) ; } ) . on ( "mouseout" , function ( ) { hoveredChordGroup = null ; my ( ) ; } ) ; } function setRibbonOpacity ( selection ) { selection . transition ( ) . duration ( transitionDuration ) . style ( "opacity" , function ( d ) { if ( selectedRibbon ) { if ( ( selectedRibbon . sourceIndex === d . source . index ) && ( selectedRibbon . targetIndex === d . target . index ) ) { return defaultOpacity ; } else { return fadedOpacity ; } } else { if ( hoveredChordGroup ) { if ( ( d . source . index === hoveredChordGroup . index ) || ( d . target . index === hoveredChordGroup . index ) ) { return defaultOpacity ; } else { return fadedOpacity ; } } else { return defaultOpacity ; } } } ) ; } } }
Renders the given data as a chord diagram.
Renders the given data as a chord diagram .
// Use the data passed into the .data() accessor. // Set properties that may have been reconfigured via accessors. // Compute things that depend on width and height. // Pre-process the data and calculate the Chord Diagram layout. // Use alphanumerically sorted source and destination names // for the color scale domain for consistent colors across refreshes. // Render the ribbons of the Chord Diagram (the connecting fibers inside the circle). // Scaffold the chord groups. // Compute locals. // Add labels // Render the chord group arcs. // Sets up hover interaction to highlight a chord group. // Used for both the arcs and the text labels. // Sets the opacity values for all ribbons. // If there is a currently selected ribbon, // show the selected chord in full color, // and show all others faded out. // If there is no currently selected ribbon, // then if there is a hovered chord group, // show the ribbons connected to the hovered chord group in full color, // and show all others faded out. // Otherwise show all ribbons with slight transparency.