2017-03-06 59 views
1

搜索了很多關於這個,但沒有根據chart.js得到任何答案。我已經問過這個問題here其中我使用highchart.js並得到了解決方案,但現在我正在使用chart.js庫並試圖找到解決方案。 下面是我試過的代碼。我需要找到這兩個折線圖組合之間的交點。查看圖形圖像。 enter image description hereChart.js中的線圖中的交點?

var config = { 
 
    type: 'bar', 
 
    data: { 
 
    labels: ["Year 0", "Year 1", "Year 2", "Year 3", "Year 4", "Year 5", "Year 6"], 
 
    datasets: [{ 
 
     type: 'line', 
 
     label: 'Cost', 
 
     data: [150, 15, 25, 14, 10, 7], 
 
     borderColor: '#E35500', 
 
     fill: false, 
 
     lineTension: 0, 
 
     borderJoinStyle: 'miter', 
 
     }, { 
 
     type: 'line', 
 
     label: 'Cash Flow', 
 
     data: [20, 180, 170, 220, 160, 190], 
 
     borderColor: '#FFC000', 
 
     fill: false, 
 
     lineTension: 0, 
 
     borderJoinStyle: 'miter', 
 
     xAxes: [{ 
 
      barPercentage: 0.4 
 
     }] 
 
     }, 
 
     { 
 
     type: 'line', 
 
     label: 'Accumulative Flow', 
 
     data: [0, -10, 20, 30, 40, 50], 
 
     borderColor: 'red', 
 
     fill: false, 
 
     lineTension: 0, 
 
     borderJoinStyle: 'miter', 
 
     xAxes: [{ 
 
      barPercentage: 0.4 
 
     }] 
 
     }, { 
 
     type: 'bar', 
 
     label: 'Benifit(One time)', 
 
     backgroundColor: "#005998", 
 
     data: [40, 50, 60, 80, 50, 60], 
 
     }, { 
 
     type: 'bar', 
 
     label: 'Benifit(Recurring)', 
 
     backgroundColor: "#0FAAFF", 
 
     data: [120, 150, 150, 180, 120, 140], 
 
     } 
 
    ] 
 
    }, 
 
    options: { 
 
    title: { 
 
     display: true, 
 
     text: 'Custom Chart Title' 
 
    }, 
 
    scales: { 
 
     xAxes: [{ 
 
     time: { 
 
      displayFormats: { 
 
      quarter: ' YYYY' 
 
      } 
 
     }, 
 
     stacked: true, 
 
     beginAtZero: true, 
 
     barPercentage: 0.3, 
 
     id: 'x-axis-label', 
 
     position: 'bottom', 
 
     scaleStartValue: 20, 
 
     gridLines: { 
 
      display: false 
 
     }, 
 
     }], 
 
     yAxes: [{ 
 
     stacked: true, 
 
     id: 'y-axis-label', 
 
     ticks: { 
 
      max: 300, 
 
      min: -50, 
 
      stepSize: 50, 
 
     }, 
 
     position: 'left', 
 
     gridLines: { 
 
      display: false 
 
     }, 
 
     }] 
 
    }, 
 
    legend: { 
 
     position: 'right' 
 
    }, 
 
    maintainAspectRatio: false, 
 
    scaleBeginAtZero: true 
 

 

 
    } 
 
}; 
 

 
var ctx = document.getElementById("myChart").getContext("2d"); 
 
new Chart(ctx, config);
.GraphContain { 
 
    max-height: 500px; 
 
    position: relative; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.0/moment.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script> 
 

 
<div class="GraphContain"> 
 
    <canvas id="myChart" width="400" height="400"></canvas> 
 
</div>

任何人有任何想法?需要這個天才!

+0

任何人對此有任何想法? –

+0

有沒有一種簡單的方法來做到這一點,這一切都取決於數學。看看這個[問題](http://stackoverflow.com/questions/28845817/chart-js-find-intersection-point-and-draw-a-circle)瞭解如何處理它的詳細大綱。既然你沒有使用貝塞爾曲線,它會簡單得多。這是一個[jsfiddle](http://jsfiddle.net/justin_c_rounds/Gd2S2/light/),其中包含數學計算以查找2行的交集。祝你好運! – jordanwillis

+0

我試過這個,但是它對我來說很有用@jordanwillis –

回答

3

我們在這裏)))

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

如果需要,以顯示與X軸交點,然後就模仿符合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

真的很不錯的答案。有沒有什麼方法可以繪製一條線,在這裏它交叉並顯示信息https://jsfiddle.net/Falseclock/8g0ucdb1/在這裏就像我的示例圖像? –