【问题标题】:Set appropriate color of element base on linear-gradient background when scrolling滚动时根据线性渐变背景设置适当的元素颜色
【发布时间】:2019-08-04 06:15:59
【问题描述】:

我需要一些关于数学/算法问题的帮助。 (你不需要知道 react-native 来解决它;只是一些数学)

我有一个带有线性渐变背景的 react-native 应用 从 rgb(24, 205, 246) 到 rgb(67, 33, 140)。

共有三个不同的文本项目,每个项目位于屏幕上不同的垂直(y 轴)位置。对于每个 Text 项,我希望其文本颜色对应于滚动时其当前 y 位置处的线性渐变背景的颜色。

这就是我想要的样子:https://imgur.com/a/8r5VcWN

我找到了一个使用 background-clip: Text 的解决方案,但不幸的是,它只适用于浏览器,不适用于手机。

经过一番研究,我决定使用 scrollview 中的 onscroll 方法,该方法将返回手机屏幕顶部的 y 位置。用户向下滑动时y位置增加,用户向上滑动时y位置减少。

这里有一些关于手机屏幕的信息:https://imgur.com/a/ui7AyY6

我已经为每个 Text 项所做的是,它的颜色将调用函数调用 changeColor(Text item A's y position),它将获取 Text 项的 y 位置并返回适当的 rgb 颜色。

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})`;
};

回想一下,线性渐变背景是从 rgb(24, 205, 246) 到 rgb(67, 33, 140)。我们最多可以分解三个不同的颜色部分:rgb(color1, color2, color3)。

我们以color1为例,color1的范围是24到67,手机屏幕的高度是0到677。

我的逻辑是使 rgb 和高度模拟相同?假设我们有两个变量:topY(向下滑动时增加;向上滑动时减少)和从 24 开始的 rgbVar。

滑动前:

topY : 0

rgbVar : 24

滑入中间时:

topY : 338.5

rgbVar:45.5

当滑到最后时:

topY : 667

rgbVar : 67

另外,由于 Text 项目位于不同的 Y 位置,所以我需要做一些数学运算并将其添加到计算中?

这是我目前所拥有的: https://snack.expo.io/@rex_rau/paranoid-toffee

对于Text item A,它有点能够更改为适当的颜色,但是,Text item B 和Text item C 没有区别(不是它们当前位置的适当颜色)。

我希望输出是这样的,当滑到中间时:

  • 文本项 A 具有 rgb(45.5, 119, 193)
  • 文本项 B 具有 rgb(50, 70, 173)
  • 文本项 C 具有 rgb(55, 40, 153)

有人有解决这个问题的想法吗?或者其他方式来实现我想要的?

谢谢

【问题讨论】:

    标签: javascript css algorithm react-native math


    【解决方案1】:

    在此应用程序中,文本项的颜色取决于其相对于背景的位置。颜色分量值(红色、绿色、蓝色)将从渐变的一端到另一端呈线性变化。这意味着如果您要在 x 轴上以数学方式绘制位置,在 y 轴上绘制颜色分量值,您将得到一条带有斜率和 y 轴截距的线。

    你肯定知道,线性方程的斜截式是

    y = mx + b

    其中m 是直线的斜率,b 是 y 轴截距。

    给定直线上的两个点(x1, y1)(x2, y2),可以从方程计算斜率m

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

    现在让我们将其应用于手头的问题。对于红色分量,我们可以将两个点定义为是

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

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

    由于每一行的 y 轴截距都发生在 x = 0,请注意,由于 position1 = 0 我们可以说 y 轴截距 b = color1 = 24

    所以方程的斜截式为

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

    每种颜色成分(红、绿、蓝)都使用相同的公式。

    在您的changeColor 函数中,您需要提供一个参数来提供文本项的垂直位置。为此,我将您的参数 bname 重命名为 y。您在三个地方的调用代码需要修改,以便它提供数字位置值而不是字符串。

    在下面的代码中,我重新排列了上述线性方程中的一些项,但原理没有改变。

    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})`;
      };
    

    【讨论】:

    • 哇。这是非常了不起的。我花了两天时间,只花了你几个小时。我真的很感谢这个答案。非常详细,解释清楚,一步一步来。再次,非常感谢你!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2017-05-02
    • 2014-08-12
    相关资源
    最近更新 更多