AmMaps - heatmap for images instead of areas - javascript

AmMaps has cool and easy feature to create heatmap for areas:
https://www.amcharts.com/demos/us-heat-map/
Is it possible to use it also for points (images) - to calculate image color basing on value, colorSteps etc.?

Technically, heat map features are not applied to images. However, it's pretty easy to apply the same principle using a very basic plugin:
AmCharts.addInitHandler(function(map) {
// check if `colorSolid` is set for `imagesSettings`
if (map.imagesSettings.colorSolid === undefined)
return;
// calculate minimum and maximum value
var minValue,
maxValue;
if (map.minValue === undefined || map.maxValue === undefined) {
for (var i = 0; i < map.dataProvider.images.length; i++) {
var image = map.dataProvider.images[i];
if (image.value !== undefined) {
if (minValue === undefined || (image.value < minValue))
minValue = image.value;
if (maxValue === undefined || (image.value > maxValue))
maxValue = image.value;
}
}
}
// use map overrides if set
if (map.minValue !== undefined)
minValue = map.minValue;
if (map.maxValue !== undefined)
maxValue = map.maxValue;
// set colors for each area
for (var i = 0; i < map.dataProvider.images.length; i++) {
var image = map.dataProvider.images[i];
if (image.color === undefined && image.value !== undefined) {
// we set colors for those images that don't have color set explicitly
var percent = (image.value - minValue) / (maxValue - minValue);
image.color = AmCharts.getColorFade(
map.imagesSettings.color,
map.imagesSettings.colorSolid,
percent);
}
}
}, ["map"]);
Add it somewhere before the map code. Also make sure both color and colorSolid is set in imagesSettings.
Here's a complete working example.

Related

Method within an object is changing values from another object

Depth-first search code that is used for enemy objects in order to path finds to the player. It is changing the values of maze1.maze whilst iterating around the loop, I believe instead of this.CurrentMaze. Do I need to post all the code to the full game for you to figure this out?
called using - let path = e.DPS() then the enemy uses path to move towards the player. maze1 is an object with a maze array inside it.
Does anyone know why this is happening???
DPS() {
this.playerpos = [0,0]
this.enemypos = [0,0]
this.CurrentMaze = [0][0]
this.playerpos[0] = Math.round(p.y / size)
this.playerpos[1] = Math.round(p.x / size)
this.enemypos[0] = Math.round(this.y / size)
this.enemypos[1] = Math.round(this.x / size)
this.CurrentMaze = pickMaze(mazecounter);
this.CurrentMaze = swap(pickMaze(mazecounter) , cells);
let queue = [];
this.CurrentMaze[this.enemypos[0]][this.enemypos[1]] = 1;
queue.push([this.enemypos]); // store a path, not just a position
while (queue.length > 0) {
console.table(maze1.maze);
var path = queue.shift(); // get the path out of the queue
var pos = path[path.length-1]; // ... and then the last position from it
var direction = [
[pos[0] + 1, pos[1]],
[pos[0], pos[1] + 1],
[pos[0] - 1, pos[1]],
[pos[0], pos[1] - 1]
];
for (var i = 0; i < direction.length; i++) {
// Perform this check first:
if (direction[i][0] === this.playerpos[0] && direction[i][1] === this.playerpos[1]) {
// return the path that led to the find
return path.concat([this.playerpos]);
}
if (direction[i][0] < 0 || direction[i][0] >= this.CurrentMaze.length
|| direction[i][1] < 0 || direction[i][1] >= this.CurrentMaze[0].length
|| this.CurrentMaze[direction[i][0]][direction[i][1]] !== 0) {
continue;
}
this.CurrentMaze[direction[i][0]][direction[i][1]] = 1;
// extend and push the path on the queue
queue.push(path.concat([direction[i]]));
}
}
}

set variable by using localstorage

i am trying to create the driver performance assistant.
when i start up the page it needs to read the variable from the last time and use that to count up.
(i have created a dashboard that reads data through a plugin from a game. i am trying to create the driver performance assistant from DAF (truck brand). the way it should work is when rolling out the vehicle it counts up a variable accordingly to the time it is rolling out (this part i have created and it works) now my problem is. i am also trying to save it in the localstorage so it wont get lost. but the variable is doing weird things when i tries to read the localstorage data.
this code only needs to be in javascript.
// variables for driver score
var startBrake = 0;
var endBrake = 0;
var timeDiffBrake = 0;
var countBrake = localStorage.getItem('brake');
var startRollout = 0;
var endRollout = 0;
var timeDiffRollout = 0;
var countRollout = localStorage.getItem('rollout');
var speed = Math.abs(data.truck.speed > 0 ? Math.floor(data.truck.speed) : Math.round(data.truck.speed));
var throttle = utils.formatFloat(data.truck.gameThrottle, 2);
var serviceBrake = utils.formatFloat(data.truck.userBrake, 2);
var retarder = data.truck.retarderBrake;
var engineBrake = data.truck.motorBrakeOn;
var cruiseControl = data.truck.cruiseControlOn;
var fuelConsumption = data.truck.fuelAverageConsumption * 100;
// ANTICIPATE
// Braking to long
if (speed >= 50) {
if (serviceBrake < 0.1) {
startBrake = new Date();
} else if (serviceBrake > 0.25) {
endBrake = new Date();
timeDiffBrake = (endBrake - startBrake) / 1000;
if (timeDiffBrake > 5) {
countBrake -= 0.01;
// add "te lang remmen" display
}
}
}
localStorage.setItem('brake', countBrake);
// Rolling out
if (speed > 30 && speed < 89) {
if (throttle > 0) {
startRollout = new Date();
} else if (throttle < 0.05 && serviceBrake == 0) {
endRollout = new Date();
timeDiffRollout = (endRollout - startRollout) / 1000;
if (timeDiffRollout > 1) {
countRollout += 0.01;
// maybe add display
}
}
}
localStorage.setItem('rollout', countRollout);
// EFFICIENT BRAKING
var brake = localStorage.getItem('brake');
var rollout = localStorage.getItem('rollout');
var anticipate = brake + rollout;
var efficientBraking = 0; // haven't done this yet
var driverScore = Math.round((efficientBraking + anticipate) / 2);
data.drivingScorePercent = driverScore <= 0 ? 0 : driverScore >= 100 ? 100 : driverScore;
the main problem is this variable
var countRollout = localStorage.getItem('rollout');
it keeps saying my data is NAN (i think undefined)
i changed the lines to what "mister jojo" suggested but somehow i get some wierd data from the localstorage. i assumed that a "var += 0.01" would count 0.01 up but somehow it goes like this "0.010.010.010.010.01" instead of 0.01, 0.02, 0.03.
When you are declaring the countBrake and countRollout variables, the value are undefined because you didn't set the values to localStorage yet. So, you can check whether there is already a value set in localStorage and set default value incase the value isn't set yet:
var countBrake = localStorage.getItem('brake') !== undefined ? localStorage.getItem('brake') : 0;
var countRollout = localStorage.getItem('rollout') !== undefined localStorage.getItem('rollout') : 0;
more simple for Shuvo answer is
with the use of the Nullish coalescing operator (??)
var countBrake = localStorage.getItem('brake') ?? 0
, countRollout = localStorage.getItem('rollout') ?? 0
;

I want to generate random number in method once which are not same with previous one

I have to change background image in method. Background images are coming from this.items service but when method runs new background image shouldn't be same with previous one.
When I run this method it changes images but new image can be same with previous one. How can I do?
export class GridManager {
changeBackground() {
var x = Math.floor(Math.random() * document.querySelectorAll(".grid-item").length);
if (this.items[x].backgroundImage != "" && this.items[x].backgroundImage != null) {
document.querySelector(".container").style.backgroundImage = `url('${this.items[x].backgroundImage}')`;
}
}
}
You need to check if the value is in the array, if exist remove it or do whatever you need to do
function checkItem(array,checkItem){
for( var i=0;i<array.length;i++){
if(array[i] == checkItem){
var removedItem= array.splice(checkItem,1); // your can remove it
/*or simply do your code here */
}
}
}
There's a lot of solutions, to give you another one not mentioned here, you can do a custom generate random number that excludes the previous index that you got.
something like:
class GridManager {
prevIndex = null;
generateRandom(min, max, excludedIndex) {
var num = Math.floor(Math.random() * (max - min + 1)) + min;
return (num === excludedIndex) ? this.generateRandom(min, max, excludedIndex) : num;
}
changeBackground() {
var x = this.generateRandom(0, document.querySelectorAll(".grid-item").length - 1, this.prevIndex);
this.prevIndex = x;
if (this.items[x].backgroundImage != "" && this.items[x].backgroundImage != null) {
document.querySelector(".container").style.backgroundImage = `url('${this.items[x].backgroundImage}')`;
}
}
}

Cycling through Javascript Array

I have a javascript array, mediaSizes as follows: ['xs','md','lg'].
I'm using a variable media to refer to the specific index in the array. So media can either be 0, 1, or 2. So mediaSizes[media] should either output xs, md, or lg.
I have up and down arrows for user to cycle through this array. However, when the user clicks the up arrow, and the media value is 2, I want the user to cycle back down to xs. Similarly, if the user presses the down arrow on xs I want them to cycle through to large.
I have the following if else statement, but it doesn't seem to be working:
var mediaSizes = ['xs','md','lg'];
var media = 0;
$scope.mediaDisplay = mediaSizes[media];
$scope.changeMedia = function(direction) {
if (media > 2 || media < 0) {
media = 0;
} else {
if (direction == 'up') {
media ++;
$scope.mediaDisplay = mediaSizes[media];
} else {
media --;
$scope.mediaDisplay = mediaSizes[media];
}
}
}
Right now, I settled for setting the media value to 0 for the sake of getting it to work. There has to be an easier way to cycle through 0, 1, 2...
The usual trick for incrementing a value that you want to wrap around is to use the % operator. For decrementing, you just have to brute force it and check for negative values:
var mediaSizes = ['xs','md','lg'];
var media = 0;
$scope.mediaDisplay = mediaSizes[media];
var changeMedia = function(direction) {
if (direction === 'up') {
media = ++media % mediaSizes.length;
} else {
if (--media < 0) media += mediaSizes.length;
}
$scope.mediaDisplay = mediaSizes[media];
}
The % operator is handy when incrementing because it will guarentee a value between 0 and operand - 1. So media % mediaSizes.length will always be a legal index of the array and it will work for wrapping around as you increment media.
Unfortunately, the % operator doesn't do what you want for negative numbers so if we find a negative number, we have to do something different. In this case, I just chose to add mediaSizes.length which will cause -1 to wrap around to the last index.
FYI, note I'm using mediaSizes.length rather than any hard-coded constants so this code would continue to work flawlessly even if you added more mediaSizes to the array. This is one of the principles of more robust code that automatically handles changes elsewhere.
For code cleanliness, this might be a nice place to capture some variables in a closure to keep them out of the global scope:
var changeMedia = (function() {
var mediaSizes = ['xs','md','lg'];
var media = 0;
$scope.mediaDisplay = mediaSizes[media];
return function(direction) {
if (direction === 'up') {
media = ++media % mediaSizes.length;
} else {
if (--media < 0) media += mediaSizes.length;
}
$scope.mediaDisplay = mediaSizes[media];
}
})();
How about:
if (direction == 'up') {
media ++;
if(media > 2){
media = 0;
}
var mediaDisplay = mediaSizes[media];
} else {
media --;
if(media < 0){
media = 2;
}
var mediaDisplay = mediaSizes[media];
}
Your code is incorrect in several ways.
It does not cycle down
You must chance mediaDisplay property of scope, not some global mediaDisplay object. UPD: already fixed
Incorrect incrementation and decrementation. For example if current media == 2 and user are making up direction, then you are incrementing that value (media++) and then trying to get mediaSizes[3] which does not exist of course.
Use this code instead:
var mediaSizes = ['xs','md','lg'];
var media = 0;
$scope.mediaDisplay = mediaSizes[media];
var changeMedia = function(direction) {
switch (direction) {
case 'up':
media = media === 2 ? 0 : media+1;
break;
case 'down':
media = media === 0 ? 2 : media-1;
break;
}
$scope.mediaDisplay = mediaSizes[media];
};
UPD
What about media = media === 2 ? 0 : media+1 - here we use ternary opertator.
First check if media === 2.
If true - ternary operator return 0 (we must set media to zero, as there is no media with index == 3)
If false - ternary operator return media+1 value.
Almost the same logic for decrementation, but in that case we check on media === 0 instead of media === 2.

multiple if statements in javascript not acting as they should

I'm creating a random image generator that displays images when a button is clicked. I'm trying to prevent the same image being displayed twice in a row by having the random number connected to each image increase by 1 if duplicated (in other words the next image will be shown rather than the same image twice). I'm trying to use if statements to achieve this but there seems to be a glitch in my code as the same image is still being displayed more than once. Not sure where the problem is. Any solutions out there ?
Thanks
document.getElementById('ranImgBtn').onclick = function() {
var ranImgDis = document.getElementById('ranImgDis');
ranImgDis.style.width = '300px';
ranImgDis.style.height = '200px';
var pic1 = href="http://farm4.staticflickr.com/3691/11268502654_f28f05966c_m.jpg";
var pic2 = href="http://farm1.staticflickr.com/33/45336904_1aef569b30_n.jpg";
var pic3 = href="http://farm6.staticflickr.com/5211/5384592886_80a512e2c9.jpg";
var num = Math.floor(Math.random() * (3 - 1 +1)) + 1;
if(num !== 2 && num !== 3) {
if(ranImgDis.src !== pic1) {
ranImgDis.src = pic1;
} ranImgDis.src = pic2;
} else if (num !== 1 && num !== 3) {
if(ranImgDis.src !== pic2) {
ranImgDis.src = pic2;
} ranImgDis.src = pic3;
} else if (num !== 1 && num !== 2) {
if(ranImgDis.src !== pic3) {
ranImgDis.src = pic3;
} ranImgDis.src = pic1;
}
}
You are missing an else in all your inner if statements. The result is that even if the code in the if statement is executed, the code after it is always executed and replaces what the code inside the if statement did.
You code like this:
if(ranImgDis.src !== pic1) {
ranImgDis.src = pic1;
} ranImgDis.src = pic2;
should be:
if(ranImgDis.src !== pic1) {
ranImgDis.src = pic1;
} else {
ranImgDis.src = pic2;
}
You can make the code simpler and more flexible by putting the images in an array, and keep the index of the current image rather than checking the source of the image. You can use the length of the array when you create the random number, then you can just add more images to the array without changing anything else in the code.
var pics = [
"http://farm4.staticflickr.com/3691/11268502654_f28f05966c_m.jpg".
"http://farm1.staticflickr.com/33/45336904_1aef569b30_n.jpg",
"http://farm6.staticflickr.com/5211/5384592886_80a512e2c9.jpg"
];
var current = 0;
document.getElementById('ranImgBtn').onclick = function() {
var ranImgDis = document.getElementById('ranImgDis');
ranImgDis.style.width = '300px';
ranImgDis.style.height = '200px';
// get a random number within a range one less than the number of images
var num = Math.floor(Math.random() * (pics.length - 1)) + 1;
// use the random number to pick a different image from the current one
current = (current + num) % pics.length;
ranImgDis.src = pics[current];
}
This'll work, and let you expand the number of images beyond three.
document.getElementById('ranImgBtn').onclick = function() {
var ranImgDis = document.getElementById('ranImgDis');
ranImgDis.style.width = '300px';
ranImgDis.style.height = '200px';
var pics = [
"http://farm4.staticflickr.com/3691/11268502654_f28f05966c_m.jpg",
"http://farm1.staticflickr.com/33/45336904_1aef569b30_n.jpg",
"http://farm6.staticflickr.com/5211/5384592886_80a512e2c9.jpg"
]
var currentSrc = document.getElementById('ranImgDis').src
var newSrc = currentSrc
while (newSrc == currentSrc) {
newSrc = pics[Math.floor( Math.random() * pics.length )]
}
ranImgDis.src = newSrc
}
JSFiddle of it at http://jsfiddle.net/X7HM2/
Why dont you change the logic abit.
Rename the images to numbers from 1 to 3 .
Than generate the random number between 1 to 3 and if that random number is same as currently loaded image regenerate the number , this logic will help you even when you will add images from 3 to finite limit.
Your logic is a bit messy, and also there are some obvious problems like:
if(ranImgDis.src !== pic1) {
ranImgDis.src = pic1;
} ranImgDis.src = pic2;
This will unconditionally set ranImgDis.src to pic2 at the end of the day. So maybe you should think this over. I suggest you to maintain an array instead to avoid dupes.

Categories

Resources