2016-10-01 23 views
8

Chcę utworzyć wskaźnik z d3.js jako komponent, którego mogę używać w Vue. Ale staram się zaimportować go we właściwy sposób, więc mogę zawinąć go w komponent niestandardowy.d3 jako składnik Vue

Poza tym zainstalowałem d3 z npm: npm install d3. Mam to na mierniku

// 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); 



})(); 

To HTML działa, ale nie jako składnik

<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> 

Odpowiedz

13

Pierwszy składnik jest zaprojektowany, aby pomóc Ci z przepisanie kodu za każdym razem, więc dlaczego nie stworzyć komponent do D3, które można ponownie wykorzystać każdy i za każdym razem jak poniżej:

uniwersalnego składnika 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> 

obok zarejestrować komponent:

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

teraz można użyć tego, aby utworzyć dowolny wykres chcesz, tak + Mierniki

<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> 
+0

Dzięki. Takiej właśnie odpowiedzi szukałem! –

+0

@ emil-moe Zawsze pamiętaj, aby zaznaczyć prawidłową odpowiedź jako zaakceptowaną odpowiedź, goodluck. –

+0

@ emil-moe również pamiętać, aby głosować w górę lub w dół, to nie tylko pomoże przyszłym użytkownikom, ale doda punkt o twojej reputacji. –