第一个和最后一个类别标签在 AmCharts XY 图表中消失

First and last category labels disappearing in AmCharts XY chart

我正在使用 amcharts.js 制作 XY 图表,试图显示对多个陈述的响应频率。陈述在 Y 类别轴中,响应作为 X 轴中的项目符号点。

我这里有一个工作演示:https://codepen.io/david-green/pen/VwKbORM

最多 5 个类别,显示所有类别。然而,如果我超过 5 个类别,首先初始类别消失,然后最后一个类别消失。在 16 个类别中,顶部和底部的 2 个消失。对于实时项目所需的 27 个类别的完整补充,前 3 个和最后 3 个类别消失了。

这可能是什么原因造成的? 是否有更好的方法来构建数据以更有效地呈现?目前渲染速度很慢。

am4core.ready(function() {
  
//========================================
//SETUP  

var amchartsConfig = {
    "questionsBackgroundColour" : "#eee",
    "questionsWrapLength" : 400,
    "cellSize" : 17,
    "transition": 1000,
  };
var minBulletSize = 3;
var maxBulletSize = 20;
var bulletValueLabelOffset = 5;
var bulletRespondents = {
  "bulletType": "respondents",
  "tooltipLabel": "Respondents",
  "strokeWidth": 1,
  "strokeColour": "#000000",
  "strokeOpacity": 1,
  "fillColour": "#cccccc",
  "fillOpacity": 1,
  "labelColour": "#999999"
};
var bulletMeanScore = {
  "bulletType": "mean",
  "tooltipLabel": "Mean Score",
  "strokeWidth": 4,
  "strokeColour": "#ff0000",
  "strokeOpacity": 1,
  "fillColour": "#ffffff",
  "fillOpacity": 0.2,
  "labelColour": "#ff0000"
};
// Define a custom theme
function am4themes_courseProfiles(target) {
  if (target instanceof am4charts.CategoryAxis) {
    target.background.fill = am4core.color(amchartsConfig.questionsBackgroundColour);
  }
  if (target instanceof am4charts.AxisRenderer) {
    //hide the 0 and 8 xaxis labels, as reponses are only 1-7
    target.minLabelPosition = 0.1;
    target.maxLabelPosition = 0.9;
  }
}
// Themes begin
//am4core.useTheme(am4themes_animated);
am4core.useTheme(am4themes_material);
am4core.useTheme(am4themes_courseProfiles);
// Themes end

//END SETUP    
//========================================
  


//========================================
//DATA
  
//Build the questions data array
  var chart1questions = new Array(
    "1. Here is a statement that wraps around a number of lines.",
    "2. Here is a statement that wraps around a number of lines.",
    "3. Here is a statement that wraps around a number of lines.",
    "4. Here is a statement that wraps around a number of lines.",
    "5. Here is a statement that wraps around a number of lines.",
    "6. Here is a statement that wraps around a number of lines.",
    "7. Here is a statement that wraps around a number of lines.",
    "8. Here is a statement that wraps around a number of lines.",
    "9. Here is a statement that wraps around a number of lines.",
    "10. Here is a statement that wraps around a number of lines.",
    "11. Here is a statement that wraps around a number of lines.",
    "12. Here is a statement that wraps around a number of lines.",
    "13. Here is a statement that wraps around a number of lines.",
    "14. Here is a statement that wraps around a number of lines.",
    "15. Here is a statement that wraps around a number of lines.",
    "16. Here is a statement that wraps around a number of lines.",
    "17. Here is a statement that wraps around a number of lines.",     
  );
//Build the Answers data array
var chart1data = [
  {'question':chart1questions[0], 'answer':4, 'mean':null, 'score':2},
    {'question':chart1questions[0], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[0], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[0], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[0], 'answer':null,'mean':5.3,'score':1},
    {'question':chart1questions[1], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[1], 'answer':4, 'mean':null, 'score':2},
    {'question':chart1questions[1], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[1], 'answer':null,'mean':5.2,'score':1},
    {'question':chart1questions[2], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[2], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[2], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[2], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[2], 'answer':null,'mean':5.3,'score':1},
    {'question':chart1questions[3], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[3], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[3], 'answer':6, 'mean':null, 'score':1},
    {'question':chart1questions[3], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[3], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[3], 'answer':null,'mean':5,'score':1},
    {'question':chart1questions[4], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[4], 'answer':4, 'mean':null, 'score':2},
    {'question':chart1questions[4], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[4], 'answer':null,'mean':4.8,'score':1},
    {'question':chart1questions[5], 'answer':2, 'mean':null, 'score':1},
    {'question':chart1questions[5], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[5], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[5], 'answer':7, 'mean':null, 'score':2},
    {'question':chart1questions[5], 'answer':null,'mean':5,'score':1},
    {'question':chart1questions[6], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[6], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[6], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[6], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[6], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[6], 'answer':null,'mean':5.2,'score':1},
    {'question':chart1questions[7], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[7], 'answer':4, 'mean':null, 'score':2},
    {'question':chart1questions[7], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[7], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[7], 'answer':null,'mean':4.7,'score':1},
    {'question':chart1questions[8], 'answer':2, 'mean':null, 'score':1},
    {'question':chart1questions[8], 'answer':5, 'mean':null, 'score':4},
    {'question':chart1questions[8], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[8], 'answer':null,'mean':4.8,'score':1},
    {'question':chart1questions[9], 'answer':2, 'mean':null, 'score':1},
    {'question':chart1questions[9], 'answer':1, 'mean':null, 'score':1},
    {'question':chart1questions[9], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[9], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[9], 'answer':null,'mean':4.7,'score':1},
    {'question':chart1questions[10], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[10], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[10], 'answer':2, 'mean':null, 'score':1},
    {'question':chart1questions[10], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[10], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[10], 'answer':null,'mean':5,'score':1},
    {'question':chart1questions[11], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[11], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[11], 'answer':5, 'mean':null, 'score':3},
    {'question':chart1questions[11], 'answer':null,'mean':5,'score':1},
    {'question':chart1questions[12], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[12], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[12], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[12], 'answer':null,'mean':5.2,'score':1},
    {'question':chart1questions[13], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[13], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[13], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[13], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[13], 'answer':null,'mean':5.7,'score':1},
    {'question':chart1questions[14], 'answer':5, 'mean':null, 'score':1},
    {'question':chart1questions[14], 'answer':3, 'mean':null, 'score':1},
    {'question':chart1questions[14], 'answer':7, 'mean':null, 'score':2},
    {'question':chart1questions[14], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[14], 'answer':null,'mean':5.7,'score':1},
    {'question':chart1questions[15], 'answer':2, 'mean':null, 'score':1},
    {'question':chart1questions[15], 'answer':1, 'mean':null, 'score':1},
    {'question':chart1questions[15], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[15], 'answer':6, 'mean':null, 'score':3},
    {'question':chart1questions[15], 'answer':null,'mean':4.7,'score':1},
    {'question':chart1questions[16], 'answer':7, 'mean':null, 'score':1},
    {'question':chart1questions[16], 'answer':4, 'mean':null, 'score':1},
    {'question':chart1questions[16], 'answer':5, 'mean':null, 'score':2},
    {'question':chart1questions[16], 'answer':6, 'mean':null, 'score':2},
    {'question':chart1questions[16], 'answer':null,'mean':5.5,'score':1},
  ]; 
//END DATA  
//========================================

  
  
//======================================== 
// Create chart
function createChart(chartName,chartData,chartDiv, amchartsConfig) {
  
     // Create chart instance
    var chartName = am4core.create(chartDiv, am4charts.XYChart);
    chartName.maskBullets = false;

    // Add data
    chartName.data = chartData;

    // Create axes
    var categoryAxis = chartName.yAxes.push(new am4charts.CategoryAxis());
    categoryAxis.dataFields.category = "question";
    categoryAxis.renderer.labels.template.properties.align = 3;
    categoryAxis.numberFormatter.numberFormat = "#";
    categoryAxis.renderer.inversed = true;
    categoryAxis.renderer.grid.template.disabled = true;

    // Configure axis label
    var label = categoryAxis.renderer.labels.template;
    label.wrap = true;
    label.maxWidth = amchartsConfig.questionsWrapLength;
    label.align = "left";

    var  valueAxis = chartName.xAxes.push(new am4charts.ValueAxis()); 
    valueAxis.renderer.opposite = true;
    valueAxis.min = 0;
    valueAxis.max = 8;
    valueAxis.keepSelection = true;
    valueAxis.renderer.minGridDistance = 50;
    valueAxis.numberFormatter = new am4core.NumberFormatter();
    valueAxis.numberFormatter.numberFormat = "#"; 

  return chartName;
};
//========================================
  

  
//========================================  
// Create series
function createSeries(chartName,field, name, bulletVars) {
  var series = chartName.series.push(new am4charts.ColumnSeries());
  series.dataFields.valueX = field;
  series.dataFields.categoryY = "question";
  series.dataFields.value = "score";
  series.columns.template.tooltipText = bulletVars.tooltipLabel+": [bold]{value}[/]";
  series.columns.template.disabled = true;
  series.columns.template.height = am4core.percent(100);
  series.sequencedInterpolation = true;
  series.stacked = true;
//  series.defaultState.transitionDuration = amchartsConfig.transition;

  var bullet = series.bullets.push(new am4core.Circle());
  bullet.tooltipText = bulletVars.tooltipLabel+": {value.workingValue.formatNumber('#.')}";
  bullet.strokeWidth = bulletVars.strokeWidth;
  bullet.stroke = am4core.color(bulletVars.strokeColour);
  bullet.strokeOpacity = bulletVars.strokeOpacity;
  bullet.fill = am4core.color(bulletVars.fillColour);
  bullet.fillOpacity = bulletVars.fillOpacity
  bullet.hiddenState.properties.scale = 0.01;
  bullet.hiddenState.properties.opacity = 0.1;

  var labelBullet = series.bullets.push(new am4charts.LabelBullet());
  labelBullet.label.text = "{value}";
  labelBullet.label.fontSize = 13;
  labelBullet.label.fontStyle = "italic";
  var bulletsCoreOffset = maxBulletSize + bulletValueLabelOffset;
  labelBullet.label.fill = am4core.color("#aaa");
  if(bulletVars.bulletType=="mean"){
    bulletsCoreOffset = 0 - bulletValueLabelOffset - maxBulletSize;    
    labelBullet.label.fill = am4core.color("#f00");
    labelBullet.label.text = "[font-style: italic]Avg: {valueX}[/]";
  };
  labelBullet.label.dy = bulletsCoreOffset;

  var hoverState = bullet.states.create("hover");
  hoverState.properties.strokeOpacity = 1;

  series.heatRules.push({
    property: "radius",
    target: bullet,
    min: minBulletSize,
    max: maxBulletSize
  });

  var categoryLabel = series.bullets.push(new am4charts.LabelBullet());
  categoryLabel.label.fill = am4core.color("#fff");
  
  // Set cell size in pixels
  chartName.events.on("datavalidated", function(ev) {
    // Get objects of interest
    var chartName = ev.target;
    var categoryAxis = chartName.yAxes.getIndex(0);
    // Calculate how we need to adjust chart height
    var adjustHeight = chartName.data.length * amchartsConfig.cellSize - categoryAxis.pixelHeight;
    // get current chart height
    var targetHeight = chartName.pixelHeight + adjustHeight;
    // Set it on chart's container
    chartName.svgContainer.htmlElement.style.height = targetHeight + "px";
  });  
}
//========================================
  
  
//======================================== 
//Finally build one or more charts. 
chart1 = createChart("chart1",chart1data,"chartdiv",amchartsConfig);
createSeries(chart1, "answer", "Answer", bulletRespondents);
createSeries(chart1, "mean", "Mean", bulletMeanScore);
//========================================
  

}); // end am4core.ready()

问题是您的自定义主题将 AxisRenderer 对象上的 minPosition 和 maxPosition 设置为隐藏 0 和 1,这也会影响 CategoryAxis 的渲染器。您最好在值轴上使用适配器来隐藏违规值:

  valueAxis.renderer.labels.template.adapter.add("text", function(text) {
    if (+text < 1 || +text > 7) {
      return "";
    }
    return text;
  });

在速度方面,我没有注意到任何缓慢,而且我使用的是旧笔记本电脑。我可以建议的唯一小改动是为了简单起见使用 LineSeries(您只需要禁用 strokeOpacity)并删除似乎没有任何用处的额外 categoryLabel 项目符号。

Updated codepen