DC.js to React conversion

断了今生、忘了曾经 提交于 2020-02-02 11:17:00

问题


Is there an example for dc.js to react conversion? Interested in line chart,table and timeSlider (bar chart with brush).

Any help would be appreciated.

Thanks!


回答1:


This is the begining of converting DC.js into React. The versions of the used library are as followed (package.json):

"dependencies": {
  "babel-polyfill": "^6.3.14",
  "bootstrap": "^3.3.6",
  "crossfilter": "^1.3.12",
  "d3": "^4.2.8",
  "d3-request": "^1.0.2",
  "d3-scale": "^1.0.3",
  "d3-time-format": "^2.0.2",
  "dc": "^2.0.0-beta.32",
  "history": "^1.17.0",
  "isomorphic-fetch": "^2.2.0",
  "keymirror": "^0.1.0",
  "react": "^0.14.8",
  "react-addons-perf": "^0.14.0",
  "react-bootstrap": "^0.29.5",
  "react-bootstrap-table": "^2.3.7",
  "react-d3-core": "^1.3.9",
  "react-dom": "^0.14.8",
  "react-redux": "^4.2.1",
  "react-router": "^2.0.0",
  "react-router-bootstrap": "^0.19.3",
  "react-router-redux": "^4.0.0-rc.1",
  "redux": "^3.2.1",
  "redux-form": "^5.3.1",
  "redux-logger": "^2.4.0",
  "redux-thunk": "^1.0.3"
},
"devDependencies": {
  "babel-core": "^6.17.0",
  "babel-loader": "^6.2.5",
  "babel-preset-es2015": "^6.16.0",
  "babel-preset-react": "^6.3.13",
  "babel-preset-react-hmre": "^1.1.1",
  "babel-preset-stage-0": "^6.16.0",
  "css-loader": "^0.12.1",
  "expect": "^1.6.0",
  "express": "^4.13.3",
  "express-history-api-fallback": "^2.0.0",
  "file-loader": "^0.8.1",
  "node-libs-browser": "^0.5.2",
  "style-loader": "^0.13.1",
  "url-loader": "^0.5.7",
  "webpack": "^1.13.2",
  "webpack-dev-middleware": "^1.2.0",
  "webpack-hot-middleware": "^2.9.1"
}

Notice that the current d3 version is 4.2.8 which implied changes in the dc.js code. Line.js is a component. In the index.html what's important is the style tag.

//////Line.js


import React, { PropTypes } from 'react';
import ReactDOM from "react-dom";
import * as d3 from 'd3';
import dc from "dc";
import * as crossfilter from 'crossfilter';
import {Jumbotron } from 'react-bootstrap'; 
import functionDCHelper from './functionDCHelper';
import {scaleTime, scaleLinear} from 'd3-scale';
import { axisLeft, axisBottom } from 'd3-axis';
import TableChart from "../components/TableChart.js";

class LineChart extends React.Component {

    componentDidMount() {
        var bitrateLineChart = dc.compositeChart(this.refs.lineChart);
        var { min15, minDate, maxDate, bitrateWeekMinIntervalGroupMove, maxbit } = functionDCHelper.generateValues(this.props.data);
        bitrateLineChart 
        .xUnits(min15.range) 
        .x(d3.scaleTime().domain([new Date(minDate), new Date(maxDate)]))
        .yAxisPadding('5%')     
        .elasticY(true)
        .width(990)
        .height(200)
        .transitionDuration(500)
        .margins({ top: 30, right: 50, bottom: 25, left: 50, padding: 1 })
        .mouseZoomable(true)
        .brushOn(false)
        .renderHorizontalGridLines(true)
        .legend(dc.legend().x(800).y(10).itemHeight(13).gap(5))
        //Render max bitrate horizontal line copied from bar-extra-line.html
         .yAxisLabel("Total Bitrate per 15 minutes")
        .on('renderlet', function (chart) {
            chart.svg().selectAll('.chart-body').attr('clip-path', null)
            var left_y = 10, right_y = 70; // use real statistics here!
            var extra_data = [{ x: chart.x().range()[0], y: chart.y()(left_y) }, { x: chart.x().range()[1], y: chart.y()(right_y) }];
            var line = d3.line()
                .x(function (d) { return d.x; })
                .y(function (d) { return maxbit; })
                .curve(d3.curveLinear); //.interpolate('linear');
            var chartBody = chart.select('g.chart-body');
            var path = chartBody.selectAll('path.extra').data([extra_data]);
            path.enter().append('path').attr({
                class: 'extra',
                stroke: 'red',
                id: 'extra-line',
            });
            path.attr('d', line);
            // Label the max line
            var text = chartBody.selectAll('text.extra-label').data([0]);
            text.enter().append('text')
                    .attr('text-anchor', 'middle')
                    .append('textPath').attr({
                     class: 'extra-label',   
                    'xlink:href': '#extra-line',
                     startOffset: '50%'
                })
                .text('Total Bitrate Max Value');      
        })
       // Title can be called by any stack layer.
        .title(function (d) {
            var value = d.value.total ? d.value.total : d.value;
            if (isNaN(value)) {
                value = 0;
            }
            return functionDCHelper.dateFormat(d.key) + ' \n Total Bit:' + functionDCHelper.numberFormat(value)
        })

      //Creating dynamic Y axis with min max ticks' values depending on min max of data - copied from http://jsfiddle.net/gordonwoodhull/7anae5c5/1/
     .compose([
      functionDCHelper.nonzero_min(dc.lineChart(bitrateLineChart)
          .dimension(min15)
          .colors('green')
          .group(bitrateWeekMinIntervalGroupMove, 'Bitrate Total')
           .valueAccessor(function (d) {
               return d.value.total;
           })
         // .dashStyle([2,2])
         .interpolate('d3.curveStepAfter') 
          .renderArea(false)
          .brushOn(false)
          .renderDataPoints(false)         
          .clipPadding(10)),
     ])
        bitrateLineChart.render();
    }

    render() {
        return(
            <div  ref="lineChart">
            </div>
        );
    }

}

export default LineChart;

//////functionDCHelper.js

import crossfilter from 'crossfilter';
import * as d3 from 'd3';
import dc from 'dc';

var minDate,min15,bitrateWeekMinIntervalGroupMove,maxDate,minIntervalWeekBitrateGroup,dateDimension,dateFormat,numberFormat,maxbit;

function nonzero_min(chart) {
    dc.override(chart, 'yAxisMin', function () {
        var min = d3.min(chart.data(), function (layer) {            
            return d3.min(layer.values, function (p) {
                return p.y + p.y0;
            });
        });
        return dc.utils.subtract(min, chart.yAxisPadding());
    });
    return chart;
}
// 15 Min Interval - copied from https://github.com/mbostock/d3/blob/master/src/time/interval.js
var d3_date = Date;
function d3_time_interval(local, step, number) {
    function round(date) {
        var d0 = local(date), d1 = offset(d0, 1);
        return date - d0 < d1 - date ? d0 : d1;
    }
    function ceil(date) {
        step(date = local(new d3_date(date - 1)), 1);
        return date;
    }
    function offset(date, k) {
        step(date = new d3_date(+date), k);
        return date;
    }
    function range(t0, t1, dt) {
        var time = ceil(t0), times = [];
        if (dt > 1) {
            while (time < t1) {
                if (!(number(time) % dt)) times.push(new Date(+time));
                step(time, 1);
            }
        } else {
            while (time < t1) times.push(new Date(+time)), step(time, 1);
        }
        return times;
    }
    function range_utc(t0, t1, dt) {
        try {
            d3_date = d3_date_utc;
            var utc = new d3_date_utc();
            utc._ = t0;
            return range(utc, t1, dt);
        } finally {
            d3_date = Date;
        }
    }
    local.floor = local;
    local.round = round;
    local.ceil = ceil;
    local.offset = offset;
    local.range = range;
    var utc = local.utc = d3_time_interval_utc(local);
    utc.floor = utc;
    utc.round = d3_time_interval_utc(round);
    utc.ceil = d3_time_interval_utc(ceil);
    utc.offset = d3_time_interval_utc(offset);
    utc.range = range_utc;
    return local;
}
function d3_time_interval_utc(method) {
    return function (date, k) {
        try {
            d3_date = d3_date_utc;
            var utc = new d3_date_utc();
            utc._ = date;
            return method(utc, k)._;
        } finally {
            d3_date = Date;
        }
    };
}
// generalization of d3.time.minute copied from- https://github.com/mbostock/d3/blob/master/src/time/minute.js
function n_minutes_interval(nmins) {
    var denom = 6e4 * nmins;
    return d3_time_interval(function (date) {
        return new d3_date(Math.floor(date / denom) * denom);
    }, function (date, offset) {
        date.setTime(date.getTime() + Math.floor(offset) * denom); // DST breaks setMinutes
    }, function (date) {
        return date.getMinutes();
    });
}


min15 = n_minutes_interval(15);
dateFormat = d3.timeFormat('%Y/%m/%d/%H:%M');
numberFormat = d3.format('d');

//### Crossfilter Dimensions 
function generateValues(data) {

    data.forEach(function (d) {
        d.bitdate = new Date(d.DATETIME);    //d.DATETIME = dateFormat.parse(d.DATETIME);
       // d.month = d3.time.month(d.bitdate);
      //  d.week = d3.time.week(d.bitdate);
        d.BITRATE = +d.BITRATE.match(/\d+/); //d.BITRATE = +d.BITRATE; 
    });

    var crossFilteredData = crossfilter(data);
    var all = crossFilteredData.groupAll();
    // Dimension by full date
     dateDimension = crossFilteredData.dimension(function (d) {
        return d.bitdate;
     });


     maxbit = d3.max(data, function (d) { return +d["BITRATE"]; }); //alert(maxbit);  

    //Group bitrate per week, 15 minInterval - maintain running tallies 
     bitrateWeekMinIntervalGroupMove = dateDimension.group(min15).reduce(
       /* callback for when data is added to the current filter results */
       function (p, v) {
           ++p.count;
           p.BITRATE = +v.BITRATE;
           p.total += +v.BITRATE;
           p.avg = p.count ? Math.round(p.total / p.count) : 0;
           return p;
       },
       /* callback for when data is removed from the current filter results */
       function (p, v) {
           --p.count;
           p.BITRATE = +v.BITRATE;
           p.total -= +v.BITRATE;
           p.avg = p.count ? Math.round(p.total / p.count) : 0;
           return p;
       },
       /* initialize p */
       function () {
           return {
               count: 0,
               bitrate: 0,
               total: 0,
               avg: 0
           };
       }
    );


    try {
        minDate = dateDimension.bottom(1)[0].DATETIME;
    } catch(err) {
        minDate = new Date("2016-06-14 0:00"); 
    }

   
    try {
        maxDate = dateDimension.top(1)[0].DATETIME;
    } catch(err) {
         maxDate = new Date("2016-06-18 23:55");
    }

    return {
        min15, minDate, maxDate, bitrateWeekMinIntervalGroupMove,minIntervalWeekBitrateGroup,dateDimension,maxbit
    };
}

export default {
    generateValues,
    nonzero_min,
    dateFormat,
    numberFormat
};
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
     <style>
          path.line {
          fill: none;
          stroke: green;
          stroke-width: 1.5px;
          }
          .y.axis line,
          .y.axis path {
          fill: none;
          stroke: black;
        }
          .x.axis line,
          .x.axis path {
          fill: none;
          stroke: black;
        }

    </style>
    <title>Line Chart DC.js,React</title>
  </head>
  <body>
    <div id="App"></div>
    <script src="/bundle.js"></script>
  </body>

</html>

The result:

Line Chart dc.js in React



来源:https://stackoverflow.com/questions/39776543/dc-js-to-react-conversion

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!