Mapbox gl js interpolate marker text-offset pitch - mapbox

How can I interpolate the text-offset of a marker depending on pitch?
Interpolation is perfectly working for:
'text-size': ['interpolate', ['linear'], ['zoom'], 10, 10, 18, 20],
but for text-offset it is not working.
'text-offset': ['interpolate', ['linear'], ['pitch'], 10, [0.2, 0], 18, [2, 0]],
What am I doing wrong?
'layout': {
'text-field': ['get', 'name'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-size': ['interpolate', ['linear'], ['zoom'], 10, 10, 18, 20],
'text-rotate': -90,
//'text-offset': [2, 0],
'text-offset': ['interpolate', ['linear'], ['pitch'], 10, [0.2, 0], 18, [2, 0]],
'text-anchor': 'left',
'text-allow-overlap': true
},
paint: {
"text-color": "rgba(0, 100, 50, 0.9)",
}

The only allowed camera expression is zoom, and so you need to set this text-offset value after each movement like below:
const map = new mapboxgl.Map({});
map.on('pitch', () => {
console.log('A pitch event occurred.');
map.setLayoutProperty(layerId, 'text-offset', newValue)
// More about setLayoutProperty https://docs.mapbox.com/mapbox-gl-js/api/map/#map#setlayoutproperty
});
If you see performance issues, you may want to change map.on('pitch') to map.on('moveend') and compare map.getPitch() to previous pitch value to evaluate if you should change the text-offset value. More about each API below:
Map.getPitch
Map.event:moveend
Map.event:pitch

Related

Chart.js 3.7.1 - How can I control the number of ticks on the y axis of a line chart?

The data will always be integers between -10 and 10, including 0 so there could be a maximum of 21 'intervals' on the y axis.
Regardless of the data, I need the y axis to display from -10 to 10 (including 0) in increments of 1. So I need a total of 21 (ticks?) on the y axis regardless of the data.
I tried this, per the docs:
I also tried it without the steps param:
options: {
scales: {
y: {
max: -10,
min: 10,
ticks: {
steps: 21,
stepSize: 1
}
}
}
}
This is what I got:
The missing part in your code is autoSkip: false.
y: {
max: 10,
min: -10,
ticks: {
stepSize: 1,
autoSkip: false
}
}
According to the Chart.js documentation, autoskip is true by default.
autoskip: If true, automatically calculates how many labels can be shown and hides labels accordingly. (...) Turn autoSkip off to show all labels no matter what.
Please take a look at below runnable code and see how it works.
new Chart('canvas', {
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D', 'E', 'F'],
datasets: [{
label: 'Dataset 1',
data: [3, 9, 7, 5, 9, 2],
backgroundColor: 'rgba(255, 99, 132, 0.2)',
borderColor: 'rgb(255, 99, 132)',
fill: false
},
{
label: 'Dataset 2',
data: [1, 2, -3, -5, -2, 1],
backgroundColor: 'rgba(255, 159, 64, 0.2)',
borderColor: 'rgb(255, 159, 64)'
}
]
},
options: {
scales: {
y: {
max: 10,
min: -10,
ticks: {
stepSize: 1,
autoSkip: false
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
<canvas id="canvas"></canvas>

Equalizer like histogram in highcharts

How can I make equalizer like histogram in highcharts as shown in this figure-
There is a similar solution to this here- https://www.highcharts.com/forum/viewtopic.php?t=38013 but it doesn't completely fits in my case.
In the solution, If I'm trying to create histogram by providing these options but then stacks are getting vanished.
column: {
pointPadding: 0,
borderWidth: 0,
groupPadding: 0,
shadow: false,
},
I think that your chart is closer to heatmap. You can use colsize and rowsize properties and null points to show the grey part of the columns.
series: [{
type: 'heatmap',
colsize: 0.9,
rowsize: 0.7,
data: [
[0, 0, 10],
[0, 1, 19],
[0, 2, null],
[0, 3, null],
...
]
}]
Live demo: https://jsfiddle.net/BlackLabel/dxw3jne2/
API Reference:
https://api.highcharts.com/highcharts/series.heatmap.colsize
https://api.highcharts.com/highcharts/series.heatmap.rowsize

Google Charts dashboard: Baseline not automatically adjusted in a Bubble Chart for bottom 40% of values

I'm just starting my adventure with Google Charts and I have a requirement to visualize over 100 points of data in a bubble chart. This naturally makes the chart harder to read, so I did some research and realized I can make the exploration of the data easier by adding filtering options (which are possible when charts are created as dashboards).
I discovered a behavior that I'm not able to fix:
Imagine the values in one attribute can range from 0 to 100
The displayed data points can be filtered using a dashboard control of the NumberRangeFilter type which has a minimal value of 0 and maximal value of 100 (asigned automatically)
When the minimal value is smaller or equal 40, the baseline stays at 0
When the minimal value is greater than or equal 41, the baseline is dynamically adjusted to reflect the minimal value found in that range (for example if the selected range is 51-100, then the baseline will be displayed starting from 60)
The problem in visual form:
The only fix that comes to mind would be to force the vAxis.baseline attribute of the options object as automatic, but that's supposedly the default value and according to the documentation this only accepts numbers.
Does anyone know how I could force the chart to be updated even for the slightest changes with the control in the dashboard?
Full code for reference:
google.charts.load('current', {
'packages': ['corechart', 'controls']
});
google.charts.setOnLoadCallback(drawDashboard);
function drawDashboard() {
// Create our data table.
var data = google.visualization.arrayToDataTable([
['Name', 'X', 'Y', 'T', 'S'],
['A', 0, 0, "-", 3],
['B', 20, 20, "-", 2],
['C', 30, 30, "-", 1],
['D', 40, 40, "-", 1],
['E', 50, 50, "-", 2],
['F', 41, 60, "-", 1],
['G', 80, 50, "-", 2],
['H', 50, 80, "-", 2],
['I', 90, 90, "-", 2],
['J', 100, 100, "-", 4],
['K', 50, 70, "-", 1],
['L', 70, 50, "-", 1],
['M', 10, 50, "-", 2],
['N', 50, 10, "-", 2],
['X', 100, 50, "-", 2],
['Y', 50, 100, "-", 2]
]);
// Create a dashboard.
var dashboard = new google.visualization.Dashboard(
document.getElementById('dashboard_div'));
// Create a range slider, passing some options
var yAxisControl = new google.visualization.ControlWrapper({
'controlType': 'NumberRangeFilter',
'containerId': 'filter_div2',
'options': {
'filterColumnLabel': 'Y'
}
});
var bubbleChart = new google.visualization.ChartWrapper({
chartType: 'BubbleChart',
containerId: 'chart_div',
options: {
width: 300,
height: 350,
chartArea: {
left: 50,
top: 20,
width: 250,
height: 250
},
legend: 'right',
hAxis: {
title: 'X Axis'
},
vAxis: {
title: 'Y Axis'
},
}
});
dashboard.bind(yAxisControl, bubbleChart);
dashboard.draw(data);
}
.dash {
display: inline-block;
width: 320px;
text-align: right;
}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<div id="dashboard_div" class="dash">
<div id="filter_div2"></div>
<div id="chart_div"></div>
</div>

How to add space between lables and horizontal axis in google line chart

have add google chart with below options, I want spacing between labels at horizontal axis and actual axis, is there option available in chart library or any other way?
var options = { colors: ['#4ED8DA'], curveType: 'none', fontName: 'Montserrat', chartArea: {left: 40, top: 10, bottom: 30, width: '95%', height: '100%'}, legend: {position: 'none'}, pointSize: 5, lineWidth: 3, hAxis: {textPosition: 'out', minTextLines: '2', slantedText: false, baselineColor: '#D6D6D6', gridlines: {color: '#D6D6D6'}, textStyle: {color: '#383939', fontSize: '12', bold: true}}, vAxis: {baselineColor: '#D6D6D6', gridlines: {color: '#D6D6D6', interval: 1}, textStyle: {color: '#383939', fontSize: '12'}} };
there are no standard config options to create space between the x-axis labels and the axis.
however, you can manually move the labels on the chart's 'ready' event.
first, we find the x-axis labels, then increase the "y" attribute of the label.
the following example increases the distance from the axis by the value of the font size.
google.visualization.events.addListener(chart, 'ready', function () {
// get all chart labels
var labels = chart.getContainer().getElementsByTagName('text');
Array.prototype.forEach.call(labels, function (label) {
// determine if x-axis label
if (label.getAttribute('text-anchor') === 'middle') {
// increase distance from axis by the font size of the label
var fontSize = parseFloat(label.getAttribute('font-size'));
var yCoord = parseFloat(label.getAttribute('y'));
label.setAttribute('y', yCoord + fontSize);
}
});
});
note: depending on how far you move the labels,
you may need to increase the area at the bottom of the chart.
chartArea.bottom
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['x', 'y0'],
[0, 0],
[1, 0],
[2, 0],
[3, 1],
[4, 1],
[5, 2],
[6, 2],
[7, 3],
[8, 3],
[9, 3]
]);
var options = {
colors: ['#4ED8DA'],
curveType: 'none',
fontName: 'Montserrat',
chartArea: {left: 40, top: 10, bottom: 30, width: '95%', height: '100%'},
legend: {position: 'none'},
pointSize: 5,
lineWidth: 3,
hAxis: {textPosition: 'out', minTextLines: '2', slantedText: false, baselineColor: '#D6D6D6', gridlines: {color: '#D6D6D6'}, textStyle: {color: '#383939', fontSize: '12', bold: true}},
vAxis: {baselineColor: '#D6D6D6', gridlines: {color: '#D6D6D6', interval: 1}, textStyle: {color: '#383939', fontSize: '12'}}
};
var chart = new google.visualization.LineChart(document.getElementById('chart'));
google.visualization.events.addListener(chart, 'ready', function () {
var labels = chart.getContainer().getElementsByTagName('text');
Array.prototype.forEach.call(labels, function (label) {
if (label.getAttribute('text-anchor') === 'middle') {
var fontSize = parseFloat(label.getAttribute('font-size'));
var yCoord = parseFloat(label.getAttribute('y'));
label.setAttribute('y', yCoord + fontSize);
}
});
});
chart.draw(data, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>

How to show only the data points that have a change in Chartjs?

Show only the data points that have a change.
In order to reduce the clutter, I want to not show the circles when the prev value or next are the same. Still when you hover over them to show the label with information.
This is how I want it to look:
The second and third circles are the same, they must be hidden and only show on hover:
you can use the following options to style the points...
pointBackgroundColor, pointBorderColor, pointBorderWidth
but instead of providing a single value...
pointBackgroundColor: '#ffffff',
pointBorderColor: 'rgb(102, 187, 106)',
pointBorderWidth: 2,
you'll need to provide an array, with values for each point in the dataset,
then you can change the value for the points in question.
for the points you do not want to show, use color such as 'transparent'.
this will hide the point, but still show tooltip on hover.
pointBackgroundColor: ['#ffffff', '#ffffff', 'transparent', 'transparent', '#ffffff', '#ffffff'],
pointBorderColor: ['rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'transparent', 'transparent', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)'],
pointBorderWidth: [2, 2, 0, 0, 2, 2]
see following working snippet...
new Chart(document.getElementById('myChart').getContext('2d'), {
type: 'line',
data: {
labels: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
datasets: [{
backgroundColor: 'rgba(102, 187, 106, 0.2)',
borderColor: 'rgb(102, 187, 106)',
borderWidth: 2,
data: [5, 6, 6, 6, 6, 7, 6, 6, 5, 4],
label: 'y',
lineTension: 0,
pointBackgroundColor: ['#ffffff', '#ffffff', 'transparent', 'transparent', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff', '#ffffff'],
pointBorderColor: ['rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'transparent', 'transparent', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)', 'rgb(102, 187, 106)'],
pointBorderWidth: [2, 2, 0, 0, 2, 2, 2, 2, 2, 2]
}]
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>
A slightly different approach to WhiteHat's (ninja'd!) that iterates the series via .forEach to build the colour options:
Edit: Minor tweak to if to account for previous and next value in deciding point visibility and added hover colour settings to show hidden point on hover.
let labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
series = [10, 5, 5, 5, 5, 2, 3, 3, 3, 10],
pointBackgroundColor = [],
pointBorderColor = [],
pointHoverBackgroundColor = 'white',
pointHoverBorderColor = 'red';
series.forEach(
(value, index) => {
if (value == series[index - 1] && value == series[index + 1]) {
pointBackgroundColor.push('transparent');
pointBorderColor.push('transparent');
} else {
pointBackgroundColor.push('white');
pointBorderColor.push('red');
}
});
myChart = new Chart(document.getElementById('chart'), {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'series1',
data: series,
pointBackgroundColor: pointBackgroundColor,
pointBorderColor: pointBorderColor,
pointHoverBackgroundColor: pointHoverBackgroundColor,
pointHoverBorderColor: pointHoverBorderColor
}]
},
options: {
maintainAspectRatio: false,
tooltips: {
mode: 'index',
intersect: false
},
hover: {
intersect: false
}
}
});
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="chart"></canvas>
WhiteHat solution is good but doesn't achieve the desired effect. When you hover over a hidden data point circle it should make the circle visible.
Here is how I did it
Step 1:
In the backend using PHP, I check if the prev and next point are different, and made a point radius 0.
$countPoints = count($points);
for ($i=1; $i < $countPoints-1; $i++) {
$prevVal = $chartChange[$i-1];
$nextVal = $chartChange[$i+1];
if($chartChange[$i] == $prevVal && $chartChange[$i] == $nextVal){
$points[$i] = 0;
}
}
Step 2 :
Add and pass the imploded array to the options object. Using [3,0,3,3] format
pointRadius: [{/literal}{$points}{literal}]
Edit:
Using only js
let labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
series = [10, 5, 5, 5, 5, 2, 3, 3, 3, 10],
pointRadius = [],
pointBackgroundColor = "rgb(230, 247, 238)",
pointBorderColor = "rgb(47, 186, 117)";
series.forEach(
(value, index) => {
if (value == series[index - 1] && value == series[index + 1]) {
pointRadius.push(0);
} else {
pointRadius.push(4);
}
});
myChart = new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'series1',
fill: 'start',
pointRadius: pointRadius,
data: series,
backgroundColor:pointBackgroundColor,
borderColor:pointBorderColor,
pointHoverRadius: 4,
pointBackgroundColor: pointBackgroundColor,
pointBorderColor: pointBorderColor,
}]
},
options: {
tooltips: {
// mode: 'index',
intersect: false
},
tooltips: {
mode: 'index',
axis: 'x',
intersect: false
},
hover: {
intersect: false
},
maintainAspectRatio: false
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script>
<canvas id="myChart"></canvas>