nswamy14 / visual-heatmap

Heatmap : Open source javascript module for high performance, large scale heatmap rendering.
BSD 3-Clause "New" or "Revised" License
55 stars 10 forks source link

setGradient implementation #22

Closed bartbutenaers closed 8 months ago

bartbutenaers commented 8 months ago

Hi @nswamy14,

I noticed that there was no setGradient method yet, to set dynamically a color gradient. By adding it, I can now dynamically chaning the gradient. You can see this example where I inject a message via Node-RED, containing a new gradient in its payload:

dynamic_gradient

Thanks for reviewing! Bart

nswamy14 commented 8 months ago

@bartbutenaers Thanks for the PR. I will add some validations around these config methods and publish the build.

bartbutenaers commented 8 months ago

@bartbutenaers,

Ah yes, good idea. I had not added that in this pull request, because I do validation already in my application.

However - unlike your rgba input - my application has opacity as a separate property (which is later on merged into the rgba values:

image

So my validations look a bit different, but I will share them here for reference:

        function isSortedAscending(arr) {
            for (let i = 0; i < arr.length - 1; i++) {
                if (arr[i + 1].offset - arr[i].offset < 0) {
                    return false;
                }
            }
            return true;
        }

        function hasDuplicates(arr) {
            let uniqueObjects = new Set();
            for (const obj of arr) {
               let identifier = `${obj.opacity}-${obj.offset}-${obj.color}`;
               if (uniqueObjects.has(identifier)) {
                   return true; // Found a duplicate
               }
               uniqueObjects.add(identifier);
            }
            return false; // No duplicates found
        }

        // Validate the options to (choose and) show configuration error if any.
        // Any changes for options (adds new or changes any value), calls validation.
        function validateColorGradient(colorGradient){
            // When no input parameter, copy all the options from the editableList to this a temporary object
            if(!colorGradient) {
                colorGradient = []

            if (hasDuplicates(colorGradient)) {
                return false
            }
            else if(colorGradient.length < 2){
                // Configure at least two lines
                return false
            }
            else if(!isSortedAscending(colorGradient)) {
                // The offset values should be ascending
                return false
            }
            else if(colorGradient[0].offset != 0){
                // The first offset should be 0
                return false
            }
            // A float is 1.0 when the remainder of a division by 1 is 0
            else if(colorGradient[colorGradient.length - 1].offset % 1 !== 0){
                // The last offset should be 1.0
                return false
            }
            else if(!colorGradient.every(obj => { return obj.opacity >= 0.0 && obj.opacity <= 1.0 })) {
                // All opacity values should be between 0.0 and 1.0
                return false
            }
            else {
                // Valid color gradient
                return true
            }
        }

After you have added your validations, I will update mine too if required. Because I would like my frontend validations to be at least as severe as yours...

Thanks again!!! Bart

nswamy14 commented 8 months ago

@bartbutenaers , Thanks for sharing.

nswamy14 commented 8 months ago

Hi @bartbutenaers , I am planning to release a 2.x version with the following improvements:

I have committed the changes to the branch -v2_branch. Will be updating the documentation accordingly.

sample example: heatmapInstance.setMin(10).setMax(100).render()