Search code examples
javascripthtmlcssamchartsamcharts4

How to round an image used as bullet with amCharts?


I have at least two image bullets in my amCharts project and I want to round images of one of them named "bullet". Here is the line where a "bullet" exists...

var bullet = series.bullets.push(new am4charts.Bullet());

I have found a tutorial on rounding custom images here. They are used as bullets in amCharts but it rounds every bullet image and I want it to only round "bullet" ignoring "bullet2"

Here is my code (full size necessary):

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

// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
var myVar = {
  Red: "#f72c69",
  Normal: "#6887cc",
};

var userA_points = 22;
var userB_points = 20;
var userC_points = 6;
var members_points = 12;
var max_points = Math.max(userA_points, userB_points, userC_points, members_points);
var maxPlus = (max_points + 10);
maxPlus = Math.min(200, Math.max(0, maxPlus));
//console.log(maxPlus);

if (userA_points < members_points) {
  var colorCompare = myVar.Red
} else {
  var colorCompare = myVar.Normal
}

// Add data
chart.data = [{
  "name": "Damon",
  "points": userA_points,
  "color": "#5479f2",
  "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Koen-VanGeert-circle-ScripturaEngage.png",
  "bullet2": "Diamonds.png",
  "gameOvers": 3
}, {
  "name": "filip",
  "points": userB_points,
  "color": "#5479f2",
  "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png",
  "bullet2": "Diamonds.png",
  "gameOvers": 2
}, {
  "name": "Patrick",
  "points": userC_points,
  "color": "#5479f2",
  "bullet": "https://www.scripturaengage.com/wp-content/uploads/2017/05/Profile-Picture-Pauline-Suy-circle-ScripturaEngage.png",
  "bullet2": "Diamonds.png",
  "gameOvers": 2
}, {
  "name": "All Members",
  "points": members_points,
  "color": colorCompare,
  "bullet": "Members.png",
  "bullet2": "Diamonds.png",
  "gameOvers": 2
}];

// Create axes
var categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "name";
categoryAxis.renderer.grid.template.disabled = true;
categoryAxis.renderer.minGridDistance = 30;
categoryAxis.renderer.inside = true;
categoryAxis.renderer.labels.template.fill = am4core.color("#fff");
categoryAxis.renderer.labels.template.fontSize = 20;

var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.renderer.grid.template.strokeDasharray = "4,4";
valueAxis.renderer.labels.template.disabled = false;
valueAxis.renderer.labels.template.fontSize = 15;
valueAxis.renderer.labels.template.fontWeight = "800";

valueAxis.min = 0;
valueAxis.max = maxPlus;
valueAxis.strictMinMax = true;
valueAxis.renderer.minGridDistance = 25;

// Do not crop bullets
chart.maskBullets = false;

// Remove padding
chart.paddingBottom = 0;
chart.paddingTop = 50;
// Create series
var series = chart.series.push(new am4charts.ColumnSeries());
series.dataFields.valueY = "points";
series.dataFields.categoryX = "name";
series.columns.template.propertyFields.fill = "color";
series.columns.template.propertyFields.stroke = "color";
series.columns.template.column.cornerRadiusTopLeft = 25;
series.columns.template.column.cornerRadiusTopRight = 25;
series.columns.template.tooltipHTML = "<img src='your-image.png' style='vertical-align:bottom; margin-right: 10px; width:21px; height:21px;'><span style='font-size:14px; color:#000000;'><b>POINTS {valueY.value}</b></span><br><img src='your-image.png' style='vertical-align:bottom; margin-right: 10px; width:21px; height:21px;'><span style='font-size:14px; color:#000000;'><b>Game overs: {gameOvers}</b></span><br><img src='your-image.png' style='vertical-align:bottom; margin-right: 10px; width:21px; height:21px;'><span style='font-size:14px; color:#000000;'><b>Game overs: {gameOvers}</b></span><br><img src='your-image.png' style='vertical-align:bottom; margin-right: 10px; width:21px; height:21px;'><span style='font-size:14px; color:#000000;'><b>Game overs: {gameOvers}</b></span>";


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

// Add bullets
var bullet2 = series.bullets.push(new am4charts.Bullet());
var image = bullet2.createChild(am4core.Image);
image.width = 60;
image.height = 60;
image.horizontalCenter = "middle";
image.verticalCenter = "bottom";
image.dy = 60;
image.dx = 50;
image.y = am4core.percent(100);
image.propertyFields.href = "bullet2";
image.tooltipHTML = series.columns.template.tooltipHTML;
image.propertyFields.fill = "color";
image.filters.push(new am4core.DropShadowFilter());
#chartdiv {
  width: 1500px;
  height: 700px;
}

body {
  margin: 130 100 100 20;
  background-color: transparent;
  overflow: hidden;
  font-family: "Helvetica Neue";
  font-weight: 800;
  src: url(helveticaneue-ultrathin.woff);
}
<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>


Solution

  • Actually, the first bullet template isn't rounding or masking anything. The images you're using are transparent PNGs. If you set a background (e.g. the color black) on the bullets, you'll see that color appear underneath the image.

    bullet.height = 120;
    bullet.width = 120;
    bullet.background.fill = am4core.color("black");
    bullet.contentValign = "top";
    bullet.verticalCenter = "top";
    bullet.horizontalCenter = "middle";
    bullet.contentAlign = "center"
    

    As for the second set of bullets (bullet2), none of the images in the data are things we can test/see, so there's no way to know what's going on there.

    Here's a quick demo:

    https://codepen.io/team/amcharts/pen/ab60df9b6b084559ec6ae2ceaa604bf1

    Now, if you want to add your own clipping mask around the image, thanks to xorspark I've figured out how to do that. Create a Circle as a child of the first set of bullets, then on the Image add an adapter for its mask property, in there you'll return the bullet's circle. You'll have to play with alignment-related properties to get the positioning just right.

    E.g.

    var mask = new am4core.Circle();
    mask.radius = 40;
    mask.horizontalCenter = "middle";
    mask.verticalCenter = "middle";
    mask.align = "center";
    mask.valign = "top";
    mask.parent = bullet;
    
    image.adapter.add("mask", function(mask, target) {
      return target.parent.children.getIndex(1)
    });
    

    Demo (you'll see less of the image shows than usual):

    https://codepen.io/team/amcharts/pen/1ee8ad3b525c8ecb3cb0c6e88da441af