"Bullets" is a collection of configurable shapes (stars, pins, flags, etc.) that you can use as chart bullets, map markers, and anywhere else.
Availability
Bullets plugin is available since amCharts 4 version 4.5.7
.
Including the module
Before you can use this plugin you need to make sure you include it.
If you are using it in a TypeScript/ES6 application, you can import it as module. For pure JavaScript applications you'll need to include a .js
vesion
import * as am4plugins_bullets from "@amcharts/amcharts4/plugins/bullets";
<script src="//cdn.amcharts.com/lib/4/plugins/bullets.js"></script>
Bullet types
There are currently 4 complex bullet types included (with more planned to add in the future) with Bullets plugin:
Class | Example | Comment |
FlagBullet | Draws a flag shape with optional text inside it. Flag is configurable down to colors, pole length, flag "waveness", etc. | |
PinBullet | Draws a pin shape with optional image and/or text inside it. | |
PointedCircle | Simple version of PinBullet : same shape but no option to add text or image. | |
ShapeBullet | A universal bullet that can take a few basic shapes as circle, diamond, square, etc. It's useful when you need to connect shape of a bullet to data or simplify your bullet code. | |
Star | Draws a star shape with configurable number of parameters, including number of points, radius, rounding, etc. |
You can click on the link for each class for a reference of all available properties. Or you can continue reading and we'll look at some of those later in the article, as well as present you with a bullet configurator.
Using
In a nutshell, a bullet from Bullets plugin is an advanced shape that can be used virtually anywhere, even as a standalone element.
We're going to look into few common usage cases shortly. But first, let's see how we instantiate a bullet shape.
Just like any other visual class that derives from Sprite
, we can instantiate it using new
syntax. The name scope for items in this plugin is as follows: am4plugins_bullets.
. E.g.:
new am4plugins_bullets.FlagBullet();
new am4plugins_bullets.FlagBullet();
As series bullets
The most common usage of bullets is enhancing Series - mostly LineSeries
.
In the course of this chapter we'll add and configure advanced bullets to a LineSeries
, tied them to data, and even make them react to heat rules.
Adding a bullet to series
MORE INFO Adding bullets to series is covered in great detail here. For advanced techniques of controlling bullets, visit the article linked. We are going to provide simplified code snippets here.
Let's add a Star
bullet to a simple LineSeries
:
let bullet = series.bullets.push(new am4plugins_bullets.Star()); bullet.radius = 20; bullet.pointCount = 8;
var bullet = series.bullets.push(new am4plugins_bullets.Star()); bullet.radius = 20; bullet.pointCount = 8;
{ // ... "series": [{ // ... "bullets": [{ "type": "Star", "radius": 20, "pointCount": 8 }] }] }
As you can see, we are not just creating a bullet instance. We're also setting some shape-specific settings, like in this instance we're making our star have 20 pixel radius, and 8 points.
Let's see how it turned out:
See the Pen PMoraX by amCharts team (@amcharts) on CodePen.
Tying to data
For purpose of this task, let's use a more complicated shape - a flag.
As it happens we have a FlagBullet
in our Bullets plugin.
It's not just a shape, though. It can also contain text label.
To make it more interesting, let's selectively put flag bullets on only a few data points with unique text in them.
Here's the code (follow comments in code for breakdown):
// Creating a bullet let bullet = series.bullets.push(new am4plugins_bullets.FlagBullet()); // Setting label to display values from data bullet.label.text = "{bulletText}\n[bold]{valueY}[/]"; bullet.label.textAlign = "middle"; // Disabling all bullets, except ones that are explicitly enabled via data bullet.disabled = true; bullet.propertyFields.disabled = "hideBullet"; // Allowing controlling pole height via data (negative height means upside down flag) // We also instruct pole to draw its color from "bulletColor" in data bullet.propertyFields.poleHeight = "height"; bullet.pole.propertyFields.stroke = "bulletColor"; // Background is a WavedRectangle, which we configure, as well as instruct // it to get its fill and border color from data field "bulletColor" bullet.background.waveLength = 15; bullet.background.fillOpacity = 0.5; bullet.background.propertyFields.fill = "bulletColor"; bullet.background.propertyFields.stroke = "bulletColor"; // Add a circle to pole base. // Bullet is a Container, so we can add there anything. let circle = bullet.createChild(am4core.Circle); circle.radius = 4; circle.strokeWidth = 2; circle.stroke = am4core.color("#fff"); circle.propertyFields.fill = "bulletColor";
// Creating a bullet var bullet = series.bullets.push(new am4plugins_bullets.FlagBullet()); // Setting label to display values from data bullet.label.text = "{bulletText}\n[bold]{valueY}[/]"; bullet.label.textAlign = "middle"; // Disabling all bullets, except ones that are explicitly enabled via data bullet.disabled = true; bullet.propertyFields.disabled = "hideBullet"; // Allowing controlling pole height via data (negative height means upside down flag) // We also instruct pole to draw its color from "bulletColor" in data bullet.propertyFields.poleHeight = "height"; bullet.pole.propertyFields.stroke = "bulletColor"; // Background is a WavedRectangle, which we configure, as well as instruct // it to get its fill and border color from data field "bulletColor" bullet.background.waveLength = 15; bullet.background.fillOpacity = 0.5; bullet.background.propertyFields.fill = "bulletColor"; bullet.background.propertyFields.stroke = "bulletColor"; // Add a circle to pole base. // Bullet is a Container, so we can add there anything. var circle = bullet.createChild(am4core.Circle); circle.radius = 4; circle.strokeWidth = 2; circle.stroke = am4core.color("#fff"); circle.propertyFields.fill = "bulletColor";
{ // ... "series": [{ // ... "bullets": [{ "type": "FlagBullet", // Setting label to display values from data "label": { "text": "{bulletText}\n[bold]{valueY}[/]", "textAlign": "middle" }, // Disabling all bullets, except ones that are explicitly enabled via data "disabled": true, "propertyFields": { "disabled": "hideBullet" }, // Allowing controlling pole height via data (negative height means upside down flag) // We also instruct pole to draw its color from "bulletColor" in data "background": { "waveLength": 15, "fillOpacity": 0.5, "propertyFields": { "fill": "bulletColor", "stroke": "bulletColor" } }, // Add a circle to pole base. // Bullet is a Container, so we can add there anything. "children": [{ "type": "Circle", "radius": 4, "strokeWidth": 2, "stroke": "#fff", "propertyFields": { "fill": "bulletColor" } }] }] }] }
See the Pen amCharts 4: Using FlagBullet by amCharts team (@amcharts) on CodePen.
Using ShapeBullet
This type of bullet deserves a special mention.
It's unique feature is that it can take multiple basic shapes, e.g. circle, diamond, triangle, etc.
Creating a shape bullet
The shape type is set via string-based parameter shape
.
For example, if we'd like to add diamond-shaped bullets to a LineSeries
we could do this:
let bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.shape = "diamond";
var bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.shape = "diamond";
{ // ... "series": [{ // ... "bullets": [{ "type": "ShapeBullet", "shape": "diamond" }] }] }
Setting size of the ShapeBullet
Another convenient aspect of a ShapeBullet
is that we don't have to care about a number of different size-related settings like width
, height
, scale
, radius
, etc.
There's a single property for that: size
. Its value is in pixels.
Setting a size for such bullet is as easy as it sounds:
let bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.shape = "diamond"; bullet.size = 20;
var bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.shape = "diamond"; bullet.size = 20;
{ // ... "series": [{ // ... "bullets": [{ "type": "ShapeBullet", "shape": "diamond", "size": 20 }] }] }
Binding shape and size to data
Having both shape and size as basic properties allows us to easily bind them to data via property fields and even heat rules.
let bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.propertyFields.shape = "bullet"; series.heatRules.push({ "target": bullet, "property": "size", "min": 15, "max": 30, "dataField": "valueY" });
var bullet = series.bullets.push(new am4plugins_bullets.ShapeBullet()); bullet.propertyFields.shape = "bullet"; series.heatRules.push({ "target": bullet, "property": "size", "min": 15, "max": 30, "dataField": "valueY" });
{ // ... "series": [{ // ... "heatRules": [{ "target": "bullets[0]", "property": "size", "min": 15, "max": 30, "dataField": "valueY" }], "bullets": [{ "type": "ShapeBullet", "shape": "diamond", "size": 20 }] }] }
Here's a complete example:
See the Pen Using ShapeBullet with property fields and heat rules by amCharts team (@amcharts) on CodePen.
As map markers
Now, let's try these out on a Map, but go even deeper.
We are going to use PinBullet
here. We'll also display an image URL for which we'll feed from data.
We'll also use "heat rules" to dynamically set radius of the bullet to indicate value set in data. Again, please follow commends in code for pointers on what we are doing.
// Image series let imageSeries = chart.series.push(new am4maps.MapImageSeries()); let imageTemplate = imageSeries.mapImages.template; imageTemplate.propertyFields.longitude = "longitude"; imageTemplate.propertyFields.latitude = "latitude"; imageTemplate.nonScaling = true; // Creating a pin bullet let pin = imageTemplate.createChild(am4plugins_bullets.PinBullet); // Set what to display on rollover tooltip pin.tooltipText = "{title}"; imageSeries.tooltip.pointerOrientation = "right"; // Configuring pin appearance pin.background.fill = chart.colors.getIndex(0); pin.background.fillOpacity = 0.7; pin.background.pointerAngle = 120; pin.background.pointerBaseWidth = 10; // Adding an image with its "href" attribute tied to values in data pin.image = new am4core.Image(); pin.image.propertyFields.href = "imageURL"; // Creating a "heat rule" to modify "radius" of the bullet based // on value in data imageSeries.heatRules.push({ "target": pin.background, "property": "radius", "min": 20, "max": 40, "dataField": "value" }); // Add a circle to pin base. // Bullet is a Container, so we can add there anything. let circle = pin.createChild(am4core.Ellipse); circle.radius = 6; circle.radiusY = 3; circle.strokeWidth = 0; circle.fillOpacity = 0.1; circle.zIndex = -1;
// Image series var imageSeries = chart.series.push(new am4maps.MapImageSeries()); var imageTemplate = imageSeries.mapImages.template; imageTemplate.propertyFields.longitude = "longitude"; imageTemplate.propertyFields.latitude = "latitude"; imageTemplate.nonScaling = true; // Creating a pin bullet var pin = imageTemplate.createChild(am4plugins_bullets.PinBullet); // Set what to display on rollover tooltip pin.tooltipText = "{title}"; imageSeries.tooltip.pointerOrientation = "right"; // Configuring pin appearance pin.background.fill = chart.colors.getIndex(0); pin.background.fillOpacity = 0.7; pin.background.pointerAngle = 120; pin.background.pointerBaseWidth = 10; // Adding an image with its "href" attribute tied to values in data pin.image = new am4core.Image(); pin.image.propertyFields.href = "imageURL"; // Creating a "heat rule" to modify "radius" of the bullet based // on value in data imageSeries.heatRules.push({ "target": pin.background, "property": "radius", "min": 20, "max": 40, "dataField": "value" }); // Add a circle to pin base. // Bullet is a Container, so we can add there anything. var circle = pin.createChild(am4core.Ellipse); circle.radius = 6; circle.radiusY = 3; circle.strokeWidth = 0; circle.fillOpacity = 0.1; circle.zIndex = -1;
{ // ... "series": [{ // Image series "type": "MapImageSeries", // Set what to display on rollover tooltip "tooltipText": "{title}", "tooltip": { "pointerOrientation": "right" }, // Creating a "heat rule" to modify "radius" of the bullet based // on value in data "heatRules": [{ "target": "children[0].background", "property": "radius", "min": 20, "max": 40, "dataField": "value" }], "mapImages": [{ "propertyFields": { "longitude": "longitude", "latitude": "latitude" }, "nonScaling": true "children": [{ // Creating a pin bullet "type": "PinBullet", // Configuring pin appearance "background": { "fill": "#c00", "fillOpacity": 0.7, "pointerAngle": 120, "pointerBaseWidth": 10, }, // Adding an image with its "href" attribute tied to values in data "image": { "type": "Image", "propertyFields":{ "href": "imageURL" } }, // Add a circle to pole base. // Bullet is a Container, so we can add there anything. "children": [{ "type": "Ellipse", "radius": 6, "radiusY": 3, "strokeWidth": 0, "fillOpacity": 0.1, "zIndex": -1 }] }] }] }] }
And, here we go:
See the Pen amCharts 4: Map with PinBullet by amCharts team (@amcharts) on CodePen.
Bullet configuration tool
The below tool will help you visually select the best options for one of your bullets.
See the Pen amCharts 4: Bullet configurator by amCharts team (@amcharts) on CodePen.