i have a simple js, html file, im using ApexCharts and want to handle the positive and negative parts of chart.
3 things about it:
is there any way to add a background to the line type chart below the line?
<div id="chart"></div>
<script src="exp.js"></script>
const dataPoints = [-10, 3, -5, -18, -10, 12, 8]
const discreteMarkers = dataPoints.map((value, index) => {
return {
shape: "circle",
size: 4,
seriesIndex: 0,
dataPointIndex: index,
fillColor: "#ffffff",
strokeColor: value >= 0 ? "#157446" : "#C13446",
strokeWidth: 1,
};
});
var options = {
chart: {
height: 380,
type: "line",
foreColor: '#aaa',
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
},
series: [
{
name: "Series 1",
data: dataPoints
}
],
stroke: {
width: 5,
curve: "monotoneCubic"
},
plotOptions: {
line: {
colors: {
threshold: 0,
colorAboveThreshold: '#157446',
colorBelowThreshold: '#C13446',
},
},
},
markers: {
discrete: discreteMarkers
},
grid: {
borderColor: '#6D6D6D',
strokeDashArray: 3,
},
xaxis: {
categories: [
"01 Jan",
"02 Jan",
"03 Jan",
"04 Jan",
"05 Jan",
"06 Jan",
"07 Jan"
]
},
stroke: {
curve: 'smooth',
width: 2
},
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
here is a link to check output. https://codepen.io/amirdoosti/pen/RNbQWPK
i figured it out. the plotOption has a property for area charts named fillTo :
fillTo = When negative values are present in the area chart, this option fill the area either from 0 (origin) or from the end of the chart as illustrated below.
area: {
fillTo: "end",
},
also i handled the colors using fill property to show positive and negative values.
andd... for better controlling data i made a function to set 0 label always in center of the chart. ( minY , minX ).
i didnt check all versions of apexcharts but i was supposed to use my script in a nuxt2 app. so the compatible version with my nuxt app was 3.40. so i can tell this script can work from 3.40 version and higher
const dataPoints = [-80, 3, -5, 100, -40, 120, 8];
let lowest_point = Math.min(...dataPoints);
let highest_point = Math.max(...dataPoints);
let zero_stop_percent = 100 - (Math.abs(lowest_point) / (Math.abs(lowest_point) + highest_point)) * 100;
const isNegativeHigher = Math.abs(lowest_point) > Math.abs(highest_point);
const minY =
Math.min(...dataPoints) === 0 && Math.max(...dataPoints) === 0
? -500
: Math.min(...dataPoints) === 0 && Math.max(...dataPoints) > 0
? Math.max(...dataPoints) * -1
: Math.abs(Math.min(...dataPoints)) < Math.max(...dataPoints)
? Math.max(...dataPoints) * -1
: Math.min(...dataPoints);
const maxY =
Math.max(...dataPoints) === 0 && Math.min(...dataPoints) === 0
? 500
: Math.max(...dataPoints) === 0 && Math.min(...dataPoints) < 0
? Math.abs(Math.min(...dataPoints))
: Math.abs(Math.min(...dataPoints)) > Math.max(...dataPoints)
? Math.abs(Math.min(...dataPoints))
: Math.max(...dataPoints);
const discreteMarkers = dataPoints.map((value, index) => {
return {
shape: "circle",
size: 4,
seriesIndex: 1,
dataPointIndex: index,
fillColor: "#ffffff",
strokeColor: value >= 0 ? "#157446" : "#C13446",
strokeWidth: 1,
};
});
var options = {
// okayyy
chart: {
height: 250,
width: 380,
toolbar: {
show: false,
},
},
// okayyy
series: [
{
name: "TEAMA",
type: "area",
data: dataPoints, // Your area chart data
zIndex: 2,
},
{
name: "TEAMB",
type: "line",
data: dataPoints, // Your area chart data
zIndex: 1,
},
],
markers: {
discrete: discreteMarkers,
},
fill: {
type: "gradient",
gradient: {
shade: "light",
type: "vertical",
shadeIntensity: 0.5,
opacityFrom: 0.2,
opacityTo: 0.2,
colorStops: [
// area
[
{
offset: 0,
color: "#589F7E", // Green for positive values
opacity: 0.15,
},
{
offset: isNegativeHigher ? zero_stop_percent : 50,
color: "#589F7E", // Transition at zero
opacity: 0.15,
},
{
offset: isNegativeHigher ? zero_stop_percent : 50,
color: "#D98B95", // Red for negative values
opacity: 0.15,
},
{
offset: 100,
color: "#FBF5F5",
opacity: 0.1,
},
],
// line
[
{
offset: 0,
color: "#157446", // Green for positive values
opacity: 1,
},
{
offset: zero_stop_percent,
color: "#157446", // Transition at zero
opacity: 1,
},
{
offset: zero_stop_percent,
color: "#C13446", // Red for negative values
opacity: 1,
},
{
offset: 100,
color: "#C13446",
opacity: 1,
},
],
],
},
},
xaxis: {
categories: ["12/20", "12/21", "12/22", "12/23", "12/24", "12/25", "12/26"],
tooltip: {
enabled: false,
},
},
legend: {
show: false,
},
tooltip: {
enabled: true, // Disable tooltip entirely if unwanted
shared: false, // Ensure no shared tooltip for markers
x: {
show: false,
},
y: {
formatter(val) {
return val;
},
title: {
formatter(seriesName) {
return "";
},
},
},
style: {
fontSize: "12px",
fontFamily: "iransansx",
width: "fit-content",
},
},
yaxis: {
forceNiceScale: true,
min: minY,
max: maxY,
tickAmount: 4,
labels: {
offsetX: -25,
style: {
colors: "#5B5C5F",
},
minWidth: 36,
show: true,
},
},
// okayyy
stroke: {
width: 2,
curve: "smooth",
colors: ["transparent"],
},
// okayyy
plotOptions: {
area: {
fillTo: "end",
},
},
grid: {
borderColor: "#EAEAEB",
strokeDashArray: 4,
position: "back",
},
};
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
.apexcharts-datalabel,
.apexcharts-datalabel-label,
.apexcharts-datalabel-value,
.apexcharts-datalabels,
.apexcharts-pie-label {
display: none !important;
}
.apexcharts-tooltip-series-group.apexcharts-active,
.apexcharts-tooltip-series-group:last-child {
padding-bottom: 0 !important;
}
.apexcharts-tooltip-series-group {
padding: 0 8px !important;
}
.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {
display: none !important;
}
.apexcharts-tooltip-text-goals-value,
.apexcharts-tooltip-text-y-value,
.apexcharts-tooltip-text-z-value {
margin-left: unset !important;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>bb</title>
</head>
<body>
<div id="chart"></div>
<script src="
https://cdn.jsdelivr.net/npm/apexcharts@3.40.0/dist/apexcharts.min.js
"></script>
<link
href="
https://cdn.jsdelivr.net/npm/apexcharts@3.40.0/dist/apexcharts.min.css
"
rel="stylesheet"
/>
</body>
</html>