1

我正在尝试将应用程序从 移植Flex 3Sencha Ext JS 4. 此应用程序有一个带有柱形图的仪表板(请参见下面的第一张图片)。它的值xField有点长。

在此处输入图像描述

尽可能地,我不希望我的标签被旋转。嗯,我觉得有点乱。如果可能的话,我希望我的标签在不合适的情况下交替放置。

label : {
    rotate : {degrees:45}
}

下图是我的Sencha自定义图表。大部分Category标签没有显示。

在此处输入图像描述

我正在考虑自定义onPlaceLabel功能,但我不知道该怎么做。我将如何做到这一点以实现我所需要的?

4

2 回答 2

5

Ext.chart.axis.Axis#drawHoriztontalLabels就是你需要覆盖。onPlaceLabel是写在图表本身的东西。就像栏顶部的标签一样,你明白我的意思吗?

干净的方法是覆盖类并实现一些快乐的选项。如果您想了解实现,我会让您探索我在帖子末尾放置的完整代码......

Ext.define('Ext.ux.chart.axis.Axis.OverlappingLabelOptions', {
    override: 'Ext.chart.axis.Axis'

    ,labelRows: 1

    ,hideOverlappingLabels: true

    ,drawHorizontalLabels: function() {
        // ... see at the end of the post for the full implementation
    }
});

使用 包含此覆盖类require后,您可以在轴定义中使用这两个选项。例如:

{
    type: 'Category',
    position: 'bottom',
    fields: ['name'],
    title: 'Sample Metrics',

    labelRows: 5,
    hideOverlappingLabels: false
}

我的第一次尝试是自动将重叠标签向下推一排。这就是你通过设置获得的labelRows: 'auto'。它在某些条件下运行良好,并且具有自动化的优势。

在此处输入图像描述

不幸的是,它会变得非常混乱:

在此处输入图像描述

所以我求助于实现一个选项,让您固定标签行数,并在这些行之间均匀分布标签。我还添加了hideOverlappingLabels确保即使我们错过运气并且某些标签结束重叠也不会丢失标签。

这是您使用此配置获得的结果:

{
    // ...
    hideOverlappingLabels: false,
    labelRows: 5
}

在此处输入图像描述

我希望这会给你你所需要的,或者至少是让 Ext 的代码满足你的愿望的知识!

全面实施

/**
 * This override adds a {@link #labelRows} option to draw horizontal axis labels on multiple
 * rows, and also an {@link #hideOverlappingLabels} option.
 */
Ext.define('Ext.ux.chart.axis.Axis.OverlappingLabelOptions', {
    override: 'Ext.chart.axis.Axis'

    ,alternateClassName: 'Ext.ux.AxisOverlappingLabelOptions'

    /**
     * @cfg {Integer/String}
     *
     * Number of label rows. If this option is set to 'auto', then overlapping labels will
     * be drawn on the next row where they don't overlap. Which can give a messy result.
     */
    ,labelRows: 1

    /**
     * @cfg {Boolean}
     *
     * Set to false to prevent automatic hiding of overlapping labels.
     */
    ,hideOverlappingLabels: true

    ,drawHorizontalLabels: function() {
        var me = this,
            labelConf = me.label,
            floor = Math.floor,
            max = Math.max,
            axes = me.chart.axes,
            insetPadding = me.chart.insetPadding,
            gutters = me.chart.maxGutters,
            position = me.position,
            inflections = me.inflections,
            ln = inflections.length,
            labels = me.labels,
            maxHeight = 0,
            ratio,
            bbox, point, prevLabel, prevLabelId,
            adjustEnd = me.adjustEnd,
            hasLeft = axes.findIndex('position', 'left') != -1,
            hasRight = axes.findIndex('position', 'right') != -1,
            textLabel, text,
            last, x, y, i, firstLabel;

        var labelRows = Ext.num(this.labelRows, 1),
            autoOffsetLabels = this.labelRows === 'auto',
            hideLabels = this.hideOverlappingLabels;

        var lastLabelOnRow = [],
            row, j;

        last = ln - 1;
        //get a reference to the first text label dimensions
        point = inflections[0];
        firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
        ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));

        for (i = 0; i < ln; i++) {
            row = 0; // rx: start at first row
            point = inflections[i];
            text = me.label.renderer(labels[i]);
            textLabel = me.getOrCreateLabel(i, text);
            bbox = textLabel._bbox;
            //maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
            x = floor(point[0] - (ratio ? bbox.height : bbox.width) / 2);
            if (adjustEnd && gutters.left == 0 && gutters.right == 0) {
                if (i == 0 && !hasLeft) {
                    x = point[0];
                }
                else if (i == last && !hasRight) {
                    x = Math.min(x, point[0] - bbox.width + insetPadding);
                }
            }
            if (position == 'top') {
                y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
            }
            else {
                y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
            }

            // rx: vertical offset
            y += (i % labelRows) * bbox.height;

            textLabel.setAttributes({
                hidden: false,
                x: x,
                y: y
            }, true);

            if (autoOffsetLabels) {
                // rx: find the row on which we can draw the label without overlapping
                for (j=0; j<lastLabelOnRow.length; j++) {
                    if (me.intersect(textLabel, lastLabelOnRow[j])) {
                        row++;
                        textLabel.setAttributes({
                            y: y + row * bbox.height
                        }, true);
                    }
                }

                // rx: calc maxHeight knowing the row
                maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding + (bbox.height * row));

                // rx: keep reference to know where we can place the next label
                lastLabelOnRow[row] = textLabel;
            } else {

                if (hideLabels) {
                    // Skip label if there isn't available minimum space
                    if (i != 0 && (me.intersect(textLabel, prevLabel)
                        || me.intersect(textLabel, firstLabel))) {
                        if (i === last && prevLabelId !== 0) {
                            prevLabel.hide(true);
                        } else {
                            textLabel.hide(true);
                            continue;
                        }
                    }
                }

                maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding + bbox.height * (i % labelRows));
            }

            prevLabel = textLabel;
            prevLabelId = i;
        }

        return maxHeight;
    }
});
于 2013-07-26T16:40:53.340 回答
0

我有一个类似的问题,xaxis 标签文本太长。如果缩短可见标签文本并使用轴标签的工具提示是您的一个选项,那么您可能会发现以下有用...

我的解决方案是:

  1. 缩短可见轴标签文本,以便标签适合(并因此呈现)

  2. 为轴标签精灵添加工具提示并使其显示完整的标签文本

代码片段:

  1. 内轴配置...

    label : {
           renderer: function(v){
    
            //if v is 'Grilled Pizza Special' then you get something like 'Grilled ...'
             return Ext.String.ellipsis(v,12);
           }                 
        }
    
  2. 修改 drawHorizo​​ntalLabels()...

    drawHorizontalLabels: function () {
    var me = this,
        labelConf = me.label,
        floor = Math.floor,
        max = Math.max,
        axes = me.chart.axes,
        insetPadding = me.chart.insetPadding,
        position = me.position,
        inflections = me.inflections,
        ln = inflections.length,
        labels = me.labels,
        maxHeight = 0,
        ratio,
        bbox, point, prevLabel, prevLabelId,
        adjustEnd = me.adjustEnd,
        hasLeft = axes.findIndex('position', 'left') != -1,
        hasRight = axes.findIndex('position', 'right') != -1,
        textLabel, text,tooltipText,
        last, x, y, i, firstLabel;
    
    last = ln - 1;
    //get a reference to the first text label dimensions
    point = inflections[0];
    firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
    ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));
    
    for (i = 0; i < ln; i++) {
        point = inflections[i];
        text = me.label.renderer(labels[i]);
        //not using text variable above for tooltip as tooltip would render the ellipsis text rather than the full label text.
        tooltipText = labels[i]; 
        textLabel = me.getOrCreateLabel(i, text);
        bbox = textLabel._bbox;
        maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
        x = floor(point[0] - (ratio ? bbox.height : bbox.width) / 2);
        if (adjustEnd && me.chart.maxGutter[0] == 0) {
            if (i == 0 && !hasLeft) {
                x = point[0];
            }
            else if (i == last && !hasRight) {
                x = Math.min(x, point[0] - bbox.width + insetPadding);
            }
        }
        if (position == 'top') {
            y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
        }
        else {
            y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
        }
    
        textLabel.setAttributes({
            hidden: false,
            x: x,
            y: y
        }, true);
    
              var labelTip = Ext.create('Ext.tip.ToolTip', {
            target : textLabel.el,
            html : tooltipText
        });
    
        // Skip label if there isn't available minimum space
        if (i != 0 && (me.intersect(textLabel, prevLabel)
            || me.intersect(textLabel, firstLabel))) {
            if (i === last && prevLabelId !== 0) {
                prevLabel.hide(true); 
            } else {
                textLabel.hide(true); 
                continue;
            }
        }
    
        prevLabel = textLabel;
        prevLabelId = i;
    }
    
    return maxHeight;
    }
    
于 2013-09-11T16:15:39.903 回答