Establishing a minimum width for the value of zero in AmCharts column series by customizing the bullet labels

Here's an interesting example where I have arranged column series with bullet labels. However, you may notice that there are some 0 values present as well. My goal is to establish a minimum width for the series so that even if the value is small or 0, the bullet label remains visible.

For instance, take a look at the series for the year 2017, which starts with a 0. Unfortunately, the label is not fully visible in this case.

/**
 * ---------------------------------------
 * This demonstration was crafted using amCharts 4.
 * 
 * For more details, please visit:
 * https://www.amcharts.com/
 * 
 * Comprehensive documentation can be found at:
 * https://www.amcharts.com/docs/v4/
 * ---------------------------------------
 */

// Initializing themes
am4core.useTheme(am4themes_animated);
// Theme settings complete

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

// Adding data
chart.data = [{
  "year": "2016",
  "europe": 1.5,
  "namerica": 1.5,
  "asia": 1.3,
  "lamerica": 0.3,
  "meast": 0.2,
  "africa": 0
}, {
  "year": "2017",
  "europe": 0,
  "namerica": 1.8,
  "asia": 1.4,
  "lamerica": 0.3,
  "meast": 0.3,
  "africa": 0.1
}, {
  "year": "2018",
  "europe": 1.9,
  "namerica": 2.0,
  "asia": 0,
  "lamerica": 0.4,
  "meast": 0.3,
  "africa": 0.1
}];

chart.legend = new am4charts.Legend();
chart.legend.position = "right";

// Establishing axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "year";
categoryAxis.renderer.grid.template.opacity = 0;

var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.renderer.grid.template.opacity = 0;
valueAxis.renderer.ticks.template.strokeOpacity = 0.5;
valueAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
valueAxis.renderer.ticks.template.length = 10;
valueAxis.renderer.line.strokeOpacity = 0.5;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.minGridDistance = 40;

// Creating series
function createSeries(field, name) {
  var series = chart.series.push(new am4charts.ColumnSeries());
  series.dataFields.valueX = field;
  series.dataFields.categoryY = "year";
  series.stacked = true;
  series.name = name;
  
  series.minWidth = `100px`;
  
  var labelBullet = series.bullets.push(new am4charts.LabelBullet());
  labelBullet.locationX = 0.5;
  labelBullet.label.text = "{valueX}";
  labelBullet.label.fill = am4core.color("#fff");
}

createSeries("europe", "Europe");
createSeries("namerica", "North America");
createSeries("asia", "Asia");
createSeries("lamerica", "Latin America");
createSeries("meast", "Middle East");
createSeries("africa", "Africa");

chart.legend.position = 'bottom';
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

#chartdiv {
  width: 100%;
  height: 500px;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>

Answer №1

It's not possible to set a minimum width/height for columns in a chart because the size is determined by the data, and forcing a minimum size could distort the values.

A more effective approach is to hide labels that are too large by using hideOversized with label bullets and utilize tooltips along with a chart cursor for better data representation.

am4core.useTheme(am4themes_animated);

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

// Adding sample data
chart.data = [{
  "year": "2016",
  "europe": 1.5,
  "namerica": 1.5,
  "asia": 1.1,
  "lamerica": 0.3,
  "meast": 0.2,
  "africa": 0
}, {
  "year": "2017",
  "europe": 0,
  "namerica": 1.7,
  "asia": 1.2,
  "lamerica": 0.3,
  "meast": 0.3,
  "africa": 0.1
}, {
  "year": "2018",
  "europe": 1.8,
  "namerica": 1.9,
  "asia": 0,
  "lamerica": 0.3,
  "meast": 0.3,
  "africa": 0.1
}];

chart.legend = new am4charts.Legend();
chart.legend.position = "right";

// Setting up axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "year";
categoryAxis.renderer.grid.template.opacity = 0;

var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.renderer.grid.template.opacity = 0;
valueAxis.renderer.ticks.template.strokeOpacity = 0.5;
valueAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
valueAxis.renderer.ticks.template.length = 10;
valueAxis.renderer.line.strokeOpacity = 0.5;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.minGridDistance = 40;

// Creating series
function createSeries(field, name) {
  var series = chart.series.push(new am4charts.ColumnSeries());
  series.dataFields.valueX = field;
  series.dataFields.categoryY = "year";
  series.stacked = true;
  series.name = name;
  series.tooltipText = "{name}: {valueX}";
  
  var labelBullet = series.bullets.push(new am4charts.LabelBullet());
  labelBullet.label.hideOversized = true;
  labelBullet.locationX = 0.5;
  labelBullet.label.text = "{valueX}";
  labelBullet.label.fill = am4core.color("#fff");
}

createSeries("europe", "Europe");
createSeries("namerica", "North America");
createSeries("asia", "Asia");
createSeries("lamerica", "Latin America");
createSeries("meast", "Middle East");
createSeries("africa", "Africa");

chart.legend.position = 'bottom';
chart.cursor = new am4charts.XYCursor();
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

#chartdiv {
  width: 100%;
  height: 500px;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>

Answer №2

Here is an alternative solution that offers a fresh perspective or you might want to consider adjusting the label positioning.

/**
 * ---------------------------------------
 * This code snippet demonstrates the usage of amCharts 4 library.
 * 
 * For detailed information, please visit:
 * https://www.amcharts.com/
 * 
 * Check out the documentation at:
 * https://www.amcharts.com/docs/v4/
 * ---------------------------------------
 */

// Themes initialization
am4core.useTheme(am4themes_animated);
// End of themes

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

// Populate data
chart.data = [{
  "year": "2016",
  "europe": 1.5,
  "namerica": 1.5,
  "asia": 1.1,
  "lamerica": 0.3,
  "meast": 0.2,
  "africa": 0
}, {
  "year": "2017",
  "europe": 0,
  "namerica": 1.7,
  "asia": 1.2,
  "lamerica": 0.3,
  "meast": 0.3,
  "africa": 0.1
}, {
  "year": "2018",
  "europe": 1.8,
  "namerica": 1.9,
  "asia": 0,
  "lamerica": 0.3,
  "meast": 0.3,
  "africa": 0.1
}];

chart.legend = new am4charts.Legend();
chart.legend.position = "right";

// Set up axes
var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
categoryAxis.dataFields.category = "year";
categoryAxis.renderer.grid.template.opacity = 0;

var valueAxis = chart.xAxes.push(new am4charts.ValueAxis());
valueAxis.min = 0;
valueAxis.renderer.grid.template.opacity = 0;
valueAxis.renderer.ticks.template.strokeOpacity = 0.5;
valueAxis.renderer.ticks.template.stroke = am4core.color("#495C43");
valueAxis.renderer.ticks.template.length = 10;
valueAxis.renderer.line.strokeOpacity = 0.5;
valueAxis.renderer.baseGrid.disabled = true;
valueAxis.renderer.minGridDistance = 40;

// Create series function
function createSeries(field, name) {
  var series = chart.series.push(new am4charts.ColumnSeries());
  series.dataFields.valueX = field;
  series.dataFields.categoryY = "year";
  series.stacked = true;
  series.name = name;
  
  series.minWidth = `100px`;
  
  var labelBullet = series.bullets.push(new am4charts.LabelBullet());
  labelBullet.locationX = 0.5;
  labelBullet.label.text = "{valueX}";
  labelBullet.label.fill = am4core.color("#fff");
  labelBullet.label.x= 4;
}

createSeries("europe", "Europe");
createSeries("namerica", "North America");
createSeries("asia", "Asia");
createSeries("lamerica", "Latin America");
createSeries("meast", "Middle East");
createSeries("africa", "Africa");

chart.legend.position = 'bottom';
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI, Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

#chartdiv {
  width: 100%;
  height: 500px;
}
<script src="https://cdn.amcharts.com/lib/4/core.js"></script>
<script src="https://cdn.amcharts.com/lib/4/charts.js"></script>
<script src="https://cdn.amcharts.com/lib/4/themes/animated.js"></script>
<div id="chartdiv"></div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is the JSON object sent over an AJAX call getting corrupted during a POST request?

While conducting tests on this application, The browser is sending a json as an array of approximately 500 objects via POST method. Upon inspecting the received json using a PHP server and debugger(xdebug), It appears that there are more elements in ...

Validating the body in Node.js for POST and PUT requests

When working in a production setting, what is considered the standard for POST / PUT body validation? I typically approach it like this: const isValid = (req.body.foo && /[a-z0-9]*/i.test(req.body.foo)) This method involves checking that the var ...

Guidelines for creating a dynamic filter in Prisma js

I am looking to create a dynamic filter based on user input from the frontend. On mapping the data, I found that the object results appear like this: { id: '2', name: 'yuhu' } The keys 'id' and 'name' need to be dyn ...

Iterating through a JavaScript object

Just starting out with JavaScript and trying to figure out how to iterate through a JSON result that has been converted into a JavaScript object. const url = 'https://api.mybitx.com/api/1/tickers?pair=XBTMYR'; fetch(url) .then(res => re ...

"Exploring the Art of Showcasing Duplicate Image Count from User Input in an

I need to showcase multiple duplicates of 2 different images on a webpage. Users are asked for the duplication speed, which I have already implemented, and also how many copies of each image they want. function show_image() { var img = document.create ...

Creating new components within A-frame

I've been attempting to implement the bubble function into my scene to generate a sphere, but unfortunately nothing is showing up. Even when I try creating a sphere without using the bubble function, it still doesn't appear in the scene. func ...

Error: TweenLite has not been recognized

/justincavery/pen/mPJadb - this is a link to CodePen After copying the code from CodePen and running it, I encountered an error: "Uncaught ReferenceError: TweenLite is not defined". The image only draws once and there is no animation unless I press "F5 ...

Fixing the hydration error in Next 13 can be challenging, especially when it occurs outside of a Suspense boundary

Encountering an issue while working with Next.js 13: Error: Hydration failed because the initial UI does not match what was rendered on the server. Warning: Expected server HTML to contain a matching <div> in <html>. Every time I attempt to r ...

Changing the InnerHTML of a tag in JavaScript using class and id attributes

When it comes to handling these links <div class="post_actions"> <a class="color-transition article_delete" href=""><i class="fa fa-pencil"></i></a> <a class="color-transition article_edit" href="#" id="1">< ...

Alpha-Beta Pruning Minimax Algorithm Fails to Determine the Best Move in Tic-Tac-Toe Artificial Intelligence

I have been developing a Tic-Tac-Toe AI system that uses the Alpha-Beta Pruning Minimax algorithm to determine the best move for the AI player (X) on the game board. Unfortunately, I am running into an issue where the algorithm is not returning the correct ...

Rails Navigation Issue: JQuery Confirmation Not Functioning Properly

Having a Rails app, I wanted to replicate the onunload effect to prompt before leaving changes. During my search, I came across Are You Sure?. After implementing it on a form, I noticed that it only works on page refreshes and not on links that take you a ...

"Upon choosing a file using the HTML input file multiple element, a triggered event

After selecting multiple files using the input type="file" HTML element, I am eager to start uploading them. Can you tell me which event I should use to execute code immediately after finalizing my file selection? This is what my HTML code looks like: &l ...

Choose a different option when there is a change

Here is an example of JSON data: [{ "user_id": "113", "employe_first_name": "Asaladauangkitamakan", "employe_last_name": "Nasibb" }, { "user_id": "105", "employe_first_name": "Ryan", "employe_last_name": ...

The symbol "#" appears in my URL whenever the link is clicked

Seeking guidance on a URL issue that I am facing. Whenever I click the source link, it adds a pound sign to the URL. How can I prevent this from happening? Can someone assist me in identifying the necessary changes required in my jQuery or HTML code? Bel ...

Mastering Meteor: Techniques for Manipulating Mongodb Data in Real Time Display

Within my Meteor application, I have accomplished the successful publication of data from the server and its subscription on the client side. Instead of directly displaying raw data on the client's screen, I am interested in performing some calculatio ...

Creating a variable to store the data retrieved from a package

Imagine you have a functioning code snippet like this: const myPackage = require('myPackage'); myPackage.internal_func(parameter).then(console.log); This outputs a JSON object, for example: { x: 'valX', y: 'valY' } ...

GraphQL Shield throws an 'Unauthorized' error for a permitted mutation

I've been working on setting up a GraphQL API with apollo-server-express, and I'm trying to handle permissions using graphql-shield middleware. However, I'm running into some issues when it comes to allowing mutations to be executed. My aim ...

Generating dynamic forms using JSON Schema in Angular 8 can greatly streamline the form creation process

Struggling with generating dynamic forms from JSON Schema in Angular 8, I stumbled upon a couple of libraries. One seemed outdated with its last commit around 2 years ago, while the other appeared to be a more recent fork of it for Angular 8. The first li ...

Transform the outcome of Request() into a variable

I'm currently working with the following code snippet: request('http://steamcommunity.com/market/priceoverview/?currency=1&appid=730&market_hash_name=Gamma Case', function (e, r, body){ var req_data = JSON.parse(body); conso ...

Encountering Errors with Angular JS Following Update from Version 1.1.0 to 1.1.1

After upgrading, I noticed that the ng-repeat function is taking significantly longer to load and is attempting to display additional content boxes without serving the actual content provided by $resource. I have pinpointed the issue to the update from ve ...