【问题标题】:Creating a CSS linear gradient based on two points relative to a rectangle基于相对于矩形的两个点创建 CSS 线性渐变
【发布时间】:2018-08-16 16:09:37
【问题描述】:

我正在尝试在 Sketch 中重新创建渐变工具。 Sketch 中的工具是使用两个不同颜色的点来定义渐变:

我希望输出采用 CSS 线性渐变值的形式。构造 CSS 线性渐变的方式是一个角度和 x 个色标,并定义了一个颜色和一个百分比:https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient

所以我想将相对于应该渲染渐变的矩形的两个点转换为 CSS 格式(两个参数具有正确的百分比)。

关于如何解决这个问题的任何想法?

【问题讨论】:

标签: javascript css gradient linear-gradients


【解决方案1】:

没有通用公式,但您必须进行一些操作/计算才能找到渐变的度数以及渐变的background-size/background-position

让我们从一个简单的例子开始:

这里我们有一个带有180deg(或0deg)的渐变。起点是顶部的50px,终点是底部的100px。考虑到这一点,我们将有以下渐变:

.box {
  width: 200px;
  height: 100px;
  border: 1px solid;
  margin: 20px;
  background-image: linear-gradient(180deg, white, black);
  background-size: 100% calc(100% + 50px + 100px);
  background-position: 0 -50px;
  background-repeat: no-repeat;
}
<div class="box"></div>

如您所见,总大小将为100% + 150px,我们将有一个-50px 的位置偏移量。考虑到100px,我们也可以有一个偏移量,它将是100% + 100px

.box {
  width:200px;
  height:100px;
  border:1px solid;
  margin:20px;
  background-image:linear-gradient(180deg,white,black);
  background-size:100% calc(100% + 50px + 100px);
  background-position:0 calc(100% + 100px);
  background-repeat:no-repeat;
}
<div class="box">

</div>

这是另一个例子:

在这种情况下,点在内部,所以我们只需要调整渐变内部的色标:

.box {
  width: 200px;
  height: 100px;
  border: 1px solid;
  margin: 20px;
  background-image: linear-gradient(90deg, white 50px, black calc(100% - 50px));
}
&lt;div class="box"&gt;&lt;/div&gt;

这是我们有外点和内点的混合:

.box {
  width: 200px;
  height: 100px;
  border: 1px solid;
  margin: 20px;
  background-image: linear-gradient(90deg, white 50px, black);
  background-size: calc(100% + 100px) 100%;
  background-position: 0 0;
  background-repeat: no-repeat;
}
&lt;div class="box"&gt;&lt;/div&gt;

如您所见,在垂直方向上它有点简单。我们只需要找到渐变的大小、它的位置和渐变内的颜色停止。

当然,当涉及到其他角度值时,它会更加棘手。

这里是一个例子的说明:

您的渐变由橙色线定义。第一步是根据the documentation画出渐变的线,这条线会和你的线平行。画完这条线,就得到了渐变的角度

之后,我们会对您的线条进行投影,您将拥有 色标。所需的值以绿色显示。

我们的渐变看起来像这样:

background-image:linear-gradient(Xdeg,white Apx,black calc(100% - Bpx));

在这种情况下,我考虑了一个示例,其中我们只有内部点,但如果橙色线的投影会导致外部点(如第一个示例),则它会变得更加复杂,在这种情况下,我们需要考虑增加background-size 在两个方向上,这也有点棘手。

如您所见,我们有一个外部点,由与渐变点的距离B 定义。我们已经建立了一个矩形三角形,以便找到如何增加background-size

我们的渐变看起来像这样:

background-image:linear-gradient(Xdeg,white Apx,black);
background-size:calc(100% + w) calc(100% + h);
background-position:0 0;

更新

如果您不想使用background-size/background-position,另一种方法是将渐变转换为使用内部点。当然,这种方法只有在点在外面时才有用,并且我们的想法是找到最近的内部点,这将使我们获得相同的梯度。

让我们重温第一个例子。在那个例子中,我们在顶部有第一个点50px,逻辑上最近的内部点是0px(与另一点相同的逻辑)。所以我们只需要找到新点的颜色并使用它们。

.box {
  width: 200px;
  height: 100px;
  border: 1px solid;
  margin: 20px;
}

.old {
  background-image: linear-gradient(180deg, white, black);
  background-size: 100% calc(100% + 50px + 100px);
  background-position: 0 -50px;
  background-repeat: no-repeat;
}
.new {
  background-image:linear-gradient(180deg,rgb(203, 203, 203),rgba(103, 103, 103));
}
<div class="box old"></div>
<div class="box new"></div>

在这个特定的例子中,计算很容易,因为初始渐变的大小是250px,在白色 (255,255,255) 和黑色 (0,0,0) 之间我们有 255 个值(几乎 250)所以我们以某种方式删除了 50 以找到第一种颜色并添加了 100 以找到最后一种颜色。

让我们采用相同的渐变,但使用不同的颜色:紫色 (128,0,128) 和橙色 (255,165,0)。渐变的大小是250px,所以第一个偏移量 (50px) 是大小的 20%,第二个偏移量 (100px) 是 40%的大小。我们使用这些百分比来寻找新的颜色。

对于 红色,我们有 128255,所以区别是 12720%25.4(和 40%50.4),因此第一个点为153.4 (128 + 25.4),最后一个点为204.2 (255 - 50.4)。我们对 greenblue 进行相同的计算,得到以下梯度:

.box {
  width: 200px;
  height: 100px;
  border: 1px solid;
  margin: 20px;
}

.old {
  background-image: linear-gradient(180deg, purple, orange);
  background-size: 100% calc(100% + 50px + 100px);
  background-position: 0 -50px;
  background-repeat: no-repeat;
}
.new {
  background-image:linear-gradient(180deg,rgb(153, 33, 102),rgba(204, 99, 51));
}
<div class="box old"></div>
<div class="box new"></div>

【讨论】:

  • 非常感谢您的深入回复!我没想过改变背景大小。这是唯一的方法吗?不能仅使用线性梯度定义来完成吗?
  • @user3449608 如您所见,这取决于具体情况。如果您的点在渐变区域内,则可以,如果不是,则必须使用大小,或者还有另一种棘手的方法是找到内部要使用的最近点,但为此您必须找到颜色[我希望你得到我的意思是,如果没有,我可以将其添加到 anwser]
  • @user3449608,我添加了另一种方法来避免使用 background-size ;)
【解决方案2】:

我就是这样解决的!

如果您查看我附上的 GIF,它说明了我在计算中使用的点。红线是矩形中心的渐变线,黑点是渐变线的起点和终点。另外两个点(黑色和白色)是用户可以随意拖动的用户控制点。两个红点是线上相对于每个用户控制点(垂直线点,p1 和 p2)的最近位置。

我得到垂直线点与渐变线起点和终点之间的距离。然后为了计算 CSS 线性渐变值所需的百分比值,我将两个距离相加,将它们除以渐变线长度,然后将值乘以 100。

ax = ((p1.x - gradientLine.point1.x) * (gradientLine.length / 2)) / (gradientLine.point2.x - gradientLine.point1.x);
ay = ((p1.y - gradientLine.point1.y) * (gradientLine.length / 2)) / (gradientLine.point2.y - gradientLine.point1.y);

percentValue = (((ax + ay) / line.length) * 100);

为了得到线性梯度值中第二个参数的值,我只是做同样的事情,除了我用计算值减去 100。

ax = ((p2.x - gradientLine.point2.x) * (gradientLine.length / 2)) / (gradientLine.point1.x - gradientLine.point2.x);
ay = ((p2.y - gradientLine.point2.y) * (gradientLine.length / 2)) / (gradientLine.point1.y - gradientLine.point2.y);
percentValue = 100 - ((((ax + ay) / gradientLine.length) * 100));

这样我得到了 2% 的值,并且可以轻松地构建我的 CSS 线性渐变值,该值由两个用户控制点的角度加上我计算的 2% 值组成:

background: linear-gradient([angle]deg, black [percentValue1]%, white [percentValue2]%)

【讨论】:

  • 是的,除了我不对颜色值做任何计算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-17
相关资源
最近更新 更多