我正在尝试将应用程序从Flex 3
移植到Sencha Ext JS 4
。此应用程序有一个带有柱形图的仪表板(请看下面的第一张图)。 xField
的值有点长。
尽可能地,我不希望我的标签被旋转。好吧,我认为这有点混乱。如果可能的话,我希望我的标签在不适合的情况下交替定位。
label : {
rotate : {degrees:45}
}
图片下方的是我的Sencha
自定义图表。大多数Category
标签都没有显示。
我正在考虑自定义onPlaceLabel
功能,但我不知道该怎么做。
我将如何做到这一点来实现我所需要的?
答案 0 :(得分:5)
你需要覆盖Ext.chart.axis.Axis#drawHoriztontalLabels
。 onPlaceLabel
用于图表本身写的东西。就像栏顶部的标签一样,你明白我的意思吗?
干净的方法是override这个类,并实现一些快乐的选择。如果你想了解实现,我会让你探讨我在帖子末尾写的完整代码......
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;
}
});
答案 1 :(得分:0)
我遇到类似的问题,xaxis标签文本太长了。如果缩短可见标签文本并使用轴标签的工具提示是一个选项,那么您可能会发现以下有用...
我的解决方案是:
缩短可见轴标签文本,使标签适合(因此 渲染)
为轴标签精灵添加工具提示,并使其显示完整的标签文字
代码段:
内轴配置......
label : {
renderer: function(v){
//if v is 'Grilled Pizza Special' then you get something like 'Grilled ...'
return Ext.String.ellipsis(v,12);
}
}
修改了drawHorizontalLabels()...
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;
}