Triple Y-axis line chart on Google

I'm looking to create a unique Google line chart that showcases temperature, humidity, and air pressure all within one single chart.

The challenge is incorporating three different y-axes with distinct ranges without them overlapping.

Most examples I've come across only feature two y-axes. Can triple y-axes be achieved? Would using the material variant instead of the classic version be beneficial?

Below is my current chart setup:

new google.visualization.LineChart(document.getElementById('visualization'))
        .draw(data, {
            vAxes : [ {
                title : 'Title 1',
                minValue : 0,
                maxValue : 20
            }, {
                title : 'Title 2',
                minValue : 40,
                maxValue : 80
            }, {
                title : 'Title 3',
                minValue : 950,
                maxValue : 1050
            } ],
            series : {
                0 : {
                    targetAxisIndex : 0
                },
                1 : {
                    targetAxisIndex : 1
                },
                2 : {
                    targetAxisIndex : 2
                }
            },
        });

You can view the live example here on this JSFiddle link.

Answer №1

you're spot on with your approach...

another consideration could be to provide a bit more space for the right side to work with,
for example:

chartArea.right

the material chart handles multiple axis labels spacing better,
although there are fewer customization options available...

take a look at the working snippet below, showcasing both implementations...

google.charts.load('current', {
  callback: drawVisualization,
  packages: ['line', 'corechart']
});

function drawVisualization() {
  var data = google.visualization.arrayToDataTable([
    ['x', 'Temperature', 'Humidity', 'Pressure'],
    ['A',   5,     55,     1000],
    ['B',   12,     57,     1001],
    ['C',   14,     57,     1001],
    ['D',   18,     58,     1010],
    ['E',   17,     58,     1010],
    ['F',   17,     60,     1012],
    ['G',   18,     61,     1013],
    ['H',   22,     62,     1010],
    ['I',   24,     62,     1012],
    ['J',   20,     62,     1005],
    ['K',   17,     60,     1005],
    ['L',   17,     58,     1004],
    ['M',   16,     58,     1005],
    ['N',   15,     57,     1003]
  ]);

  // classic
  new google.visualization.LineChart(document.getElementById('visualization')).
    draw(data, {
      chartArea: {
        right: 136
      },
      curveType : 'function',
      lineWidth : 2,
      pointSize : 2,
      vAxes: {
        0: {title: '°C', textPosition: 'out', minValue: -10, maxValue: 25 },
        1: {title: '% rel', textPosition: 'in', minValue: 20, maxValue: 90 },
        2: {title: 'hPa', textPosition: 'out', minValue: 900, maxValue: 1100 }
      },
      series:{
        0: {targetAxisIndex:0, color : 'blue'},
        1: {targetAxisIndex:1, color : 'red'},
        2: {targetAxisIndex:2, color : 'green'}
      }
    }
  );

  // material
  new google.charts.Line(document.getElementById('visualization_matl')).
    draw(data, {
      series: {
        0: {axis: 'Temperature'},
        1: {axis: 'Humidity'},
        2: {axis: 'Pressure'}
      },
      axes: {
        y: {
          Temperature: {label: '°C'},
          Humidity: {label: '% rel'},
          Pressure: {label: 'hPa'}
        }
      }
    }
  );
};
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="visualization"></div>
<div id="visualization_matl"></div>

Answer №2

To make the axes visible, I could manipulate the textPosition property by setting one axis to be out and the other to be in:

vAxes : {
    0 : {
        title : 'Temperature (°C)',
        textPosition : "out",
        minValue : -10,
        maxValue : 25
    },
    1 : {
        title : 'Relative Humidity (%)',
        textPosition : "in",
        minValue : 20,
        maxValue : 90
    },
    2 : {
        title : 'Pressure (hPa)',
        textPosition : "out",
        minValue : 900,
        maxValue : 1100
    }
}

Check out the updated fiddle here: https://jsfiddle.net/1b3hd0ya/3/

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

What is the best way to display form input fields depending on the selected value?

I've been struggling with a seemingly simple issue that I can't seem to find the right solution for, even after scouring Google. I have a form field for input and a select field with various values, including an "Other" option. Here's what ...

Accessing a variable within a bound function using .bind() in Javascript/Typescript

I am facing an issue where I need to bind a variable to a callback function in Mongoose, but the function already has a parameter named "val" embedded in it. Whenever I try to use .bind() to add another value to the callback function, I end up losing the o ...

Adding the Root Node to an extjs 4 MVC Tree Panel: A Step-by-Step Guide

I have a tree structure displaying all my tasks which are fetched from the database. Now, I am looking to dynamically add a Root node. This means that when a user clicks the 'Add New Root Node' button, a new Root will be created in the Tree view ...

Change the order of numbering in ordered lists

I am seeking a way to change the ordering of an ordered list to be in descending order. You can view a live example here. Instead of having the counter span multiple ol elements, I would like the counter to reset after each ol. For the live demo, the des ...

Odd behavior in Google Chrome when PHP includes JavaScript code

When working with my application built on Zend Framework, I have a layout.phtml file that contains the <head> section with some javascripts included using the following method: <head> // Some code <?php include('template/javascript ...

Exporting Data in ReactJS

Hey there, take a look at the code snippet provided: import React, { Component } from 'react'; let ok; class Mydata extends Component { constructor() { super(); this.state = { rif: [{ "instituteName": ...

Module Ionic not found

When I attempt to run the command "ionic info", an error is displayed: [ERROR] Error loading @ionic/react package.json: Error: Cannot find module '@ionic/react/package' Below is the output of my ionic info: C:\Users\MyPC>ionic i ...

Using AngularJS and the ng-show directive, you can set a <div> element to

Objective: My aim is to show the content of a div according to the status of checkboxes, while also ensuring that these divs are visible by default If I have this code snippet: <html> <head> <script src="https://ajax.googleapis.com/ajax/li ...

The type 'IProduct' cannot be assigned to type '[]'

Looking for help with dispatching events between parent and child components. Interfaces: export interface IProduct { id: string; name: string; price: string; image: string; inStock: number; fastDelivery: bo ...

Verify if JavaScript is enabled on the browser and show a notification if it is not using a custom ASP control

I am currently working with a combination of Javascript, ASP.net, and C# for my project. My goal is to create a custom control that checks if Javascript is enabled in the user's browser and displays a message accordingly. Here is the approach I have t ...

Can anyone recommend any JavaScript or jQuery thumbnail scripts that are similar to TimThimb (PHP)?

TimThumb is a versatile tool that can quickly generate thumbnails from images of any size or dimensions to fit any desired size. It has the ability to resize, crop, or zoom crop images without any hassle. I've been on the lookout for JavaScript alter ...

Utilizing document.getElementById dynamically to access multiple elements with the same ID

const imageOne = document.getElementById('imageOne'); const modalImage = document.getElementById("img01"); let altText = document.getElementById("caption"); imageOne.onclick = function(){ modal.style.display = "block"; modalImg.src = this ...

What causes lodash's mapValues to fail when using _.first as a callback function?

Trying my hand at converting some code: var data = { 1234: [{ name: "obj1" }], 3456: [{ name: "obj2" }] }; I want it to look like this: { 1234: { name: "obj1" }, 3456: { name: "obj2" } } (single items, not arrays). I discovered that: _.mapValues(data ...

Having issues with inline conditional statements in Angular 5

There is a minor issue that I've been struggling to understand... so In my code, I have an inline if statement like this: <button *ngIf="item?.fields?.assetType !== 'tool' || item?.fields?.assetType !== 'questions'">NEXT< ...

State variables in React hooks like useState always return the previous value before

Whenever I choose a value, it seems to always display the previously selected option instead of the current one. What I really want is for the selection to update and store the current value immediately. const [postsPerPage, setPostsPerPage] = useState(1 ...

Scrolling and hovering now triggers the fixed button to toggle class seamlessly

Currently, I am attempting to modify the class of a button on my website. The initial state of the button is wide, but as the user scrolls, it should shrink in size. When hovering over the shrunken button, it should expand back to its original width. Alt ...

Class selectors can be used for jQuery drag and drop functionality

Seeking help from experienced individuals, as I am new to JS/jQuery. I have come across a script for drag and copy functionality which I have customized to fit my needs. However, the script currently uses "id" selectors and I wish to switch to using "class ...

Monitor when users enter commas into input fields in AngularJS

My current challenge involves monitoring user input in a text field and validating the input when a comma is typed, instead of using ng-click="action()". I am looking to implement something like Comma-Typed="action()", but my attempts with ng-change and sc ...

Is the concept of Controlled and Uncontrolled Components in VueJs similar to that of React?

When it comes to React, there is a distinction between controlled and uncontrolled components explained in detail at this link. Controlled components function within the React model where state is managed in the virtual DOM. In contrast, uncontrolled com ...

How can I repeatedly send a request without having to do a hard refresh using AJAX?

Whenever I send an AJAX request to delete a file, everything works fine the first time. However, the second time it does not work anymore and I end up having to do a "hard refresh". This is the code snippet in question: <?php if(isset($_POST['del ...