用颜色部分填充形状的边框
Partially fill a shape's border with colour
我正在尝试创建一种进度效果,使颜色填充 DOM 对象的边框(或可能是背景)。所附图片应该可以让您更好地了解我要做什么。我通过在灰线上添加一个具有纯色背景颜色的对象并设置其高度来实现当前结果。此对象已应用 mix-blend-mode: color-burn;
,这就是为什么它只为其下方的灰色线条着色。
这工作正常,但破坏了圆周围的抗锯齿,而且产生的颜色也是不可预测的(根据线条的颜色而变化)。
我觉得一定有更好的方法来实现这一点,或许可以使用 canvas 元素。有人能给我指出正确的方向吗?
提前致谢!
这应该可以用 Canvas 来做,甚至可以用 CSS 本身通过玩多个元素等来实现,但我绝对建议您使用 SVG。 SVG 在编码、维护和生成响应式输出的容易程度方面提供了很多好处(不像 Canvas,它在缩放时往往会变得像素化)。
以下是组件:
- 一个
rect
元素,它与父元素 svg
大小相同,并且具有 linear-gradient
填充。渐变有两种颜色 - 一种是基础色(浅灰色),另一种是渐变色(青色)。
- A
mask
应用于 rect
元素。面具有一个 path
,它只是直线和圆圈。当 mask
应用于 rect
时,只有 path
会透过 rect
的实际背景(或填充)显示,其余区域将被遮盖由 mask
. 中添加的另一个 rect
输出
mask
还有一个text
元素来显示进度值。
-
linear-gradient
的 stop offset
设置为与进度相等。通过更改 offset
,我们始终可以确保 path
仅显示所需长度的进度填充,其余部分显示基础(浅灰色)。
window.onload = function() {
var progress = document.querySelector('#progress'),
base = document.querySelector('#base'),
prgText = document.querySelector('#prg-text'),
prgInput = document.querySelector('#prg-input');
prgInput.addEventListener('change', function() {
prgText.textContent = this.value + '%';
progress.setAttribute('offset', this.value + '%');
base.setAttribute('offset', this.value + '%');
});
}
svg {
width: 200px;
height: 300px;
}
path {
stroke-width: 4;
}
#rect {
fill: url(#grad);
mask: url(#path);
}
/* just for demo */
.controls {
position: absolute;
top: 0;
right: 0;
height: 100px;
line-height: 100px;
border: 1px solid;
}
.controls * {
vertical-align: middle;
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 200 300' id='shape-container'>
<linearGradient id='grad' gradientTransform='rotate(90 0 0)'>
<stop offset='50%' stop-color='rgb(0,218,235)' id='progress' />
<stop offset='50%' stop-color='rgb(238,238,238)' id='base' />
</linearGradient>
<mask id='path' maskUnits='userSpaceOnUse' x='0' y='0' width='200' height='300'>
<rect x='0' y='0' width='200' height='300' fill='black' />
<path d='M100,0 100,100 A50,50 0 0,0 100,200 L100,300 M100,200 A50,50 0 1,0 100,100' stroke='white' />
<text id='prg-text' x='100' y='155' font-size='20' text-anchor='middle' fill='white'>50%</text>
</mask>
<rect id='rect' x='0' y='0' width='200' height='300' />
</svg>
<!-- just for demo -->
<div class='controls'>
<label>Set Progress:</label>
<input type='range' id='prg-input' min='0' max='100' value='50' />
</div>
如果您不熟悉 SVG,可以参考 MDN 文档(下面提供的链接)以获取有关元素、它们的属性和值的更多信息。
我正在尝试创建一种进度效果,使颜色填充 DOM 对象的边框(或可能是背景)。所附图片应该可以让您更好地了解我要做什么。我通过在灰线上添加一个具有纯色背景颜色的对象并设置其高度来实现当前结果。此对象已应用 mix-blend-mode: color-burn;
,这就是为什么它只为其下方的灰色线条着色。
这工作正常,但破坏了圆周围的抗锯齿,而且产生的颜色也是不可预测的(根据线条的颜色而变化)。
我觉得一定有更好的方法来实现这一点,或许可以使用 canvas 元素。有人能给我指出正确的方向吗?
提前致谢!
这应该可以用 Canvas 来做,甚至可以用 CSS 本身通过玩多个元素等来实现,但我绝对建议您使用 SVG。 SVG 在编码、维护和生成响应式输出的容易程度方面提供了很多好处(不像 Canvas,它在缩放时往往会变得像素化)。
以下是组件:
- 一个
rect
元素,它与父元素svg
大小相同,并且具有linear-gradient
填充。渐变有两种颜色 - 一种是基础色(浅灰色),另一种是渐变色(青色)。 - A
mask
应用于rect
元素。面具有一个path
,它只是直线和圆圈。当mask
应用于rect
时,只有path
会透过rect
的实际背景(或填充)显示,其余区域将被遮盖由mask
. 中添加的另一个 mask
还有一个text
元素来显示进度值。-
linear-gradient
的stop offset
设置为与进度相等。通过更改offset
,我们始终可以确保path
仅显示所需长度的进度填充,其余部分显示基础(浅灰色)。
rect
输出
window.onload = function() {
var progress = document.querySelector('#progress'),
base = document.querySelector('#base'),
prgText = document.querySelector('#prg-text'),
prgInput = document.querySelector('#prg-input');
prgInput.addEventListener('change', function() {
prgText.textContent = this.value + '%';
progress.setAttribute('offset', this.value + '%');
base.setAttribute('offset', this.value + '%');
});
}
svg {
width: 200px;
height: 300px;
}
path {
stroke-width: 4;
}
#rect {
fill: url(#grad);
mask: url(#path);
}
/* just for demo */
.controls {
position: absolute;
top: 0;
right: 0;
height: 100px;
line-height: 100px;
border: 1px solid;
}
.controls * {
vertical-align: middle;
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 200 300' id='shape-container'>
<linearGradient id='grad' gradientTransform='rotate(90 0 0)'>
<stop offset='50%' stop-color='rgb(0,218,235)' id='progress' />
<stop offset='50%' stop-color='rgb(238,238,238)' id='base' />
</linearGradient>
<mask id='path' maskUnits='userSpaceOnUse' x='0' y='0' width='200' height='300'>
<rect x='0' y='0' width='200' height='300' fill='black' />
<path d='M100,0 100,100 A50,50 0 0,0 100,200 L100,300 M100,200 A50,50 0 1,0 100,100' stroke='white' />
<text id='prg-text' x='100' y='155' font-size='20' text-anchor='middle' fill='white'>50%</text>
</mask>
<rect id='rect' x='0' y='0' width='200' height='300' />
</svg>
<!-- just for demo -->
<div class='controls'>
<label>Set Progress:</label>
<input type='range' id='prg-input' min='0' max='100' value='50' />
</div>
如果您不熟悉 SVG,可以参考 MDN 文档(下面提供的链接)以获取有关元素、它们的属性和值的更多信息。