Intersection point in line graph in Chart.js?

后端 未结 1 1215
梦谈多话
梦谈多话 2020-12-03 20:35

Searched a lot about this but din\'t got any answer on this based on chart.js. I had already asked this question here in which I was using highchart.js and got the solution

相关标签:
1条回答
  • 2020-12-03 20:41

    Here we are )))

    https://jsfiddle.net/Falseclock/5nbecn0z/

    If you need to show intersections with X axis, then just imitate line with Y=0 https://jsfiddle.net/Falseclock/8g0ucdb1/

    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 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);
    
            var intersects = findIntersects(ORDER_STATS['2015'], ORDER_STATS['2014'] );
            var context = chartInstance.chart.ctx;
                
            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;
    };
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
    <canvas id="myChart" width="650" height="241" style="display: block; width: 650px; height: 241px;"></canvas>

    0 讨论(0)
提交回复
热议问题