I have some data saved and it is huge, 100.000 plus points saved in the database. In this format:
database_data = [
{ x: 100, y: 100, value: 1},
{ x: 200, y: 100, value: 1},
{ x: 120, y: 320, value: 1},
...
]
I am giving the value of 1 for each point as you can see above. I would like to use:
heatmap.setData({
max: max_value,
data: database_data
});
To plot the data on the screen. How can I calculate the max_value of the heatmap? Because I wanna have the information been displayed on the screen where the most red color is the points where we have more frequently in the database and the less red color would be the point where we have only once in the database. But as we know, (x:100, y:100) and x:120, y: 120) will have some intersection between them, and that would also need to be consider, just like the normal heat map.
In other words, I want to know how to automatically calculate the value for "max" in the heatmap using setData function!
Here below it is a function that is working fine, but it takes too much time:
var body = document.body;
var bodyStyle = getComputedStyle(body);
var hmEl = document.querySelector(".heatmap-wrapper");
hmEl.style.width = bodyStyle.width;
hmEl.style.height = bodyStyle.height;
hmEl.style.background = "#3e1852";
hmEl.style.zIndex = "1000";
var hm = document.querySelector(".heatmap");
var heatmap = h337.create({
container: hm,
radius: 40,
});
var dbh_x = <?php echo $dbh_x;?>; //LIKE THIS->["100", "200", "300","400", "420", "500", "600", "600"];
var dbh_y = <?php echo $dbh_y;?>;//LIKE THIS->["100", "200", "300","400", "420", "500", "600", "600"];
for ( var i =0; i< dbh_x.length; i++){
heatmap.addData({
x: dbh_x[i],
y: dbh_y[i],
});
};
Because of the loading time, I was trying to use setData instead:
var body = document.body;
var bodyStyle = getComputedStyle(body);
var hmEl = document.querySelector(".heatmap-wrapper");
hmEl.style.width = bodyStyle.width;
hmEl.style.height = bodyStyle.height;
hmEl.style.background = "#3e1852";
hmEl.style.zIndex = "1000";
var hm = document.querySelector(".heatmap");
var heatmap = h337.create({
container: hm,
radius: 40,
});
heatmap.setData({//This function will show the data kind a fast for 100000+points
max: 10, //This is the problem
data: [{ x: 891, y: 50, value: 1},{ x: 891, y: 50, value: 1},...]
});
Appreciate your guys time!
Related
I am using AMCharts for my project, what I want is to accomplish this:
given 1. data points:
const data = [{x: 23, y: 0},{x: 24, y: 0},{x: 25, y: 23},...,{x: 26, y: 24}]
I want to extract any Y value given X value from the series...
Partial code I am using to create chart:
this.chart = am4core.create(this.chartDiv, am4charts.XYChart);
this.title = this.chart.titles.create();
// chartData is just an array of x,y values
this.chart.data = this.props.chartData;
const X_AXIS = this.chart.xAxes.push(new am4charts.ValueAxis());
X_AXIS.title.text = "X VALUES";
const Y_AXIS = this.chart.yAxes.push(new am4charts.ValueAxis());
Y_AXIS.title.text = "Y VALUES";
this.series = this.chart.series.push(new am4charts.LineSeries());
this.series.dataFields.valueX = "xValue";
this.series.dataFields.valueY = "yValue";
// cursor
this.chart.cursor = new am4charts.XYCursor();
this.chart.cursor.xAxis = X_AXIS;
this.chart.cursor.yAxis = Y_AXIS;
this.chart.cursor.snapToSeries = this.series;
How can I accomplish this? Say Y value for X = 24 in JS (something like this.series.get(25))
Why not just search through the data using the Array.prototype.find method since you're generating your points based on the data array anyways.
const data = [{x: 23, y: 0},{x: 24, y: 0},{x: 25, y: 23},{x: 26, y: 24}];
console.log(data.find(item => item.x === 23).y);
Background info:
I am trying to create a multi series doughnut chart with the data labels positioned in the center of each slice like this (see below) however I want the data labels to reposition itself if the div is resized:
Problem:
I am struggling to reposition the data labels accurately when the div is resized.
I need to get the current doughnut chart plot size in percentage with which I could calculate accurate distance from doughnut edges to place the data labels.
Example Fiddle
Here's a mockup in fiddle: http://jsfiddle.net/simkus/bo2eumkd/30/
$(function() {
var container = $('#container')[0];
$('#resizer').resizable({
// On resize, set the chart size to that of the
// resizer minus padding. If your chart has a lot of data or other
// content, the redrawing might be slow. In that case, we recommend
// that you use the 'stop' event instead of 'resize'.
// TODO we need to calculate the distance of dataLabels from the edges of the
// doughnut chart. The main thing is that the chart might be resized, to e.g. 200pxx200px
// and then the labels now gets scatared by the current algorythm where we calculate `distance`
// the `distance` should be calculated I think not in pixels by % of the current
// chart placeholder size. The chart it self has a `size` of 80% for all series.
// the inner size is also measured in %, so the distance somehow has to be done
// similary, but at this point, the `distance` doesn't work with % as size and innerSize
resize: function() {
chart.setSize(
this.offsetWidth - 20,
this.offsetHeight - 20,
false
);
}
});
let seriesData = [{
"base": 1949,
"data": [106, 105, 26, 43, 55, 136],
"name": "Total",
},
{
"base": 871,
"data": [38, 44, 14, 20, 25, 75],
"name": "Male",
},
{
"base": 1063,
"data": [65, 61, 12, 23, 31, 60],
"name": "Female",
}
]
let categories = [
"Don't know",
"Australia",
"India",
"Japan",
"Brazil",
"I don’t know"
]
let series = [];
let plotArea = 350;
let centerInnerSize = 40; // 40%
for (let i = 0; i < seriesData.length; i++) {
var showInLegend = false,
data = [],
innerSize = centerInnerSize + ((100 - centerInnerSize) / seriesData.length) * i,
width = (plotArea / 2) * ((1 - centerInnerSize / 100) / seriesData.length),
distance = (plotArea / 2) * (1 - innerSize / 100) - width / 2;
if (i == 0) {
showInLegend = true;
}
for (let j = 0; j < categories.length; j++) {
data.push({
'name': categories[j],
'y': seriesData[i].data[j]
})
}
series.push({
name: seriesData[i].name,
data: data,
innerSize: innerSize + '%',
size: "80%",
showInLegend: true,
dataLabels: {
enabled: true,
distance: -distance,
}
})
}
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
plotBackgroundColor: null,
plotBorderWidth: 1,
plotShadow: false,
type: 'pie',
events: {
render() {
let chart = this;
chart.series.forEach(s => {
s.points.forEach(p => {
let label = p.dataLabel;
p.dataLabel.translate(label.translateX, label.translateY)
})
})
}
}
},
subtitle: {
text: 'Drag the handle in the lower right to resize'
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.2f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: false,
cursor: 'pointer',
minSize: 1,
dataLabels: {
enabled: true,
color: '#000000',
format: '{percentage:.2f} %',
}
}
},
series: series,
});
});
Any ideas how I can resolve this problem?
I need to get the current doughnut chart plot size in pixels with which I could calculate accurate distance from doughnut edges to place the data labels.
I am not sure what is your idea to place the data labels, but you should be able to achieve it by using the render callback where you can get access to each point and his label.
Demo: http://jsfiddle.net/BlackLabel/5m41p986/
events: {
render() {
let chart = this;
chart.series.forEach(s => {
s.points.forEach(p => {
let label = p.dataLabel;
p.dataLabel.translate(label.translateX, label.translateY)
})
})
}
}
API: https://api.highcharts.com/highcharts/chart.events.render
Updated the distance calculation using percentage and now it works.
http://jsfiddle.net/4g1pxvqb/36/
for (let i = 0; i < seriesData.length; i++) {
var showInLegend = false,
data = [],
innerSize = centerInnerSize + ((100 - centerInnerSize) / seriesData.length) * i,
width = (100 - centerInnerSize) / 3;
distance = '-' + (10 + width * (2 - i)) + '%';
I start with interract.js and try to figure out how to snap my elements to defined sizes in the index targets. It works well when I set the values statically but actually I would like to dynamize the values so that each element can snap to each other.
I didn't find how to do this in the doc, would you have a research track allowing me to make the values evolve according to the displacement of the blocks, so that they become "snappable" ?
ideally I think these values should be able to change dynamically each time you move an element, so using dragend event, but how do you make the change in values take effect...
thank you for your feedback.
// here I define my static values for the snap
var dynamicRestrictions = [
{x: 200, range: 20},
{x: 400, range: 20},
{y: 300, range: 20}
];
interact('.resize-drag')
.draggable({
inertia: true,
modifiers: [
interact.modifiers.snap({
targets: dynamicRestrictions, // <= how to dynamic edit them ?
relativePoints: [
{x: 0, y: 0},
{x: 1, y: 1},
{x: 0, y: 1},
{x: 1, y: 0},
],
offset: 'parent'
}),
],
autoScroll: true,
listeners: {
move: dragMoveListener,
}
})
you can use a function on the onstart event.
.draggable({
//...
onstart: dragMoveStartListener,
//...
})
which will allow you to set your hang values.
function dragMoveStartListener(event) {
var element = $(event.target);
dynamicRestrictions.length = 0;
$('.resize-drag').each(function () {
if (!$(this).is(element)) {
var thisPosition = $(this).position(),
snapX = thisPosition.left,
snapY = thisPosition.top,
snapWidth = $(this).width(),
snapHeight = $(this).height(),
range = 20;
var sumWidth = parseInt(snapX + snapWidth),
sumHeight = parseInt(snapY + snapHeight);
dynamicRestrictions.push({x: snapX, y: snapY, range: 10});
dynamicRestrictions.push({x: snapX, range: range});
dynamicRestrictions.push({x: sumWidth, range: range});
dynamicRestrictions.push({y: snapY, range: range});
dynamicRestrictions.push({y: sumHeight, range: range});
}
});
}
I tested it and it works pretty well, except that I don't know how to snap both vertically and horizontally, each time it's one or the other...
looking for a little bit more, should do the job
I'm creating a Polygon with fabric.js and set its value "perPixelTargetFind" true.
When you click, for example, on the right top end (not inside the polygon, inside its bounding box), the polygon gets selcected, although "perPixelTargetFind" is set ( I though with this value it is only possible to select an object by directly clicking on it).
The polygon should only be selected, if you click directly on it, is this possible?
Here is a link to the issue on jsfiddle: Polygon perPixelTargetFind
And here is my code so far:
var canvas = new fabric.Canvas('canvas');
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
document.getElementById("canvas").tabIndex = 1000;
var pol = new fabric.Polygon([
{x: 200, y: 0},
{x: 250, y: 50},
{x: 250, y: 100},
{x: 150, y: 100},
{x: 150, y: 50} ], {
left: 250,
top: 150,
fill: 'green',
perPixelTargetFind: true
}
);
canvas.add(pol);
thank you for your help! :)
Here is what i have got so far with help of stackoverflow answers.
I am able to add description to bars on the bar chart but now struggling with putting label and scale on Y axis.
window.onload = function ()
{
var r = Raphael("diagram"),
data3 = [25, 20, 13, 32, 15, 5, 6, 10],
txtattr = { font: "24px 'Allerta Stencil', sans-serif", fill: "rgb(105, 136, 39)" };
r.text(250, 10, "Sample Chart").attr(txtattr);
var bc = r.barchart(10, 10, 500, 400, data3,
{
stacked: false,
type: "sharp"
});
bc.attr({ fill: "#2f69bf" });
var x = 1;
labelBarChart(r, bc,
['abc', 'b', 'card', 'd', 'elph', 'fun', 'gurr', 'ha'],
{ fill: "#2f69bf", font: "16px sans-serif" }
);
};
function labelBarChart(r, bc, labels, attrs)
{
for (var i = 0; i < bc.bars.length; i++)
{
var bar = bc.bars[i];
var gutterY = bar.w * 0.4;
var labelX = bar.x;
var labelY = bar.y + bar.h + gutterY;
var labelText = labels[i];
var labelAttr = { fill: "#2f69bf", font: "16px sans-serif" };
r.text(labelX, labelY, labelText).attr(labelAttr);
}
}
I would like the graph to look like this with description and units on Y Axis, don’t need anything fancy like emboss effects etc.
!