I am using Chart.js v2.6 to output a pie chart. The data is obtained from MySQL database. The chart renders properly, but I need to add arrows to data values as shown in the screenshot below.
Example pie chart with arrows:
Below is my code to output pie chart using Chart.js:
var chartdata_order_status = {
labels: status,
datasets: [{
label: 'Order status',
backgroundColor: ["#00b0f0","#92d050","#ffc000","#ff6dd9"],
data: count_status
}]
};
var pieGraph = new Chart(ctx3, {
type: 'pie',
data: chartdata_country_orders,
options: {
pieceLabel: {
mode: 'value',
position: 'outside',
fontColor: '#000',
format: function (value) {
return '$' + value;
}
},
title: {
display: true,
text: 'Total Sales by Country - Top 5',
fontSize: 15,
fontStyle: 'bold'
},
legend: {
display: true,
position: 'bottom',
},
}
});
I have not included the PHP code for obtaining data from the MySQLtable.
You can now use Chart.PieceLabel.js and get labels outside the slices.s,
DEMO
angular.module("app", ["chart.js"]).controller("ChartCtrl", function($scope) {
$scope.labels = ["January", "February", "March", "April", "May", "June", "July"];
$scope.data = [65, 59, 80, 81, 56, 55, 40];
$scope.options = {
pieceLabel: {
render: 'label',
fontColor: '#000',
position: 'outside',
segment: true
}
};
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.2.1/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
<script src="https://cdn.jsdelivr.net/angular.chartjs/latest/angular-chart.js"></script>
<script src="https://rawgit.com/beaver71/Chart.PieceLabel.js/master/build/Chart.PieceLabel.min.js"></script>
<div ng-app="app" ng-controller="ChartCtrl">
<canvas id="pie" class="chart chart-pie"
chart-data="data" chart-labels="labels" chart-options="options">
</canvas>
</div>
For chartjs 3.xx you can try this
var ctx = document.getElementById("myChart");
var data = [61, 10, 28];
const getSuitableY = (y, yArray = [], direction) => {
let result = y;
yArray.forEach((existedY) => {
if (existedY - 14 < result && existedY + 14 > result) {
if (direction === "right") {
result = existedY + 14;
} else {
result = existedY - 14;
}
}
});
return result;
};
const getOriginPoints = (source, center, l) => {
// console.log(source, center, l)
let a = {x: 0, y: 0};
var dx = (center.x - source.x) / l
var dy = (center.y - source.y) / l
a.x = center.x + l * dx
a.y = center.y + l * dy
return a
};
const options = {
plugins: {
legend: {
display: true,
position: "bottom"
},
},
layout: {
padding: {
top: 30,
left: 0,
right: 0,
bottom: 30
}
}
};
const plugins = [
{
afterDraw: (chart) => {
const ctx = chart.ctx;
ctx.save();
ctx.font = "10px 'Averta Std CY'";
const leftLabelCoordinates = [];
const rightLabelCoordinates = [];
const chartCenterPoint = {
x:
(chart.chartArea.right - chart.chartArea.left) / 2 +
chart.chartArea.left,
y:
(chart.chartArea.bottom - chart.chartArea.top) / 2 +
chart.chartArea.top
};
chart.config.data.labels.forEach((label, i) => {
const meta = chart.getDatasetMeta(0);
const arc = meta.data[i];
const dataset = chart.config.data.datasets[0];
// Prepare data to draw
// important point 1
const centerPoint = arc.getCenterPoint();
let color = chart.config._config.data.datasets[0].backgroundColor[i];
let labelColor = chart.config._config.data.datasets[0].backgroundColor[i];
const angle = Math.atan2(
centerPoint.y - chartCenterPoint.y,
centerPoint.x - chartCenterPoint.x
);
// important point 2, this point overlapsed with existed points
// so we will reduce y by 14 if it's on the right
// or add by 14 if it's on the left
let originPoint = getOriginPoints(chartCenterPoint, centerPoint, arc.outerRadius)
const point2X =
chartCenterPoint.x + Math.cos(angle) * (centerPoint.x < chartCenterPoint.x ? arc.outerRadius + 10 : arc.outerRadius + 10);
let point2Y =
chartCenterPoint.y + Math.sin(angle) * (centerPoint.y < chartCenterPoint.y ? arc.outerRadius + 15 : arc.outerRadius + 15);
let suitableY;
if (point2X < chartCenterPoint.x) {
// on the left
suitableY = getSuitableY(point2Y, leftLabelCoordinates, "left");
} else {
// on the right
suitableY = getSuitableY(point2Y, rightLabelCoordinates, "right");
}
point2Y = suitableY;
let value = dataset.data[i];
// if (dataset.polyline && dataset.polyline.formatter) {
// value = dataset.polyline.formatter(value);
// }
let edgePointX = point2X < chartCenterPoint.x ? chartCenterPoint.x - arc.outerRadius - 10 : chartCenterPoint.x + arc.outerRadius + 10;
if (point2X < chartCenterPoint.x) {
leftLabelCoordinates.push(point2Y);
} else {
rightLabelCoordinates.push(point2Y);
}
//DRAW CODE
// first line: connect between arc's center point and outside point
ctx.lineWidth = 2;
ctx.strokeStyle = color;
ctx.beginPath();
ctx.moveTo(originPoint.x, originPoint.y);
ctx.lineTo(point2X, point2Y);
ctx.stroke();
// second line: connect between outside point and chart's edge
ctx.beginPath();
ctx.moveTo(point2X, point2Y);
ctx.lineTo(edgePointX, point2Y);
ctx.stroke();
//fill custom label
const labelAlignStyle =
edgePointX < chartCenterPoint.x ? "right" : "left";
const labelX = edgePointX < chartCenterPoint.x ? edgePointX : edgePointX + 0;
const labelY = point2Y + 7;
ctx.textAlign = labelAlignStyle;
ctx.textBaseline = "bottom";
ctx.font = "bold 12px Lato";
// ctx.fillStyle = labelColor;
ctx.fillText(value, labelX, labelY);
});
ctx.restore();
}
}
];
var myChart = new Chart(ctx, {
type: 'pie',
plugins: plugins,
options: options,
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Greek", "Greek"],
datasets: [
{
label: "# of Votes",
data: [30, 1, .4, 2, 0.3, 80],
backgroundColor: [
"rgba(255, 99, 132, 0.8)",
"rgba(54, 162, 235, 0.8)",
"rgba(255, 206, 86, 0.8)",
"rgba(75, 192, 192, 0.8)",
"rgba(153, 102, 255, 0.8)",
"rgba(75, 192, 192, 0.8)",
"rgba(255, 159, 64, 0.8)"
],
borderColor: [
"rgba(255, 99, 132, 1)",
"rgba(54, 162, 235, 1)",
"rgba(255, 206, 86, 1)",
"rgba(75, 192, 192, 1)",
"rgba(153, 102, 255, 1)",
"rgba(255, 159, 64, 1)",
"rgba(75, 192, 192, 1)"
],
borderWidth: 1,
polyline: {
// color: "gray",
// labelColor: "gray",
formatter: (value) => `${value}`
}
}
]
}
});
.wrapper {
height: 200px;
width: 400px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.8.0/chart.min.js"></script>
<style>
.wrapper {
height: 200px;
width: 400px;
}
</style>
</head>
<body>
<div class="wrapper">
<canvas id="myChart"></canvas>
</div>
</body>
</html>
`
Related
I want to use chart canvasjs to display 4 different data.
My data is for the balances of 4 different accounts in the last 10 days and I want the x-axis of the days and the y-axis of the balance amounts.
my code :
const ColorBac = ["rgba(255, 0, 50, 0.2)", "rgba(27, 68, 128, 0.2)", "rgba(246, 162, 30, 0.2)", "rgba(23, 135, 95, 0.2)"];
const Colorborder = ["rgba(255, 0, 50, 0.6)", "rgba(27, 68, 128, 0.6)", "rgba(246, 162, 30, 0.6)", "rgba(23, 135, 95, 0.6)"];
Api = api('Chart');
console.log("load Api Array");
console.log(Api.ExData);
function setColor(chart) {
for (var i = 0; i < chart.options.data.length; i++) {
dataSeries = chart.options.data[i];
for (var j = 0; j < dataSeries.dataPoints.length; j++) {
if (dataSeries.dataPoints[j].y <= 0)
dataSeries.dataPoints[j].color = ColorBac[j];
}
}
}
function ShowChart() {
var dataPoints = [];
//GetData();
$.each(Api.ExData, function(index, Info) {
dataPoints.push({
x: parseInt(Info.fldHesabID),
y: parseInt(Info.fldMojoodi),
label: Info.fldDate,
mouseover: onMouseover,
});
});
console.log('load dataPoints');
console.log(dataPoints);
///////
var chart = new CanvasJS.Chart("chartContainer", {
animationEnabled: true,
theme: "light2", // "light1", "light2", "dark1", "dark2"
axisY: {
//title: "Reserves(MMbbl)"
//labelAngle: 30
},
axisX: {
interval: 1,
//minimum: 0,
// maximum: 20,
labelAngle: 30
},
data: [{
type: "line",
toolTipContent: "{label}: {y} ",
dataPoints: dataPoints,
}]
});
console.log('load Chart');
setColor(chart);
chart.render();
function onMouseover(e) {
createGauge(e.dataPoint.progressVal);
}
}
ShowChart();
console.log('end Chart');
<div id="chartContainer" style="height: 370px; width: 100%;border: 1px solid green;"></div>
<br>
<script type="text/javascript" src="https://canvasjs.com/assets/script/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
My data output is in the form of a photo.
Please help me to display this chart
I need to change background color of bar when selected it in the legend. When I updated chart with ci.update() color is reset.
options: {
plugins: {
legend: {
display: true,
position: 'right',
onClick: function (e, legendItem, legend) {
const index = legendItem.datasetIndex;
const ci = legend.chart;
const meta = ci.getDatasetMeta(index);
const element = meta.data[0];
if (!legendItem.checked) {
element.options.backgroundColor = 'rgba(255, 159, 64, 1)';
legendItem.lineWidth = 2;
legendItem.strokeStyle = 'rgba(0,0,0, 1)';
legendItem.checked = true;
} else {
legendItem.checked = false;
}
ci.update();
}
}
}
}
When the chart.update() is invoked, the chart is re-configuring itself starting from chart.data.datasets and all element options (changed in the meanwhile) are lost.
The chart.data.datasets must be changed.
The original backgroundColors must be stored because otherwise they will be lost.
const ctx = document.getElementById("myChart");
const backgroundColors = ['rgba(40, 139, 170, 1)', 'rgba(40, 139, 0, 1)'];
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['January', 'Fabruary', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
label: 'user 1 online',
data: [50, 35, 45, 47, 10, 3, 27],
backgroundColor: backgroundColors[0],
borderWidth: 0,
borderSkipped: 'start'
},
{
label: 'user 2 online',
data: [50, 35, 45, 47, 10, 3, 27],
backgroundColor: backgroundColors[1],
borderWidth: 0,
borderSkipped: 'start'
}]
},
options: {
plugins: {
legend: {
display: true,
position: 'right',
onClick: function (e, legendItem, legend) {
const index = legendItem.datasetIndex;
const ci = legend.chart;
const dataset = ci.data.datasets[index];
if (!dataset.checked) {
dataset.backgroundColor = 'rgba(255, 159, 64, 1)';
dataset.borderWidth = 2;
dataset.borderColor = 'rgba(0,0,0, 1)';
dataset.checked = true;
} else {
dataset.backgroundColor = backgroundColors[index];
dataset.borderWidth = 0;
dataset.borderColor = null;
dataset.checked = false;
}
ci.update();
}
}
}
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
}
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.9.1/dist/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"/>
</div>
</body>
</html>
I am starting to learn the chart.js library.
I drew a pie chart (like "pie"). When you hover over the slices of the diagram, a number appears in the pop-up window that sets the size of the sector.
new chart(
document.getElementById('diagram_1').getContext('2d'), {
type: 'pie',
data: {
labels: [
'Завершенная задача',
'Новая задача',
'Ошибка выполнения'
],
datasets: [{
label: '# of Votes',
data: [#successful_tasks, #new_tasks, #error_tasks],
backgroundColor: [
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(255, 99, 132, 0.2)'
],
borderColor: [
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(255, 99, 132, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
y: {
beginAtZero: true
}
},
responsive: false
}
}
)
How can you make this number still displayed at the top, where the sectors are listed (I marked this place with a red circle in the picture)?
I can add the required number to the labels array
...
data: {
labels: [
'Завершенная задача: ' + #successful_tasks,
'Новая задача: ' + #new_tasks,
'Ошибка выполнения: ' + #error_tasks
],
...
But then this number will appear twice in the tooltip
You can use the plugin system for this:
var options = {
type: 'pie',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
}]
},
options: {
plugins: {
customNumber: {
textColor: 'red',
xOffset: 10,
yOffset: 0,
font: '24px Comic Sans MS'
}
}
},
plugins: [{
id: 'customNumber',
afterDraw: (chart, args, opts) => {
const hoveredSlice = chart._active[0];
const {
ctx,
chartArea: {
right
}
} = chart;
if (!hoveredSlice) {
return;
}
ctx.font = opts.font || '24px verdana, sans-serif'
ctx.fillStyle = opts.textColor || 'black'
const val = chart.data.datasets[hoveredSlice.datasetIndex].data[hoveredSlice.index];
const meassures = ctx.measureText(val);
const height = ctx.measureText('M').width;
ctx.fillText(val, (right - meassures.width - (opts.xOffset || 0)), height + (opts.yOffset || 0))
}
}]
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.js"></script>
</body>
I found the answer. My project is written in CoffeeScript, but I think it would be more useful for the StackOverflow community to post the code in JS.
options: {
legend: {
labels: {
generateLabels: function(chart) {
var data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
var meta = chart.getDatasetMeta(0);
var ds = data.datasets[0];
var arc = meta.data[i];
var custom = arc && arc.custom || {};
var getValueAtIndexOrDefault = Chart.helpers.getValueAtIndexOrDefault;
var arcOpts = chart.options.elements.arc;
var fill = custom.backgroundColor ? custom.backgroundColor : getValueAtIndexOrDefault(ds.backgroundColor, i, arcOpts.backgroundColor);
var stroke = custom.borderColor ? custom.borderColor : getValueAtIndexOrDefault(ds.borderColor, i, arcOpts.borderColor);
var bw = custom.borderWidth ? custom.borderWidth : getValueAtIndexOrDefault(ds.borderWidth, i, arcOpts.borderWidth);
var value = chart.config.data.datasets[arc._datasetIndex].data[arc._index];
return {
text: label + ": " + value,
fillStyle: fill,
strokeStyle: stroke,
lineWidth: bw,
hidden: isNaN(ds.data[i]) || meta.data[i].hidden,
index: i
};
});
} else {
return [];
}
}
}
}
}
I am populating my bar chart with very simple data. But it seems that it stays always left with little width no matter what I do. How can I solve this can you pls tell me?I also tried with bar thickness and bar percentage doesn't seem to change any thing. Is there anything I can do? Thank you.
Js part:
var labels = ["Request for Information", "Product Availability", "Offer Eligibility", "Price Query", "How To Order",
"Delivery Duration", "Offer Duration", "Product Feature Query", "Delivery Charge", "Order Confirmation"]
var barData=[17076, 16313, 11337, 11000, 6116, 5957, 5590, 4815, 3825, 335]
var tempbackgroundColor=['rgba(192, 57, 43, 1)',
'rgba(155, 89, 182, 1)',
'rgba(84, 153, 199, 1)',
'rgba(69, 179, 157, 1)',
'rgba(245, 176, 65 , 1)',
'rgba(236, 240, 241, 1)',
'rgba(127, 140, 141, 1)',
'rgba(44, 62, 80, 1)'
]
var dataSets = [];
for (var i = 0; i < labels.length; i++) {
var tmp = { data: [] };
tmp.label = labels[i];
tmp.borderColor = [tempbackgroundColor[i]];
tmp.backgroundColor = [tempbackgroundColor[i]];
tmp.borderWidth = 1;
tmp.data = [barData[i]];
dataSets.push(tmp);
}
if (data != '') {
$scope.trendChartLoading = '0';
}
showMBSLineChart(this.canvasId, labels, dataSets, "bar", this.area,true,false);
showMBSLineChart function
var showMBSLineChart = function (canvasId, labels, dataSets, chartType = 'line',xlabelstring="",ticksunitdisplay=true,labeldisplayx=false) {
var ctxL = document.getElementById(canvasId).getContext('2d');
var aspratio = 1;
var ticksdisplay = true;
var scalelabeldisplayx = false;
var scalestringx = xlabelstring;
if (chartType == 'line') {
aspratio = 1;
ticksdisplay = ticksunitdisplay;
scalelabeldisplayx = labeldisplayx;
} else if (chartType == 'bar') {
aspratio = 1;
ticksdisplay = ticksunitdisplay;
scalelabeldisplayx = labeldisplayx;
}
var myLineChart = new Chart(ctxL, {
type: chartType,
data: {
labels: labels,
datasets: dataSets
},
options: {
responsive: true,
legend: {
display: true,
labels: {
boxWidth: 8,
fontSize:10
}
},
aspectRatio: aspratio,
scales: {
xAxes: [{
ticks: {
display: ticksdisplay,
fontSize: 10
},
scaleLabel: {
display: scalelabeldisplayx,
labelString: scalestringx
},
}]
}
}
});
}
In time of calling the showMBSLinechart function just call with single array data.Like this
showMBSLineChart(this.canvasId, ["counts"], dataSets, "bar", this.area,false,true);
I'm using ChartJS V2 to create a chart. Chartjs V2 supports the fill color feature. But I would like to fill overlap area with different color.
Please see screenshot below. I have two line. A represents overlap area for two lines.
I would like to fill with 3 different color for 2 lines.
When the Line1 and Line2 overlaps, fill color should be A
If Line1 does not overlap Line2, fill color should be B
If Line2 does not overlap Line1, fill color should be C
I added a fiddle for this.
See Fiddle http://jsfiddle.net/qcs1t9ag/
Thanks!
var lineChartData = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [{
label: "My First dataset",
data: [50, 85, 56, 50, 60, 70, 80],
yAxisID: "y-axis-1",
borderColor: "#0ad4e6"
}, {
label: "My Second dataset",
data: [35, 45, 75, 40, 55, 50, 62],
yAxisID: "y-axis-2",
borderColor: "#f6c63e"
}]
};
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = Chart.Line(ctx, {
data: lineChartData,
options: {
responsive: true,
hoverMode: 'label',
stacked: false,
title: {
display: false,
text: 'Chart.js Line Chart - Multi Axis'
},
animation: {
duration: 0
},
legend: {
display: false,
position: 'top',
},
scales: {
xAxes: [{
display: true,
gridLines: {
offsetGridLines: false
}
}],
yAxes: [{
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "left",
id: "y-axis-1",
scaleLabel: {
display: true,
labelString: "Cost"
}
}, {
type: "linear", // only linear but allow scale type registration. This allows extensions to exist solely for log scale for instance
display: true,
position: "right",
id: "y-axis-2",
scaleLabel: {
display: true,
labelString: "Students",
},
// grid line settings
gridLines: {
drawOnChartArea: false, // only want the grid lines for one axis to show up
},
}],
}
}
});
JueDoe, Here's an example below of how you could do this.
Fiddle: Charts intersection example
var ORDER_STATS = {
"2016": [10, 181, 194, -56, 130, 181, 179, 189, 30, 60, 193, 154],
"2015": [124, -50, 152, 187, 10, 164, 129, -16, 115, 119, 129, 171],
"2014": [-90, 80, 30, 59, 100, -30, 60, 116, 191, 181, -60, 106]
};
var colors = ['206,191,26', '119,206,26', '26,200,206', '236,124,98', '206,26,140', '26,77,206'];
// Definning X
var ordersChartData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: []
}
Object.keys(ORDER_STATS).forEach(function(key) {
color = colors.shift();
ordersChartData.datasets.push({
label: key,
lineTension: 0,
type: 'line',
backgroundColor: "rgba(" + color + ",0.1)",
borderColor: "rgba(" + color + ",1)",
borderWidth: 2,
pointBackgroundColor: "rgba(" + color + ",1)",
pointBorderColor: "#fff",
pointBorderWidth: 1,
pointRadius: 4,
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(" + color + ",1)",
pointHoverBorderWidth: 1,
data: ORDER_STATS[key]
});
});
var ctx = document.getElementById("myChart").getContext("2d");
Chart.defaults.global.defaultFontColor = 'grey';
Chart.defaults.global.defaultFontFamily = "Tahoma";
Chart.defaults.global.defaultFontSize = 11;
Chart.defaults.global.defaultFontStyle = 'normal';
var myChart = new Chart(ctx, {
type: 'line',
data: ordersChartData,
defaultFontSize: 11,
options: {
responsive: true,
title: {
display: true,
text: 'Intersection realization',
fontColor: "#444",
fontFamily: 'Tahoma',
padding: 0
},
legend: {
display: true,
labels: {
fontColor: 'grey',
usePointStyle: true
}
},
tooltips: {
mode: "index",
intersect: true,
position: 'nearest',
bodySpacing: 4
}
}
});
Chart.plugins.register({
afterDatasetsDraw: function(chartInstance, easing) {
var intersects = findIntersects(ORDER_STATS['2015'], ORDER_STATS['2014']);
var context = chartInstance.chart.ctx;
var Y = chartInstance.scales['y-axis-0'];
var X = chartInstance.scales['x-axis-0'];
zeroPointY = Y.top + ((Y.bottom - Y.top) / (Y.ticks.length - 1) * Y.zeroLineIndex);
zeroPointX = Y.right;
yScale = (Y.bottom - Y.top) / (Y.end - Y.start);
xScale = (X.right - X.left) / (X.ticks.length - 1);
intersects.forEach(function(result, idx) {
context.fillStyle = 'red';
context.beginPath();
context.arc((result.x * xScale) + zeroPointX, (Y.end - Y.start) - (result.y * yScale) - ((Y.end - Y.start) - zeroPointY), 3, 0, 2 * Math.PI, true);
context.fill();
});
}
});
function findIntersects(line1, line2) {
var intersects = [];
line1.forEach(function(val, idx) {
var line1StartX = idx;
var line1StartY = line1[idx];
var line1EndX = idx + 1;
var line1EndY = line1[idx + 1];
var line2StartX = idx;
var line2StartY = line2[idx];
var line2EndX = idx + 1;
var line2EndY = line2[idx + 1];
result = checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY);
if (result.onLine1 && result.onLine2) {
intersects.push(result);
}
});
return intersects;
}
function checkLineIntersection(line1StartX, line1StartY, line1EndX, line1EndY, line2StartX, line2StartY, line2EndX, line2EndY) {
// if the lines intersect, the result contains the x and y of the intersection (treating the lines as infinite) and booleans for whether line segment 1 or line segment 2 contain the point
var denominator, a, b, numerator1, numerator2, result = {
x: null,
y: null,
onLine1: false,
onLine2: false
};
denominator = ((line2EndY - line2StartY) * (line1EndX - line1StartX)) - ((line2EndX - line2StartX) * (line1EndY - line1StartY));
if (denominator == 0) {
return result;
}
a = line1StartY - line2StartY;
b = line1StartX - line2StartX;
numerator1 = ((line2EndX - line2StartX) * a) - ((line2EndY - line2StartY) * b);
numerator2 = ((line1EndX - line1StartX) * a) - ((line1EndY - line1StartY) * b);
a = numerator1 / denominator;
b = numerator2 / denominator;
// if we cast these lines infinitely in both directions, they intersect here:
result.x = line1StartX + (a * (line1EndX - line1StartX));
result.y = line1StartY + (a * (line1EndY - line1StartY));
/*
// it is worth noting that this should be the same as:
x = line2StartX + (b * (line2EndX - line2StartX));
y = line2StartX + (b * (line2EndY - line2StartY));
*/
// if line1 is a segment and line2 is infinite, they intersect if:
if (a > 0 && a < 1) {
result.onLine1 = true;
}
// if line2 is a segment and line1 is infinite, they intersect if:
if (b > 0 && b < 1) {
result.onLine2 = true;
}
// if line1 and line2 are segments, they intersect if both of the above are true
return result;
};
If it is not what you want, I recommend you draw the third line with the difference between the first and second line... or draw another graph with only the third line (calculate the difference between line A and line B).
Fiddle: Third Line
Official documentation.
Here (official) you have several graph examples.