lundi 23 octobre 2017

Highcharts misbehaving while trying to render dashed line/colored markers for points

I have created an Ember JS component which uses Highcharts 6 library to create different types of charts based on data and configuration provided to the component. However, when I am trying to use "dashStyle" or "marker: { fillColor: "#FFFF00"}" for any series(to get dashed line) or data point(to get colored marker based on point data) respectively, am not getting the desired results. However, on pasting the same config on jsfiddle, am able to get the desired chart output. Any help would be sincerely appreciated. Pasting the component code below:

    import Ember from 'ember';

    export default Ember.Component.extend({
      chartId: undefined,
      chartData: undefined,
      selectedChartType: undefined,
      chart: undefined,
      allowedChartTypes: undefined,
      customSlider: false,
      slider: false,
      showChartTypeSelector: false,
      chartTypes: [
    {label: 'Bar chart', value: 'bar', stacked: false, id: 'bar1', group: 1},       
    {label: 'Stacked Bar chart', value: 'bar', stacked: true, id: 'bar2', group: 1},
    {label: 'Bar Range chart', value: 'columnrange', stacked: false, inverted: true, id: 'bar3', group: 2},
    {label: '3D Bar chart', value: 'bar', stacked: false, threeD: true, id: 'bar4', group: 1},

    {label: 'Column chart', value: 'column', stacked: false, id: 'column1', group: 1},
    {label: 'Stacked Column chart', value: 'column', stacked: true, id: 'column2', group: 1},
    {label: 'Column Range chart', value: 'columnrange', stacked: false, id: 'column3', group: 2},       
    {label: '3D Column chart', value: 'column', stacked: false, threeD: true, id: 'column4', group: 1},

    {label: 'Area chart', value: 'area', stacked: false, id: 'area1', group: 1},
    {label: 'Stacked Area chart', value: 'area', stacked: true, id: 'area2', group: 1},
    {label: 'Area Range chart', value: 'arearange', stacked: false, id: 'area3', group: 2},

    {label: 'Line chart', value: 'line', stacked: false, id: 'line', group: 1},
    {label: 'Spline chart', value: 'spline', stacked: false, id: 'spline', group: 1},

    {label: 'Pie chart', value: 'pie', stacked: false, id: 'pie1', group: 3},       
    {label: '3D Pie chart', value: 'pie', stacked: false, threeD: true, id: 'pie2', group: 3},

    {label: 'Donut chart', value: 'pie', stacked: false, donut: true, id: 'donut1', group: 3},
    {label: '3D Donut chart', value: 'pie', stacked: false, threeD: true, donut: true, id: 'donut2', group: 3},

    {label: 'Scatter plot', value: 'scatter', stacked: false, id: 'scatter', group: 4},
    {label: 'Bubble chart', value: 'bubble', stacked: false, id: 'bubble', group: 4},

    {label: 'Progress chart', value: 'solidgauge', stacked: false, id: 'progress', group: 5}
],
chartDataObserver: Ember.observer('chartData', function(){
    this.setChartType();
    if(this.selectedChartType !== undefined){
        this.drawChart();
    }
}),
init() {
    this._super(...arguments);
    if(this.chartId === undefined){
        this.set('chartId', `chart_${this.generateUUID()}`);
    }
    this.setChartType();
    if(this.chartData.customTheme !== false){
        this.setChartsTheme();
    }
    else {
        this.removeTheme();
    }
},
didInsertElement() {
    this._super(...arguments);
    if(this.selectedChartType !== undefined){
        this.drawChart();
    }
},
generateUUID() {
    var d = new Date().getTime();
    var uuid = 'xxxxxxxxxxxxyy45'.replace(/[xy]/g, function(c) {
        return Math.floor((d+Math.random()*16)%16).toString(16);
    });
    return uuid;
},
removeTheme() {
    let stylesheet = document.getElementById('custom-chart-styles');
    if (stylesheet) {
        stylesheet.remove();
    }
},
setChartsTheme(){
    let colors = ['#234EA1', '#FCBC06', '#EC2027', '#70BE44', '#C1D331', '#C979CB', '#32CD9F', '#0099FF', '#87A1FF', '#9C7ACB'];
    if(this.chartData.colors !== undefined && this.chartData.colors.length > 0){
        colors = Ember.copy(this.chartData.colors);
    }
    this.addCustomColorStyles(colors);
    Highcharts.setOptions({
        colors: colors
    });
},
addCustomColorStyles(colors) {
    let stylesheet = document.getElementById('custom-chart-styles');
    if (!stylesheet) {
        stylesheet = Ember.$('<style id="custom-chart-styles">').appendTo('head')[0];
    }
    let html = '';
    colors.forEach((c,i)=>{
        html += `\n.highcharts-color-${i} { fill: ${c} !important; stroke: ${c} !important; } `;
    });
    stylesheet.innerHTML = html;
},
setChartType(){
    if(this.chartData.type !== undefined){
        this.chartTypes.every(t=>{
            if(t.id === this.chartData.type){
                this.set('selectedChartType', t);
                return false;
            }
            return true;
        });
        if(this.selectedChartType !== undefined){
            this.set('allowedChartTypes', this.chartTypes.filter(type=>{
                return this.selectedChartType.group === type.group;
            }));
        }
        if([1,2,4].indexOf(this.selectedChartType.group) > -1){
            if(this.chartData.customSlider === null){
                this.set('slider', false);
                this.set('customSlider', false);
            }
            else {
                if(this.chartData.customSlider !== undefined){
                    this.set('customSlider', this.chartData.customSlider);
                }
                this.set('slider', !this.customSlider);
            }
        }
        if(this.chartData.showChartTypeSelector !== undefined){
            this.set('showChartTypeSelector', this.chartData.showChartTypeSelector);
        }
    }
},
getAxisObject(axis) {
    let self = this, axisObject = {
        type: axis.type,
        categories: axis.categories,
        description: axis.description,
        max: axis.max,
        min: axis.min,
        title: {
            text: axis.title
        },
        stackLabels: {
            enabled: false,
            style: {
                fontWeight: 'bold',
                color: (Highcharts.theme && Highcharts.theme.textColor) || 'gray'
            }
        },
        opposite: axis.opposite
    };
    if(axis.type === 'datetime'){
        axisObject.events = {
            afterSetExtremes: function(){
                self.sendAction('onRangeChanged', this);
            }
        };
    }
    return axisObject;
},
processSeriesInformation(){
    let series = [];
    this.chartData.series.forEach((s,i)=>{
        if(typeof s === 'string'){
            series.push({
                name: s,
                data: this.chartData.data[i],
                yAxis: 0
            });
        }
        else {
            series.push({
                name: s.name,
                data: this.chartData.data[i],
                yAxis: s.yAxis !== undefined ? s.yAxis : 0,
                colorIndex: s.colorIndex,
                dashStyle: s.dashStyle
            }); 
        }
    });
    if(this.chartData.customSeries !== undefined){
        if(this.chartData.customSeries.constructor === Array){
            series.push(...this.chartData.customSeries);
        }
        else {
            series.push(this.chartData.customSeries);
        }
    }
    if(this.selectedChartType.group !== 3){
        series.forEach(s=>{
            if(s.data.length > 0){
                if(s.data[0].constructor === Array) {
                    s.data.sort((a,b)=>{
                        return a[0] > b[0] ? 1 : b[0] > a[0] ? -1 : 0;
                    });
                }
                else {
                    let sort = s.data[0].sort === 'x' ? 'x' : 'y';
                    s.data.sort((a,b)=>{
                        return a[sort] > b[sort] ? 1 : b[sort] > a[sort] ? -1 : 0;
                    });
                }
            }
        });
        if(series.length > 0 && series[0].data.length > 0 && series[0].data[0].constructor === Array){
            series.sort((a,b)=>{
                return a.data[0][0] > b.data[0][0] ? 1 : b.data[0][0] > a.data[0][0] ? -1 : 0;
            });
        }
    }
    return series;
},
drawChart() {
    let self = this;
    if(Ember.$(`#${this.chartId}`)){
        let series = this.processSeriesInformation(), stackTotalFormat = '', tooltipFormat = {}, config, axes = {},
        legend = {
            enabled: true,
            layout: 'vertical',
            align: 'right',
            verticalAlign: 'middle'
        };          
        if(this.selectedChartType.stacked){
            stackTotalFormat = '<br/>Total: {point.stackTotal}<br/>';
        }
        if(this.chartData.legend !== undefined){
            if(this.chartData.legend === false){
                legend = false;
            }
            else if(this.chartData.legend === 'left' || this.chartData.legend === 'right') {
                legend = {
                    enabled: true,
                    layout: 'vertical',
                    align: this.chartData.legend,
                    verticalAlign: 'middle'
                };
            }
            else {
                legend = {
                    enabled: true,
                    layout: 'horizontal',
                    align: 'center',
                    verticalAlign: this.chartData.legend
                };
            }
        }
        if(this.chartData.tooltipFormat !== undefined){
            tooltipFormat = this.chartData.tooltipFormat;
        }
        if(this.chartData.axes === undefined || this.chartData.axes.x === undefined || this.chartData.axes.y === undefined){
            axes = {x: [{}], y: [{}]};
        }
        else {
            axes.x = [];
            axes.y = [];
            if(this.chartData.axes.x.constructor === Array){
                this.chartData.axes.x.forEach(x=>{
                    axes.x.push(this.getAxisObject(x));
                });
            }
            else {
                axes.x.push(this.getAxisObject(this.chartData.axes.x));
            }
            if(this.chartData.axes.y.constructor === Array){
                this.chartData.axes.y.forEach(y=>{
                    axes.y.push(this.getAxisObject(y));
                });
            }
            else {
                axes.y.push(this.getAxisObject(this.chartData.axes.y));
            }
        }
        config = {
            chart: {
                renderTo: this.chartId,
                type: this.selectedChartType.value,
                borderColor: '#EBBA95',
                borderWidth: 2,
                borderRadius: '10px',
                backgroundColor: '#FFF',
                zoomType: 'xy',
                inverted: this.selectedChartType.inverted,
                options3d: {
                    enabled: this.selectedChartType.threeD,
                    alpha: 40
                },
                height: this.chartData.height,
                width: this.chartData.width
            },
            credits: {
                enabled: false
            },
            title: {
                text: this.chartData.title
            },
            exporting: false,
            series: series,
            subtitle: {
                text: this.chartData.subtitle
            },
            legend: legend,
            xAxis: axes.x,
            yAxis: axes.y,
            tooltip: {
                borderRadius: 10,
                delay: 500,
                headerFormat: tooltipFormat.header !== undefined ? tooltipFormat.header : '<b>Category: {point.x}</b><br/>',
                pointFormat: tooltipFormat.point !== undefined ? tooltipFormat.point : `Series {series.name}: {point.y}<br/>`,
                formatter: tooltipFormat.formatter,
                split: tooltipFormat.split,
                shared: !tooltipFormat.shared
            },
            plotOptions: {
                column: {
                    stacking: this.selectedChartType.stacked ? 'normal' : false,
                    dataLabels: {
                        enabled: true,
                        color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
                    }
                },
                columnrange: {
                    dataLabels: {
                        enabled: true,
                        style: {
                            color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
                        }
                    }   
                },
                pie: {
                    allowPointSelect: true,
                    cursor: 'pointer',
                    dataLabels: {
                        enabled: true,
                        format: '<b>{point.name}</b>: {point.percentage:.1f} %',
                        style: {
                            color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                        }
                    },
                    showInLegend: true,
                    innerSize: this.selectedChartType.donut ? this.chartData.innerSize ? this.chartData.innerSize : 70 : 0,
                    depth: this.selectedChartType.threeD ? 30 : 0
                },
                solidgauge: {
                    dataLabels: {
                        enabled: false,
                        style: {
                            color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
                        }
                    },
                    stickyTracking: false,
                    rounded: false
                },
                series: {
                    marker: {
                        enabled: this.chartData.markersEnabled
                    },
                    stacking: this.selectedChartType.stacked ? 'normal' : false,
                    dataLabels: {
                        enabled: false,
                        color: (Highcharts.theme && Highcharts.theme.dataLabelsColor) || 'gray'
                    },
                    point: {
                        events: {
                            click: function(e) {
                                self.sendAction('onChartClicked', this);
                            },
                            legendItemClick: function () {
                                return false;
                            }
                        }
                    },
                    turboThreshold: 10000,
                    cursor: 'pointer'
                }
            },
            rangeSelector: {
                enabled: this.chartData.rangeSelector ? this.chartData.rangeSelector : false
            },
            navigator: {
                enabled: this.slider
            },
            scrollbar: {
                enabled: this.slider
            }
        };
        if(this.selectedChartType.value === 'solidgauge'){
            config.pane = {
                startAngle: 0,
                endAngle: 360,
                background: [{
                    outerRadius: '100%',
                    innerRadius: '63%',
                    backgroundColor: Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0.3).get(),
                    borderWidth: 0
                }]
            };
            config.tooltip.positioner = (labelWidth) => {
                return {
                    x: 200 - labelWidth / 4,
                    y: 180
                };
            };
            config.yAxis.max = 100;
            config.yAxis.min = 0;
            config.series.forEach(s=>{
                s.data = s.data.map(d=>{
                    return {
                        color: Highcharts.Color(Highcharts.getOptions().colors[0]),
                        outerRadius: '112%',
                        innerRadius: '63%',
                        y: d
                    };
                });
            });
        }
        this.set('chart', Highcharts.stockChart(config));
        if(this.customSlider && this.chartData.rangeConfig === undefined){
            this.chart.axes.forEach(axis=>{
                if(axis.isXAxis){
                    Ember.set(this.chartData, 'rangeConfig', { min: axis.min, max: axis.max, type: this.chartData.axes.x.type === 'datetime' ? 'datetime': 'numeric', start: [axis.min, axis.max] });
                }
            });
        }
    }
},
actions: {
    selectChartType(event, type){
        this.set('selectedChartType', type);
        this.drawChart();
    },
    rangeChanged(newRangeValues){
        Ember.set(this.chartData.axes.x, 'min', newRangeValues[0]);
        Ember.set(this.chartData.axes.x, 'max', newRangeValues[1]);
        this.drawChart();
        this.sendAction('onRangeChanged', this.chartData.axes.x);
    }
}

});




Aucun commentaire:

Enregistrer un commentaire