d3作为Vue组件

时间:2016-10-01 14:12:38

标签: d3.js vue.js

我想从d3.js制作一个Gauge作为我可以在Vue中使用的组件。但是我正在努力以正确的方式导入它,所以我可以将它包装在一个自定义组件中。

除了从npm安装了d3:npm install d3。我有这个用于仪表

// data which need to be fetched

var name = " ";

var value = 840;

var gaugeMaxValue = 1680; 

// donn�es � calculer 
var percentValue = value / gaugeMaxValue; 

////////////////////////

var needleClient;



(function(){

var barWidth, chart, chartInset, degToRad, repaintGauge,
    height, margin, numSections, padRad, percToDeg, percToRad, 
    percent, radius, sectionIndx, svg, totalPercent, width,
    valueText, formatValue, k;

  percent = percentValue;

  numSections = 1;
  sectionPerc = 1 / numSections / 2;
  padRad = 0.025;
  chartInset = 10;

  // Orientation of gauge:
  totalPercent = .75;

  el = d3.select('.chart-gauge');

  margin = {
    top: 30,
    right: 30,
    bottom: 30,
    left: 30
  };

  width = el[0][0].offsetWidth - margin.left - margin.right;
  height = width;
  radius = Math.min(width, height) / 2;
  barWidth = 40 * width / 300;



  //Utility methods 

  percToDeg = function(perc) {
    return perc * 360;
  };

  percToRad = function(perc) {
    return degToRad(percToDeg(perc));
  };

  degToRad = function(deg) {
    return deg * Math.PI / 180;
  };

  // Create SVG element
  svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom);

  // Add layer for the panel
  chart = svg.append('g').attr('transform', "translate(" + ((width) / 2 + margin.left) + ", " + ((height + margin.top) / 2) + ")");

  chart.append('path').attr('class', "arc chart-red");
  chart.append('path').attr('class', "arc chart-yellow");
  chart.append('path').attr('class', "arc chart-green");
  chart.append('path').attr('class', "arc chart-yellow_");
  chart.append('path').attr('class', "arc chart-red_");

  valueText = chart.append("chart")
  formatValue = d3.format('1%');

  arc5 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc4 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc3 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc2 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)
  arc1 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth)

  repaintGauge = function () 
  {
    perc = 0.5;
    var next_start = totalPercent;
    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(0.175);
    next_start += 0.175;


    arc1.startAngle(arcStartRad).endAngle(arcEndRad);

    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(0.05);
    next_start += 0.05;

    arc2.startAngle(arcStartRad + padRad).endAngle(arcEndRad);

    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(0.05);
    next_start += 0.05;

    arc3.startAngle(arcStartRad + padRad).endAngle(arcEndRad);
    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(0.05);
    next_start += 0.05;

    arc4.startAngle(arcStartRad + padRad).endAngle(arcEndRad);
    arcStartRad = percToRad(next_start);
    arcEndRad = arcStartRad + percToRad(0.175);
    next_start += 0.175;

    arc5.startAngle(arcStartRad + padRad).endAngle(arcEndRad);


    chart.select(".chart-red").attr('d', arc1);
    chart.select(".chart-yellow").attr('d', arc2);
    chart.select(".chart-green").attr('d', arc3);
    chart.select(".chart-yellow_").attr('d', arc4);
    chart.select(".chart-red_").attr('d', arc5);
  }
/////////


    var Needle = (function() {

    //Helper function that returns the `d` value for moving the needle
    var recalcPointerPos = function(perc) {
      var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
      thetaRad = percToRad(perc / 2);
      centerX = 0;
      centerY = 0;
      topX = centerX - this.len * Math.cos(thetaRad);
      topY = centerY - this.len * Math.sin(thetaRad);
      leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
      leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
      rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
      rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);


        return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY;




    };

    function Needle(el) {
      this.el = el;
      this.len = width / 2.5;
      this.radius = this.len / 8;
    }

    Needle.prototype.render = function() {
      this.el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);




      return this.el.append('path').attr('class', 'needle').attr('id', 'client-needle').attr('d', recalcPointerPos.call(this, 0));


    };

    Needle.prototype.moveTo = function(perc) {
      var self,
          oldValue = this.perc || 0;

      this.perc = perc;
      self = this;

      // Reset pointer position
      this.el.transition().delay(100).ease('quad').duration(200).select('.needle').tween('reset-progress', function() {
        return function(percentOfPercent) {
          var progress = (1 - percentOfPercent) * oldValue;




          repaintGauge(progress);
          return d3.select(this).attr('d', recalcPointerPos.call(self, progress));
        };
      });

      this.el.transition().delay(300).ease('bounce').duration(1500).select('.needle').tween('progress', function() {
        return function(percentOfPercent) {
          var progress = percentOfPercent * perc;

          repaintGauge(progress);

          var thetaRad = percToRad(progress / 2);
          var textX = - (self.len + 45) * Math.cos(thetaRad);
          var textY = - (self.len + 45) * Math.sin(thetaRad);

          valueText.text(formatValue(progress))
            .attr('transform', "translate("+textX+","+textY+")")

          return d3.select(this).attr('d', recalcPointerPos.call(self, progress));
        };
      });

    };


    return Needle;

  })();



  needle = new Needle(chart);
  needle.render();
  needle.moveTo(percent);

  setTimeout(displayValue, 1350);



})();

这是有效的HTML,但不是作为组件

<html>
    <head>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <style type="text/css" src="gauge.css">
            .chart-gauge
            {
              width: 400px;
              margin: 100px auto  
             } 
            .chart-green
            {
                fill: #9FBD35;
            }
            .chart-yellow
            {
                fill: #F2BA3A;
            }
            .chart-yellow_
            {
                fill: #F2BA3A;
            }
      .chart-red
      {
        fill: #FB3033;
      }
      .chart-red_
      {
        fill: #FB3033;
      }

            .needle, .needle-center
            {
                fill: #000000;
            }
            .text {
                color: "#112864";
                font-size: 16px;
            }


            svg {
              font: 10px sans-serif;
            }


        </style>

    </head>
    <body>


        <div class="chart-gauge"></div>



        <script type="text/javascript" src="./gaugeClient.js"></script>
        <script type="text/javascript" src="./labels.js"></script>
        <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    </body>

</html>

1 个答案:

答案 0 :(得分:13)

第一个组件旨在帮助您每次都重写代码,所以为什么不为d3创建一个组件,您可以像以下那样每次都重复使用

通用c3组件,c3.vue

<template>
<div :style="style" v-bind:class="class"  id="{{ randomid }}" ></div>
</template>

<script>
import c3 from 'c3'


module.exports = {
  props: {
     legend: {
      type: Object,


    },
    size: {
      type: Object,


    },
     colour: {
      type: Object,
     },
   axis: {
      type: Object,


    },
     bar: {
      type: Object,


    },

    chartdata:{
          type: Object,
          default: function () {
            return  {
                    columns: [
                        ['data1', 30, 200, 100, 400, 150, 250],
                        ['data2', 50, 20, 10, 40, 15, 25]
                    ]
           }
         }

    },

   class:{
          type: Object,

    },
   styles: {
          type: Object,

    }
 },
   created: function() {


   },
    ready: function(){

       this.drawChart();
    },
    methods : {

        drawChart: function () {
            var self = this 
          var chart = c3.generate({
                 bindto: document.getElementById(self.randomid) ,
                 data: self.chartdata,
                 size : self.size,
                 colour : self.colour,
                 legend : self.legend,
                 bar : self.bar,
                 axis : self.axis
            });


      }

    },
  computed: {
     randomid: function () {
      return _.uniqueId('c3_')
    }
  }

}
</script>

接下来注册组件:

Vue.component('c3-chart', require('./c3.vue'))

现在您可以使用它来创建您想要的任何图表,是+仪表

<template>
<div>
 <c3-chart :chartdata="gauge.data" :colour="gauge.colour" :size="gauge.size"></c3-chart>
</div>
 </template>

<script>


module.exports = {
    props:  {


    },
    components:  {


    },
    data: function () {
            return {
             gauge : {
                  data: {
                     columns: [
                       ['data', 91.4]
                     ],
                     type: 'gauge',
                     onclick: function (d, i) { console.log("onclick", d, i); },
                     onmouseover: function (d, i) { console.log("onmouseover", d, i); },
                     onmouseout: function (d, i) {    console.log("onmouseout", d, i); }
                },
            color: {
              pattern: ['#FF0000', '#F97600', '#F6C600', '#60B044'], 
              threshold: {
                 values: [30, 60, 90, 100]
              }
            },
           size: {
                height: 180
               }
             }
          }
     },
    created: function() {


    },
    ready: function(){

    },
    methods : {



    },
    events: {

   },
   computed: {

  }

}
</script>