2016-12-30 5 views
0

したがって、ディレクティブをコンポーネントに変換しようとしています。ディレクティブは基本的に、入力データセットが与えられたときに伝説のあるドーナツチャートをレンダリングします。また、ドーナツ上の円弧上にマウスを置くと、ポップアップアニメーションが表示されます。この指令は絶対にうまく動作します。問題は、ディレクティブをコンポーネントに変換したときです。上記のテンプレートがangularJSはd3jsのカスタムドーナツディレクティブをコンポーネントに変換します

<div layout="row" id={{$ctrl.chartId}} layout-align="center center"></div> 

上記のコンポーネントが正常に動作し、意図したとおりにドーナツグラフを描画する成分

(() => { 
    angular 
    .module('charts.donut-chart') 
    .component('donutChart', { 
    templateUrl: 'charts/donut-chart/donut-chart.html', 
    controller: DonutChartController, 
    bindings: { 
     chartData: '=', 
     chartColors: '=', 
     chartHeight: '=', 
     chartWidth: '=', 
     legendHeight: '=', 
     hover: '@', 
     tooltips: '=', 
     enableLegend: '=', 
     id: '=', 
    }, 
    }); 

    function DonutChartController ($document, donutOptionsFactory, $filter, $scope, $timeout, $window, $element, $attrs, $compile) { 
    // console.log($element, $attrs); 

    const d3 = $window.d3; 

    const vm = this; 

    const timestamp = new Date().getTime(); 

    vm.chartId = `donut_chart_${timestamp}`; 

    const donutOptions = { 
     chartWidth: vm.chartWidth, 
     chartHeight: vm.chartHeight, 
     legendHeight: vm.legendHeight, 
    }; 

    // chart options 
    let chartWidth; 
    let chartHeight; 
    let enableLegend; 
    let legendHeight; 
    let outerRadiusOfArc; 
    let innerRadiusOfArc; 
    let color; 
    let arcColors; 

    let pie; 
    let arc; 

    let svgContainer; 
    let formattedDonutChartOptions; 
    let svgElement; 

    const deregistrationFn = $scope.$watch(() => $document[0].querySelector(`#${this.chartId}`), (newValue) => { 
     if (newValue !== null) { 
     deregistrationFn(); 
     svgContainer = d3.select(`#${vm.chartId}`); 
     vm.initChartOptions(); 
     createChart(); 
     // bindMouseEvents(); 
     } 
    }); 

    vm.initChartOptions =() => { 
     formattedDonutChartOptions = donutOptionsFactory.getOptionsForDonutChart(donutOptions, svgContainer); 
     chartWidth = formattedDonutChartOptions.chartWidth; 
     chartHeight = formattedDonutChartOptions.chartHeight; 
     enableLegend = formattedDonutChartOptions.enableLegend; 
     legendHeight = formattedDonutChartOptions.legendHeight; 
     outerRadiusOfArc = formattedDonutChartOptions.outerRadiusOfArc; 
     innerRadiusOfArc = formattedDonutChartOptions.innerRadiusOfArc; 
     color = formattedDonutChartOptions.chartColors; 
    }; 

    function onArcMouseOver (d, path) { 
     console.log('mouseover', d, path); 
     d3.select(path).transition() 
     .attr('d', d3.svg.arc() 
      .innerRadius(outerRadiusOfArc * 1.5) 
      .outerRadius(outerRadiusOfArc)); 
    } 

    function onArcMouseOut (d, path) { 
     console.log('mouseout', d, path); 
     d3.select(path).transition() 
      .duration(500) 
      .ease('bounce') 
      .attr('d', d3.svg.arc() 
      .innerRadius(innerRadiusOfArc) 
      .outerRadius(outerRadiusOfArc)); 
    } 

    function createChart() { 
     arcColors = d3.scale.ordinal() 
     .range(color); 

     pie = d3.layout.pie() 
     .sort(null) 
     .value(d => d.value); 

     arc = d3.svg.arc() 
     .innerRadius(innerRadiusOfArc) 
     .outerRadius(outerRadiusOfArc); 

     svgElement = svgContainer.append('svg') 
     .attr('width', chartWidth) 
     .attr('height', chartHeight) 
     .append('g') 
     .attr('transform', `translate(${chartWidth/2}, ${chartHeight/2})`); 

     svgElement.selectAll('path') 
     .data(pie(vm.chartData)) 
     .enter() 
     .append('path') 
     .attr('fill', (d, i) => arcColors(i)) 
     .attr('d', arc) 
     .on('mouseover', (d, i, j) => { 
      console.log(d, i, j, this); 
      const ref = this; 
      const dObject = d; 
      // (() => { 
      // onArcMouseOver(dObject, d3.select(this)); 
      // })(dObject, ref); 
      d3.select(this).transition() 
      .attr('d', d3.svg.arc() 
       .innerRadius(outerRadiusOfArc * 1.5) 
       .outerRadius(outerRadiusOfArc)); 
     }) 
     .on('mouseout', (d, i, j) => { 
      console.log(d, i, j, this); 
      // onArcMouseOut(d, d3.select(this)); 
      const ref = this; 
      const dObject = d; 
      // (() => { 
      // onArcMouseOut(dObject, d3.select(this)); 
      // })(dObject, ref); 
      d3.select(this).transition() 
       .duration(500) 
       .ease('bounce') 
       .attr('d', d3.svg.arc() 
       .innerRadius(innerRadiusOfArc) 
       .outerRadius(outerRadiusOfArc)); 
     }); 
    } 


    function bindMouseEvents() { 
     /* function pathAnim (path, dir) { 
     switch (dir) { 
     case 0: // mouseout 
      path.transition() 
       .duration(500) 
       .ease('bounce') 
       .attr('d', d3.svg.arc() 
       .innerRadius(innerRadiusOfArc) 
       .outerRadius(outerRadiusOfArc)); 
      break; 
     case 1:// mouseover 
      path.transition() 
      .attr('d', d3.svg.arc() 
       .innerRadius(outerRadiusOfArc * 1.5) 
       .outerRadius(outerRadiusOfArc)); 
      break; 
     default: break; 
     } 
     }*/ 

     const eventObject = { 
     mouseover (d) { 
      console.log('mouseover', this, d); 
      // pathAnim(d3.select(this), 1); 
     }, 
     mouseout (d) { 
      console.log('mouseout', this, d); 
      // pathAnim(d3.select(this), 0); 
     }, 
     }; 
     svgElement.on(eventObject); 
    } 
    } 
})(); 

については、以下のコードを見つけてください。問題の領域は、私が指示のようなホバー効果を行うことができないということです。私はマウスイベントをバインドする2つの方法を試みました。最初の関数は関数bindMouseEvents()を使用して別々にあり、この関数は動作し、円弧のすべての始点と終点の値を持つ 'd'引数を返しますが、これらの関数のthisは定義されていないか、DonutControllerを指しています。 thisは、ホバリングされていない要素を指す必要があります。

私は2番目のアプローチを試しました。私は、パスのセクション.on('mouseover', (d, i, j) => {にデータを追加するイベントをバインドします。私は匿名のコールバックを割り当て、その中から私自身の関数を起動して、自分の関数に引数を渡します。ここで私はクロムのデバッガを使用してコードをデバッグしているときにthisがホバリングされた要素を正しく指していることを示していますが、私自身の関数に渡すときにはthisのオブジェクト値がすべて空または未定義として渡され、 。

だから最初のアプローチでは、私は必要に応じてdオブジェクトを取得しますがthisがめちゃくちゃされ、第二のアプローチでは、私は適切にthisを取得するが、私は私の関数を呼び出すと、それにthisを渡すとき、それは次のように渡されています空のオブジェクト(すべてのキーを持ち、それらのキーの値が空または未定義のオブジェクト)。

私は何かを指摘できますか?または、私のディレクティブをコンポーネントに変換するための良い方法はありますか?事前に

おかげで脂肪矢印表記のための主な理由の

答えて

0

一つは、親スコープからthisを保存することです。あなたのようにそれを呼び出すときに:

.on('mouseover', (d, i, j) => { 

保存されthisd3ホバー要素を注入するためには適用されません。簡単な修正は、従来の機能を使用するようにされています。おかげで返事を@マーク

(() => { 
 
    angular 
 
    .module('charts.donut-chart') 
 
    .component('donutChart', { 
 
     template: "<div layout=\"ro\" id={{$ctrl.chartId}} layout-align=\"center center\"></div>", 
 
     controller: DonutChartController, 
 
     bindings: { 
 
     chartData: '=', 
 
     chartColors: '=', 
 
     chartHeight: '=', 
 
     chartWidth: '=', 
 
     legendHeight: '=', 
 
     hover: '@', 
 
     tooltips: '=', 
 
     enableLegend: '=', 
 
     id: '=', 
 
     }, 
 
    }); 
 

 
    function DonutChartController($document, $filter, $scope, $timeout, $window, $element, $attrs, $compile) { 
 
    // console.log($element, $attrs); 
 

 
    const d3 = $window.d3; 
 

 
    const vm = this; 
 

 
    const timestamp = new Date().getTime(); 
 

 
    vm.chartId = `donut_chart_${timestamp}`; 
 

 
    const donutOptions = { 
 
     chartWidth: vm.chartWidth, 
 
     chartHeight: vm.chartHeight, 
 
     legendHeight: vm.legendHeight, 
 
    }; 
 

 
    // chart options 
 
    let chartWidth; 
 
    let chartHeight; 
 
    let enableLegend; 
 
    let legendHeight; 
 
    let outerRadiusOfArc; 
 
    let innerRadiusOfArc; 
 
    let color; 
 
    let arcColors; 
 

 
    let pie; 
 
    let arc; 
 

 
    let svgContainer; 
 
    let formattedDonutChartOptions; 
 
    let svgElement; 
 

 
    const deregistrationFn = $scope.$watch(() => $document[0].querySelector(`#${this.chartId}`), (newValue) => { 
 
     if (newValue !== null) { 
 
     deregistrationFn(); 
 
     svgContainer = d3.select(`#${vm.chartId}`); 
 
     vm.initChartOptions(); 
 
     createChart(); 
 
     } 
 
    }); 
 

 
    vm.initChartOptions =() => { 
 
     //formattedDonutChartOptions = donutOptionsFactory.getOptionsForDonutChart(donutOptions, svgContainer); 
 
     chartWidth = 500; //formattedDonutChartOptions.chartWidth; 
 
     chartHeight = 500; //formattedDonutChartOptions.chartHeight; 
 
     enableLegend = true; //formattedDonutChartOptions.enableLegend; 
 
     legendHeight = 50; //formattedDonutChartOptions.legendHeight; 
 
     outerRadiusOfArc = 250; //formattedDonutChartOptions.outerRadiusOfArc; 
 
     innerRadiusOfArc = 200; //formattedDonutChartOptions.innerRadiusOfArc; 
 
     color = ['red', 'green', 'yellow']; //formattedDonutChartOptions.chartColors; 
 
    }; 
 

 
    function onArcMouseOver(d, path) { 
 
     console.log('mouseover', d, path); 
 
     d3.select(path).transition() 
 
     .attr('d', d3.svg.arc() 
 
      .innerRadius(outerRadiusOfArc * 1.5) 
 
      .outerRadius(outerRadiusOfArc)); 
 
    } 
 

 
    function onArcMouseOut(d, path) { 
 
     console.log('mouseout', d, path); 
 
     d3.select(path).transition() 
 
     .duration(500) 
 
     .ease('bounce') 
 
     .attr('d', d3.svg.arc() 
 
      .innerRadius(innerRadiusOfArc) 
 
      .outerRadius(outerRadiusOfArc)); 
 
    } 
 

 
    function createChart() { 
 
     arcColors = d3.scale.ordinal() 
 
     .range(color); 
 

 
     pie = d3.layout.pie() 
 
     .sort(null) 
 
     .value(d => d.value); 
 

 
     arc = d3.svg.arc() 
 
     .innerRadius(innerRadiusOfArc) 
 
     .outerRadius(outerRadiusOfArc); 
 

 
     svgElement = svgContainer.append('svg') 
 
     .attr('width', chartWidth) 
 
     .attr('height', chartHeight) 
 
     .append('g') 
 
     .attr('transform', `translate(${chartWidth/2}, ${chartHeight/2})`); 
 

 
     svgElement.selectAll('path') 
 
     .data(pie([{ 
 
      value: 10 
 
     }, { 
 
      value: 20 
 
     }, { 
 
      value: 30 
 
     }])) 
 
     .enter() 
 
     .append('path') 
 
     .attr('fill', (d, i) => arcColors(i)) 
 
     .attr('d', arc) 
 
     .on('mouseover', function(d, i, j) { 
 
      d3.select(this).transition() 
 
      .attr('d', d3.svg.arc() 
 
       .innerRadius(outerRadiusOfArc * 1.5) 
 
       .outerRadius(outerRadiusOfArc)); 
 
     }) 
 
     .on('mouseout', function(d, i, j) { 
 
      d3.select(this).transition() 
 
      .duration(500) 
 
      .ease('bounce') 
 
      .attr('d', d3.svg.arc() 
 
       .innerRadius(innerRadiusOfArc) 
 
       .outerRadius(outerRadiusOfArc)); 
 
     }); 
 
    } 
 
    } 
 
})();
<!doctype html> 
 
<html lang="en"> 
 

 
<head> 
 
    <meta charset="UTF-8"> 
 

 
    <script src="//code.angularjs.org/snapshot/angular.min.js"></script> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script> 
 
    <script src="index.js"></script> 
 
    <script src="donutChart.js"></script> 
 

 

 
</head> 
 

 
<body ng-app="charts.donut-chart"> 
 
    <!-- components match only elements --> 
 
    <div ng-controller="MainCtrl as ctrl"> 
 
    <donut-chart></donut-detail> 
 
    </div> 
 

 
    <script> 
 
    (function(angular) { 
 
     'use strict'; 
 
     angular.module('charts.donut-chart', []).controller('MainCtrl', function MainCtrl() { 
 

 
     }); 
 
    })(window.angular); 
 
    </script> 
 

 
</body> 
 

 
</html>

+0

:ここにあなたのコードを使用した作業のデモンストレーションだ

.on('mouseover', function(d, i, j){ 

。私は、矢印の表記法を使用していることが「これ」を保存しないことを理解しました。 Mozillaのドキュメントが私を助けてくれました。 – digitalis

関連する問題