Search code examples
javascripthtmlamcharts

How do I get rid of this amCharts distortion?


I want to show my users ranking using the amCharts Javascript library. Users are ranked like this (It's good and with no problem) :

enter image description here

The problem is if I have two identical Profile names (for example if I have two Sara names as profile name or even two similar slogan sentences) something like this happens : (Here I changed John to Sara so we have two Saras)

Note: The whole text area goes down as arrows shown. and it seems I've lost one of those Saras ( Now I can see only 5 profiles instead of 6 profiles).

enter image description here

Plus I found this code and this one in amCharts demos that seems to be a solution or a hint for this.

Here is my code on CodePen.

And Here is my javascript code:

// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end


var chart = am4core.create("chartdiv", am4charts.XYChart);

chart.data = [{
        "profileName": "John",
        "slogan": "Slogan Sentence Related to Profile Name 6",
        "level": "6.",
        "income": 0,
        "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"

    }, {
        "profileName": "Sara",
        "slogan": "Slogan Sentence Related to Profile Name 5",
        "level": "5.",
        "income": 0,
        "bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
    }, {
        "profileName": "Nima",
        "slogan": "Slogan Sentence Related to Profile Name 4",
        "level": "4.",
        "income": 0,
        "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
    }, {
        "profileName": "Max",
        "slogan": "Slogan Sentence Related to Profile Name 3",
        "level": "3.",
        "income": 0,
        "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"
    }, {
        "profileName": "Megan",
        "slogan": "Slogan Sentence Related to Profile Name 2",
        "level": "2.",
        "income": 0,
        "bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
    }, {
        "profileName": "Inna",
        "slogan": "Slogan Sentence Related to Profile Name 1",
        "level": "1.",
        "income": 0,
        "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
    }  ];

// Chart A:

//create category axis for Names Column 
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "profileName";
categoryAxis.renderer.grid.template.location = -100;
categoryAxis.renderer.inside = true;
categoryAxis.renderer.labels.template.dy = -60;
categoryAxis.renderer.labels.template.dx = 200;
categoryAxis.labelsEnabled = false;
categoryAxis.renderer.labels.template.fontSize = 20;
categoryAxis.renderer.labels.template.fill = am4core.color("#4286f4");


//create category axis for Slogans Column 
var categoryAxis2 = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis2.dataFields.category = "slogan";
categoryAxis2.renderer.grid.template.location = 100;
categoryAxis2.renderer.inside = true;
categoryAxis2.renderer.labels.template.dy = -20;
categoryAxis2.renderer.labels.template.dx = 200;
categoryAxis2.renderer.labels.template.fontSize = 12;

//create category level
var categoryAxis3 = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis3.dataFields.category = "level";
categoryAxis3.renderer.grid.template.location = 100;
categoryAxis3.renderer.inside = true;
categoryAxis3.renderer.labels.template.dy = -20;
categoryAxis3.renderer.labels.template.dx = 170;
categoryAxis3.renderer.labels.template.fontSize = 16;
categoryAxis3.renderer.labels.template.fill = am4core.color("#ccd3e0");


//create value axis for income and expenses
var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.opposite = true;



valueAxis.min = 0;
valueAxis.max = 10;
valueAxis.strictMinMax = true;  
valueAxis.renderer.minGridDistance = 25;
valueAxis.renderer.labels.template.disabled = true;
valueAxis.disabled = true;

//create columns
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.categoryY = "profileName";
series.dataFields.valueX = "income";
series.name = "Income";
series.columns.template.fillOpacity = 0.5;
series.columns.template.strokeOpacity = 0;


// Do not crop bullets
chart.maskBullets = false;
chart.paddingTop = 64;
chart.paddingBottom = -30;

// Add bullets
var bullet = series.bullets.push(new am4charts.Bullet());
var image = bullet.createChild(am4core.Image);
image.horizontalCenter = "middle";
image.verticalCenter = "bottom";
image.width = 120;
image.height = 120;
image.dy = 0;
image.dx = 100;
image.y = am4core.percent(100);
image.propertyFields.href = "bullet";
image.tooltipText = series.columns.template.tooltipText;
image.propertyFields.fill = "color";
image.filters.push(new am4core.DropShadowFilter());

Solution

  • CategoryAxis is a, well, a category axis. This means that items on your chart are grouped by "category", or profileName in your case.

    If you have to identical categories (two Saras for example), they are grouped into a single slot, hence the issue you are having.

    The only solution is to ensure all categories are unique. For example you can suffix each name with a "~[userid]".

    Then add an adapter which strips that suffix off:

    // Themes begin
    am4core.useTheme(am4themes_animated);
    // Themes end
    
    
    var chart = am4core.create("chartdiv", am4charts.XYChart);
    
    chart.data = [{
            "profileName": "Sara~2",
    		"slogan": "Slogan Sentence Related to Profile Name 6",
    		"level": "6.",
            "income": 0,
    		"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"
    
        }, {
            "profileName": "Sara",
    		"slogan": "Slogan Sentence Related to Profile Name 5",
    		"level": "5.",
            "income": 0,
    		"bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
        }, {
            "profileName": "Nima",
    		"slogan": "Slogan Sentence Related to Profile Name 4",
    		"level": "4.",
            "income": 0,
    		"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
        }, {
            "profileName": "Max",
    		"slogan": "Slogan Sentence Related to Profile Name 3",
    		"level": "3.",
            "income": 0,
    		"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png"
        }, {
            "profileName": "Megan",
    		"slogan": "Slogan Sentence Related to Profile Name 2",
    		"level": "2.",
            "income": 0,
    		"bullet": "https://i1.wp.com/teacupwellness.com/wp-content/uploads/2018/03/Amanda-Blankinship-profile-circle.png?fit=300%2C300&ssl=1"
        }, {
            "profileName": "Inna",
    		"slogan": "Slogan Sentence Related to Profile Name 1",
    		"level": "1.",
            "income": 0,
    		"bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png"
        }  ];
    	
    // Chart A:
    
    //create category axis for Names Column 
    var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
    categoryAxis.dataFields.category = "profileName";
    categoryAxis.renderer.grid.template.location = -100;
    categoryAxis.renderer.inside = true;
    categoryAxis.renderer.labels.template.dy = -60;
    categoryAxis.renderer.labels.template.dx = 200;
    categoryAxis.labelsEnabled = false;
    categoryAxis.renderer.labels.template.fontSize = 20;
    categoryAxis.renderer.labels.template.fill = am4core.color("#4286f4");
    categoryAxis.renderer.labels.template.adapter.add("textOutput", stripSuffix);
    
    
    //create category axis for Slogans Column 
    var categoryAxis2 = chart.yAxes.push(new am4charts.CategoryAxis());
    categoryAxis2.dataFields.category = "slogan";
    categoryAxis2.renderer.grid.template.location = 100;
    categoryAxis2.renderer.inside = true;
    categoryAxis2.renderer.labels.template.dy = -20;
    categoryAxis2.renderer.labels.template.dx = 200;
    categoryAxis2.renderer.labels.template.fontSize = 12;
    categoryAxis2.renderer.labels.template.adapter.add("textOutput", stripSuffix);
    
    //create category level
    var categoryAxis3 = chart.yAxes.push(new am4charts.CategoryAxis());
    categoryAxis3.dataFields.category = "level";
    categoryAxis3.renderer.grid.template.location = 100;
    categoryAxis3.renderer.inside = true;
    categoryAxis3.renderer.labels.template.dy = -20;
    categoryAxis3.renderer.labels.template.dx = 170;
    categoryAxis3.renderer.labels.template.fontSize = 16;
    categoryAxis3.renderer.labels.template.fill = am4core.color("#ccd3e0");
    
    function stripSuffix(category) {
      return category.split("~").shift();
    }
    
    
    //create value axis for income and expenses
    var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
    valueAxis.renderer.opposite = true;
    
    
    
    valueAxis.min = 0;
    valueAxis.max = 10;
    valueAxis.strictMinMax = true;  
    valueAxis.renderer.minGridDistance = 25;
    valueAxis.renderer.labels.template.disabled = true;
    valueAxis.disabled = true;
    
    //create columns
    var series = chart.series.push(new am4charts.ColumnSeries());
    series.dataFields.categoryY = "profileName";
    series.dataFields.valueX = "income";
    series.name = "Income";
    series.columns.template.fillOpacity = 0.5;
    series.columns.template.strokeOpacity = 0;
    
    
    // Do not crop bullets
    chart.maskBullets = false;
    chart.paddingTop = 64;
    chart.paddingBottom = -30;
    
    // Add bullets
    var bullet = series.bullets.push(new am4charts.Bullet());
    var image = bullet.createChild(am4core.Image);
    image.horizontalCenter = "middle";
    image.verticalCenter = "bottom";
    image.width = 120;
    image.height = 120;
    image.dy = 0;
    image.dx = 100;
    image.y = am4core.percent(100);
    image.propertyFields.href = "bullet";
    image.tooltipText = series.columns.template.tooltipText;
    image.propertyFields.fill = "color";
    image.filters.push(new am4core.DropShadowFilter());
    #chartdiv {
      width: 1500px;
      height: 840px;
    }
    
    body {	
    	margin: 40 100 100 20;
    	background-color: transparent;
        overflow:hidden;
      font-family: "Helvetica Neue";
      font-weight: 800;
      src: url(helveticaneue-ultrathin.woff);	
     }
    <!-- Resources -->
    <script src="https://www.amcharts.com/lib/4/core.js"></script>
    <script src="https://www.amcharts.com/lib/4/charts.js"></script>
    <script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
    
    <div id="chartdiv"></div>