'All Histogram get same rgb colour

i am trying draw multiple histogram with different colour scale of rgb colour in loop but first histogram colour scale applied to all remain histograms. after change first histogram rgb range using handles update both histogram, but second histogram handle change wont affect on range code like follow

rgb color array

let colorsMap = [
    [165, 0, 38, 255],
    [166, 1, 38, 255],
    [168, 3, 38, 255],
    [170, 5, 38, 255],
    [172, 7, 38, 255],
    [174, 9, 38, 255],
    [176, 11, 38, 255],
    [178, 13, 38, 255],
    [180, 15, 38, 255],
    [182, 16, 38, 255],
    [184, 18, 38, 255],
    [186, 20, 38, 255],
    [188, 22, 38, 255],
    [190, 24, 38, 255],
    [192, 26, 38, 255],
    [194, 28, 38, 255],
    [196, 30, 38, 255],
    [198, 32, 38, 255],
    [200, 33, 38, 255],
    [202, 35, 38, 255],
    [204, 37, 38, 255],
    [206, 39, 38, 255],
    [208, 41, 38, 255],
    [210, 43, 38, 255],
    [212, 45, 38, 255],
    [214, 47, 38, 255],
    [215, 49, 39, 255],
    [216, 51, 40, 255],
    [217, 53, 41, 255],
    [218, 56, 42, 255],
    [220, 58, 43, 255],
    [221, 61, 45, 255],
    [222, 63, 46, 255],
    [223, 65, 47, 255],
    [224, 68, 48, 255],
    [225, 70, 49, 255],
    [226, 73, 50, 255],
    [228, 75, 51, 255],
    [229, 77, 52, 255],
    [230, 80, 53, 255],
    [231, 82, 54, 255],
    [232, 85, 56, 255],
    [233, 87, 57, 255],
    [234, 89, 58, 255],
    [236, 92, 59, 255],
    [237, 94, 60, 255],
    [238, 97, 61, 255],
    [239, 99, 62, 255],
    [240, 101, 63, 255],
    [241, 104, 64, 255],
    [242, 106, 65, 255],
    [244, 109, 67, 255],
    [244, 111, 68, 255],
    [244, 114, 69, 255],
    [245, 116, 70, 255],
    [245, 119, 71, 255],
    [245, 121, 72, 255],
    [246, 124, 74, 255],
    [246, 126, 75, 255],
    [246, 129, 76, 255],
    [247, 131, 77, 255],
    [247, 134, 78, 255],
    [247, 137, 79, 255],
    [248, 139, 81, 255],
    [248, 142, 82, 255],
    [248, 144, 83, 255],
    [249, 147, 84, 255],
    [249, 149, 85, 255],
    [250, 152, 86, 255],
    [250, 154, 88, 255],
    [250, 157, 89, 255],
    [251, 159, 90, 255],
    [251, 162, 91, 255],
    [251, 165, 92, 255],
    [252, 167, 94, 255],
    [252, 170, 95, 255],
    [252, 172, 96, 255],
    [253, 174, 97, 255],
    [253, 176, 99, 255],
    [253, 178, 101, 255],
    [253, 180, 102, 255],
    [253, 182, 104, 255],
    [253, 184, 106, 255],
    [253, 186, 107, 255],
    [253, 188, 109, 255],
    [253, 190, 110, 255],
    [253, 192, 112, 255],
    [253, 194, 114, 255],
    [253, 196, 115, 255],
    [253, 198, 117, 255],
    [253, 200, 119, 255],
    [253, 202, 120, 255],
    [253, 204, 122, 255],
    [253, 206, 124, 255],
    [253, 208, 125, 255],
    [253, 210, 127, 255],
    [253, 212, 129, 255],
    [253, 214, 130, 255],
    [253, 216, 132, 255],
    [253, 218, 134, 255],
    [253, 220, 135, 255],
    [253, 222, 137, 255],
    [254, 224, 139, 255],
    [254, 225, 141, 255],
    [254, 226, 143, 255],
    [254, 227, 145, 255],
    [254, 228, 147, 255],
    [254, 230, 149, 255],
    [254, 231, 151, 255],
    [254, 232, 153, 255],
    [254, 233, 155, 255],
    [254, 234, 157, 255],
    [254, 236, 159, 255],
    [254, 237, 161, 255],
    [254, 238, 163, 255],
    [254, 239, 165, 255],
    [254, 241, 167, 255],
    [254, 242, 169, 255],
    [254, 243, 171, 255],
    [254, 244, 173, 255],
    [254, 245, 175, 255],
    [254, 247, 177, 255],
    [254, 248, 179, 255],
    [254, 249, 181, 255],
    [254, 250, 183, 255],
    [254, 251, 185, 255],
    [254, 253, 187, 255],
    [254, 254, 189, 255],
    [254, 254, 189, 255],
    [252, 254, 187, 255],
    [251, 253, 185, 255],
    [249, 252, 183, 255],
    [248, 252, 181, 255],
    [246, 251, 179, 255],
    [245, 250, 177, 255],
    [243, 250, 175, 255],
    [242, 249, 173, 255],
    [240, 249, 171, 255],
    [239, 248, 169, 255],
    [237, 247, 167, 255],
    [236, 247, 165, 255],
    [234, 246, 163, 255],
    [233, 245, 161, 255],
    [231, 245, 159, 255],
    [230, 244, 157, 255],
    [228, 244, 155, 255],
    [227, 243, 153, 255],
    [225, 242, 151, 255],
    [224, 242, 149, 255],
    [222, 241, 147, 255],
    [221, 240, 145, 255],
    [219, 240, 143, 255],
    [218, 239, 141, 255],
    [217, 239, 139, 255],
    [215, 238, 137, 255],
    [213, 237, 136, 255],
    [211, 236, 135, 255],
    [209, 235, 133, 255],
    [207, 234, 132, 255],
    [205, 233, 131, 255],
    [203, 232, 129, 255],
    [201, 232, 128, 255],
    [199, 231, 127, 255],
    [197, 230, 126, 255],
    [195, 229, 124, 255],
    [193, 228, 123, 255],
    [191, 227, 122, 255],
    [189, 226, 120, 255],
    [187, 226, 119, 255],
    [185, 225, 118, 255],
    [183, 224, 117, 255],
    [181, 223, 115, 255],
    [179, 222, 114, 255],
    [177, 221, 113, 255],
    [175, 220, 111, 255],
    [173, 220, 110, 255],
    [171, 219, 109, 255],
    [169, 218, 107, 255],
    [167, 217, 106, 255],
    [164, 216, 105, 255],
    [162, 215, 105, 255],
    [159, 214, 105, 255],
    [157, 213, 105, 255],
    [154, 212, 104, 255],
    [152, 210, 104, 255],
    [149, 209, 104, 255],
    [147, 208, 103, 255],
    [144, 207, 103, 255],
    [142, 206, 103, 255],
    [139, 205, 103, 255],
    [137, 204, 102, 255],
    [134, 203, 102, 255],
    [132, 202, 102, 255],
    [129, 201, 102, 255],
    [127, 199, 101, 255],
    [124, 198, 101, 255],
    [122, 197, 101, 255],
    [119, 196, 100, 255],
    [117, 195, 100, 255],
    [114, 194, 100, 255],
    [112, 193, 100, 255],
    [109, 192, 99, 255],
    [107, 191, 99, 255],
    [104, 190, 99, 255],
    [102, 189, 99, 255],
    [99, 187, 98, 255],
    [96, 186, 97, 255],
    [93, 184, 96, 255],
    [90, 183, 96, 255],
    [87, 181, 95, 255],
    [84, 180, 94, 255],
    [81, 178, 93, 255],
    [78, 177, 93, 255],
    [75, 175, 92, 255],
    [72, 174, 91, 255],
    [69, 173, 90, 255],
    [66, 171, 90, 255],
    [63, 170, 89, 255],
    [60, 168, 88, 255],
    [57, 167, 87, 255],
    [54, 165, 87, 255],
    [51, 164, 86, 255],
    [48, 162, 85, 255],
    [45, 161, 84, 255],
    [42, 159, 84, 255],
    [39, 158, 83, 255],
    [36, 157, 82, 255],
    [33, 155, 81, 255],
    [30, 154, 81, 255],
    [27, 152, 80, 255],
    [25, 151, 79, 255],
    [24, 149, 78, 255],
    [23, 147, 77, 255],
    [22, 145, 76, 255],
    [21, 143, 75, 255],
    [20, 141, 74, 255],
    [19, 139, 73, 255],
    [18, 137, 72, 255],
    [17, 136, 71, 255],
    [16, 134, 70, 255],
    [15, 132, 69, 255],
    [14, 130, 68, 255],
    [13, 128, 67, 255],
    [12, 126, 66, 255],
    [11, 124, 65, 255],
    [10, 122, 64, 255],
    [9, 120, 63, 255],
    [8, 119, 62, 255],
    [7, 117, 61, 255],
    [6, 115, 60, 255],
    [5, 113, 59, 255],
    [4, 111, 58, 255],
    [3, 109, 57, 255],
    [2, 107, 56, 255],
    [1, 105, 55, 255],
    [0, 104, 55, 255]
];

histogram min-max array

let results: [
{
max: "0.586"
min: "-0.1429"
statistics:
1:histogram: (2) [Array(255), Array(256)]
max: 0.5862068965517241
min: -0.3333333333333333
percentiles: (2) [-0.14285714285714285, 0.044534412955465584]
std: 0.041693440775719376
valid_percent: 56.69100747804611
},
{
max: "-0.177"
min: "-0.333"
statistics:
1:histogram: (2) [Array(255), Array(256)]
max: 0.5862068965517241
min: -0.3333333333333333
percentiles: (2) [-0.14285714285714285, 0.044534412955465584]
std: 0.041693440775719376
valid_percent: 56.69100747804611
},
]

passing to histogram component like

results.map((result) =>{
return (
<Histogram width = {180}
statistics={report.statistics}
colorMap={colorsMap}
initialMin={report.min}
initialMax={report.max}>);
})

Histogram component like follow

import React from 'react';
import PropTypes from 'prop-types';
import './Histogram.scss';
import d3, { color, fcumsum } from 'd3';
import { _ } from './gettext';

export default class HistogramCustom extends React.Component {
    static defaultProps = {
        width: 280,
        colorMap: null,
        onUpdate: null,
        loading: false,
    };
    static propTypes = {
        statistics: PropTypes.object.isRequired,
        colorMap: PropTypes.array,
        width: PropTypes.number,
        onUpdate: PropTypes.func,
        loading: PropTypes.bool
    }

    constructor(props) {
        super(props);
        // Colors in absence of a color map
        this.defaultBandColors = [
            '#ff0000',
            '#00ff00',
            '#0000ff',
            '#ff8000',
            '#ffff00',
            '#00ff80',
            '#00ffff',
            '#0080ff',
        ];

        this.reset();
    }

    reset = () => {
        const minY = 0;
        let maxY = 0;
        let minX = 2147483647;
        let maxX = -2147483646;

        for (let i in this.props.statistics) {
            const band = this.props.statistics[i];
            minX = Math.min(minX, band.min);
            maxX = Math.max(maxX, band.max);
            // let xw = (this.props.min - maxY)/(this.props.max - maxY) 
            maxY = Math.max(maxY, Math.max(...band.histogram[0]));
        }

        this.rangeX = [minX, maxX];
        this.rangeY = [minY, maxY];

        const st = {
            min: this.props.initialMin,
            max: this.props.initialMax
        };

        if (!this.state) {
            this.state = st;
        } else {
            this.setState(st);
        }
    }

    redraw = () => {
        let margin = { top: 5, right: 10, bottom: 15, left: 10 },
            width = this.props.width - margin.left - margin.right,
            height = 85 - margin.top - margin.bottom;
        let hgContainer = document.getElementById('body')
        // if (this.hgContainer.firstElementChild) {
        //     this.hgContainer.removeChild(this.hgContainer.firstElementChild);
        // }

        const svgContainer = d3.select(this.hgContainer)
            .append("svg")
            .attr('class', 'histogram-container')
            .attr('x',function(d,i){
                // get y coord
                console.log(this)
            })
            .attr("width", width + margin.left + margin.right)
            .attr("height", this.props.histogramUnavailable ? 30 : height + margin.top + margin.bottom);

        if (this.props.colorMap) {
            this.colorMapElem = svgContainer.append("defs")
                .append("linearGradient")
                .attr('id', 'linear')
                .attr('x1', '0%')
                .attr('y1', '0%')
                .attr('x2', '100%')
                .attr('y2', '0%');
            this.updateColorMap(true);
        }

        let svg = svgContainer.append("g")
            .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");

        // add the x Axis
        let x = d3.scale.linear()
            .domain(this.rangeX)
            .range([0, width]);

        svg.append("g")
            .attr("class", "x axis theme-fill-primary")
            .attr("transform", "translate(0," + (height - 5) + ")")
            .call(d3.svg.axis().scale(x).tickValues(this.rangeX).orient("bottom"));

        // add the y Axis
        // let mm = d3.min()

        let y = d3.scale.linear()
            .domain(this.rangeY)
            .range([height, 0]);

        for (let i in this.props.statistics) {
            const band = this.props.statistics[i];
            const data = band.histogram[0].map((e, i) => {
                return [band.histogram[1][i], e];
            });

            // Make sure histogram starts and ends at 0
            // to prevent oblique looking charts
            data.unshift([data[0][0], 0]);
            data.push([data[data.length - 1][0], 0]);

            // Plot the area
            svg.append('g')
                .append("path")
                .datum(data)
                .attr("fill", !this.colorMapElem ? this.defaultBandColors[i - 1] : 'url(#linear)')
                .attr("opacity", 1 / Object.keys(this.props.statistics).length)
                .attr("d", d3.svg.line()
                    .x(function (d) { return x(d[0]); })
                    .y(function (d) { return y(d[1]); })
                );
        }

        // Add sliders
        this.maxDown = false;
        this.minDown = false;
        let maxPosX = null;
        let minPosX = null;

        const minXStart = ((this.state.min - this.rangeX[0]) / (this.rangeX[1] - this.rangeX[0])) * width;
        const minLine = svg.append('g')
            .append('line')
            .attr('x1', minXStart)
            .attr('y1', 0)
            .attr('x2', minXStart)
            .attr('y2', height)
            .attr('class', 'theme-stroke-primary slider-line min')
            .on("mousedown", function () { self.maxDown = false; self.minDown = true; })[0][0];


        const maxXStart = ((this.state.max - this.rangeX[0]) / (this.rangeX[1] - this.rangeX[0])) * width;
        const maxLine = svg.append('g')
            .append('line')
            .attr('x1', maxXStart)
            .attr('y1', 0)
            .attr('x2', maxXStart)
            .attr('y2', height)
            .attr('class', 'theme-stroke-primary slider-line max')
            .on("mousedown", function () { self.minDown = false; self.maxDown = true; })[0][0];

        const handleLeave = () => {
            this.maxDown = this.minDown = false;
            maxPosX = null;
            minPosX = null;
        };

        const self = this;

        const handleMoveMax = function () {
            if (self.maxDown) {
                const mouseX = (d3.mouse(this))[0];
                if (!maxPosX) maxPosX = mouseX;

                const deltaX = mouseX - maxPosX;
                const prevX = parseInt(maxLine.getAttribute('x1'));
                const newX = Math.max(Math.min(width, prevX + deltaX), parseInt(minLine.getAttribute('x1')));
                maxPosX = mouseX;
                maxLine.setAttribute('x1', newX);
                maxLine.setAttribute('x2', newX);

                if (prevX !== newX) {
                    self.setState({ max: (self.rangeX[0] + ((self.rangeX[1] - self.rangeX[0]) / width) * newX).toFixed(3) });
                }
            }
        };

        const handleMoveMin = function () {
            if (self.minDown) {
                console.log(d3)
                console.log(d3.color)
                console.log(d3.color.arguments)
                const mouseX = (d3.mouse(this))[0];
                if (!minPosX) minPosX = mouseX;

                const deltaX = mouseX - minPosX;
                const prevX = parseInt(minLine.getAttribute('x1'));
                const newX = Math.max(0, Math.min(prevX + deltaX, parseInt(maxLine.getAttribute('x1'))));
                minPosX = mouseX;
                minLine.setAttribute('x1', newX);
                minLine.setAttribute('x2', newX);

                if (prevX !== newX) {
                    self.setState({ min: (self.rangeX[0] + ((self.rangeX[1] - self.rangeX[0]) / width) * newX).toFixed(3) });
                }
            }
        };

        svgContainer
            .on("mousemove", function () {
                handleMoveMax.apply(this);
                handleMoveMin.apply(this);
            })
            .on("mouseup", handleLeave)
            .on("mouseleave", handleLeave)
            .on("mousedown", function () {
                const mouseX = (d3.mouse(this))[0];
                const maxBarX = parseInt(maxLine.getAttribute('x1')) + margin.right;
                const minBarX = parseInt(minLine.getAttribute('x1')) + margin.right;

                // Move bar closest to click
                if (Math.abs(mouseX - maxBarX) < Math.abs(mouseX - minBarX)) {
                    self.maxDown = true;
                    maxPosX = parseInt(maxLine.getAttribute('x1')) + margin.right;
                    handleMoveMax.apply(this);
                } else {
                    self.minDown = true;
                    minPosX = parseInt(minLine.getAttribute('x1')) + margin.right;
                    handleMoveMin.apply(this);
                }
            });
    }


    componentDidMount() {
        this.redraw();
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState.min !== this.state.min ||
            prevState.max !== this.state.max ||
            prevProps.colorMap !== this.props.colorMap ||
            prevProps.statistics !== this.props.statistics) {

            if (prevProps.statistics !== this.props.statistics) this.reset();
            if (!this.maxDown && !this.minDown) this.redraw();
            this.updateColorMap(prevProps.colorMap !== this.props.colorMap);

            if (this.props.onUpdate !== undefined) this.props.onUpdate({ min: this.state.min, max: this.state.max });
        }
    }

    updateColorMap = (recreate) => {
        if (!this.colorMapElem) return;

        if (recreate) {
            this.colorMapElem.select("stop").remove();

            this.props.colorMap.forEach((color, i) => {
                this.colorMapElem.append("stop")
                    .attr('offset', `${(i / (this.props.colorMap.length - 1)) * 100.0}%`)
                    .attr('stop-color', `rgb(${color.join(",")})`);
            });
        }

        const { min, max } = this.state;

        const minPerc = Math.abs(min - this.rangeX[0]) / (this.rangeX[1] - this.rangeX[0]) * 100.0;
        const maxPerc = Math.abs(max - this.rangeX[0]) / (this.rangeX[1] - this.rangeX[0]) * 100.0;

        this.colorMapElem.attr('x1', `${minPerc}%`)
            .attr('x2', `${maxPerc}%`);
    }

output getting like first histogram shows red colour and second shows green but its same colour of histogram this histogram getting correct rgb colour scale

but second getting wrong its get first histogram rgb colour scale



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source