简体   繁体   中英

Set appropriate color of element base on linear-gradient background when scrolling

I need some help on a math/algorithm problem. (You don't need to know react-native in order to solve it; just some math)

I have a react-native app having a linear-gradient background from rgb(24, 205, 246) to rgb(67, 33, 140).

There are three different Text items, each at a different vertical (y-axis) position on the screen. For each Text item, I want its text color to correspond to the color of the linear-gradient background at its current y position when scrolling.

This is what I want it to look like: https://imgur.com/a/8r5VcWN

I found a solution that is using background-clip: Text, but unfortunately that only works in a browser, not in a phone.

After some research, I decided to use the onscroll method from scrollview that will return the y position at the top of the phone's screen. The y position is increased when the user slides down, and decreased when the user slides up.

Here's some information about the phone screen: https://imgur.com/a/ui7AyY6 .

What I already did was for each Text item, its color will invoke a function call changeColor(Text item A's y position) which will take the Text item's y position and return the appropriate rgb color.

changeColor = bname => {
    let topY = this.state.topY;

    let color1 = Math.round(67 - topY / ((24 / 67) * 100));
    let color2 = Math.round(33 + topY / ((33 / 205) * 30));
    let color3 = Math.round(140 + topY / ((140 / 246) * 15));

    return `rgb(${color1},${color2},${color3})`;
};

Recall that the Linear gradient Background is from rgb(24, 205, 246) to rgb(67, 33, 140). We can break up to three different color portions : rgb(color1, color2, color3).

Let's use color1 for example, the range of color1 is from 24 to 67 and the height of the phone screen is from 0 to 677.

My logic is to make the rgb and height simulate to the same? Let say we have two variables: topY (increase when sliding down; decrease when sliding up) and rgbVar which is starting at 24.

Before sliding:

topY : 0

rgbVar : 24

When sliding into the middle:

topY : 338.5

rgbVar : 45.5

When sliding into the end:

topY : 667

rgbVar : 67

Moreover, because the Text items are in different Y positions, so I need to do some math and add that into the calculation?

Here's what I have so far: https://snack.expo.io/@rex_rau/paranoid-toffee

It is somewhat able to change to the appropriate color for Text item A, however, Text item B and Text item C are not different (not the appropriate color for their current position).

I expect the output to be something like this, when sliding to the middle:

  • Text item A has rgb(45.5, 119, 193)
  • Text item B has rgb(50, 70, 173)
  • Text item C has rgb(55, 40, 153)

Anyone have any ideas to solve this? Or other ways to achieve what I want?

Thanks

In this application, the color of a text item depends on its position relative to the background. The color component values (red, green, blue) will each vary linearly from one end of the gradient to the other. This means if you were to mathematically plot position on the x-axis, and color component value on the y-axis, you would have a line with a slope and a y-intercept.

As you surely know, the slope-intercept form of a linear equation is

y = mx + b

where m is the slope of the line, and b is the y-intercept.

Given two points (x1, y1) and (x2, y2) on the line, the slope m can be calculated from the equation

m = (y2 - y1) / (x2 - x1)

Now let's apply this to the problem at hand. For the red component, we can define the two points as being

(x1, y1) = (position1, color1) = (0, 24)

(x2, y2) = (position2, color2) = (screenHeight, 67)

Since the y-intercept of every line occurs at x = 0 , notice that since position1 = 0 we can say that the y-intercept b = color1 = 24 .

So the slope-intercept form of the equation is

textColor = color1 + textPosition * (color2 - color1) / (position2 - position1)

Each color component (red, green, blue) uses the same formula.

In your changeColor function, you need to supply a parameter that provides the vertical position of the text item. I renamed your parameter bname to y for this purpose. Your calling code in three places needs to be modified so that it provides a numeric position value instead of a string.

In the code below, I rearranged some of the terms in the linear equation described above, but the principle is unchanged.

changeColor = y => {
    let topY = this.state.topY;

    const topRed = 24
    const topGreen = 205
    const topBlue = 246
    const bottomRed = 67
    const bottomGreen = 33
    const bottomBlue = 140

    let pos = (y - topY) / screenHeight

    let colorRed = topRed + (bottomRed - topRed) * pos
    let colorGreen = topGreen + (bottomGreen - topGreen) * pos
    let colorBlue = topBlue + (bottomBlue - topBlue) * pos

    return `rgb(${colorRed},${colorGreen},${colorBlue})`;
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM