Example #1
0
  _setupD3Functions = (props) => {
    const dataSets = props.data.map(item => {
      return item.value;
    });
    const startAngle = (-135 * this.state.radiansMultiplier);
    const endAngle = (135 * this.state.radiansMultiplier);
    const pie = d3.layout.pie().padAngle(props.padAngle).endAngle(endAngle);
    const values = pie(dataSets);
    const radius = Math.min(props.width, props.height) / 2;
    const standardArc = d3.svg.arc().outerRadius(radius - props.activeOffset).innerRadius(radius - props.arcWidth);
    const hoveredArc = d3.svg.arc().outerRadius(radius).innerRadius(radius - props.arcWidth);
    const baseArc = d3.svg.arc().outerRadius(radius - props.activeOffset).innerRadius(radius - props.arcWidth).startAngle(startAngle).endAngle(endAngle);

    this.setState({
      baseArc,
      endAngle,
      hoveredArc,
      pie,
      radius,
      standardArc,
      values
    });
  };
Example #2
0
      this.gaugeConfig.colorsRange.forEach(range => {
        const color = this.getColorBucket(range.from);

        const scaleArc = d3.svg.arc()
          .startAngle(angle(range.from))
          .endAngle(angle(range.to))
          .innerRadius(radius)
          .outerRadius(radius + scaleWidth);

        scale
          .append('path')
          .attr('d', scaleArc)
          .style('stroke', color)
          .style('fill', color);
      });
Example #3
0
Arc.update = function(el, state) {
	
	var arc = d3.svg.arc()
	    .innerRadius(40)
	    .outerRadius(60)
	    .startAngle(0);

	var v = state / 100;

	d3.select(el).select('.foreground')
		.transition()
      	.duration(750)
      	.call(arcTween, v * tau, arc);

}
Example #4
0
      selection.each(function (data, index) {
        var pie = d3.layout.pie()
          .sort(sort)
          .value(value);

        data = pie(data).map(function (d) {
          return [d];
        });

        var radius = Math.min(width, height) / 2;

        var svgEvents = events().listeners(listeners);

        var svg = d3.select(this).append("svg")
          .attr("width", width)
          .attr("height", height)
          .call(svgEvents);

        var g = svg.append("g")
          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

        var arc = d3.svg.arc()
          .outerRadius(outerRadius || radius)
          .innerRadius(innerRadius);

        var piePath = path()
          .pathGenerator(arc)
          .class(pieClass)
          .fill(fill)
          .stroke(stroke);

        var pieText = textElement()
          .transform(text.transform || function (d) {
            return "translate(" + arc.centroid(d) + ")";
          })
          .dy(text.dy)
          .anchor(text.anchor)
          .fill(text.fill)
          .text(function (d, i) {
            return label.call(this, d.data, i);
          });

        g.selectAll("groups")
          .data(data)
          .enter().append("g")
          .call(piePath)
          .call(pieText);
      });
Example #5
0
  drawChart () {
    const div = document.getElementById('chart' + this.props.elem.id);
    while (div.firstChild) {
      div.removeChild(div.firstChild);
    }
    let data = Object.keys(this.props.elem.categories).map(key => {
      return {
        label: key,
        value: this.props.elem.categories[key]
      };
    })
            .filter(elem => elem.value !== 0);
    if (!data.length) {
      data = [{label: 'no votes', value: 1}];
    }

    const w = 128;
    const h = 128;
    const r = h / 2;
    const color = d3.scale.category20c();
    const vis = d3.select('#chart' + this.props.elem.id)
            .append('svg:svg')
            .data([data])
            .attr('width', w)
            .attr('height', h)
            .append('svg:g')
            .attr('transform', 'translate(' + r + ',' + r + ')');
    const pie = d3.layout.pie().value(d => d.value);

    const arc = d3.svg.arc().outerRadius(r);

    const arcs = vis.selectAll('g.slice')
            .data(pie)
            .enter()
            .append('svg:g')
            .attr('class', 'slice');
    arcs.append('svg:path')
      .attr('fill', (d, i) => color(i))
      .attr('d', (d) => arc(d));

    // add the text
    arcs.append('svg:text').attr('transform', d => {
      d.innerRadius = 0;
      d.outerRadius = r;
      return 'translate(' + arc.centroid(d) + ')';
    })
    .attr('text-anchor', 'middle').text((d, i) => data[i].label);
  }
Example #6
0
Timer.prototype._initialDraw = function () {
  this.group = this.svg.append('g').attr(
    'transform',
    'translate(' + this.outerRadius + ',' + this.outerRadius +')'
  );

  this.group.append('path').attr('fill', '#eee');
  this._updatePath(1);

  var arc = d3.svg.arc().innerRadius(this.innerRadius).outerRadius(this.outerRadius);
  this.group.append('text')
      .text(this.timeLeft)
      .attr('fill', '#eee')
      .attr('text-anchor', 'middle')
      .attr('alignment-baseline', 'middle');
};
Example #7
0
  /**
   * Render the arc and the value in the top of the chart.
   */
  renderText () {
    let padding = 40;
    let labelArc = d3.svg.arc()
        .outerRadius(this.radius - padding)
        .innerRadius(this.radius - padding);

    this.container
      .append('g')
      .attr('class', 'label')
      .append('text')
      .attr('transform', d => `translate(${labelArc.centroid(d)})`)
      .attr('dy', '.35em')
      .text(d => d.data.label);

    return this;
  }
Example #8
0
const arc = function (radius, itemNumber, width) {
  if (width == null) {
    width = 30
  }
  itemNumber = itemNumber - 1
  const startAngle = ((2 * Math.PI) / numberOfItemsInContextMenu) * itemNumber
  const endAngle = startAngle + (2 * Math.PI) / numberOfItemsInContextMenu
  const innerRadius = Math.max(radius + 8, 20)
  return d3.svg
    .arc()
    .innerRadius(innerRadius)
    .outerRadius(innerRadius + width)
    .startAngle(startAngle)
    .endAngle(endAngle)
    .padAngle(0.03)
}
    /**
     * Draws the donut chart
     */
    createTheDonutChart()
    {
        const { totalTablet, totalSmartphone, dataEntries } = this.props;
        const dataset = [ totalTablet, totalSmartphone ];

        const pie = d3.layout.pie()
            .sort(null);

        const arc = d3.svg.arc()
            .innerRadius(this.radius)
            .outerRadius(this.radius - this.donutWidth);

        const path = this.svg.selectAll('path')
            .data(pie(dataset))
            .enter().append('path')
            .attr('fill', (d, i) => this.colors[i])
            .attr('d', arc);


         const lineHeight = 5;

         // Draws the tick in the donut
         for(let t in [1,2,3,4])
         {
            let sign = Math.pow( -1, t%2 );
            let inversesign = -sign;
            var pos = ( sign * this.radius ) + ( inversesign * this.donutWidth );
            let x1 = 0, x2 = 0, y1 = pos, y2 = pos - sign * lineHeight;

            if( t > 1 )
            {
              y1 = 0;
              y2 = 0;
              x1 = pos;
              x2 = pos - sign*lineHeight;
            }

            this.svg.append('line')
                    .attr('x1', x1)
                    .attr('y1', y1)
                    .attr('x2', x2)
                    .attr('y2', y2)
                    .attr('stroke-width', 2)
                    .attr('stroke', `${this.colors[1]}`);
         }
    }
    createChart: function(node, props) {
      var diameter = props.diameter;
      var radius = diameter / 2;
      var ratio = props.correctResponseRatio;
      var arc, foreground, caption;

      var svg = d3.select(node)
        .attr('width', radius)
        .attr('height', radius)
        .attr('aria-hidden', true)
        .append('g')
          .attr('transform', 'translate(' + radius + ',' + radius + ')');

      arc = d3.svg.arc()
        .innerRadius(radius)
        .outerRadius(diameter / 2.5)
        .startAngle(0);

      // background circle that's always "empty" (shaded in light color)
      svg.append('path')
        .datum({ endAngle: CIRCLE })
        .attr('class', 'background')
        .attr('d', arc);

      // foreground circle that fills up based on ratio (green, or flashy)
      foreground = svg.append('path')
        .datum({ endAngle: 0 })
        .attr('class', 'foreground')
        .attr('d', arc);

      // text inside the circle
      caption = svg.selectAll('text').data([ ratio ]);
      caption.enter().append('text')
        .attr('text-anchor', 'middle')
        .text(getLabel(props.correctResponseRatio));

      // we need these for updating
      this.arc = arc;
      this.foreground = foreground;
      this.caption = caption;

      this.updateChart(svg, props);

      return svg;
    },
    return dataPoints.map((dataPoint, index) => {
      const endAngle = dataPoint / this.props.chartTotal;

      const dataPointArc = d3.svg.arc()
        .outerRadius(radius - this.props.activeOffset)
        .innerRadius(radius - this.props.arcWidth)
        .startAngle(0)
        .endAngle(endAngle * 2 * 2 * Math.PI);

      return (
        <circle
          cx='0'
          cy='0'
          fill={this.props.dataPointColors[index]}
          key={index}
          r={this.props.dataPointRadius}
          transform={'translate(' + dataPointArc.centroid() + ')'}
        />
      );
    });
Example #12
0
proto._drawBand = function (start, end, clazz) {
  var self = this;

  function transform () {
    return 'translate(' + self._cx + ', ' + self._cy +') rotate(270)';
  }

  var arc = d3.svg.arc()
    .startAngle(this._toRadians(start))
    .endAngle(this._toRadians(end))
    .innerRadius(0.65 * this._radius)
    .outerRadius(0.85 * this._radius)
    ;

  this._gauge
    .append('svg:path')
    .attr('class', clazz)
    .attr('d', arc)
    .attr('transform', transform)
}
Example #13
0
    return dataPoints.map((dataPoint, index) => {
      const percentOfTotal = dataPoint / this.props.chartTotal;
      const endAngle = (percentOfTotal * 270) - 135;

      const dataPointArc = d3.svg.arc()
        .outerRadius(this.state.radius - this.props.activeOffset)
        .innerRadius(this.state.radius - this.props.arcWidth)
        .startAngle(endAngle * this.state.radiansMultiplier)
        .endAngle(endAngle * this.state.radiansMultiplier);

      return (
        <circle
          cx='0'
          cy='0'
          fill={dataPointColors[index]}
          key={index}
          r={this.props.dataPointRadius}
          transform={'translate(' + dataPointArc.centroid() + ')'}
        />
      );
    });
Example #14
0
 render () {
   const arc = d3.svg.arc()
     .outerRadius(this.props.outerRadius)
     .innerRadius(this.props.innerRadius);
   return (
     <g className="arc">
       <path
           d={arc(this.props.point)}
           fill={this.props.color}
       ></path>
       <text
           className="chart__text"
           dy="0.35em"
           textAnchor="middle"
           transform={'translate(' + arc.centroid(this.props.point) + ')'}
       >
         {this.props.label}
       </text>
     </g>
   );
 }
Example #15
0
	function generateMonthsArc(){

		var months = [];

		start = start_date;

		do {
			end = moment(start).endOf('month').format('YYYY-MM-DD');
			name = moment(start).format('MMM');
			months.push({
				start: start,
				end: end, 
				name: name,
				startAngle: dateToRadians(start),
				endAngle: dateToRadians(end, true)
			});
			start = moment(start).add(1, 'month').startOf('month').format('YYYY-MM-DD');
		} while (start < end_date);

		var monthArcs = d3.svg.arc()
			.startAngle(function(d){return d.startAngle})
			.endAngle(function(d){return d.endAngle})
			.innerRadius(radius - 213)
			.outerRadius(radius - 190)


		var monthsArcs = monthsCanvas.selectAll(".arc")
						.data(months)
						.enter()
						.append("g")
						.attr("class", "arc");


	    monthsArcs.append("path")
	        .attr("d", monthArcs)
	        .attr("fill", "rgba(206,206,206,0.9)")
	        .attr("stroke","#FFF")
	        .attr("stroke-width",2)
	        .attr("id", function (d) { return d.name});
	}
Example #16
0
    function configure(configuration) {
        var prop;
        for (prop in configuration) {
            config[prop] = configuration[prop];
        }

        range = config.maxAngle - config.minAngle;
        r = config.size / 2;
        pointerHeadLength = Math.round(r * config.pointerHeadLengthPercent);

        // a linear scale that maps domain values to a percent from 0..1
        scale = d3.scale.linear()
            .range([0, 1])
            .domain([config.minValue, config.maxValue]);

        var colorDomain = [config.lowThreshhold, config.highThreshhold].map(scale),
            colorRange = [config.lowThreshholdColor, config.defaultColor, config.highThreshholdColor];

        arcColorFn = d3.scale.threshold().domain(colorDomain).range(colorRange);

        ticks = scale.ticks(config.majorTicks);

        tickData = [config.lowThreshhold, config.highThreshhold, config.maxValue]
            .map(function(d) {
                return scale(d);
            });

        arc = d3.svg.arc()
            .innerRadius(r - config.ringWidth - config.ringInset)
            .outerRadius(r - config.ringInset)
            .startAngle(function(d, i) {
                var ratio = i > 0 ? tickData[i - 1] : config.minValue; //d * i;
                return deg2rad(config.minAngle + (ratio * range));
            })
            .endAngle(function(d, i) {
                var ratio = tickData[i]; //d * (i+1);
                return deg2rad(config.minAngle + (ratio * range));
            });
    }
Example #17
0
  render() {
    const {props} = this;

    const arc = d3.svg.arc()
      .innerRadius(props.innerRadius)
      .outerRadius(props.outerRadius)
      .startAngle(props.startAngle)
      .endAngle(props.endAngle);

    return (
      <g className="rd3-piechart-arc">
        <path
          d={arc()}
          fill={props.fill}
          stroke={props.sectorBorderColor}
          onMouseOver={props.handleMouseOver}
          onMouseLeave={props.handleMouseLeave}
        />
        {props.showOuterLabels ? this.renderOuterLabel(props, arc) : null}
        {props.showInnerLabels ? this.renderInnerLabel(props, arc) : null}
      </g>
    );
  }
Example #18
0
  renderBox: function(g) {

    var r = this.getH() * 0.4
      , arcPath = d3.svg.arc()({  
          innerRadius: r,
          outerRadius: r,
          startAngle: 0,
          endAngle: Math.PI / 2
        })
      , linePath = d3.svg.line()([
          [this.getW() - r, 0], [0, 0], [0, this.getH()],
          [this.getW(), this.getH()], [this.getW(), r]
        ])

    g.append('svg:path')
      .attr('d', linePath)
      .attr('style', 'stroke:black;fill:white;')

    g.append('svg:path')
      .attr('d', arcPath)
      .attr('transform', 'translate(' + (this.getW() - r) + ' ' + r + ')')
      .attr('style', 'stroke:black;fill:white;')
  }
Example #19
0
ReactPieChartD3.update = function (el, props) {
  var radius = Math.min(width, height) / 2;
  var data = props.data;
  if (!data) return;

  var color = d3.scale.category20b();

  var arc = d3.svg.arc()
    .outerRadius(radius);

  var pie = d3.layout.pie()
    .value(function(d) { return d.votes; })
    .sort(null);

  var path = svg.selectAll('path')
    .data(pie(data.choices));

  path.exit().remove();

  path.enter()
    .append('path');

  path.attr('d', arc)
    .attr('fill', function(d) {
      return color(d.data.title);
    });

  var keys = html.selectAll('li.key')
    .data(color.domain());

  keys.enter().append('li')
    .attr('class', 'key')
    .style('background', color)
    .text(function (d) {
      return d;
    });
};
GeometryDiagram.prototype.drawAngleMarker = function(vertex, azimuths) {
    var startAzimuth = Math.min(azimuths.start, azimuths.end);
    var endAzimuth = Math.max(azimuths.start, azimuths.end);
    
    var innerRadius = 20;
    var strokeWidth = 1;
    
    if (isRightAngle(startAzimuth, endAzimuth)) {
        var squareWidth = innerRadius / 4 * 3;
        
        this._svg.append("line")
            .attr("x1", vertex.x + Math.sin(startAzimuth) * squareWidth)
            .attr("y1", vertex.y - Math.cos(startAzimuth) * squareWidth)
            .attr("x2", vertex.x + Math.sin(startAzimuth) * squareWidth + Math.cos(startAzimuth) * squareWidth)
            .attr("y2", vertex.y - Math.cos(startAzimuth) * squareWidth + Math.sin(startAzimuth) * squareWidth)
            .attr("transform", this._translation(0, 0))
            .style("stroke", "#000");
        
        this._svg.append("line")
            .attr("x1", vertex.x + Math.cos(startAzimuth) * squareWidth)
            .attr("y1", vertex.y + Math.sin(startAzimuth) * squareWidth)
            .attr("x2", vertex.x + Math.cos(startAzimuth) * squareWidth + Math.sin(startAzimuth) * squareWidth)
            .attr("y2", vertex.y + Math.sin(startAzimuth) * squareWidth - Math.cos(startAzimuth) * squareWidth)
            .attr("transform", this._translation(0, 0))
            .style("stroke", "#000");
    } else {
        var arc = d3.svg.arc()
            .innerRadius(innerRadius)
            .outerRadius(innerRadius + strokeWidth)
            .startAngle(startAzimuth)
            .endAngle(endAzimuth);
            
        this._svg.append("path")
            .attr("d", arc)
            .attr("transform", this._translation(vertex.x, vertex.y));
    }
};
Example #21
0
    draw: function () {
        var self = this;
        var computed = self.computed;
        var layout = self.options.layout;
        var behavior = self.options.behavior;
        var chart = this._createChart();
        var data = self.data;
        var color = d3.scale.category20b();

        var arc = d3.svg.arc().outerRadius(computed.radius);
        var pie = d3.layout.pie();

        pie.value(self.fn.value)
            .sort(null);

        var path = chart.selectAll('path');

        var pieTip = d3.tip()
            .attr('class', 'bar-tooltip')
            .offset([-10, 0])
            .html(function(d) {
                return '<span class="label">' + self.fn.label(d.data) + '</span>:&nbsp;<span class="value">' + self.fn.value(d.data) + '</span>';
            });

        chart.call(pieTip);

        path.data(pie(data))
            .enter()
            .append('path')
            .attr('class', 'pie-segment')
            .attr('d', arc)
            .attr('fill', function(d) {
                return color(d.data[self.options.segments.label]);
            })
            .on('mouseover', pieTip.show)
            .on('mouseout', pieTip.hide);
    }
Example #22
0
  renderBox: function(g) {

    var r = this.getH() * 0.75
      , teta = Math.asin(this.getH() / (2 * r)) 
      , arcPath = d3.svg.arc()({  
          innerRadius: r,
          outerRadius: r,
          startAngle: -Math.PI / 2 - teta,
          endAngle: -Math.PI / 2 + teta
        })
      , linePath = d3.svg.line()([
          [this.getW(), 0], [0, 0],
          [0, this.getH()], [this.getW(), this.getH()]
        ])

    g.append('svg:path')
      .attr('d', linePath)
      .attr('style', 'stroke:black;fill:white;')

    g.append('svg:path')
      .attr('d', arcPath)
      .attr('transform', 'translate(' + (this.getW() + r * Math.cos(teta)) + ' ' + this.getH()/2 + ')')
      .attr('style', 'stroke:black;fill:white;')
  },
Example #23
0
  function renderNode(node, offset) {
    var startAngle = offset * angleScale;
    var arc = d3.svg
      .arc()
      .innerRadius(node.level * sliceSize)
      .outerRadius((node.level + 1) * sliceSize - slicePadding)
      .startAngle(startAngle)
      .endAngle(startAngle + node.size * angleScale);

    var weight = node.size / rootNode.size;
    var position = offset / rootNode.size;
    var depth = (node.level + 1) / (maxLevel + 1);

    svg
      .append('path')
      .attr('d', arc)
      .attr('fill', sliceColor(weight, position, depth))
      .attr('stroke', '#fff')
      .on('mouseover', showNodeInfo.bind(null, node))
      .on('mouseout', resetNodeInfo)
      .on('click', function onNodeClick() {
        if (node.children.length < 1) return;

        if (node !== rootNode) {
          renderWithRoot(node);
        } else if (node.parent) {
          renderWithRoot(node.parent);
        }
      });

    var childOffset = offset + node.self;
    node.children.forEach(function renderChild(child) {
      renderNode(child, childOffset);
      childOffset += child.size;
    });
  }
  getClockArc() {
    let self = this;
    let clockArcScale = d3.time.scale()
                          .domain([
                            this.getTimelogs().getBeginTime(),
                            this.getTimelogs().getEndTime()
                          ])
                          .range([0, 2 * Math.PI])
                          .clamp(true);

    return d3.svg.arc()
                 .innerRadius((d) => {
                   return self.getInnerRadius(d.floor, d.top_floor);
                 })
                 .outerRadius((d) => {
                   return self.getOuterRadius(d.floor, d.top_floor);
                 })
                 .startAngle((d) => {
                   return clockArcScale(d.start_time);
                 })
                 .endAngle((d) => {
                   return clockArcScale(d.end_time);
                 });
  }
Example #25
0
if(typeof this.onRender=="function"){this.onRender(args)}},_addListeners:function(){this.graph.element.addEventListener("mousemove",function(e){this.visible=true;this.update(e)}.bind(this),false);this.graph.onUpdate(function(){this.update()}.bind(this));this.graph.element.addEventListener("mouseout",function(e){if(e.relatedTarget&&!(e.relatedTarget.compareDocumentPosition(this.graph.element)&Node.DOCUMENT_POSITION_CONTAINS)){this.hide()}}.bind(this),false)}});Rickshaw.namespace("Rickshaw.Graph.JSONP");Rickshaw.Graph.JSONP=Rickshaw.Class.create(Rickshaw.Graph.Ajax,{request:function(){$.ajax({url:this.dataURL,dataType:"jsonp",success:this.success.bind(this),error:this.error.bind(this)})}});Rickshaw.namespace("Rickshaw.Graph.Legend");Rickshaw.Graph.Legend=function(args){var element=this.element=args.element;var graph=this.graph=args.graph;var self=this;element.classList.add("rickshaw_legend");var list=this.list=document.createElement("ul");element.appendChild(list);var series=graph.series.map(function(s){return s}).reverse();this.lines=[];this.addLine=function(series){var line=document.createElement("li");line.className="line";var swatch=document.createElement("div");swatch.className="swatch";swatch.style.backgroundColor=series.color;line.appendChild(swatch);var label=document.createElement("span");label.className="label";label.innerHTML=series.name;line.appendChild(label);list.appendChild(line);line.series=series;if(series.noLegend){line.style.display="none"}var _line={element:line,series:series};if(self.shelving){self.shelving.addAnchor(_line);self.shelving.updateBehaviour()}if(self.highlighter){self.highlighter.addHighlightEvents(_line)}self.lines.push(_line)};series.forEach(function(s){self.addLine(s)});graph.onUpdate(function(){})};Rickshaw.namespace("Rickshaw.Graph.RangeSlider");Rickshaw.Graph.RangeSlider=function(args){var element=this.element=args.element;var graph=this.graph=args.graph;$(function(){$(element).slider({range:true,min:graph.dataDomain()[0],max:graph.dataDomain()[1],values:[graph.dataDomain()[0],graph.dataDomain()[1]],slide:function(event,ui){graph.window.xMin=ui.values[0];graph.window.xMax=ui.values[1];graph.update();if(graph.dataDomain()[0]==ui.values[0]){graph.window.xMin=undefined}if(graph.dataDomain()[1]==ui.values[1]){graph.window.xMax=undefined}}})});element[0].style.width=graph.width+"px";graph.onUpdate(function(){var values=$(element).slider("option","values");$(element).slider("option","min",graph.dataDomain()[0]);$(element).slider("option","max",graph.dataDomain()[1]);if(graph.window.xMin==undefined){values[0]=graph.dataDomain()[0]}if(graph.window.xMax==undefined){values[1]=graph.dataDomain()[1]}$(element).slider("option","values",values)})};Rickshaw.namespace("Rickshaw.Graph.Renderer");Rickshaw.Graph.Renderer=Rickshaw.Class.create({initialize:function(args){this.graph=args.graph;this.tension=args.tension||this.tension;this.graph.unstacker=this.graph.unstacker||new Rickshaw.Graph.Unstacker({graph:this.graph});this.configure(args)},seriesPathFactory:function(){},seriesStrokeFactory:function(){},defaults:function(){return{tension:.8,strokeWidth:2,unstack:true,padding:{top:.01,right:0,bottom:.01,left:0},stroke:false,fill:false}},domain:function(){var values={xMin:[],xMax:[],y:[]};var stackedData=this.graph.stackedData||this.graph.stackData();var firstPoint=stackedData[0][0];var xMin=firstPoint.x;var xMax=firstPoint.x;var yMin=firstPoint.y+firstPoint.y0;var yMax=firstPoint.y+firstPoint.y0;stackedData.forEach(function(series){series.forEach(function(d){var y=d.y+d.y0;if(y<yMin)yMin=y;if(y>yMax)yMax=y});if(series[0].x<xMin)xMin=series[0].x;if(series[series.length-1].x>xMax)xMax=series[series.length-1].x});xMin-=(xMax-xMin)*this.padding.left;xMax+=(xMax-xMin)*this.padding.right;yMin=this.graph.min==="auto"?yMin:this.graph.min||0;yMax=this.graph.max||yMax;if(this.graph.min==="auto"||yMin<0){yMin-=(yMax-yMin)*this.padding.bottom}if(this.graph.max===undefined){yMax+=(yMax-yMin)*this.padding.top}return{x:[xMin,xMax],y:[yMin,yMax]}},render:function(){var graph=this.graph;graph.vis.selectAll("*").remove();var nodes=graph.vis.selectAll("path").data(this.graph.stackedData).enter().append("svg:path").attr("d",this.seriesPathFactory());var i=0;graph.series.forEach(function(series){if(series.disabled)return;series.path=nodes[0][i++];this._styleSeries(series)},this)},_styleSeries:function(series){var fill=this.fill?series.color:"none";var stroke=this.stroke?series.color:"none";series.path.setAttribute("fill",fill);series.path.setAttribute("stroke",stroke);series.path.setAttribute("stroke-width",this.strokeWidth);series.path.setAttribute("class",series.className)},configure:function(args){args=args||{};Rickshaw.keys(this.defaults()).forEach(function(key){if(!args.hasOwnProperty(key)){this[key]=this[key]||this.graph[key]||this.defaults()[key];return}if(typeof this.defaults()[key]=="object"){Rickshaw.keys(this.defaults()[key]).forEach(function(k){this[key][k]=args[key][k]!==undefined?args[key][k]:this[key][k]!==undefined?this[key][k]:this.defaults()[key][k]},this)}else{this[key]=args[key]!==undefined?args[key]:this[key]!==undefined?this[key]:this.graph[key]!==undefined?this.graph[key]:this.defaults()[key]}},this)},setStrokeWidth:function(strokeWidth){if(strokeWidth!==undefined){this.strokeWidth=strokeWidth}},setTension:function(tension){if(tension!==undefined){this.tension=tension}}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Line");Rickshaw.Graph.Renderer.Line=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"line",defaults:function($super){return Rickshaw.extend($super(),{unstack:true,fill:false,stroke:true})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.line().x(function(d){return graph.x(d.x)}).y(function(d){return graph.y(d.y)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Stack");Rickshaw.Graph.Renderer.Stack=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"stack",defaults:function($super){return Rickshaw.extend($super(),{fill:true,stroke:false,unstack:false})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.area().x(function(d){return graph.x(d.x)}).y0(function(d){return graph.y(d.y0)}).y1(function(d){return graph.y(d.y+d.y0)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Bar");Rickshaw.Graph.Renderer.Bar=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"bar",defaults:function($super){var defaults=Rickshaw.extend($super(),{gapSize:.05,unstack:false});delete defaults.tension;return defaults},initialize:function($super,args){args=args||{};this.gapSize=args.gapSize||this.gapSize;$super(args)},domain:function($super){var domain=$super();var frequentInterval=this._frequentInterval();domain.x[1]+=parseInt(frequentInterval.magnitude);return domain},barWidth:function(){var stackedData=this.graph.stackedData||this.graph.stackData();var data=stackedData.slice(-1).shift();var frequentInterval=this._frequentInterval();var barWidth=this.graph.x(data[0].x+frequentInterval.magnitude*(1-this.gapSize));return barWidth},render:function(){var graph=this.graph;graph.vis.selectAll("*").remove();var barWidth=this.barWidth();var barXOffset=0;var activeSeriesCount=graph.series.filter(function(s){return!s.disabled}).length;var seriesBarWidth=this.unstack?barWidth/activeSeriesCount:barWidth;var transform=function(d){var matrix=[1,0,0,d.y<0?-1:1,0,d.y<0?graph.y.magnitude(Math.abs(d.y))*2:0];return"matrix("+matrix.join(",")+")"};graph.series.forEach(function(series){if(series.disabled)return;var nodes=graph.vis.selectAll("path").data(series.stack.filter(function(d){return d.y!==null})).enter().append("svg:rect").attr("x",function(d){return graph.x(d.x)+barXOffset}).attr("y",function(d){return graph.y(d.y0+Math.abs(d.y))*(d.y<0?-1:1)}).attr("width",seriesBarWidth).attr("height",function(d){return graph.y.magnitude(Math.abs(d.y))}).attr("transform",transform);Array.prototype.forEach.call(nodes[0],function(n){n.setAttribute("fill",series.color)});if(this.unstack)barXOffset+=seriesBarWidth},this)},_frequentInterval:function(){var stackedData=this.graph.stackedData||this.graph.stackData();var data=stackedData.slice(-1).shift();var intervalCounts={};for(var i=0;i<data.length-1;i++){var interval=data[i+1].x-data[i].x;intervalCounts[interval]=intervalCounts[interval]||0;intervalCounts[interval]++}var frequentInterval={count:0};Rickshaw.keys(intervalCounts).forEach(function(i){if(frequentInterval.count<intervalCounts[i]){frequentInterval={count:intervalCounts[i],magnitude:i}}});this._frequentInterval=function(){return frequentInterval};return frequentInterval}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Area");Rickshaw.Graph.Renderer.Area=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"area",defaults:function($super){return Rickshaw.extend($super(),{unstack:false,fill:false,stroke:false})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.area().x(function(d){return graph.x(d.x)}).y0(function(d){return graph.y(d.y0)}).y1(function(d){return graph.y(d.y+d.y0)}).interpolate(graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory},seriesStrokeFactory:function(){var graph=this.graph;var factory=d3.svg.line().x(function(d){return graph.x(d.x)}).y(function(d){return graph.y(d.y+d.y0)}).interpolate(graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory},render:function(){var graph=this.graph;graph.vis.selectAll("*").remove();var method=this.unstack?"append":"insert";var nodes=graph.vis.selectAll("path").data(this.graph.stackedData).enter()[method]("svg:g","g");nodes.append("svg:path").attr("d",this.seriesPathFactory()).attr("class","area");if(this.stroke){nodes.append("svg:path").attr("d",this.seriesStrokeFactory()).attr("class","line")}var i=0;graph.series.forEach(function(series){if(series.disabled)return;series.path=nodes[0][i++];this._styleSeries(series)},this)},_styleSeries:function(series){if(!series.path)return;d3.select(series.path).select(".area").attr("fill",series.color);if(this.stroke){d3.select(series.path).select(".line").attr("fill","none").attr("stroke",series.stroke||d3.interpolateRgb(series.color,"black")(.125)).attr("stroke-width",this.strokeWidth)}if(series.className){series.path.setAttribute("class",series.className)}}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Pie");Rickshaw.Graph.Renderer.Pie=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"pie",defaults:function($super){var defaults=Rickshaw.extend($super(),{innerRadius:0,outerRadius:100,scheme:"classic9",unstack:false});delete defaults.tension;return defaults},initialize:function($super,args){args=args||{};this.innerRadius=args.innerRadius||this.innerRadius;this.scheme=args.scheme||this.scheme;$super(args)},render:function(){var graph=this.graph;graph.vis.selectAll("*").remove();var pie=d3.layout.pie().sort(null).value(function(d){return d.y});var palette=new Rickshaw.Color.Palette({scheme:graph.scheme});var arc=d3.svg.arc().outerRadius(this.outerRadius-10).innerRadius(this.innerRadius);var g=graph.vis.selectAll(".arc").data(pie(graph.series[0].data)).enter().append("g").attr("transform","translate("+graph.width/2+","+graph.height/2+")").attr("class","arc");g.append("path").attr("d",arc).style("fill",function(d){return palette.color()});g.append("text").attr("transform",function(d){return"translate("+arc.centroid(d)+")"}).attr("dy",".35em").style("text-anchor","middle").text(function(d){return d.label})}});Rickshaw.namespace("Rickshaw.Graph.Renderer.ScatterPlot");Rickshaw.Graph.Renderer.ScatterPlot=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"scatterplot",defaults:function($super){return Rickshaw.extend($super(),{unstack:true,fill:true,stroke:false,padding:{top:.01,right:.01,bottom:.01,left:.01},dotSize:4})},initialize:function($super,args){$super(args)},render:function(){var graph=this.graph;graph.vis.selectAll("*").remove();graph.series.forEach(function(series){if(series.disabled)return;var nodes=graph.vis.selectAll("path").data(series.stack.filter(function(d){return d.y!==null})).enter().append("svg:circle").attr("cx",function(d){return graph.x(d.x)}).attr("cy",function(d){return graph.y(d.y)}).attr("r",function(d){return"r"in d?d.r:graph.renderer.dotSize});Array.prototype.forEach.call(nodes[0],function(n){n.setAttribute("fill",series.color)})},this)}});Rickshaw.namespace("Rickshaw.Graph.Smoother");Rickshaw.Graph.Smoother=function(args){this.graph=args.graph;this.element=args.element;var self=this;this.aggregationScale=1;if(this.element){$(function(){$(self.element).slider({min:1,max:100,slide:function(event,ui){self.setScale(ui.value);self.graph.update()}})})}self.graph.stackData.hooks.data.push({name:"smoother",orderPosition:50,f:function(data){if(self.aggregationScale==1)return data;var aggregatedData=[];data.forEach(function(seriesData){var aggregatedSeriesData=[];while(seriesData.length){var avgX=0,avgY=0;var slice=seriesData.splice(0,self.aggregationScale);slice.forEach(function(d){avgX+=d.x/slice.length;avgY+=d.y/slice.length});aggregatedSeriesData.push({x:avgX,y:avgY})}aggregatedData.push(aggregatedSeriesData)});return aggregatedData}});this.setScale=function(scale){if(scale<1){throw"scale out of range: "+scale}this.aggregationScale=scale;this.graph.update()}};Rickshaw.namespace("Rickshaw.Graph.Unstacker");Rickshaw.Graph.Unstacker=function(args){this.graph=args.graph;var self=this;this.graph.stackData.hooks.after.push({name:"unstacker",f:function(data){if(!self.graph.renderer.unstack)return data;data.forEach(function(seriesData){seriesData.forEach(function(d){d.y0=0})});return data}})};Rickshaw.namespace("Rickshaw.Series");Rickshaw.Series=Rickshaw.Class.create(Array,{initialize:function(data,palette,options){options=options||{};this.palette=new Rickshaw.Color.Palette(palette);this.timeBase=typeof options.timeBase==="undefined"?Math.floor((new Date).getTime()/1e3):options.timeBase;var timeInterval=typeof options.timeInterval=="undefined"?1e3:options.timeInterval;this.setTimeInterval(timeInterval);if(data&&typeof data=="object"&&data instanceof Array){data.forEach(function(item){this.addItem(item)},this)}},addItem:function(item){if(typeof item.name==="undefined"){throw"addItem() needs a name"}item.color=item.color||this.palette.color(item.name);item.data=item.data||[];if(item.data.length==0&&this.length&&this.getIndex()>0){this[0].data.forEach(function(plot){item.data.push({x:plot.x,y:0})})}else if(item.data.length==0){item.data.push({x:this.timeBase-(this.timeInterval||0),y:0})}this.push(item);if(this.legend){this.legend.addLine(this.itemByName(item.name))}},addData:function(data){var index=this.getIndex();Rickshaw.keys(data).forEach(function(name){if(!this.itemByName(name)){this.addItem({name:name})}},this);this.forEach(function(item){item.data.push({x:(index*this.timeInterval||1)+this.timeBase,y:data[item.name]||0})},this)},getIndex:function(){return this[0]&&this[0].data&&this[0].data.length?this[0].data.length:0},itemByName:function(name){for(var i=0;i<this.length;i++){if(this[i].name==name)return this[i]}},setTimeInterval:function(iv){this.timeInterval=iv/1e3},setTimeBase:function(t){this.timeBase=t},dump:function(){var data={timeBase:this.timeBase,timeInterval:this.timeInterval,items:[]};this.forEach(function(item){var newItem={color:item.color,name:item.name,data:[]};item.data.forEach(function(plot){newItem.data.push({x:plot.x,y:plot.y})});data.items.push(newItem)});return data},load:function(data){if(data.timeInterval){this.timeInterval=data.timeInterval}if(data.timeBase){this.timeBase=data.timeBase}if(data.items){data.items.forEach(function(item){this.push(item);if(this.legend){this.legend.addLine(this.itemByName(item.name))}},this)}}});Rickshaw.Series.zeroFill=function(series){Rickshaw.Series.fill(series,0)};Rickshaw.Series.fill=function(series,fill){var x;var i=0;var data=series.map(function(s){return s.data});while(i<Math.max.apply(null,data.map(function(d){return d.length}))){x=Math.min.apply(null,data.filter(function(d){return d[i]}).map(function(d){return d[i].x}));data.forEach(function(d){if(!d[i]||d[i].x!=x){d.splice(i,0,{x:x,y:fill})}});i++}};Rickshaw.namespace("Rickshaw.Series.FixedDuration");Rickshaw.Series.FixedDuration=Rickshaw.Class.create(Rickshaw.Series,{initialize:function(data,palette,options){var options=options||{};if(typeof options.timeInterval==="undefined"){throw new Error("FixedDuration series requires timeInterval")}if(typeof options.maxDataPoints==="undefined"){throw new Error("FixedDuration series requires maxDataPoints")}this.palette=new Rickshaw.Color.Palette(palette);this.timeBase=typeof options.timeBase==="undefined"?Math.floor((new Date).getTime()/1e3):options.timeBase;this.setTimeInterval(options.timeInterval);if(this[0]&&this[0].data&&this[0].data.length){this.currentSize=this[0].data.length;this.currentIndex=this[0].data.length}else{this.currentSize=0;this.currentIndex=0}this.maxDataPoints=options.maxDataPoints;if(data&&typeof data=="object"&&data instanceof Array){data.forEach(function(item){this.addItem(item)},this);this.currentSize+=1;this.currentIndex+=1}this.timeBase-=(this.maxDataPoints-this.currentSize)*this.timeInterval;if(typeof this.maxDataPoints!=="undefined"&&this.currentSize<this.maxDataPoints){for(var i=this.maxDataPoints-this.currentSize-1;i>0;i--){this.currentSize+=1;this.currentIndex+=1;this.forEach(function(item){item.data.unshift({x:((i-1)*this.timeInterval||1)+this.timeBase,y:0,i:i})},this)}}},addData:function($super,data){$super(data);this.currentSize+=1;this.currentIndex+=1;if(this.maxDataPoints!==undefined){while(this.currentSize>this.maxDataPoints){this.dropData()}}},dropData:function(){this.forEach(function(item){item.data.splice(0,1)});this.currentSize-=1},getIndex:function(){return this.currentIndex}});
Example #26
0
  },

  mainFunction(loc, data, params, reactComp) {
    this.reactComp = reactComp;

    this.par = Object.assign({}, this.defaultParams, params);

    let size = 250;

    let width = size - 20,
      height = size - 20,
      radius = Math.min(width, height) / 2;
    let fullWidth = size;
    let fullHeight = size;

    this.arc = d3.svg.arc()
      .outerRadius(radius - 10);

    this.pie = d3.layout.pie()
      .sort(null)
      .value(function(d) {
        return d.value;
      });

    this.svg = loc.append('svg')
      .attr('id', 'd3graphSVG')
      .style('display', 'inline-block')
      .style('position', 'absolute')
      .attr('preserveAspectRatio', 'xMinYMin slice')
      .attr('viewBox', '0 0 ' + fullWidth + ' ' + fullHeight)
      .append('g')
Example #27
0
	render: function render() {
		var _props = this.props;
		var data = _props.data;
		var width = _props.width;
		var height = _props.height;
		var margin = _props.margin;
		var colorScale = _props.colorScale;
		var innerRadius = _props.innerRadius;
		var outerRadius = _props.outerRadius;
		var labelRadius = _props.labelRadius;
		var padRadius = _props.padRadius;
		var cornerRadius = _props.cornerRadius;
		var sort = _props.sort;
		var x = _props.x;
		var y = _props.y;
		var values = _props.values;
		var innerWidth = this._innerWidth;
		var innerHeight = this._innerHeight;

		var pie = d3.layout.pie().value(function (e) {
			return y(e);
		});

		if (typeof sort !== "undefined") {
			pie = pie.sort(sort);
		}

		var radius = Math.min(innerWidth, innerHeight) / 2;
		if (!innerRadius) {
			innerRadius = radius * 0.8;
		}

		if (!outerRadius) {
			//outerRadius = radius * 0.4;
		}

		if (!labelRadius) {
			// labelRadius = radius * 0.9;
		}

		var arc = d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius).padRadius(padRadius).cornerRadius(cornerRadius);

		var outerArc = d3.svg.arc().innerRadius(labelRadius).outerRadius(labelRadius);

		var pieData = pie(values(data));

		var translation = "translate(" + innerWidth / 2 + ", " + innerHeight / 2 + ")";
		return React.createElement(
			"div",
			null,
			React.createElement(
				Chart,
				{ height: height, width: width, margin: margin },
				React.createElement(
					"g",
					{ transform: translation },
					React.createElement(DataSet, {
						width: innerWidth,
						height: innerHeight,
						colorScale: colorScale,
						pie: pieData,
						arc: arc,
						outerArc: outerArc,
						radius: radius,
						x: x,
						y: y,
						onMouseEnter: this.onMouseEnter,
						onMouseLeave: this.onMouseLeave
					})
				),
				this.props.children
			),
			React.createElement(Tooltip, this.state.tooltip)
		);
	}
Example #28
0
// Modified from http://bl.ocks.org/kerryrodden/7090426
function sunburstVis(slice, payload) {
  const container = d3.select(slice.selector);

  // vars with shared scope within this function
  const margin = { top: 10, right: 5, bottom: 10, left: 5 };
  const containerWidth = slice.width();
  const containerHeight = slice.height();
  const breadcrumbHeight = containerHeight * 0.085;
  const visWidth = containerWidth - margin.left - margin.right;
  const visHeight = containerHeight - margin.top - margin.bottom - breadcrumbHeight;
  const radius = Math.min(visWidth, visHeight) / 2;

  let colorByCategory = true; // color by category if primary/secondary metrics match
  let maxBreadcrumbs;
  let breadcrumbDims; // set based on data
  let totalSize; // total size of all segments; set after loading the data.
  let colorScale;
  let breadcrumbs;
  let vis;
  let arcs;
  let gMiddleText; // dom handles

  // Helper + path gen functions
  const partition = d3.layout.partition()
    .size([2 * Math.PI, radius * radius])
    .value(function (d) { return d.m1; });

  const arc = d3.svg.arc()
    .startAngle(d => d.x)
    .endAngle(d => d.x + d.dx)
    .innerRadius(function (d) {
      return Math.sqrt(d.y);
    })
    .outerRadius(function (d) {
      return Math.sqrt(d.y + d.dy);
    });

  const formatNum = d3.format('.3s');
  const formatPerc = d3.format('.3p');

  container.select('svg').remove();

  const svg = container.append('svg:svg')
    .attr('width', containerWidth)
    .attr('height', containerHeight);

  function createBreadcrumbs(rawData) {
    const firstRowData = rawData.data[0];
    // -2 bc row contains 2x metrics, +extra for %label and buffer
    maxBreadcrumbs = (firstRowData.length - 2) + 1;
    breadcrumbDims = {
      width: visWidth / maxBreadcrumbs,
      height: breadcrumbHeight * 0.8, // more margin
      spacing: 3,
      tipTailWidth: 10,
    };

    breadcrumbs = svg.append('svg:g')
      .attr('class', 'breadcrumbs')
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

    breadcrumbs.append('svg:text')
      .attr('class', 'end-label');
  }

  // Given a node in a partition layout, return an array of all of its ancestor
  // nodes, highest first, but excluding the root.
  function getAncestors(node) {
    const path = [];
    let current = node;
    while (current.parent) {
      path.unshift(current);
      current = current.parent;
    }
    return path;
  }

  // Generate a string that describes the points of a breadcrumb polygon.
  function breadcrumbPoints(d, i) {
    const points = [];
    points.push('0,0');
    points.push(breadcrumbDims.width + ',0');
    points.push(
      breadcrumbDims.width + breadcrumbDims.tipTailWidth + ',' + (breadcrumbDims.height / 2));
    points.push(breadcrumbDims.width + ',' + breadcrumbDims.height);
    points.push('0,' + breadcrumbDims.height);
    if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
      points.push(breadcrumbDims.tipTailWidth + ',' + (breadcrumbDims.height / 2));
    }
    return points.join(' ');
  }

  function updateBreadcrumbs(sequenceArray, percentageString) {
    const g = breadcrumbs.selectAll('g')
      .data(sequenceArray, function (d) {
        return d.name + d.depth;
      });

    // Add breadcrumb and label for entering nodes.
    const entering = g.enter().append('svg:g');

    entering.append('svg:polygon')
        .attr('points', breadcrumbPoints)
        .style('fill', function (d) {
          return colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1);
        });

    entering.append('svg:text')
        .attr('x', (breadcrumbDims.width + breadcrumbDims.tipTailWidth) / 2)
        .attr('y', breadcrumbDims.height / 4)
        .attr('dy', '0.35em')
        .style('fill', function (d) {
          // Make text white or black based on the lightness of the background
          const col = d3.hsl(colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1));
          return col.l < 0.5 ? 'white' : 'black';
        })
        .attr('class', 'step-label')
        .text(function (d) { return d.name.replace(/_/g, ' '); })
        .call(wrapSvgText, breadcrumbDims.width, breadcrumbDims.height / 2);

    // Set position for entering and updating nodes.
    g.attr('transform', function (d, i) {
      return 'translate(' + i * (breadcrumbDims.width + breadcrumbDims.spacing) + ', 0)';
    });

    // Remove exiting nodes.
    g.exit().remove();

    // Now move and update the percentage at the end.
    breadcrumbs.select('.end-label')
        .attr('x', (sequenceArray.length + 0.5) * (breadcrumbDims.width + breadcrumbDims.spacing))
        .attr('y', breadcrumbDims.height / 2)
        .attr('dy', '0.35em')
        .text(percentageString);

    // Make the breadcrumb trail visible, if it's hidden.
    breadcrumbs.style('visibility', null);
  }

  // Fade all but the current sequence, and show it in the breadcrumb trail.
  function mouseenter(d) {
    const sequenceArray = getAncestors(d);
    const parentOfD = sequenceArray[sequenceArray.length - 2] || null;

    const absolutePercentage = (d.m1 / totalSize).toPrecision(3);
    const conditionalPercentage = parentOfD ? (d.m1 / parentOfD.m1).toPrecision(3) : null;

    const absolutePercString = formatPerc(absolutePercentage);
    const conditionalPercString = parentOfD ? formatPerc(conditionalPercentage) : '';

    // 3 levels of text if inner-most level, 4 otherwise
    const yOffsets = ['-25', '7', '35', '60'];
    let offsetIndex = 0;

    // If metrics match, assume we are coloring by category
    const metricsMatch = Math.abs(d.m1 - d.m2) < 0.00001;

    gMiddleText.selectAll('*').remove();

    gMiddleText.append('text')
      .attr('class', 'path-abs-percent')
      .attr('y', yOffsets[offsetIndex++])
      .text(absolutePercString + ' of total');

    if (conditionalPercString) {
      gMiddleText.append('text')
        .attr('class', 'path-cond-percent')
        .attr('y', yOffsets[offsetIndex++])
        .text(conditionalPercString + ' of parent');
    }

    gMiddleText.append('text')
      .attr('class', 'path-metrics')
      .attr('y', yOffsets[offsetIndex++])
      .text('m1: ' + formatNum(d.m1) + (metricsMatch ? '' : ', m2: ' + formatNum(d.m2)));

    gMiddleText.append('text')
      .attr('class', 'path-ratio')
      .attr('y', yOffsets[offsetIndex++])
      .text((metricsMatch ? '' : ('m2/m1: ' + formatPerc(d.m2 / d.m1))));

    // Reset and fade all the segments.
    arcs.selectAll('path')
      .style('stroke-width', null)
      .style('stroke', null)
      .style('opacity', 0.7);

    // Then highlight only those that are an ancestor of the current segment.
    arcs.selectAll('path')
      .filter(function (node) {
        return (sequenceArray.indexOf(node) >= 0);
      })
      .style('opacity', 1)
      .style('stroke-width', '2px')
      .style('stroke', '#000');

    updateBreadcrumbs(sequenceArray, absolutePercString);
  }

  // Restore everything to full opacity when moving off the visualization.
  function mouseleave() {
    // Hide the breadcrumb trail
    breadcrumbs.style('visibility', 'hidden');

    gMiddleText.selectAll('*').remove();

    // Deactivate all segments during transition.
    arcs.selectAll('path').on('mouseenter', null);

    // Transition each segment to full opacity and then reactivate it.
    arcs.selectAll('path')
      .transition()
      .duration(200)
      .style('opacity', 1)
      .style('stroke', null)
      .style('stroke-width', null)
      .each('end', function () {
        d3.select(this).on('mouseenter', mouseenter);
      });
  }


  function buildHierarchy(rows) {
    const root = {
      name: 'root',
      children: [],
    };

    // each record [groupby1val, groupby2val, (<string> or 0)n, m1, m2]
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      const m1 = Number(row[row.length - 2]);
      const m2 = Number(row[row.length - 1]);
      const levels = row.slice(0, row.length - 2);
      if (isNaN(m1)) { // e.g. if this is a header row
        continue;
      }
      let currentNode = root;
      for (let level = 0; level < levels.length; level++) {
        const children = currentNode.children || [];
        const nodeName = levels[level];
        // If the next node has the name '0', it will
        const isLeafNode = (level >= levels.length - 1) || levels[level + 1] === 0;
        let childNode;
        let currChild;

        if (!isLeafNode) {
          // Not yet at the end of the sequence; move down the tree.
          let foundChild = false;
          for (let k = 0; k < children.length; k++) {
            currChild = children[k];
            if (currChild.name === nodeName &&
                currChild.level === level) {
// must match name AND level

              childNode = currChild;
              foundChild = true;
              break;
            }
          }
          // If we don't already have a child node for this branch, create it.
          if (!foundChild) {
            childNode = {
              name: nodeName,
              children: [],
              level,
            };
            children.push(childNode);
          }
          currentNode = childNode;
        } else if (nodeName !== 0) {
          // Reached the end of the sequence; create a leaf node.
          childNode = {
            name: nodeName,
            m1,
            m2,
          };
          children.push(childNode);
        }
      }
    }

    function recurse(node) {
      if (node.children) {
        let sums;
        let m1 = 0;
        let m2 = 0;
        for (let i = 0; i < node.children.length; i++) {
          sums = recurse(node.children[i]);
          m1 += sums[0];
          m2 += sums[1];
        }
        node.m1 = m1;
        node.m2 = m2;
      }
      return [node.m1, node.m2];
    }

    recurse(root);
    return root;
  }

  // Main function to draw and set up the visualization, once we have the data.
  function createVisualization(rawData) {
    const tree = buildHierarchy(rawData.data);

    vis = svg.append('svg:g')
      .attr('class', 'sunburst-vis')
      .attr('transform', (
        'translate(' +
          `${(margin.left + (visWidth / 2))},` +
          `${(margin.top + breadcrumbHeight + (visHeight / 2))}` +
        ')'
      ))
      .on('mouseleave', mouseleave);

    arcs = vis.append('svg:g')
      .attr('id', 'arcs');

    gMiddleText = vis.append('svg:g')
      .attr('class', 'center-label');

    // Bounding circle underneath the sunburst, to make it easier to detect
    // when the mouse leaves the parent g.
    arcs.append('svg:circle')
      .attr('r', radius)
      .style('opacity', 0);

    // For efficiency, filter nodes to keep only those large enough to see.
    const nodes = partition.nodes(tree)
      .filter(function (d) {
        return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
      });

    let ext;
    const fd = slice.formData;

    if (fd.metric !== fd.secondary_metric) {
      colorByCategory = false;
      ext = d3.extent(nodes, d => d.m2 / d.m1);
      colorScale = d3.scale.linear()
        .domain([ext[0], ext[0] + ((ext[1] - ext[0]) / 2), ext[1]])
        .range(['#00D1C1', 'white', '#FFB400']);
    }

    const path = arcs.data([tree]).selectAll('path')
      .data(nodes)
      .enter()
      .append('svg:path')
      .attr('display', function (d) {
        return d.depth ? null : 'none';
      })
      .attr('d', arc)
      .attr('fill-rule', 'evenodd')
      .style('fill', d => colorByCategory ? category21(d.name) : colorScale(d.m2 / d.m1))
      .style('opacity', 1)
      .on('mouseenter', mouseenter);

    // Get total size of the tree = value of root node from partition.
    totalSize = path.node().__data__.value;
  }
  createBreadcrumbs(payload);
  createVisualization(payload);
}
Example #29
0
  PieChart.prototype.addPath = function (width, height, svg, slices) {
    var self = this;
    var marginFactor = 0.95;
    var isDonut = self._attr.isDonut;
    var radius = (Math.min(width, height) / 2) * marginFactor;
    var color = self.handler.data.getPieColorFunc();
    var tooltip = self.tooltip;
    var isTooltip = self._attr.addTooltip;

    var partition = d3.layout.partition()
    .sort(null)
    .value(function (d) {
      return d.percentOfParent * 100;
    });
    var x = d3.scale.linear()
    .range([0, 2 * Math.PI]);
    var y = d3.scale.sqrt()
    .range([0, radius]);
    var arc = 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) {
      // option for a single layer, i.e pie chart
      if (d.depth === 1 && !isDonut) {
        // return no inner radius
        return 0;
      }

      return Math.max(0, y(d.y));
    })
    .outerRadius(function (d) {
      return Math.max(0, y(d.y + d.dy));
    });

    var path = svg
    .datum(slices)
    .selectAll('path')
    .data(partition.nodes)
    .enter()
      .append('path')
      .attr('d', arc)
      .attr('class', function (d) {
        if (d.depth === 0) { return; }
        return 'slice';
      })
      .call(self._addIdentifier, 'name')
      .style('stroke', '#fff')
      .style('fill', function (d) {
        if (d.depth === 0) { return 'none'; }
        return color(d.name);
      });

    if (isTooltip) {
      path.call(tooltip.render());
    }

    return path;
  };
Example #30
0
var React = require('react');
var ReactDOM = require('react-dom');
var _ = require('underscore');

var d3 = require('d3');


var Arc = React.createClass({
    render() {

        let radius = Math.min(960, 500) / 2;
 
        let arc = d3.svg.arc()
            .outerRadius(radius - 10)
            .innerRadius(0);

        let attrs = {};
            attrs.startAngle = this.props.startAngle;
            attrs.endAngle = this.props.endAngle;
            attrs.padAngle = this.props.padAngle;
            attrs.value = this.props.value;
            attrs.data = this.props.data;

        let path = arc(attrs);

        if (this.props.data.party == "D") {
            var fill = "#ff8c00";
        } else if (this.props.data.party == "R"){
            var fill = "#a05d56";
        } else if (this.props.data.party == "I"){
            var fill = "#8a89a6";