如何使用vue.js组件实现d3功能?

时间:2017-09-15 13:00:23

标签: javascript d3.js vue.js vuejs2 vue-component

当我在index.html文件中使用以下方式时,它可以工作!

<script type="text/javascript">

        function getTextWidth(text, fontSize, fontName) {
            c = document.createElement("canvas");
            ctx = c.getContext("2d");
            ctx.font = fontSize + ' ' + fontName;
            return ctx.measureText(text).width;
        }

        function DataSegregator(array, on) {
            var SegData;
            OrdinalPositionHolder = {
                valueOf: function () {
                    thisObject = this;
                    keys = Object.keys(thisObject);
                    keys.splice(keys.indexOf("valueOf"), 1);
                    keys.splice(keys.indexOf("keys"), 1);
                    return keys.length == 0 ? -1 : d3.max(keys, function (d) { return thisObject[d] })
                }
                , keys: function () {
                    keys = Object.keys(thisObject);
                    keys.splice(keys.indexOf("valueOf"), 1);
                    keys.splice(keys.indexOf("keys"), 1);
                    return keys;
                }
            }
            array[0].map(function (d) { return d[on] }).forEach(function (b) {
                value = OrdinalPositionHolder.valueOf();
                OrdinalPositionHolder[b] = OrdinalPositionHolder > -1 ? ++value : 0;
            })

            SegData = OrdinalPositionHolder.keys().map(function () {
                return [];
            });

            array.forEach(function (d) {
                d.forEach(function (b) {
                    SegData[OrdinalPositionHolder[b[on]]].push(b);
                })
            });

            return SegData;
        }


        Data = [
          { Date: "Januar", Categories: [{ Name: "Cat.1", Value: 368 }, { Name: "Cat.2", Value: 321 }], LineCategory: [{ Name: "Line1", Value: 69 }, { Name: "Line2", Value: 63 }] },
          { Date: "Februar", Categories: [{ Name: "Cat.1", Value: 521 }, { Name: "Cat.2", Value: 123 }], LineCategory: [{ Name: "Line1", Value: 89 }, { Name: "Line2", Value: 96 }] },
          { Date: "März", Categories: [{ Name: "Cat.1", Value: 368 }, { Name: "Cat.2", Value: 236 }], LineCategory: [{ Name: "Line1", Value: 63 }, { Name: "Line2", Value: 35 }] }
        ];

        var margin = { top: 20, right: 30, bottom: 60, left: 40 },
            width = 800 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        var textWidthHolder = 0;
        /// Adding Date in LineCategory
        Data.forEach(function (d) {
            d.LineCategory.forEach(function (b) {
                b.Date = d.Date;
            })
        });




        var Categories = new Array();
        // Extension method declaration

        // Categories.pro;

        var Data;
        var ageNames;
        var x0 = d3.scale.ordinal()
            .rangeRoundBands([0, width], .1);
        var XLine = d3.scale.ordinal()
            .rangeRoundPoints([0, width], .1);
        var x1 = d3.scale.ordinal();

        var y = d3.scale.linear()
            .range([height, 0]);

        var YLine = d3.scale.linear().range([height, 0])
        .domain([0, d3.max(Data, function (d) { return d3.max(d.LineCategory, function (b) { return b.Value }) })]);

        var color = d3.scale.ordinal()
            .range(["#6aae6a", "#639ce4", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

        var line = d3.svg.line().x(function (d) {
            return x0(d.Date) + x0.rangeBand() / 2;
        }).y(function (d) { return YLine(d.Value) });




        var xAxis = d3.svg.axis()
            .scale(x0)
            .orient("bottom");

        // var yAxis = d3.svg.axis()
        //     .scale(y)
        //     .orient("left")
        //     .tickFormat(d3.format(".2s"));

        // var YLeftAxis = d3.svg.axis().scale(YLine).orient("right").tickFormat(d3.format(".2s"));

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





        // Bar Data categories
        Data.forEach(function (d) {
            d.Categories.forEach(function (b) {
                if (Categories.findIndex(function (c) { return c.Name===b.Name}) == -1) {
                    b.Type = "bar";
                    // console.log(JSON.stringify(b))
                    Categories.push(b)
                }
            })
        });


        // Line Data categories
        Data.forEach(function (d) {
            d.LineCategory.forEach(function (b) {
                if (Categories.findIndex(function (c) { return c.Name === b.Name }) == -1) {
                    b.Type = "line";
                    // console.log(JSON.stringify(b))
                    Categories.push(b)
                }
            })
        });

        // Processing Line data
        lineData = DataSegregator(Data.map(function (d) { return d.LineCategory }), "Name");

        // Line Coloring
        LineColor = d3.scale.ordinal();
        LineColor.domain(Categories.filter(function (d) { return d.Type == "line" }).map(function (d) { return d.Name }));
        LineColor.range(["#333471", "#386a07", "#7f8ed4", "#671919", "#0b172b"])
        x0.domain(Data.map(function (d) { return d.Date; }));
        XLine.domain(Data.map(function (d) { return d.Date; }));
        x1.domain(Categories.filter(function (d) { return d.Type == "bar" }).map(function (d) { return d.Name})).rangeRoundBands([0, x0.rangeBand()]);
        y.domain([0, d3.max(Data, function (d) { return d3.max(d.Categories, function (d) { return d.Value; }); })]);

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        var state = svg.selectAll(".state")
            .data(Data)
          .enter().append("g")
            .attr("class", "state")
            .attr("transform", function (d) { return "translate(" + x0(d.Date) + ",0)"; });

        state.selectAll("rect")
            .data(function (d) { return d.Categories; })
          .enter().append("rect")
            .attr("width", x1.rangeBand())
            .attr("x", function (d) { return x1(d.Name); })
            .attr("y", function (d) { return y(d.Value); })
            //.attr("height", function (d) { return height - y(d.Value); })
            .style("fill", function (d) { return color(d.Name); })
            .transition().delay(500).attrTween("height", function (d) {
                var i = d3.interpolate(0, height - y(d.Value));
                return function (t)
                {
                    return i(t);
                }
            });

        // drawaing lines
        svg.selectAll(".lines").data(lineData).enter().append("g").attr("class", "line")
        .each(function (d) {
            Name=d[0].Name
            d3.select(this).append("path").attr("d", function (b) { return line(b) }).style({ "stroke-width": "3px", "fill": "none" }).style("stroke", LineColor(Name)).transition().duration(1500);
        })


        // Legends
        var LegendHolder = svg.append("g").attr("class", "legendHolder");
        var legend = LegendHolder.selectAll(".legend")
            .data(Categories.map(function (d) { return {"Name":d.Name,"Type":d.Type}}))
          .enter().append("g")
            .attr("class", "legend")
            .attr("transform", function (d, i) { return "translate(0," +( height+ margin.bottom/2 )+ ")"; })
            .each(function (d,i) {
                //  Legend Symbols


                d3.select(this).append("rect")
                .attr("width", function () { return 18 })
                .attr("x", function (b) {

                    left = (i+1) * 15 + i * 18 + i * 5 + textWidthHolder;
                    return left;
                })
                 .attr("y", function (b) { return b.Type == 'bar'?0:7})
                .attr("height", function (b) { return b.Type== 'bar'? 18:5 })
                .style("fill", function (b) { return b.Type == 'bar' ? color(d.Name) : LineColor(d.Name) });

                //  Legend Text

                d3.select(this).append("text")
                .attr("x", function (b) {

                    left = (i+1) * 15 + (i+1) * 18 + (i + 1) * 5 + textWidthHolder;

                    return left;
                })
                .attr("y", 9)
                .attr("dy", ".35em")
                .style("text-anchor", "start")
                .text(d.Name);

                textWidthHolder += getTextWidth(d.Name, "10px", "calibri");
            });


        // Legend Placing (center)
        d3.select(".legendHolder").attr("transform", function (d) {
            thisWidth = d3.select(this).node().getBBox().width;
            return "translate(" + ((width) / 2 - thisWidth / 2) + ",0)";
        })

        // round the rectangle corners
        svg.selectAll('rect').attr('rx', 5).attr('ry', 5);


        </script>
<div id="chart2"></div>

但是当我尝试在我的Vue js组件上实现它时,它不起作用。 你能告诉我如何在我的Vue js上实现它。 我想在vue文件中使用 self.combodata 中的 Data = 值。

这是我的Vue组件代码:

<template>
  <div class="grapha">
  <p>Chart Page</p>
    <div id="chart2"></div>
  </div>
</template>

<script>

const d3 = require('d3');
  // var apiURL = 'https://jsonplaceholder.typicode.com/users';
var apiURL = 'http://localhost:3000/db';

export default {

  name: 'grapha',
    data () {
      return {
        combodata:[]
      }
    },
    methods: {
      fetchData: function () {
      var self = this;
      $.get(apiURL, function( data ) {
          self.combodata = data.comboChart;
          console.log('Graph:',self.combodata);
      });

    }
    },
    created: function (){
      this.fetchData();
    },


  mounted: function() {
    /////////////////d3 data ////////////////
      function getTextWidth(text, fontSize, fontName) {
          c = document.createElement("canvas");
          ctx = c.getContext("2d");
          ctx.font = fontSize + ' ' + fontName;
          return ctx.measureText(text).width;
      }

      function DataSegregator(array, on) {
          var SegData;
          OrdinalPositionHolder = {
              valueOf: function () {
                  thisObject = this;
                  keys = Object.keys(thisObject);
                  keys.splice(keys.indexOf("valueOf"), 1);
                  keys.splice(keys.indexOf("keys"), 1);
                  return keys.length == 0 ? -1 : d3.max(keys, function (d) { return thisObject[d] })
              }
              , keys: function () {
                  keys = Object.keys(thisObject);
                  keys.splice(keys.indexOf("valueOf"), 1);
                  keys.splice(keys.indexOf("keys"), 1);
                  return keys;
              }
          }
          array[0].map(function (d) { return d[on] }).forEach(function (b) {
              value = OrdinalPositionHolder.valueOf();
              OrdinalPositionHolder[b] = OrdinalPositionHolder > -1 ? ++value : 0;
          })

          SegData = OrdinalPositionHolder.keys().map(function () {
              return [];
          });

          array.forEach(function (d) {
              d.forEach(function (b) {
                  SegData[OrdinalPositionHolder[b[on]]].push(b);
              })
          });

          return SegData;
      }


      Data = [
        { Date: "Januar", Categories: [{ Name: "Cat.1", Value: 368 }, { Name: "Cat.2", Value: 321 }], LineCategory: [{ Name: "Line1", Value: 69 }, { Name: "Line2", Value: 63 }] },
        { Date: "Februar", Categories: [{ Name: "Cat.1", Value: 521 }, { Name: "Cat.2", Value: 123 }], LineCategory: [{ Name: "Line1", Value: 89 }, { Name: "Line2", Value: 96 }] },
        { Date: "März", Categories: [{ Name: "Cat.1", Value: 368 }, { Name: "Cat.2", Value: 236 }], LineCategory: [{ Name: "Line1", Value: 63 }, { Name: "Line2", Value: 35 }] }
      ];

      var margin = { top: 20, right: 30, bottom: 60, left: 40 },
          width = 800 - margin.left - margin.right,
          height = 500 - margin.top - margin.bottom;

      var textWidthHolder = 0;
      /// Adding Date in LineCategory
      Data.forEach(function (d) {
          d.LineCategory.forEach(function (b) {
              b.Date = d.Date;
          })
      });




      var Categories = new Array();
      // Extension method declaration

      // Categories.pro;

      var Data;
      var ageNames;
      var x0 = d3.scale.ordinal()
          .rangeRoundBands([0, width], .1);
      var XLine = d3.scale.ordinal()
          .rangeRoundPoints([0, width], .1);
      var x1 = d3.scale.ordinal();

      var y = d3.scale.linear()
          .range([height, 0]);

      var YLine = d3.scale.linear().range([height, 0])
      .domain([0, d3.max(Data, function (d) { return d3.max(d.LineCategory, function (b) { return b.Value }) })]);

      var color = d3.scale.ordinal()
          .range(["#6aae6a", "#639ce4", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

      var line = d3.svg.line().x(function (d) {
          return x0(d.Date) + x0.rangeBand() / 2;
      }).y(function (d) { return YLine(d.Value) });




      var xAxis = d3.svg.axis()
          .scale(x0)
          .orient("bottom");

      // var yAxis = d3.svg.axis()
      //     .scale(y)
      //     .orient("left")
      //     .tickFormat(d3.format(".2s"));

      // var YLeftAxis = d3.svg.axis().scale(YLine).orient("right").tickFormat(d3.format(".2s"));

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





      // Bar Data categories
      Data.forEach(function (d) {
          d.Categories.forEach(function (b) {
              if (Categories.findIndex(function (c) { return c.Name===b.Name}) == -1) {
                  b.Type = "bar";
                  // console.log(JSON.stringify(b))
                  Categories.push(b)
              }
          })
      });


      // Line Data categories
      Data.forEach(function (d) {
          d.LineCategory.forEach(function (b) {
              if (Categories.findIndex(function (c) { return c.Name === b.Name }) == -1) {
                  b.Type = "line";
                  // console.log(JSON.stringify(b))
                  Categories.push(b)
              }
          })
      });

      // Processing Line data
      lineData = DataSegregator(Data.map(function (d) { return d.LineCategory }), "Name");

      // Line Coloring
      LineColor = d3.scale.ordinal();
      LineColor.domain(Categories.filter(function (d) { return d.Type == "line" }).map(function (d) { return d.Name }));
      LineColor.range(["#333471", "#386a07", "#7f8ed4", "#671919", "#0b172b"])
      x0.domain(Data.map(function (d) { return d.Date; }));
      XLine.domain(Data.map(function (d) { return d.Date; }));
      x1.domain(Categories.filter(function (d) { return d.Type == "bar" }).map(function (d) { return d.Name})).rangeRoundBands([0, x0.rangeBand()]);
      y.domain([0, d3.max(Data, function (d) { return d3.max(d.Categories, function (d) { return d.Value; }); })]);

      svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(0," + height + ")")
          .call(xAxis);

      var state = svg.selectAll(".state")
          .data(Data)
        .enter().append("g")
          .attr("class", "state")
          .attr("transform", function (d) { return "translate(" + x0(d.Date) + ",0)"; });

      state.selectAll("rect")
          .data(function (d) { return d.Categories; })
        .enter().append("rect")
          .attr("width", x1.rangeBand())
          .attr("x", function (d) { return x1(d.Name); })
          .attr("y", function (d) { return y(d.Value); })
          //.attr("height", function (d) { return height - y(d.Value); })
          .style("fill", function (d) { return color(d.Name); })
          .transition().delay(500).attrTween("height", function (d) {
              var i = d3.interpolate(0, height - y(d.Value));
              return function (t)
              {
                  return i(t);
              }
          });

      // drawaing lines
      svg.selectAll(".lines").data(lineData).enter().append("g").attr("class", "line")
      .each(function (d) {
          Name=d[0].Name
          d3.select(this).append("path").attr("d", function (b) { return line(b) }).style({ "stroke-width": "3px", "fill": "none" }).style("stroke", LineColor(Name)).transition().duration(1500);
      })


      // Legends
      var LegendHolder = svg.append("g").attr("class", "legendHolder");
      var legend = LegendHolder.selectAll(".legend")
          .data(Categories.map(function (d) { return {"Name":d.Name,"Type":d.Type}}))
        .enter().append("g")
          .attr("class", "legend")
          .attr("transform", function (d, i) { return "translate(0," +( height+ margin.bottom/2 )+ ")"; })
          .each(function (d,i) {
              //  Legend Symbols


              d3.select(this).append("rect")
              .attr("width", function () { return 18 })
              .attr("x", function (b) {

                  left = (i+1) * 15 + i * 18 + i * 5 + textWidthHolder;
                  return left;
              })
               .attr("y", function (b) { return b.Type == 'bar'?0:7})
              .attr("height", function (b) { return b.Type== 'bar'? 18:5 })
              .style("fill", function (b) { return b.Type == 'bar' ? color(d.Name) : LineColor(d.Name) });

              //  Legend Text

              d3.select(this).append("text")
              .attr("x", function (b) {

                  left = (i+1) * 15 + (i+1) * 18 + (i + 1) * 5 + textWidthHolder;

                  return left;
              })
              .attr("y", 9)
              .attr("dy", ".35em")
              .style("text-anchor", "start")
              .text(d.Name);

              textWidthHolder += getTextWidth(d.Name, "10px", "calibri");
          });


      // Legend Placing (center)
      d3.select(".legendHolder").attr("transform", function (d) {
          thisWidth = d3.select(this).node().getBBox().width;
          return "translate(" + ((width) / 2 - thisWidth / 2) + ",0)";
      })

      // round the rectangle corners
      svg.selectAll('rect').attr('rx', 5).attr('ry', 5);

  }
}

</script>


<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

    vue.esm.js?65d7:479 [Vue warn]: Error in mounted hook: "TypeError: Cannot read property 'ordinal' of undefined"

    found in

    ---> <Grapha> at src/components/GraphA.vue
           <App> at src/App.vue
             <Root>
    warn @ vue.esm.js?65d7:479
    handleError @ vue.esm.js?65d7:562
    callHook @ vue.esm.js?65d7:2667
    insert @ vue.esm.js?65d7:3526
    invokeInsertHook @ vue.esm.js?65d7:5469
    patch @ vue.esm.js?65d7:5639
    Vue._update @ vue.esm.js?65d7:2414
    updateComponent @ vue.esm.js?65d7:2538
    get @ vue.esm.js?65d7:2881
    Watcher @ vue.esm.js?65d7:2870
    mountComponent @ vue.esm.js?65d7:2542
    Vue$3.$mount @ vue.esm.js?65d7:7863
    Vue$3.$mount @ vue.esm.js?65d7:10066
    Vue._init @ vue.esm.js?65d7:4236
    Vue$3 @ vue.esm.js?65d7:4321
    (anonymous) @ main.js?1c90:26
    (anonymous) @ app.js:785
    __webpack_require__ @ app.js:660
    fn @ app.js:86
    (anonymous) @ app.js:1032
    __webpack_require__ @ app.js:660
    (anonymous) @ app.js:709
    (anonymous) @ app.js:712
    vue.esm.js?65d7:566 TypeError: Cannot read property 'ordinal' of undefined
        at VueComponent.mounted (GraphA.vue?6492:111)
        at callHook (vue.esm.js?65d7:2665)
        at Object.insert (vue.esm.js?65d7:3526)
        at invokeInsertHook (vue.esm.js?65d7:5469)
        at Vue$3.patch [as __patch__] (vue.esm.js?65d7:5639)
        at Vue$3.Vue._update (vue.esm.js?65d7:2414)
        at Vue$3.updateComponent (vue.esm.js?65d7:2538)
        at Watcher.get (vue.esm.js?65d7:2881)
        at new Watcher (vue.esm.js?65d7:2870)
        at mountComponent (vue.esm.js?65d7:2542)

0 个答案:

没有答案