Create a heatmap/punchcard Using Chart.js - javascript

I have multiple charts on page, one of them is HeatMap.
I am using chartjs to create my charts. I am unable to create a heatmap using chartjs. Also is it possible to get look like github punchcard with chartJS
punchcard example

Use bubble chart to draw chart. Below is the image for the same.
[Sample-code]
var ctx = document.getElementById("myChart");
var data = {
datasets: [
{
label : "Monday",
data: [
{
x: 2,
y: 5,
r: 12
},
{
x: 6,
y: 5,
r: 8
},
{
x: 10,
y: 5,
r: 8
},
{
x: 14,
y: 5,
r: 6
},
{
x: 18,
y: 5,
r: 6
},
{
x: 22,
y: 5,
r: 2
},
{
x: 26,
y: 5,
r: 2
},
{
x: 30,
y: 5,
r: 6
},
{
x: 34,
y: 5,
r: 8
},
{
x: 38,
y: 5,
r: 12
},
{
x: 42,
y: 5,
r: 12
},
{
x: 46,
y: 5,
r: 10
},
{
x: 50,
y: 5,
r: 12
},
{
x: 54,
y: 5,
r: 8
},
{
x: 58,
y: 5,
r: 8
}
],
backgroundColor:"#444",
hoverBackgroundColor: "#FF6384",
},
{
label : "Tuesday",
data: [
{
x: 2,
y: 15,
r: 12
},
{
x: 6,
y: 15,
r: 8
},
{
x: 10,
y: 15,
r: 8
},
{
x: 14,
y: 15,
r: 6
},
{
x: 18,
y: 15,
r: 6
},
{
x: 22,
y: 15,
r: 2
},
{
x: 26,
y: 15,
r: 2
},
{
x: 30,
y: 15,
r: 6
},
{
x: 34,
y: 15,
r: 8
},
{
x: 38,
y: 15,
r: 12
},
{
x: 42,
y: 15,
r: 12
},
{
x: 46,
y: 15,
r: 10
},
{
x: 50,
y: 15,
r: 12
},
{
x: 54,
y: 15,
r: 8
},
{
x: 58,
y: 15,
r: 8
}
],
backgroundColor:"#444",
},
{
label : "Wednesday",
data: [
{
x: 2,
y: 25,
r: 12
},
{
x: 6,
y: 25,
r: 4
},
{
x: 10,
y: 25,
r: 4
},
{
x: 14,
y: 25,
r: 2
},
{
x: 18,
y: 25,
r: 6
},
{
x: 22,
y: 25,
r: 12
},
{
x: 26,
y: 25,
r: 12
},
{
x: 30,
y: 25,
r: 6
},
{
x: 34,
y: 25,
r: 8
},
{
x: 38,
y: 25,
r: 12
},
{
x: 42,
y: 25,
r: 12
},
{
x: 46,
y: 25,
r: 10
},
{
x: 50,
y: 25,
r: 12
},
{
x: 54,
y: 25,
r: 8
},
{
x: 58,
y: 25,
r: 8
}
],
backgroundColor:"#444",
}
]
};
var myBubbleChart = new Chart(ctx,{
type: 'bubble',
data: data,
options: {
scales : {
xAxes : [{
display : false,
ticks : {
beginAtZero : true,
max : 70
}
}],
yAxes : [{
ticks: {
beginAtZero : true,
max : 40,
stepSize : 10
}
}]
}
}
});

Related

Sorting coordinates

Im coding a Paint version for Minecraft with the CC Tweaked Mod
The Problem is i give my program an array and the program follows the order of the array one after the other.
That means if i draw something in the top left and then bottom right and then i fill everything else it will follow this order (which isnt very efficient)
I have an array called output
Here is how the array could look like
[
{ x: 0, y: 0, color: 12 },
{ x: 1, y: 0, color: 3 },
{ x: 2, y: 0, color: 5 },
{ x: 0, y: 1, color: 8 },
{ x: 1, y: 1, color: 10 },
{ x: 2, y: 1, color: 11 },
{ x: 0, y: 2, color: 12 },
{ x: 2, y: 2, color: 3 },
{ x: 1, y: 2, color: 14 }
]
The array comes from this "drawing"(ignore the arrows for now)
Now the question
How can i get from the first array to an array that looks like this
[
{ x: 0, y: 0, color: 12 },
{ x: 1, y: 0, color: 3 },
{ x: 2, y: 0, color: 5 },
{ x: 2, y: 1, color: 11 },
{ x: 1, y: 1, color: 10 },
{ x: 0, y: 1, color: 8 },
{ x: 0, y: 2, color: 12 },
{ x: 1, y: 2, color: 14 }
{ x: 2, y: 2, color: 3 },
]
(See how it follows the arrows?)
This would be much faster.
It is possibles that some squares are not filled with any color. Idk how important that might be
If important these are the colorcodes
const LISTOFCOLORS = {
white: 1,
orange: 2,
magenta: 3,
dodgerblue: 4,
yellow: 5,
lime: 6,
pink: 7,
gray: 8,
lightgray: 9,
cyan: 10,
purple: 11,
blue: 12,
SaddleBrown: 13,
green: 14,
red: 15,
black: 16
}
If you are only reversing the 3 - 6 entries, you could create a new array from slices of the old array using slice() and reverse the specified entries using reverse().
const rowByRow = [
{ x: 0, y: 0, color: 12 },
{ x: 1, y: 0, color: 3 },
{ x: 2, y: 0, color: 5 },
{ x: 0, y: 1, color: 8 },
{ x: 1, y: 1, color: 10 },
{ x: 2, y: 1, color: 11 },
{ x: 0, y: 2, color: 12 },
{ x: 2, y: 2, color: 3 },
{ x: 1, y: 2, color: 14 }
];
const result = [
...rowByRow.slice(0, 3),
...rowByRow.slice(3, 6).reverse(), // reverse 3 - 6 entries
...rowByRow.slice(6, 9)
];
console.log(result);
#axtck Thank you very much. I ended up not using slice but the "slicing the array in multiple arrays and work from there" part i got from your post
i ended up with this
const arr = [
{ x: 1, y: 4, color: 12 },
{ x: 2, y: 4, color: 12 },
{ x: 2, y: 3, color: 12 },
{ x: 2, y: 2, color: 12 },
{ x: 2, y: 1, color: 12 },
{ x: 0, y: 0, color: 12 },
{ x: 1, y: 0, color: 12 },
{ x: 1, y: 1, color: 12 },
{ x: 4, y: 1, color: 12 },
{ x: 3, y: 2, color: 12 },
{ x: 1, y: 3, color: 12 },
{ x: 0, y: 3, color: 12 },
{ x: 0, y: 1, color: 12 },
{ x: 0, y: 2, color: 12 },
{ x: 1, y: 2, color: 12 },
{ x: 3, y: 4, color: 12 },
{ x: 4, y: 4, color: 12 },
{ x: 4, y: 0, color: 12 },
{ x: 3, y: 0, color: 12 },
{ x: 2, y: 0, color: 12 },
{ x: 3, y: 1, color: 12 },
{ x: 4, y: 2, color: 12 },
{ x: 4, y: 3, color: 12 },
{ x: 0, y: 4, color: 12 },
{ x: 3, y: 3, color: 12 }
]
const ArrayOfArrays = []
const dimension = 5
for (let i = 0; i < dimension; i++) {
let array = []
for (let j = 0; j < arr.length; j++) {
if (i == arr[j].y) {
array.push(arr[j])
}
}
ArrayOfArrays.push(i % 2 === 0 ?
array.sort(function (a, b) {
return a.x - b.x;
}) : array.sort(function (a, b) {
return b.x - a.x;
}))
}
console.log(ArrayOfArrays)
The output would be
[
[
{ x: 0, y: 0, color: 12 },
{ x: 1, y: 0, color: 12 },
{ x: 2, y: 0, color: 12 },
{ x: 3, y: 0, color: 12 },
{ x: 4, y: 0, color: 12 }
],
[
{ x: 4, y: 1, color: 12 },
{ x: 3, y: 1, color: 12 },
{ x: 2, y: 1, color: 12 },
{ x: 1, y: 1, color: 12 },
{ x: 0, y: 1, color: 12 }
],
[
{ x: 0, y: 2, color: 12 },
{ x: 1, y: 2, color: 12 },
{ x: 2, y: 2, color: 12 },
{ x: 3, y: 2, color: 12 },
{ x: 4, y: 2, color: 12 }
],
[
{ x: 4, y: 3, color: 12 },
{ x: 3, y: 3, color: 12 },
{ x: 2, y: 3, color: 12 },
{ x: 1, y: 3, color: 12 },
{ x: 0, y: 3, color: 12 }
],
[
{ x: 0, y: 4, color: 12 },
{ x: 1, y: 4, color: 12 },
{ x: 2, y: 4, color: 12 },
{ x: 3, y: 4, color: 12 },
{ x: 4, y: 4, color: 12 }
]
]
notice how the x value goes up and down

sort 2 array's with objects of coordinates to get a list of which are closest to each-other

I have 2 array's with objects of coordinates. For example:
const coordinates = [
{ x: 2, y: 6 },
{ x: 14, y: 10 },
{ x: 7, y: 10 },
{ x: 11, y: 6 },
];
const coordinates2 = [
{ x: 8, y: 9 },
{ x: 25, y: 11 },
{ x: 2, y: 11 },
{ x: 7, y: 8 },
];
I want to make an sort function which will return which are closest to each other.
I tried multiple things but can not figure it out.
Any solution is accepted. Maybe sort 1 to the other or sort both at the same time.
This is wat I want to achive:
result array 1[
{ x: 2, y: 6 },
{ x: 14, y: 10 },
{ x: 7, y: 10 },
{ x: 11, y: 6 },
];
result array 2 = [
{ x: 2, y: 11 }, // beceause it is closest to {x: 2,y: 6}
{ x: 25, y: 11 }, // beceayse it is closest to {x: 14,y: 10},
{ x: 7, y: 8 }, // beceause it is closest to { x: 7, y: 10 }
{ x: 8, y: 9 }, // beceause it is closest to {x: 11,y: 6} after x: 7, y:10 but x:7, y:8 is even closer
];
^ the result can be different. But I want the most efficient distance between them.
The formula to see the distance of coordination a and coordination b is the following:
distance=√((x1-x2)²+(y1-y2)²).
If anyone has an idea or an tip please let me know !
You could map the first array by getting the closest coordinate from the second array.
const
getClosest = ({ x, y }, data) => data.reduce((a, b) => Math.hypot(x - a.x, y - a.y) < Math.hypot(x - b.x, y - b.y) ? a : b),
coordinates = [{ x: 2, y: 6 }, { x: 14, y: 10 }, { x: 7, y: 10 }, { x: 11, y: 6 }, { x: 6, y: 2 }],
coordinates2 = [{ x: 8, y: 9 }, { x: 25, y: 11 }, { x: 2, y: 11 }, { x: 18, y: 21 }, { x: 7, y: 8 }],
pairs = coordinates.map(o => [o, getClosest(o, coordinates2)]);
console.log(pairs);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to show custom label in line chart or scatter chart

I am adding data to charts like this
const data = [
["2020-05-22 14:20:22", "173.9"],
["2020-05-22 14:20:40", "175.3"],
["2020-05-22 14:20:58", "172.4"]
]
function stringToDate(s) {
s = s.split(/[-: ]/);
return new Date(s[0], s[1]-1, s[2], s[3], s[4], s[5]);
}
for(var key in data)
{
var xTime = stringToDate(data[key][0]);
var yVal = parseFloat(data[key][1]);
series.add({ x: xTime.getTime() - dateOrigin.getTime(), y: yVal})
}
How do I show custom label to it, For example I want to show full date for above line series and also for other scatter charts , I want to show custom label like below.
series.add({ x: xTime.getTime() - dateOrigin.getTime(), y: yVal , label : "my own text" })
To show a full date for a series using a DateTime axis you can take a look at my previously posted answer: https://stackoverflow.com/a/59839354/6198227 The sort version of it is to define a format options based on Intl.DateTimeFormat when defining the axis tick strategy for a axis.
Custom labels can be done by creating custom ticks. The text inside the tick can be defined with a text formatter set by Axis.setTextFormatter. The formatter function gets the position and the tick itself as parameters so those can be used to define the text inside the tick if that's needed.
const tick = lineSeries.axisX.addCustomTick()
.setGridStrokeLength(0)
.setTextFormatter(()=>'My Text')
.setValue(dataFrequency * 50)
See below snippet for a implementation of both custom DateTime formatting and the use of custom ticks. The snippet is based on DateTime Axis example from the LightningChart JS Interactive Examples.
LightningChart JS v1.3.1 example:
// Extract required parts from LightningChartJS.
const {
lightningChart,
AxisTickStrategies,
DataPatterns,
emptyFill,
emptyLine
} = lcjs
// Create a XY Chart.
const dateOrigin = new Date(2008, 0, 1)
const chart = lightningChart().ChartXY({
defaultAxisXTickStrategy: AxisTickStrategies.DateTime(
dateOrigin,
undefined,
{
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
}
)
})
.setTitle('Customer Satisfaction')
chart.setPadding({ right: '5' })
// Add a progressive line series.
// Using the DataPatterns object to select the horizontalProgressive pattern for the line series.
const lineSeries = chart.addLineSeries({ dataPattern: DataPatterns.horizontalProgressive })
.setName('Customer Satisfaction')
// Generate some points using for each month
const dataFrequency = 30 * 24 * 60 * 60 * 1000
// Setup view nicely.
chart.getDefaultAxisY()
.setScrollStrategy(undefined)
.setInterval(0, 100)
.setTitle('Satisfaction %')
// Data for the plotting
const satisfactionData = [
{ x: 0, y: 0 },
{ x: 1, y: 8 },
{ x: 2, y: 12 },
{ x: 3, y: 18 },
{ x: 4, y: 22 },
{ x: 5, y: 32 },
{ x: 6, y: 40 },
{ x: 7, y: 48 },
{ x: 8, y: 50 },
{ x: 9, y: 54 },
{ x: 10, y: 59 },
{ x: 11, y: 65 },
{ x: 12, y: 70 },
{ x: 13, y: 68 },
{ x: 14, y: 70 },
{ x: 15, y: 69 },
{ x: 16, y: 66 },
{ x: 17, y: 65.4 },
{ x: 18, y: 64 },
{ x: 19, y: 65 },
{ x: 20, y: 63.5 },
{ x: 21, y: 62 },
{ x: 22, y: 61.2 },
{ x: 23, y: 63 },
{ x: 24, y: 61 },
{ x: 25, y: 62 },
{ x: 26, y: 62 },
{ x: 27, y: 60 },
{ x: 28, y: 57.8 },
{ x: 29, y: 58 },
{ x: 30, y: 61 },
{ x: 31, y: 59 },
{ x: 32, y: 63 },
{ x: 33, y: 61 },
{ x: 34, y: 61.8 },
{ x: 35, y: 62 },
{ x: 36, y: 59.9 },
{ x: 37, y: 58 },
{ x: 38, y: 60 },
{ x: 39, y: 63 },
{ x: 40, y: 59.5 },
{ x: 41, y: 62.5 },
{ x: 42, y: 59.7 },
{ x: 43, y: 57 },
{ x: 44, y: 61 },
{ x: 45, y: 59 },
{ x: 46, y: 61 },
{ x: 47, y: 65 },
{ x: 48, y: 62 },
{ x: 49, y: 60 },
{ x: 50, y: 58 },
{ x: 51, y: 59 },
{ x: 52, y: 61 },
{ x: 53, y: 64 },
{ x: 54, y: 65.5 },
{ x: 55, y: 67 },
{ x: 56, y: 68 },
{ x: 57, y: 69 },
{ x: 58, y: 68 },
{ x: 59, y: 69.5 },
{ x: 60, y: 69.9 },
{ x: 61, y: 68.5 },
{ x: 62, y: 67 },
{ x: 63, y: 65 },
{ x: 64, y: 63 },
{ x: 65, y: 60 },
{ x: 66, y: 61.6 },
{ x: 67, y: 62 },
{ x: 68, y: 61 },
{ x: 69, y: 60 },
{ x: 70, y: 63.3 },
{ x: 71, y: 62.7 },
{ x: 72, y: 64.3 },
{ x: 73, y: 63 },
{ x: 74, y: 61.2 },
{ x: 75, y: 60 },
{ x: 76, y: 61 },
{ x: 77, y: 64 },
{ x: 78, y: 61.9 },
{ x: 79, y: 61 },
{ x: 80, y: 58 },
{ x: 81, y: 59 },
{ x: 82, y: 60.5 },
{ x: 83, y: 61 },
{ x: 84, y: 63 },
{ x: 85, y: 64.5 },
{ x: 86, y: 65 },
{ x: 87, y: 66.2 },
{ x: 88, y: 64.9 },
{ x: 89, y: 63 },
{ x: 90, y: 62 },
{ x: 91, y: 63 },
{ x: 92, y: 61.8 },
{ x: 93, y: 62 },
{ x: 94, y: 63 },
{ x: 95, y: 64.2 },
{ x: 96, y: 63 },
{ x: 97, y: 61 },
{ x: 98, y: 59.7 },
{ x: 99, y: 61 },
{ x: 100, y: 58 },
{ x: 101, y: 59 },
{ x: 102, y: 58 },
{ x: 103, y: 58 },
{ x: 104, y: 57.5 },
{ x: 105, y: 59.2 },
{ x: 106, y: 60 },
{ x: 107, y: 61.9 },
{ x: 108, y: 63 },
{ x: 109, y: 64.1 },
{ x: 110, y: 65.9 },
{ x: 111, y: 64 },
{ x: 112, y: 65 },
{ x: 113, y: 62 },
{ x: 114, y: 60 },
{ x: 115, y: 58 },
{ x: 116, y: 57 },
{ x: 117, y: 58.2 },
{ x: 118, y: 58.6 },
{ x: 119, y: 59.3 },
{ x: 120, y: 61 }
]
// Adding points to the series
lineSeries.add(satisfactionData.map((point) => ({ x: point.x * dataFrequency, y: point.y })))
// Show the customized result table for each point
lineSeries.setResultTableFormatter((builder, series, xValue, yValue) => {
return builder
.addRow('Customer Satisfaction')
.addRow(series.axisX.formatValue(xValue))
.addRow(yValue.toFixed(2) + "%")
})
const tick = lineSeries.axisX.addCustomTick()
.setGridStrokeLength(0)
.setTextFormatter(()=>'My Text')
.setValue(dataFrequency * 50)
<script src="https://unpkg.com/#arction/lcjs#2.2.1/dist/lcjs.iife.js"></script>
Update for LightningChart JS v3.4.0
DateTime axis formatting options have changed a little bit, there are more options to format based on the zoom level. And setResultTableFormatter has been renamed to setCursorResultTableFormatter.
const formatting = {year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric'}
chart.getDefaultAxisX().setTickStrategy(AxisTickStrategies.DateTime, (styler)=>
styler.setDateOrigin(dateOrigin)
.setFormattingDay(formatting, formatting, formatting)
.setFormattingDecade(formatting, formatting, formatting)
.setFormattingHour(formatting, formatting, formatting)
.setFormattingMilliSecond(formatting, formatting, formatting)
.setFormattingMinute(formatting, formatting, formatting)
.setFormattingMonth(formatting, formatting, formatting)
.setFormattingSecond(formatting, formatting, formatting)
.setFormattingWeek(formatting, formatting, formatting)
.setFormattingYear(formatting, formatting, formatting)
)
LightningChart JS v3.4.0 example:
// Import LightningChartJS
const {
lightningChart,
AxisTickStrategies,
DataPatterns,
emptyFill,
emptyLine
} = lcjs
// Create a XY Chart.
const dateOrigin = new Date(2008, 0, 1)
const chart = lightningChart().ChartXY()
.setTitle('Customer Satisfaction')
const formatting = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric'
}
chart.getDefaultAxisX().setTickStrategy(AxisTickStrategies.DateTime, (styler) =>
styler.setDateOrigin(dateOrigin)
.setFormattingDay(formatting, formatting, formatting)
.setFormattingDecade(formatting, formatting, formatting)
.setFormattingHour(formatting, formatting, formatting)
.setFormattingMilliSecond(formatting, formatting, formatting)
.setFormattingMinute(formatting, formatting, formatting)
.setFormattingMonth(formatting, formatting, formatting)
.setFormattingSecond(formatting, formatting, formatting)
.setFormattingWeek(formatting, formatting, formatting)
.setFormattingYear(formatting, formatting, formatting)
)
chart.setPadding({
right: '5'
})
// Add a progressive line series.
// Using the DataPatterns object to select the horizontalProgressive pattern for the line series.
const lineSeries = chart.addLineSeries({
dataPattern: DataPatterns.horizontalProgressive
})
.setName('Customer Satisfaction')
// Generate some points using for each month
const dataFrequency = 30 * 24 * 60 * 60 * 1000
// Setup view nicely.
chart.getDefaultAxisY()
.setScrollStrategy(undefined)
.setInterval(0, 100)
.setTitle('Satisfaction %')
// Data for the plotting
const satisfactionData = [
{ x: 0, y: 0 },
{ x: 1, y: 8 },
{ x: 2, y: 12 },
{ x: 3, y: 18 },
{ x: 4, y: 22 },
{ x: 5, y: 32 },
{ x: 6, y: 40 },
{ x: 7, y: 48 },
{ x: 8, y: 50 },
{ x: 9, y: 54 },
{ x: 10, y: 59 },
{ x: 11, y: 65 },
{ x: 12, y: 70 },
{ x: 13, y: 68 },
{ x: 14, y: 70 },
{ x: 15, y: 69 },
{ x: 16, y: 66 },
{ x: 17, y: 65.4 },
{ x: 18, y: 64 },
{ x: 19, y: 65 },
{ x: 20, y: 63.5 },
{ x: 21, y: 62 },
{ x: 22, y: 61.2 },
{ x: 23, y: 63 },
{ x: 24, y: 61 },
{ x: 25, y: 62 },
{ x: 26, y: 62 },
{ x: 27, y: 60 },
{ x: 28, y: 57.8 },
{ x: 29, y: 58 },
{ x: 30, y: 61 },
{ x: 31, y: 59 },
{ x: 32, y: 63 },
{ x: 33, y: 61 },
{ x: 34, y: 61.8 },
{ x: 35, y: 62 },
{ x: 36, y: 59.9 },
{ x: 37, y: 58 },
{ x: 38, y: 60 },
{ x: 39, y: 63 },
{ x: 40, y: 59.5 },
{ x: 41, y: 62.5 },
{ x: 42, y: 59.7 },
{ x: 43, y: 57 },
{ x: 44, y: 61 },
{ x: 45, y: 59 },
{ x: 46, y: 61 },
{ x: 47, y: 65 },
{ x: 48, y: 62 },
{ x: 49, y: 60 },
{ x: 50, y: 58 },
{ x: 51, y: 59 },
{ x: 52, y: 61 },
{ x: 53, y: 64 },
{ x: 54, y: 65.5 },
{ x: 55, y: 67 },
{ x: 56, y: 68 },
{ x: 57, y: 69 },
{ x: 58, y: 68 },
{ x: 59, y: 69.5 },
{ x: 60, y: 69.9 },
{ x: 61, y: 68.5 },
{ x: 62, y: 67 },
{ x: 63, y: 65 },
{ x: 64, y: 63 },
{ x: 65, y: 60 },
{ x: 66, y: 61.6 },
{ x: 67, y: 62 },
{ x: 68, y: 61 },
{ x: 69, y: 60 },
{ x: 70, y: 63.3 },
{ x: 71, y: 62.7 },
{ x: 72, y: 64.3 },
{ x: 73, y: 63 },
{ x: 74, y: 61.2 },
{ x: 75, y: 60 },
{ x: 76, y: 61 },
{ x: 77, y: 64 },
{ x: 78, y: 61.9 },
{ x: 79, y: 61 },
{ x: 80, y: 58 },
{ x: 81, y: 59 },
{ x: 82, y: 60.5 },
{ x: 83, y: 61 },
{ x: 84, y: 63 },
{ x: 85, y: 64.5 },
{ x: 86, y: 65 },
{ x: 87, y: 66.2 },
{ x: 88, y: 64.9 },
{ x: 89, y: 63 },
{ x: 90, y: 62 },
{ x: 91, y: 63 },
{ x: 92, y: 61.8 },
{ x: 93, y: 62 },
{ x: 94, y: 63 },
{ x: 95, y: 64.2 },
{ x: 96, y: 63 },
{ x: 97, y: 61 },
{ x: 98, y: 59.7 },
{ x: 99, y: 61 },
{ x: 100, y: 58 },
{ x: 101, y: 59 },
{ x: 102, y: 58 },
{ x: 103, y: 58 },
{ x: 104, y: 57.5 },
{ x: 105, y: 59.2 },
{ x: 106, y: 60 },
{ x: 107, y: 61.9 },
{ x: 108, y: 63 },
{ x: 109, y: 64.1 },
{ x: 110, y: 65.9 },
{ x: 111, y: 64 },
{ x: 112, y: 65 },
{ x: 113, y: 62 },
{ x: 114, y: 60 },
{ x: 115, y: 58 },
{ x: 116, y: 57 },
{ x: 117, y: 58.2 },
{ x: 118, y: 58.6 },
{ x: 119, y: 59.3 },
{ x: 120, y: 61 }
]
// Adding points to the series
lineSeries.add(satisfactionData.map((point) => ({
x: point.x * dataFrequency,
y: point.y
})))
// Show the customized result table for each point
lineSeries.setCursorResultTableFormatter((builder, series, xValue, yValue) => {
return builder
.addRow('Customer Satisfaction')
.addRow(series.axisX.formatValue(xValue))
.addRow(yValue.toFixed(2) + "%")
})
const tick = lineSeries.axisX.addCustomTick()
.setGridStrokeLength(0)
.setTextFormatter(() => 'My Text')
.setValue(dataFrequency * 50)
<script src="https://unpkg.com/#arction/lcjs#3.4.0/dist/lcjs.iife.js"></script>

Bubble Chart-Cannot read property 'length' of null at Object.acquireContext (Chart.min.js:14)

var popCanvas = document.getElementById("popChart");
Chart.defaults.global.defaultFontFamily = "Lato";
Chart.defaults.global.defaultFontSize = 18;
var popData = {
datasets: [{
label: ['Deer Population'],
//data to plot bubble on chart
data: [{
x: 100,
y: 0,
r: 10
}, {
x: 60,
y: 30,
r: 20
}, {
x: 40,
y: 60,
r: 25
}, {
x: 80,
y: 80,
r: 50
}, {
x: 20,
y: 30,
r: 25
}, {
x: 0,
y: 100,
r: 5
}],
//color properties for chart
backgroundColor: "#9966FF",
hoverBackgroundColor: "#000000",
hoverBorderColor: "#9966FF",
hoverBorderWidth: 5,
hoverRadius: 5
}]
};
var bubbleChart = new Chart(popCanvas, {
type: 'bubble',
data: popData
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<canvas id="popChart" width="600" height="400"></canvas>

Javascript library for multiple factor legend plot

I am trying to draw a plot with multiple factors. I hope these different factors are distinguished by color, size, and shape of the scatter. An example of this kind of plot is here https://github.com/slfan2013/tempPlot/blob/master/Rplot.png.
I'd like to use a javascript library to draw a similar plot. I usually use plotly.js to draw plots. But I think plotly can only handle one factor at a time (different colors). My question is can plotly handle multiple (nested) factors in one single plot (like color, size, and shape)? If not, if there is any javascript library can achieve these? How about CanvasJS?
#### EDIT.
I understand how to draw scatter with different color and different size (shape, etc) on the same plot. I just would like to have a multiple-factor legend on the plot, so that if I click "red", for example, then the red scatters would hide no matter what size it is AND if I click size "big", big scatters would hide no matter what color it is.
Thanks!
This can be done in CanvasJS using scatter chart and by controlling markerType and markerSize. Check the example shown below.
Refer these pages for markerType and markerSize.
http://canvasjs.com/docs/charts/chart-options/data/markertype/
http://canvasjs.com/docs/charts/chart-options/data/markersize/
var chart = new CanvasJS.Chart("chartContainer",
{
title: {
text: "Scatter Chart with Different Marker Types"
},
legend: {
horizontalAlign: "right",
verticalAlign: "center"
},
data: [
{
type: "scatter",
showInLegend: true,
legendText: "Circle",
dataPoints: [
{ x: 1, y: 91, markerSize: 10 },
{ x: 2, y: 75, markerSize: 20 },
{ x: 3, y: 70, markerSize: 30 },
{ x: 4, y: 85, markerSize: 40 },
{ x: 5, y: 75, markerSize: 50 }
]
},
{
type: "scatter",
markerType: "square", //default "circle"
showInLegend: true,
legendText: "Square",
dataPoints: [
{ x: 1, y: 71, markerSize: 10 },
{ x: 2, y: 55, markerSize: 20 },
{ x: 3, y: 50, markerSize: 30 },
{ x: 4, y: 65, markerSize: 40 },
{ x: 5, y: 55, markerSize: 50 }
]
},
{
type: "scatter",
markerType: "triangle",
showInLegend: true,
legendText: "Triangle",
dataPoints: [
{ x: 1, y: 51, markerSize: 10 },
{ x: 2, y: 35, markerSize: 20 },
{ x: 3, y: 30, markerSize: 30 },
{ x: 4, y: 45, markerSize: 40 },
{ x: 5, y: 35, markerSize: 50 }
]
},
{
type: "scatter",
markerType: "cross",
showInLegend: true,
legendText: "Cross",
dataPoints: [
{ x: 1, y: 31, markerSize: 10 },
{ x: 2, y: 15, markerSize: 20 },
{ x: 3, y: 10, markerSize: 30 },
{ x: 4, y: 25, markerSize: 40 },
{ x: 5, y: 15, markerSize: 50 }
]
}
]
});
chart.render();
<script src="http://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>
You would just need to define multiple traces and set the parameters for each trace individually.
trace0 is just the default settings
trace1 has a custom color
trace2 has a custom color and custom size
trace3 has a custom color, custom size and custom symbol
var trace0 = {
x: [1, 2, 3],
y: [1, 2, 3],
type: 'scatter',
mode:'markers'};
var trace1 = {
x: [1, 2, 3],
y: [2, 1.8, 1],
type: 'scatter',
mode:'markers',
marker: {
color: 'red'
}};
var trace2 = {
x: [1, 2, 3],
y: [2.8, 2.3, 1.2],
type: 'scatter',
mode:'markers',
marker: {
color: 'green',
size: [10, 15, 20]
}};
var trace3 = {
x: [1, 2, 3],
y: [3, 2.5, 1],
type: 'scatter',
mode:'markers',
marker: {
color: 'pink',
size: [10, 15, 20],
symbol: 303
}};
Plotly.plot('myDiv', [trace0, trace1, trace2, trace3])
<div id='myDiv'></div>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>

Categories

Resources