apexcharts / apexcharts.js

πŸ“Š Interactive JavaScript Charts built on SVG
https://apexcharts.com
MIT License
14.39k stars 1.3k forks source link

range chart in mixed chart #4712

Open Hongmebuilding opened 1 month ago

Hongmebuilding commented 1 month ago

Summary

i want to know whether it is possible to put range chart in mixed chart. it would be very nice put together

API Changes

import ApexChart from 'react-apexcharts';

export default function MixChart() {
  return (
    <ApexChart
      height={500}
      series={[
        {
          name: 'oxygen',
          type: 'bar',
          data: [73.1, 81.5, 65, 88, 60.3, 90, 79.1, 80, 90, 75, 80],
        },
        {
          name: 'bloodpressure',
          type: 'rangeBar',
          data: [
            { x: '1', y: [80, 120] },
            { x: '2', y: [85, 130] },
            { x: '3', y: [75, 115] },
            { x: '4', y: [78, 118] },
            { x: '5', y: [82, 125] },
            { x: '6', y: [80, 122] },
            { x: '7', y: [85, 128] },
            { x: '8', y: [76, 116] },
            { x: '9', y: [80, 120] },
            { x: '10', y: [82, 124] },
            { x: '11', y: [85, 130] },
          ],
        },
        {
          name: 'pulse',
          type: 'line',
          data: [51.1, 61.5, 40, 35, 46.3, 41, 65.1, 38, 46, 37, 50],
        },
        {
          name: 'temperature',
          type: 'line',
          data: [50, 60, 65, 70, 80, 60, 70, 30, 61, 45, 33],
        },
        {
          name: 'walk',
          type: 'line',
          data: [43.1, 51.5, 45, 45, 40.3, 45, 41.1, 46, 50, 55, 40],
        },
        {
          name: 'battery',
          type: 'line',
          data: [100, 95.5, 90, 84, 80.3, 75, 70.1, 65, 60, 53, 47],
        },
      ]}
      options={{
        chart: {
          type: 'line',
          stacked: false,
        },
        grid: {
          yaxis: {
            lines: {
              show: false,
            },
          },
        },
        colors: [
          '#53C9FA',
          '#FF59C2',
          '#FF8A3C',
          '#EF5151',
          '#A354D8',
          '#78D153',
        ],
        stroke: {
          width: [0, 3, 3, 3, 3, 3],
          curve: 'smooth',
        },
        plotOptions: {
          bar: {
            columnWidth: '15px',
            borderRadius: 5,
          },
        },
        xaxis: {
          type: 'category',
        },
        yaxis: [
          {
            seriesName: 'μ‚°μ†Œν¬ν™”λ„',
            title: {
              text: 'μ‚°μ†Œν¬ν™”λ„ (%)',
            },
          },
          {
            seriesName: 'ν˜ˆμ••',
            title: {
              text: 'ν˜ˆμ•• (mmHg)',
            },
            min: 60,
            max: 140,
          },
          {
            seriesName: 'μ‹¬λ°•μˆ˜',
            title: {
              text: 'μ‹¬λ°•μˆ˜ (bpm)',
            },
          },
          {
            seriesName: '체온',
            title: {
              text: '체온 (°C)',
            },
          },
          {
            seriesName: 'ν™œλ™λŸ‰',
            title: {
              text: 'ν™œλ™λŸ‰',
            },
          },
          {
            seriesName: '배터리',
            title: {
              text: '배터리 (%)',
            },
            min: 0,
            max: 100,
          },
        ],
        tooltip: {
          shared: true,
          intersect: false,
          y: {
            formatter: function (y) {
              if (typeof y !== "undefined") {
                return y.toFixed(0) + " units";
              }
              return y;
            }
          }
        },
        legend: {
          horizontalAlign: 'left',
          offsetX: 40
        }
      }}
    />
  );
}

Intended Use Case

synthesis graph in health care service

rosco54 commented 1 month ago

At this time it doesn't seem possible but it would be a worthwhile addition. I had a quick look and it didn't appear to be trivial.

There is a way to simulate it using stacked column series, but it may be messier than you want under the hood. Here's the chart followed by the HTML.

You can see how it works from the HTML but a few things that Apexcharts is doing for it to work:

  1. I've used yaxis.seriesName as an array to associate the two split blood pressure series' with the same yaxis. I could have given both series the same series.group name explicitly but Apexcharts will automatically group together series of the same type on the same yaxis if they don't have a series.group defined.
  2. In setting chart.stacked: true it will only stack series that are members of the same group, that is, just the two blood pressure column series'.
  3. The lower column in the stack was made transparent.

gqeni9v3

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Combo Chart with rangeBar simulated with stacked columns</title>

    <link href="apexcharts.js/samples/assets/styles.css" rel="stylesheet" />

    <style>

        #chart {
      max-width: 1000px;
      margin: 35px auto;
    }

    </style>

    <script src="https://cdn.jsdelivr.net/npm/apexcharts/dist/apexcharts.js"></script>

  </head>

  <body>
     <div id="chart"></div>

    <script>
const bloodPressure = [
            { x: '1', y: [80, 120] },
            { x: '2', y: [85, 130] },
            { x: '3', y: [75, 115] },
            { x: '4', y: [78, 118] },
            { x: '5', y: [82, 125] },
            { x: '6', y: [80, 122] },
            { x: '7', y: [85, 128] },
            { x: '8', y: [76, 116] },
            { x: '9', y: [80, 120] },
            { x: '10', y: [82, 124] },
            { x: '11', y: [85, 130] },
          ];
const bpLower = bloodPressure.map(el => el.y[0]);
const bpUpperToLower = bloodPressure.map(el => el.y[1]-el.y[0]);

const options={
      series: [
        {
          name: 'μ‚°μ†Œν¬ν™”λ„',
          type: 'bar',
          data: [73.1, 81.5, 65, 88, 60.3, 90, 79.1, 80, 90, 75, 80],
        },
        {
          name: 'ν˜ˆμ••_Lower',
          type: 'bar',
          data: bpLower
        },
        {
          name: 'ν˜ˆμ••',
          type: 'bar',
          data: bpUpperToLower
        },
        {
          name: 'μ‹¬λ°•μˆ˜',
          type: 'line',
          data: [51.1, 61.5, 40, 35, 46.3, 41, 65.1, 38, 46, 37, 50],
        },
        {
          name: '체온',
          type: 'line',
          data: [50, 60, 65, 70, 80, 60, 70, 30, 61, 45, 33],
        },
        {
          name: 'ν™œλ™λŸ‰',
          type: 'line',
          data: [43.1, 51.5, 45, 45, 40.3, 45, 41.1, 46, 50, 55, 40],
        },
        {
          name: '배터리',
          type: 'line',
          data: [100, 95.5, 90, 84, 80.3, 75, 70.1, 65, 60, 53, 47],
        },
      ],
      chart: {
          type: 'line',
          stacked: true,
        },
        grid: {
          yaxis: {
            lines: {
              show: false,
            },
          },
        },
        colors: [
          '#53C9FA',
          'rgba(0,0,0,0)',
          '#FF59C2',
          '#FF8A3C',
          '#EF5151',
          '#A354D8',
          '#78D153',
        ],
        stroke: {
          width: [0, 0, 3, 3, 3, 3, 3],
          curve: 'smooth',
        },
        plotOptions: {
          bar: {
            borderRadius: 5,
            borderRadiusWhenStacked: 5
          },
        },
        xaxis: {
          type: 'category',
        },
        yaxis: [
          {
            seriesName: 'μ‚°μ†Œν¬ν™”λ„',
            title: {
              text: 'μ‚°μ†Œν¬ν™”λ„ (%)',
            },
          },
          {
            seriesName: ['ν˜ˆμ••_Lower', 'ν˜ˆμ••'],
            title: {
              text: 'ν˜ˆμ•• (mmHg)',
            },
            min: 60,
            max: 160, // To keep a range of 100 for nice axis labels.
          },
          {
            seriesName: 'μ‹¬λ°•μˆ˜',
            title: {
              text: 'μ‹¬λ°•μˆ˜ (bpm)',
            },
          },
          {
            seriesName: '체온',
            title: {
              text: '체온 (°C)',
            },
          },
          {
            seriesName: 'ν™œλ™λŸ‰',
            title: {
              text: 'ν™œλ™λŸ‰',
            },
          },
          {
            seriesName: '배터리',
            title: {
              text: '배터리 (%)',
            },
            min: 0,
            max: 100,
          },
        ],
        tooltip: {
          shared: true,
          intersect: false,
          y: {
            formatter: function (y, o) {
              if (typeof y !== "undefined") {
                  if (o.seriesIndex === 2) {
                    var bpu = o.series[o.seriesIndex][o.dataPointIndex];
                    var bpl = o.series[o.seriesIndex-1][o.dataPointIndex];
                    bpu = bpu + bpl;
                    return bpu.toFixed(0) + " units";
                  }
                  return y.toFixed(0) + " units";
              }
              return y;
            }
          }
        },
        legend: {
          horizontalAlign: 'left',
          offsetX: 40,
        }
};

var chart = new ApexCharts(document.querySelector("#chart"), options);

chart.render();

    </script>

  </body>
</html>
Hongmebuilding commented 1 month ago

Although there is no feature about it, there's a way to overcome it! Thank you for your help