Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I implement an invert function for a point scale?

I am trying to add a tooltip for my dual line chart graph.

However, instead of using timeScale or scaleLinear, I used scalePoint to graph my chart.

I am trying to achieve the following effect: https://bl.ocks.org/mbostock/3902569

this.x  = d3.scalePoint().range([ this.margin.left, this.width - this.margin.right ]);
this.xAxis      = d3.axisBottom(this.x);
this.x.domain(
       this.dataArray.map(d => {
       return this.format(d[ 'year' ]);
}));

Here is my mouseover function,

function mousemove() {
            //d3.mouse(this)[ 0 ]
            //x.invert

            var x0 = d3.mouse(this)[ 0 ],
                i  = bisectDate(data, x0, 1),
                d0 = data[ i - 1 ],
                d1 = data[ i ],
                d  = x0 - d0.year > d1.year - x0 ? d1 : d0;

            console.log(x0);
            // focus.attr("transform", "translate(" + x(format(d.year)) + "," + y(d.housing_index_change) + ")");
            // focus.select("text").text(d.housing_index_change);
        }

Since I am using scalePoint, there is obviously no invert function to map the coordinates to my data. and I am only retrieving the first element in the array and it is the only one that is being display regardless of the position of the mouse.

So my question is, how can I implement the invert functionality here while still using scalePoint?

Thank you :)

like image 896
abedzantout Avatar asked Nov 13 '16 12:11

abedzantout


People also ask

Is there a function that inverse of scale?

Is there a function that inverse of scale? For example, Show activity on this post. Yes, there is, and it's aptly named invert. Thanks for contributing an answer to Stack Overflow! Please be sure to answer the question. Provide details and share your research! But avoid … Asking for help, clarification, or responding to other answers.

How do you find the inverse of a function with points?

If a function were to contain the point ( 3,5 ), its inverse would contain the point ( 5,3 ). If the original function is f (x), then its inverse f -1(x) is not the same as . To find the inverse of a function, you need to do the opposite of what the original function does to x.

What is the invert() function in CSS?

CSS | invert () Function Last Updated : 03 Jun, 2020 The invert () function is an inbuilt function that is used to apply a filter to the image to set the invert of the color of the sample image.

What is the inverse of F-1 (X)?

First multiply by 3. Then subtract 5. #N#Inverse function. f -1 (x) =. First add 5. Then divide by 3. Not all functions have inverses. A function must be a one-to-one function, meaning that each y -value has a unique x -value paired to it. Basically, the same y -value cannot be used twice.


1 Answers

You are right, there is no invert for a point scale. But you can create your own function to get the corresponding domain of a given x position:

function scalePointPosition() {
    var xPos = d3.mouse(this)[0];
    var domain = xScale.domain(); 
    var range = xScale.range();
    var rangePoints = d3.range(range[0], range[1], xScale.step())
    var yPos = domain[d3.bisect(rangePoints, xPos) -1];
    console.log(yPos);
}

Step by step explanation

First, we get the x mouse position.

var xPos = d3.mouse(this)[0];

Then, based on your scale's range and domain...

var domain = xScale.domain(); 
var range = xScale.range();

...we create an array with all the steps in the point scale using d3.range:

var rangePoints = d3.range(range[0], range[1], xScale.step())

Finally, we get the corresponding domain using bisect:

var yPos = domain[d3.bisect(rangePoints, xPos) -1];

Check the console.log in this demo:

var data = [{
    A: "groupA",
    B: 10
}, {
    A: "groupB",
    B: 20
}, {
    A: "groupC",
    B: 30
}, {
    A: "groupD",
    B: 10
}, {
    A: "groupE",
    B: 17
}]

var width = 500,
    height = 200;

var svg = d3.selectAll("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height);

var color = d3.scaleOrdinal(d3.schemeCategory10)
    .domain(data.map(function(d) {
        return d.A
    }));

var xScale = d3.scalePoint()
    .domain(data.map(function(d) {
        return d.A
    }))
    .range([50, width - 50])
    .padding(0.5);

var yScale = d3.scaleLinear()
    .domain([0, d3.max(data, function(d) {
        return d.B
    }) * 1.1])
    .range([height - 50, 10]);

var circles = svg.selectAll(".circles")
    .data(data)
    .enter()
    .append("circle")
    .attr("r", 8)
    .attr("cx", function(d) {
        return xScale(d.A)
    })
    .attr("cy", function(d) {
        return yScale(d.B)
    })
    .attr("fill", function(d) {
        return color(d.A)
    });

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

svg.append("g").attr("transform", "translate(0,150)")
    .attr("class", "xAxis")
    .call(xAxis);

svg.append("g")
    .attr("transform", "translate(50,0)")
    .attr("class", "yAxis")
    .call(yAxis);

svg.append("rect")
    .attr("opacity", 0)
    .attr("x", 50)
    .attr("width", width - 50)
    .attr("height", height)
    .on("mousemove", scalePointPosition);

function scalePointPosition() {
    var xPos = d3.mouse(this)[0];
    var domain = xScale.domain();
    var range = xScale.range();
    var rangePoints = d3.range(range[0], range[1], xScale.step())
    var yPos = domain[d3.bisect(rangePoints, xPos) - 1];
    console.log(yPos);
}
.as-console-wrapper { max-height: 20% !important;}
<script src="https://d3js.org/d3.v4.min.js"></script>
like image 174
Gerardo Furtado Avatar answered Oct 04 '22 06:10

Gerardo Furtado