Я делаю диаграмму XY, используя amcharts.js, стремясь показать частоту ответов на ряд утверждений. Утверждения расположены на оси категорий 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()
Проблема заключается в вашей пользовательской теме, которая устанавливает minPosition и maxPosition для объектов AxisRenderer, чтобы скрыть 0 и 1, что также влияет на средство визуализации CategoryAxis. Вам лучше использовать адаптер на оси значений, чтобы скрыть оскорбительные значения:
valueAxis.renderer.labels.template.adapter.add("text", function(text) {
if (+text < 1 || +text > 7) {
return "";
}
return text;
});
Что касается скорости, я не замечаю никакой медлительности, и я использую старый ноутбук. Единственные незначительные изменения, которые я могу предложить, — это использование LineSeries для простоты (вам нужно только отключить strokeOpacity
) и удаление дополнительного маркера categoryLabel, который, похоже, не имеет никакого смысла.
xorspark - отлично! Это сделало это! Большое спасибо за ваше время помочь мне с этим. Я опробую ваши мысли о LineSeries после нашего раннего рождественского обеда — если я еще смогу встать. ;-) Проблема со скоростью действительно проявляется, когда на странице есть все 27 категорий и более одной диаграммы вместе с кодом jquery из начальной загрузки. С Рождеством!