【发布时间】:2016-12-30 07:52:41
【问题描述】:
所以我正在尝试将指令转换为组件。当给定输入数据集时,该指令基本上会呈现带有图例的圆环图。此外,当您将鼠标悬停在甜甜圈上的弧上时,我会显示弹出动画。该指令工作得很好。问题是当我将指令转换为组件时。请在下面找到组件的代码
(() => {
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);
}
}
})();
上面的模板是
<div layout="row" id={{$ctrl.chartId}} layout-align="center center"></div>
上述组件工作正常并按预期呈现圆环图。问题区域是我无法像指令那样做悬停效果。我尝试了两种绑定鼠标事件的方法。第一个是单独使用函数 bindMouseEvents(),该函数工作并返回“d”参数以及弧的所有起始角和结束角值,但这些函数中的 this 未定义或指向 DonutController。 this 应该指向它没有的悬停元素。
所以我尝试了第二种方法。我将添加数据的事件绑定到路径部分.on('mouseover', (d, i, j) => {。我分配匿名回调,并在其中触发我自己的函数,将参数传递给我自己的函数。在这里,当我使用 chrome 的调试器调试代码时,它显示this 正确指向悬停的元素,但是当我将它传递给我自己的函数时,this 的所有对象值都被传递为空或未定义,并且因此我的动画失败了。
因此,在第一种方法中,我根据需要获得了 d 对象,但 this 被搞砸了,在第二种方法中,我正确地获得了 this,但是当我调用我的函数并将 this 传递给它时,它被作为一个空对象(具有所有键但这些键的值是空或未定义的对象)传递。
有人能指出我在搞砸什么吗?或者有什么更好的方法将我的指令转换为组件?
提前致谢
【问题讨论】:
标签: javascript angularjs d3.js angularjs-components