基于相对于矩形的两个点创建 CSS 线性渐变
Creating a CSS linear gradient based on two points relative to a rectangle
我正在尝试在 Sketch 中重新创建渐变工具。 Sketch 中的工具使用不同颜色的两个点来定义渐变:
我希望输出采用 CSS 线性渐变值的形式。 CSS 线性渐变的构建方式是一个角度和 x 个颜色停止,颜色和百分比定义为:https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient
所以我想将相对于应该渲染渐变的矩形的两个点转换为CSS格式(两个参数具有正确的百分比)。
关于如何解决这个问题有什么想法吗?
没有通用公式,但您必须做一些 manipulation/calculation 才能找到梯度的度数以及梯度的 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));
}
<div class="box"></div>
这是我们有外点和内点的混合:
.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;
}
<div class="box"></div>
如您所见,在垂直方向上它在某种程度上很容易。我们只需要找到渐变的大小,它的位置和渐变内的颜色停止。
当然,当涉及到其他角度值时就比较棘手了。
这是一个示例的说明:
您的渐变由橙色线定义。第一步是根据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% 的大小。我们使用这些百分比来查找新颜色。
对于 red 我们有 128
和 255
所以区别是 127
和 20%[=它的 163=] 是 25.4
(而 40% 是 50.4
)因此第一个点将具有 153.4 (128 + 25.4)
,最后一个点将具有 204.2 (255 - 50.4)
。我们对 green 和 blue 进行相同的计算,得到以下梯度:
.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>
我就是这样解决的!
如果您查看我附上的 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));
通过这种方式,我得到了两个百分比值,并且可以轻松构建我的 CSS 线性梯度值,该值由两个用户控制点的角度加上我计算的两个百分比值组成:
background: linear-gradient([angle]deg, black [percentValue1]%, white [percentValue2]%)
我正在尝试在 Sketch 中重新创建渐变工具。 Sketch 中的工具使用不同颜色的两个点来定义渐变:
我希望输出采用 CSS 线性渐变值的形式。 CSS 线性渐变的构建方式是一个角度和 x 个颜色停止,颜色和百分比定义为:https://developer.mozilla.org/en-US/docs/Web/CSS/linear-gradient
所以我想将相对于应该渲染渐变的矩形的两个点转换为CSS格式(两个参数具有正确的百分比)。
关于如何解决这个问题有什么想法吗?
没有通用公式,但您必须做一些 manipulation/calculation 才能找到梯度的度数以及梯度的 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));
}
<div class="box"></div>
这是我们有外点和内点的混合:
.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;
}
<div class="box"></div>
如您所见,在垂直方向上它在某种程度上很容易。我们只需要找到渐变的大小,它的位置和渐变内的颜色停止。
当然,当涉及到其他角度值时就比较棘手了。
这是一个示例的说明:
您的渐变由橙色线定义。第一步是根据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% 的大小。我们使用这些百分比来查找新颜色。
对于 red 我们有 128
和 255
所以区别是 127
和 20%[=它的 163=] 是 25.4
(而 40% 是 50.4
)因此第一个点将具有 153.4 (128 + 25.4)
,最后一个点将具有 204.2 (255 - 50.4)
。我们对 green 和 blue 进行相同的计算,得到以下梯度:
.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>
我就是这样解决的!
如果您查看我附上的 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));
通过这种方式,我得到了两个百分比值,并且可以轻松构建我的 CSS 线性梯度值,该值由两个用户控制点的角度加上我计算的两个百分比值组成:
background: linear-gradient([angle]deg, black [percentValue1]%, white [percentValue2]%)