I have to add gradient inside a foot shape according to the value of a point inside the foot. I have X and Y coordinates of a point and a value is attached to it. According to the value I have to assign color gradient like in the picture below. Higher the value of a point, darker the area is
So far, I have created the foot and added 2 color gradient to the whole foot, but I am unable to add gradient like this in the picture. Below is what I have achieved. Please if anyone could help me to find any solution to this
Here is the Stackblitz Link
Sample data :
[
{sensor: 0, value: 7.4, x: 108, y: 406}
{sensor: 1, value: 8.1, x: 68, y: 412}
{sensor: 2, value: 3.6, x: 108, y: 346}
{sensor: 3, value: 4.5, x: 61, y: 350}
{sensor: 4, value: 0.5, x: 108, y: 280}
{sensor: 5, value: 1, x: 49, y: 288}
{sensor: 6, value: 1, x: 122, y: 200}
{sensor: 7, value: 0.5, x: 30, y: 218}
{sensor: 8, value: 3.3, x: 140, y: 109}
{sensor: 9, value: 3.4, x: 105, y: 114}
{sensor: 10, value: 2.7, x: 78, y: 119}
{sensor: 11, value: 2.3, x: 51, y: 124}
{sensor: 12, value: 1.6, x: 22, y: 136}
{sensor: 13, value: 3.5, x: 121, y: 41}
{sensor: 14, value: 1.2, x: 85, y: 45}
{sensor: 15, value: 1, x: 50, y: 59}
]
Here is a hit map with 'populated' data (based on average value of closest points):
Just add the mask of the foot contour...
const data = [
{sensor: 0, value: 7.4, x: 108, y: 406},
{sensor: 1, value: 8.1, x: 68, y: 412},
{sensor: 2, value: 3.6, x: 108, y: 346},
{sensor: 3, value: 4.5, x: 61, y: 350},
{sensor: 4, value: 0.5, x: 108, y: 280},
{sensor: 5, value: 1, x: 49, y: 288},
{sensor: 6, value: 1, x: 122, y: 200},
{sensor: 7, value: 0.5, x: 30, y: 218},
{sensor: 8, value: 3.3, x: 140, y: 109},
{sensor: 9, value: 3.4, x: 105, y: 114},
{sensor: 10, value: 2.7, x: 78, y: 119},
{sensor: 11, value: 2.3, x: 51, y: 124},
{sensor: 12, value: 1.6, x: 22, y: 136},
{sensor: 13, value: 3.5, x: 121, y: 41},
{sensor: 14, value: 1.2, x: 85, y: 45},
{sensor: 15, value: 1, x: 50, y: 59},
];
const populateData = (points, width, height, step) => {
const populated = [];
for (let x = 0; x < width; x += step)
for (let y = 0; y < height; y += step) {
const distances = points.map(p =>
({...p, distance: Math.hypot(p.x - x, p.y - y)})).filter(d => d.distance < 100);
const sum = distances.reduce((s, d) => s + 1 / d.distance, 0);
const value = distances.reduce((a, d) => a + 1 / sum / d.distance * d.value, 0);
populated.push({x, y, value});
}
return populated;
};
const pd = populateData(data, 300, 500, 10);
const RECT_SIZE = 20;
const getColor = v => `rgb(255,${255 - v * 25},0)`
const svg = d3.select('svg');
pd.forEach(d => {
svg.append('rect')
.attr('x', d.x - RECT_SIZE / 2)
.attr('y', d.y - RECT_SIZE / 2)
.attr('width', RECT_SIZE / 2)
.attr('height', RECT_SIZE / 2)
.style('fill', getColor(d.value));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="500" />
Here is a simple plot with the data you provided:
If you have more points, it can be a more precise picture
const data = [
{sensor: 0, value: 7.4, x: 108, y: 406},
{sensor: 1, value: 8.1, x: 68, y: 412},
{sensor: 2, value: 3.6, x: 108, y: 346},
{sensor: 3, value: 4.5, x: 61, y: 350},
{sensor: 4, value: 0.5, x: 108, y: 280},
{sensor: 5, value: 1, x: 49, y: 288},
{sensor: 6, value: 1, x: 122, y: 200},
{sensor: 7, value: 0.5, x: 30, y: 218},
{sensor: 8, value: 3.3, x: 140, y: 109},
{sensor: 9, value: 3.4, x: 105, y: 114},
{sensor: 10, value: 2.7, x: 78, y: 119},
{sensor: 11, value: 2.3, x: 51, y: 124},
{sensor: 12, value: 1.6, x: 22, y: 136},
{sensor: 13, value: 3.5, x: 121, y: 41},
{sensor: 14, value: 1.2, x: 85, y: 45},
{sensor: 15, value: 1, x: 50, y: 59},
];
const RECT_SIZE = 20;
const getColor = v => `rgb(255,${255 - v * 25},0)`
const svg = d3.select('svg');
data.forEach(d => {
svg.append('rect')
.attr('x', d.x - RECT_SIZE / 2)
.attr('y', d.y - RECT_SIZE / 2)
.attr('width', RECT_SIZE / 2)
.attr('height', RECT_SIZE / 2)
.style('fill', getColor(d.value));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="300" height="500" />
I need to get normalized histogram.
So in Danfo notebooks I tried syntax like this:
s = new dfd.Series([1, 3, 2, 2, 2, 6, 10, 10, 34, 40, 51, 90, 90, 90, 90, 1, 3, 2, 2, 2, 6, 10, 10, 34, 40, 51, 90, 90, 90, 90, 1, 3, 2, 2, 2, 6, 10, 10, 34, 40, 51, 90, 90, 90, 90, 1, 3, 2, 2, 2, 6, 10, 10, 34, 40, 51, 90, 90, 90, 90, 1, 3, 2, 2, 2, 6, 10, 10, 34, 40, 51, 90, 90, 90, 90, 75])
s.plot(this_div()).hist({histnorm: 'probability', layout: {title: 'Normalized Histogram'}})
But it looks like danfo.js ignores Plotly histnorm trace attribute.
So the question is: Is it possible to use Plotly trace attributes with danfojs's plots, and if it's possible then what is correct syntax for that?
I'm working on a histogram like column chart with React-JSX-Highcharts. I have 6 categories, 10 data points for 5 categories, and 30 data points for the 6 and final category. I'm trying to achieve having the tick marks start at each category, but have the category label, be centered inbetween the tick marks. I was able to achieve this by setting x-axis labels x: 150, however, I learned that is not responsive.
Here is what i'm looking to achieve:
Curious to hear if I'm (A) taking the wrong approach, (B) Using the wrong series type (I tried histogram, but my bins are by category so the results were stacked columns), or (C) if i'm close and if anyone can find a solution to responsively center the labels.
Highcharts.chart('container', {
chart: {
type: 'column'
},
xAxis: {
categories: [
"VERY LOW",
"LOW",
"MEDIUM",
"HIGH",
"VERY HIGH",
"EXTREMELY HIGH"
],
tickInterval: 10,
startOnTick: true,
tickMarkPlacement: 'between',
type: 'category',
endOnTick: false,
showTempty: true,
},
series: [{
data: [
{x: 0, name: 'VERY LOW', y: 0.2},
{x: 1, name: 'VERY LOW', y: 0.2},
{x: 2, name: 'VERY LOW', y: 0.8},
{x: 3, name: 'VERY LOW', y: 1},
{x: 4, name: 'VERY LOW', y: 1.1},
{x: 5, name: 'VERY LOW', y: 1.1},
{x: 6, name: 'VERY LOW', y: 1.3},
{x: 7, name: 'VERY LOW', y: 1.5},
{x: 8, name: 'VERY LOW', y: 2},
{x: 9, name: 'VERY LOW', y: 1.5},
{y: 2.1, x: 10, name: 'LOW'},
{y: 2.1, x: 11, name: 'LOW'},
{y: 2.4, x: 12, name: 'LOW'},
{y: 2.5, x: 13, name: 'LOW'},
{y: 2.1, x: 14, name: 'LOW'},
{y: 2.6, x: 15, name: 'LOW'},
{y: 2.0, x: 16, name: 'LOW'},
{y: 2.7, x: 17, name: 'LOW'},
{y: 2.9, x: 18, name: 'LOW'},
{y: 2.5, x: 19, name: 'LOW'},
{y: 2.5, x: 20, name: 'MEDIUM'},
{y: 3.3, x: 21, name: 'MEDIUM'},
{y: 3.0, x: 22, name: 'MEDIUM'},
{y: 2.9, x: 23, name: 'MEDIUM'},
{y: 2.8, x: 24, name: 'MEDIUM'},
{y: 2.6, x: 25, name: 'MEDIUM'},
{y: 2.5, x: 26, name: 'MEDIUM'},
{y: 2.1, x: 27, name: 'MEDIUM'},
{y: 2.2, x: 28, name: 'MEDIUM'},
{y: 2.2, x: 29, name: 'MEDIUM'},
{y: 2.2, x: 29, name: 'MEDIUM'},
{y: 2.0, x: 30, name: 'HIGH' },
{y: 2.0, x: 31, name: 'HIGH' },
{y: 1.5, x: 32, name: 'HIGH' },
{y: 1.3, x: 33, name: 'HIGH' },
{y: 1.2, x: 34, name: 'HIGH' },
{y: 1.1, x: 35, name: 'HIGH' },
{y: 1.1, x: 36, name: 'HIGH' },
{y: 1.0, x: 37, name: 'HIGH' },
{y: 0.9, x: 38, name: 'HIGH' },
{y: 0.7, x: 39, name: 'HIGH' },
{y: 3.1, x: 40, name: 'VERY HIGH'},
{y: 0.3, x: 41, name: "VERY HIGH"},
{y: 0.3, x: 42, name: "VERY HIGH"},
{y: 0.1, x: 43, name: "VERY HIGH"},
{y: 0.1, x: 44, name: "VERY HIGH"},
{y: 0.1, x: 45, name: "VERY HIGH"},
{y: 0, x: 46, name: "VERY HIGH"},
{y: 0, x: 47, name: "VERY HIGH"},
{y: 0, x: 48, name: "VERY HIGH"},
{y: 0, x: 49, name: "VERY HIGH"},
{y: 0.3, x: 50, name: "EXTREMELY HIGH"},
{y: 0.3, x: 51, name: "EXTREMELY HIGH"},
{y: 0.3, x: 52, name: "EXTREMELY HIGH"},
{y: 0.1, x: 53, name: "EXTREMELY HIGH"},
{y: 0.1, x: 54, name: "EXTREMELY HIGH"},
{y: 0.1, x: 55, name: "EXTREMELY HIGH"},
{y: 0, x: 56, name: "EXTREMELY HIGH"},
{y: 0, x: 57, name: "EXTREMELY HIGH"},
{y: 0, x: 58, name: "EXTREMELY HIGH"},
{y: 0, x: 59, name: "EXTREMELY HIGH"},
{y: 0, x: 60, name: "EXTREMELY HIGH"},
{y: 0, x: 61, name: "EXTREMELY HIGH"},
{y: 0, x: 62, name: "EXTREMELY HIGH"},
{y: 0, x: 63, name: "EXTREMELY HIGH"},
{y: 0, x: 64, name: "EXTREMELY HIGH"},
{y: 0, x: 65, name: "EXTREMELY HIGH"},
{y: 0, x: 66, name: "EXTREMELY HIGH"},
{y: 0, x: 67, name: "EXTREMELY HIGH"},
{y: 0, x: 68, name: "EXTREMELY HIGH"},
{y: 0, x: 69, name: "EXTREMELY HIGH"},
]
}]
});
JSFiddle
One way to do this in a responsive manner by using jQuery resize events to detect when the size of the chart has changed, and update dynamically after that (don't forget to include jQuery if you use this solution). Like this:
$(window).resize(function() {
setTimeout(function() {
chart.update({
xAxis: {
labels: {
x: chart.xAxis[0].len / (chart.xAxis[0].tickPositions.length * 2)
}
}
}, true)
}, 100)
});
I am using the same xAxis.labels.x value as you did, but I am calculating it dynamically.
chart.xAxis[0].len - is the length of the xAxis in pixels.
(chart.xAxis[0].tickPositions.length * 2) is the number of ticks on the xAxis, times 2 because we want to be in the center between two ticks, not at the tick marker.
setTimeout is used because if we update the page right as the user is resizing, the position will not be correct. So we wait 0.1 seconds and then update instead.
In addition to that, on the first render of the page, there is no resize event. So to take care of the resizing then, I used the highchart load event like this:
chart: {
type: 'column',
events: {
load: function() {
this.update({
xAxis: {
labels: {
x: this.xAxis[0].len / (this.xAxis[0].tickPositions.length * 2)
}
}
}, true)
}
}
},
The same update function, using this instead of chart because chart is not fully initialized yet.
var chart = Highcharts.chart('container', {
chart: {
type: 'column',
events: {
load: function() {
//Position the labels for the initial rendering
this.update({
xAxis: {
labels: {
x: this.xAxis[0].len / (this.xAxis[0].tickPositions.length * 2)
}
}
}, true)
}
}
},
xAxis: {
categories: [
"VERY LOW",
"LOW",
"MEDIUM",
"HIGH",
"VERY HIGH",
"EXTREMELY HIGH"
],
labels: {
rotation: 0,
},
tickInterval: 10,
startOnTick: true,
tickMarkPlacement: 'between',
type: 'category',
endOnTick: false,
showTempty: true,
},
series: [{
data: [
{x: 0, name: 'VERY LOW', y: 0.2},
{x: 1, name: 'VERY LOW', y: 0.2},
{x: 2, name: 'VERY LOW', y: 0.8},
{x: 3, name: 'VERY LOW', y: 1},
{x: 4, name: 'VERY LOW', y: 1.1},
{x: 5, name: 'VERY LOW', y: 1.1},
{x: 6, name: 'VERY LOW', y: 1.3},
{x: 7, name: 'VERY LOW', y: 1.5},
{x: 8, name: 'VERY LOW', y: 2},
{x: 9, name: 'VERY LOW', y: 1.5},
{y: 2.1, x: 10, name: 'LOW'},
{y: 2.1, x: 11, name: 'LOW'},
{y: 2.4, x: 12, name: 'LOW'},
{y: 2.5, x: 13, name: 'LOW'},
{y: 2.1, x: 14, name: 'LOW'},
{y: 2.6, x: 15, name: 'LOW'},
{y: 2.0, x: 16, name: 'LOW'},
{y: 2.7, x: 17, name: 'LOW'},
{y: 2.9, x: 18, name: 'LOW'},
{y: 2.5, x: 19, name: 'LOW'},
{y: 2.5, x: 20, name: 'MEDIUM'},
{y: 3.3, x: 21, name: 'MEDIUM'},
{y: 3.0, x: 22, name: 'MEDIUM'},
{y: 2.9, x: 23, name: 'MEDIUM'},
{y: 2.8, x: 24, name: 'MEDIUM'},
{y: 2.6, x: 25, name: 'MEDIUM'},
{y: 2.5, x: 26, name: 'MEDIUM'},
{y: 2.1, x: 27, name: 'MEDIUM'},
{y: 2.2, x: 28, name: 'MEDIUM'},
{y: 2.2, x: 29, name: 'MEDIUM'},
{y: 2.2, x: 29, name: 'MEDIUM'},
{y: 2.0, x: 30, name: 'HIGH' },
{y: 2.0, x: 31, name: 'HIGH' },
{y: 1.5, x: 32, name: 'HIGH' },
{y: 1.3, x: 33, name: 'HIGH' },
{y: 1.2, x: 34, name: 'HIGH' },
{y: 1.1, x: 35, name: 'HIGH' },
{y: 1.1, x: 36, name: 'HIGH' },
{y: 1.0, x: 37, name: 'HIGH' },
{y: 0.9, x: 38, name: 'HIGH' },
{y: 0.7, x: 39, name: 'HIGH' },
{y: 3.1, x: 40, name: 'VERY HIGH'},
{y: 0.3, x: 41, name: "VERY HIGH"},
{y: 0.3, x: 42, name: "VERY HIGH"},
{y: 0.1, x: 43, name: "VERY HIGH"},
{y: 0.1, x: 44, name: "VERY HIGH"},
{y: 0.1, x: 45, name: "VERY HIGH"},
{y: 0, x: 46, name: "VERY HIGH"},
{y: 0, x: 47, name: "VERY HIGH"},
{y: 0, x: 48, name: "VERY HIGH"},
{y: 0, x: 49, name: "VERY HIGH"},
{y: 0.3, x: 50, name: "EXTREMELY HIGH"},
{y: 0.3, x: 51, name: "EXTREMELY HIGH"},
{y: 0.3, x: 52, name: "EXTREMELY HIGH"},
{y: 0.1, x: 53, name: "EXTREMELY HIGH"},
{y: 0.1, x: 54, name: "EXTREMELY HIGH"},
{y: 0.1, x: 55, name: "EXTREMELY HIGH"},
{y: 0, x: 56, name: "EXTREMELY HIGH"},
{y: 0, x: 57, name: "EXTREMELY HIGH"},
{y: 0, x: 58, name: "EXTREMELY HIGH"},
{y: 0, x: 59, name: "EXTREMELY HIGH"},
{y: 0, x: 60, name: "EXTREMELY HIGH"},
{y: 0, x: 61, name: "EXTREMELY HIGH"},
{y: 0, x: 62, name: "EXTREMELY HIGH"},
{y: 0, x: 63, name: "EXTREMELY HIGH"},
{y: 0, x: 64, name: "EXTREMELY HIGH"},
{y: 0, x: 65, name: "EXTREMELY HIGH"},
{y: 0, x: 66, name: "EXTREMELY HIGH"},
{y: 0, x: 67, name: "EXTREMELY HIGH"},
{y: 0, x: 68, name: "EXTREMELY HIGH"},
{y: 0, x: 69, name: "EXTREMELY HIGH"},
]
}]
});
$(window).resize(function() {
setTimeout(function() {
chart.update({
xAxis: {
labels: {
x: chart.xAxis[0].len / (chart.xAxis[0].tickPositions.length * 2)
}
}
}, true)
}, 100)
});
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<div id="container" style="height: 400px"></div>
Working JSFiddle example: https://jsfiddle.net/ewolden/nLcveqp9/29/