Issue with Google Charts where the label does not show outside of the bar if the bar is too small

I am encountering an issue with my Google Bar Chart where the bar label is not displaying outside of the bar when it is too large to fit inside. This behavior should be the default, but my charts are not working as expected. The problem can be seen in rows 2, 3, 5, 7, and 8 in the screenshot provided below.

https://i.sstatic.net/TPj2d.png

Below is the code snippet:

// START Disease Resistance
function disease() {
  var data = google.visualization.arrayToDataTable([
    ['Disease', 'Resistance Rating', { role: 'annotation'}, { role: 'style'}, { role: 'tooltip'}],

    ['Barley Yellow Dwarf', 5, '5', '#221f72', 'Barley Yellow Dwarf | Resistance Rating: 5'], // Resistance rating is calculated by subtracting the value from 10
    ['Fusarium Head Blight', 1, '9', '#221f72', 'Fusarium Head Blight | Resistance Rating: 9'],
    ['Hessian Fly', 1, '9', '#221f72', 'Hessian Fly | Resistance Rating: 9'],
    ['Leaf Rust', 2, '8', '#221f72', 'Leaf Rust | Resistance Rating: 8'],
    ['Powdery Mildew', 1, '9', '#221f72', 'Powdery Mildew | Resistance Rating: 9'],
    ['Soil-Borne Mosaic', 4, '6', '#221f72', 'Soil-Borne Mosaic | Resistance Rating: 6'],
    ['Stem Rust', 1, '9', '#221f72', 'Stem Rust | Resistance Rating: 9'],
    ['Stripe Rust', 1, '9', '#221f72', 'Stripe Rust | Resistance Rating: 9'],
    ['Tan Spot', 5, '5', '#221f72', 'Tan Spot | Resistance Rating: 5'],
    ['Wheat Streak Mosaic', 5, '5', '#221f72', 'Wheat Streak Mosaic | Resistance Rating: 5'],

  ]);
  var paddingHeight = 80;
  var rowHeight = data.getNumberOfRows() * 80;
  var chartHeight = rowHeight + paddingHeight;

  var options = {
      'backgroundColor': 'transparent',
    annotations: {textStyle: {fontSize: 16, fontName: 'Source Sans Pro'}},
    legend: { position: 'none'},
    height: chartHeight,
    colors: ['#F4AA00'],
    chartArea: {
      width: '100%',
      height: rowHeight
    },
    hAxis: {
        ticks: [{v:1, f:'9'}, {v:2, f:'8'}, {v:3, f:'7'}, {v:4, f:'6'}, {v:5, f:'5'}, {v:6, f:'4'}, {v:7, f:'3'}, {v:8, f:'2'}, {v:9, f:'1'}, {v:10, f:'0'}],
      title: '7-9 Susceptible | 4-6 Intermediate | 1-3 Resistant',
        viewWindow: {
        min: 0,
        max: 10
    },
      minValue: 0,
      textStyle: {
        fontName: 'Source Sans Pro',
          bold: true,
        fontSize: 12,
        color: '#4d4d4d'
      },
      titleTextStyle: {
        fontName: 'Source Sans Pro',
          bold: true,
        fontSize: 14,
        color: '#4d4d4d'
      }
    },
    vAxis: {
        textPosition: 'in',
      title: 'Disease',
      textStyle: {
        fontName: 'Source Sans Pro',
          fontSize: 14,
        bold: false,
        color: '#fff'
      },
      titleTextStyle: {
        fontName: 'Source Sans Pro',
          fontSize: 14,
        bold: true,
        color: '#848484'
      }
    }
  };
  var chart = new google.visualization.BarChart(document.getElementById('disease'));
  chart.draw(data, options);

    // redraw charts responsively
    (function($) {
        function resizeCharts () {
        chart.draw(data, options);
        }
        $(window).resize(resizeCharts);
    })( jQuery );
}
// END Disease Resistance

Any help would be greatly appreciated!

Answer №1

It is evident that the option provided below is not functioning effectively...

vAxis.textPosition: 'in'

Alternatively, the only other available option that may work adequately...

theme: 'maximized'

This allows the text to extend beyond the bar's boundaries.
Consequently, half of the text will be displayed on a blue background,
while the remainder will be on a white background.
With an appropriate font color, this appears acceptable but leads to overlap with the annotation.

The sole remaining option I have devised entails adding the label to the annotation.
And subsequently removing it from the y-axis.

While this results in the same outcome as previously,
it prevents any conflicting overlap with the annotation.

However, this also gives rise to another challenge.
The text is positioned at the end of the bar,
rather than the beginning.
To address this, we can manually shift the annotations once the chart's 'ready' event triggers.
Yet, any interactivity such as "hover/mouseover" would cause the chart to reposition them back.
Therefore, we need to utilize a MutationObserver to keep them consistently at the start of the bar.

Please refer to the functional snippet below for clarification...

google.charts.load('current', {
  packages: ['corechart']
}).then(disease);

function disease() {
  var data = google.visualization.arrayToDataTable([
    ['Disease', 'Resistance Rating', { role: 'annotation'}, { role: 'style'}, { role: 'tooltip'}],

    ['', 5, 'Barley Yellow Dwarf: 5', '#221f72', 'Barley Yellow Dwarf | Resistance Rating: 5'], // Resistance rating is calculated by subracting the value from 10
    ['', 1, 'Fusarium Head Blight: 9', '#221f72', 'Fusarium Head Blight | Resistance Rating: 9'],
    ['', 1, 'Hessian Fly: 9', '#221f72', 'Hessian Fly | Resistance Rating: 9'],
    ['', 2, 'Leaf Rust: 8', '#221f72', 'Leaf Rust | Resistance Rating: 8'],
    ['', 1, 'Powdery Mildew: 9', '#221f72', 'Powdery Mildew | Resistance Rating: 9'],
    ['', 4, 'Soil-Borne Mosaic: 6', '#221f72', 'Soil-Borne Mosaic | Resistance Rating: 6'],
    ['', 1, 'Stem Rust: 9', '#221f72', 'Stem Rust | Resistance Rating: 9'],
    ['', 1, 'Stripe Rust: 9', '#221f72', 'Stripe Rust | Resistance Rating: 9'],
    ['', 5, 'Tan Spot: 5', '#221f72', 'Tan Spot | Resistance Rating: 5'],
    ['', 5, 'Wheat Streak Mosaic: 5', '#221f72', 'Wheat Streak Mosaic | Resistance Rating: 5'],

  ]);
  var paddingHeight = 80;
  var rowHeight = data.getNumberOfRows() * 80;
  var chartHeight = rowHeight + paddingHeight;

  var options = {
    backgroundColor: 'transparent',
    annotations: {textStyle: {fontSize: 16, fontName: 'Source Sans Pro'}},
    legend: {position: 'none'},
    height: chartHeight,
    colors: ['#F4AA00'],
    chartArea: {
      width: '100%',
      height: rowHeight
    },
    hAxis: {
      ticks: [{v:1, f:'9'}, {v:2, f:'8'}, {v:3, f:'7'}, {v:4, f:'6'}, {v:5, f:'5'}, {v:6, f:'4'}, {v:7, f:'3'}, {v:8, f:'2'}, {v:9, f:'1'}, {v:10, f:'0'}],
      title: '7-9 Susceptible | 4-6 Intermediate | 1-3 Resistant',
      viewWindow: {
        min: 0,
        max: 10
      },
      minValue: 0,
      textStyle: {
        fontName: 'Source Sans Pro',
        bold: true,
        fontSize: 12,
        color: '#4d4d4d'
      },
      titleTextStyle: {
        fontName: 'Source Sans Pro',
        bold: true,
        fontSize: 14,
        color: '#4d4d4d'
      }
    },
    vAxis: {
      title: 'Disease',
      textStyle: {
        fontName: 'Source Sans Pro',
        fontSize: 14,
        bold: false
      },
      titleTextStyle: {
        fontName: 'Source Sans Pro',
        fontSize: 14,
        bold: true,
        color: '#848484'
      }
    }
  };
  var chart = new google.visualization.BarChart(document.getElementById('disease'));

  google.visualization.events.addListener(chart, 'ready', function () {
    var observer = new MutationObserver(moveAnnotations);
    observer.observe(chart.getContainer(), {
      childList: true,
      subtree: true
    });
  });

  function moveAnnotations() {
    var chartLayout = chart.getChartLayoutInterface();
    var chartBounds = chartLayout.getChartAreaBoundingBox();
    var barBounds = chartLayout.getBoundingBox('bar#0#0');
    var labels = chart.getContainer().getElementsByTagName('text');
    Array.prototype.forEach.call(labels, function(label, index) {
      if (label.getAttribute('font-size') === '16') {
        label.setAttribute('x', barBounds.left + chartBounds.left + 4);
        label.setAttribute('fill', 'magenta');
        label.setAttribute('text-anchor', 'start');
      }
    });
  }

  chart.draw(data, options);

    // redraw charts responsively
    (function($) {
        function resizeCharts () {
        chart.draw(data, options);
        }
        $(window).resize(resizeCharts);
    })( jQuery );
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="disease"></div>

Kindly note: While 'magenta' is not recommended as the color choice,
it serves to exemplify the necessity for an alternative color...

Answer №2

Special thanks to @WhiteHat for the detailed response. I decided to integrate the disease information into the annotation:

['Disease', 'Resistance Rating', { role: 'annotation'}, { role: 'style'}, { role: 'tooltip'}],

    ['Barley Yellow Dwarf', 5, 'Barley Yellow Dwarf | 5', '#221f72', 'Barley Yellow Dwarf | Resistance Rating: 5'], // Resistance rating is calculated by subtracting the value from 10
    ['Fusarium Head Blight', 1, 'Fusarium Head Blight | 9', '#221f72', 'Fusarium Head Blight | Resistance Rating: 9'],
    ['Hessian Fly', 1, 'Hessian Fly | 9', '#221f72', 'Hessian Fly | Resistance Rating: 9'],
    ['Leaf Rust', 2, 'Leaf Rust | 8', '#221f72', 'Leaf Rust | Resistance Rating: 8'],
    ['Powdery Mildew', 1, 'Powdery Mildew | 9', '#221f72', 'Powdery Mildew | Resistance Rating: 9'],
    ['Soil-Borne Mosaic', 4, 'Soil-Borne Mosaic | 6', '#221f72', 'Soil-Borne Mosaic | Resistance Rating: 6'],
    ['Stem Rust', 1, 'Stem Rust | 9', '#221f72', 'Stem Rust | Resistance Rating: 9'],
    ['Stripe Rust', 1, 'Stripe Rust | 9', '#221f72', 'Stripe Rust | Resistance Rating: 9'],
    ['Tan Spot', 5, 'Tan Spot | 5', '#221f72', 'Tan Spot | Resistance Rating: 5'],
    ['Wheat Streak Mosaic', 5, 'Wheat Streak Mosaic | 5', '#221f72', 'Wheat Streak Mosaic | Resistance Rating: 5'],

Next, I utilized the existing 'none' textPosition property to hide the VAxis:

    vAxis: {
        textPosition: 'none',
      ...etc.

The final outcome can be viewed here: https://i.sstatic.net/EjjcQ.png

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

Convert epoch time to HHMM format using JavaScript

I have a specific variable that stores epoch time data. My goal is to showcase the time information in HHMM format. Below you can find the code I am currently using; function convertEpochTimeToDateObj(epoch_time) { var utcSeconds = epoch_time; va ...

Perform individual conditions (filters) sequentially within a MongoDB query

Currently, I am working on a query that involves using $and to apply multiple filters or conditions. While explaining the query, I realized that $and does not function in the same way as the JavaScript && operator. How can I simulate JavaScript && functi ...

In what way is the JavaScript file able to locate the dependencies following the execution of npm install?

Upon receiving a javascript file named "neededjavascriptfile.js" along with a package.json file, I am faced with the task of running it in an html index file while utilizing certain functions from the javascript file. After executing "npm install --omit=d ...

Difficulty in decoding intricate JSON response using JQuery (or simply JavaScript)

Consider the function below, which retrieves JSON data from a Solr instance: var url = "http://myserver:8080/solr/select?indent=on&version=2.2&q=(title:*Hollis* OR sub_title:*Hollis*+OR+creator:*Hollis*+OR+publisher:*Hollis*+OR+format:*Hollis*++OR ...

Express.js throwing an unexpected 404 error

I'm really struggling to understand why Node (express) only renders the index page and returns a 404 error for other pages, like "comproAffitto" in this example. In my app.js file: var index = require('./routes/index'); var comproAffitto= ...

Is there a way to insert a secured page right before accessing the dashboard?

I am trying to create a locked page that will display a message when users access the web app from a mobile device and load a mobile layout page displaying a message like mobile is not supported. I was considering using document.addEventListener('DOMC ...

Prevented a frame from "https://googleads.g.doubleclick.net" from accessing another frame

After placing ads on my website, they are displaying properly. However, I am receiving an error repeatedly in the console when the page loads: A frame from origin "" is being blocked from accessing a frame with origin "". The requesting frame has an "ht ...

Establishing a TCP connection to a server using Javascript

Currently, I have developed a server daemon that generates various data, such as messages. However, my main focus is on client monitoring. For instance, I have a webpage and I aim to maintain a constant TCP connection to the server in order to display all ...

Preventing bots and spiders from infiltrating the ad network. Stepping up efforts to block unwanted traffic

We are facing a constant battle against bots and spiders with our in-house ad system, striving for 100% valid impressions. To achieve this goal, I conduct experiments on a specific ad zone that is only displayed on one page of our site. By comparing the G ...

Sharing environment variables in gulpfile with other JavaScript files outside NODE_ENV

Is it possible to pass a variable other than NODE_ENV from the gulpfile.js to another javascript file? gulpfile.js // Not related to NODE_ENV! let isDevelopment = true; somejsfile.js /* I need to access "isDevelopment" from the gulpfile.js... For the ...

Encountering issues with connecting to the MongoDB server through Node.js

When working with MongoDB in Python, everything runs smoothly without any errors. However, when using Node.js, an error keeps popping up. Can someone please guide me on how to resolve this issue? jdcaovuwqxoqppwwqmjcawpwuaciwowjqwqhpaiwdoqi Below is the ...

Having trouble accessing properties within a JavaScript object array in React.js?

I have a React.js component that fetches its initial state data from an API call in the componentDidMount(). This data comprises an array of objects. While I can see the entire array and individual elements using JSON.stringify (for debugging purposes), a ...

Tips for designing a sleek and seamless floating button

I attempted to implement a floating button feature that remains in view while smoothly flowing using jQuery. I followed a tutorial I found online to create this for my website. The tutorial can be accessed at this link. However, after following all the ste ...

Maximizing JavaScript DOM efficiency

In my code, I have numerous elements that need to be hidden and displayed dynamically. To facilitate this, I plan on utilizing the document.getElementById('x').style.display method. However, instead of directly using this method each time, I have ...

When utilizing express-formidable to retrieve multipart data, it causes basic post requests with request body to hang indefinitely

app.js const express = require('express') const app = express() const appInstance = express() const PORT = process.env.SERVER_PORT || 8080 app.use(express.json()) app.use(express.urlencoded({ extended : true })) app.use(formidableMiddleware ...

Encountering difficulties reading data from a database in a Next.js/Firebase application

I am encountering a problem within a nextJS app that I developed on Firebase. In my realtime DB, I have some stored data that I want to read using a component. Below is my firebase/config.js file: import {initializeApp} from "firebase/app"; imp ...

Adjust the styling with jQuery according to the selected value from the dropdown menu

Check out this Fiddle I have a jQuery script that is supposed to change the style of an input box to display:block if the selected value is "<>" (Between). However, currently it is changing the css for all selected items instead of just the target i ...

Is it possible to use different names for the parameters in a function while still maintaining the same

(Apologies for any language barriers!) It's difficult to articulate my thoughts in English, but here is the code I've written: function calculateAge(yearBorn){ return 2020 - yearBorn; } var johnAge = calculateAge(1990); var janeAge = calcul ...

How to properly escape JSON with hyphen or dash in AngularJS ngSrc

Having trouble displaying an image from a json url with dashes. I attempted to use bracket notation but it does not seem to be functioning: <img ng-src="{{image.['small-size'].url || image.thumb}}"> When using single quotes, my angular vi ...

Crafting LayerGroups on the Fly with Leaflet

Dynamic Creation of LayerGroups: Is it Achievable? I am currently working on a web map showcasing the various tree species present in parks. My goal is to create a separate LayerGroup for each species so that users can toggle visibility using a LayerContro ...