简体   繁体   中英

How to change line color based on data - chartist or chart.js

Been looking for a solution to this with either chartist or chart.js, but keep coming up empty. I'm looking for a way to create a line graph and change the color of the line based on the data.

Example data set:

[
    {time: '3:00:00', speed: 20, direction: 345},
    {time: '3:01:00', speed: 0, direction: 0},
    {time: '3:02:00', speed: 25, direction: 90},
    {time: '3:03:00', speed: 10, direction: 180},
    {time: '3:04:00', speed: 5, direction: 0}
]

I'm looking for the time to be the x axis, the speed to be the y axis, and then to change the color of the line segment based on the direction. Seems like most of the charting libraries (unless I start digging into d3) when they create line graphs create one big line for the whole series and doesn't let you style the individual segments of the line. There's a great chartjs example here, but the color isn't based on the data (it's just an arbitrary set of colors):

https://blog.vanila.io/chart-js-tutorial-how-to-make-gradient-line-chart-af145e5c92f9

You could create a scatter chart and draw the lines directly on the canvas using the Plugin Core API . The API offers a range of hooks that may be used for performing custom code.

In below code snippet, I use the afterDraw hook to draw connection lines between data points. Their color depends on the direction property of the start data point.

 const rawData = [ {time: '3:00:00', speed: 20, direction: 345}, {time: '3:01:00', speed: 0, direction: 0}, {time: '3:02:00', speed: 25, direction: 290}, {time: '3:03:00', speed: 10, direction: 180}, {time: '3:04:00', speed: 5, direction: 0} ]; const data = rawData.map(o => ({ x: moment(o.time, 'H:mm:ss').toDate().getTime(), y: o.speed})); const colorsPer100 = ['green', 'orange', 'blue', 'red']; new Chart(document.getElementById("myChart"), { type: "scatter", plugins: [{ afterDraw: chart => { var ctx = chart.chart.ctx; var xAxis = chart.scales['x-axis-1']; var yAxis = chart.scales['y-axis-1']; chart.config.data.datasets[0].data.forEach((value, index) => { if (index > 0) { var valueFrom = data[index - 1]; var xFrom = xAxis.getPixelForValue(valueFrom.x); var yFrom = yAxis.getPixelForValue(valueFrom.y); var direction = rawData[index -1].direction; var xTo = xAxis.getPixelForValue(value.x); var yTo = yAxis.getPixelForValue(value.y); ctx.save(); ctx.strokeStyle = colorsPer100[Math.floor(direction / 100)]; ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(xFrom, yFrom); ctx.lineTo(xTo, yTo); ctx.stroke(); ctx.restore(); } }); } }], data: { datasets: [{ label: "My Dataset", data: data, borderColor: "rgb(75, 192, 192)" }] }, options: { legend: { display: false }, scales: { xAxes: [{ type: 'time', time: { unit: 'minute', displayFormats: { minute: 'H:mm:ss' } }, }] } } });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script> <canvas id="myChart" height="90"></canvas>

uminder has an interesting solution. In another thread, someone posted a solution which I went with - they just created an array of colors that's the same size as the dataset (and just feed that in with the data). That worked great and was much simpler than I think I was trying to make it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM