是否可能仅使用HTML5/CSS3创建一个圆形,其边框仅部分环绕圆形?如果不行,有哪些技术可以实现这种效果?我更喜欢使用纯DOM元素,但如果必须的话,我可以在画布上绘制或启动SVG。
是否可能仅使用HTML5/CSS3创建一个圆形,其边框仅部分环绕圆形?如果不行,有哪些技术可以实现这种效果?我更喜欢使用纯DOM元素,但如果必须的话,我可以在画布上绘制或启动SVG。
这种方法不需要JS,不需要额外的元素,甚至不需要任何伪元素,只需要一些CSS声明。即使元素除了这部分的border
还有一个(半)透明的background
,这种方法也适用。
它使用了两层mask
,其中一层是conic-gradient
,用于创建可见的饼状选择区域,其大小相对于border-box
,第二层是一个简单的全覆盖层,限制在padding-box
内。
首先,我们将元素设置为圆形(任意的width
,aspect-ratio
为1
,border-radius
设置为50%
),并给它添加一个border
。
然后,我们设置一个mask
,它是一个相对于border-box
的conic-gradient()
,覆盖了我们元素的百分比--p
(默认从12点钟开始,顺时针方向)。
.circular-progress {
border: solid 1.5em hotpink;
width: 50vmin;
aspect-ratio: 1;
border-radius: 50%;
background: hsla(180, 100%, 50%, .5);
--mask:
linear-gradient(red, red) padding-box,
conic-gradient(red var(--p, 17%), transparent 0%) border-box;
-webkit-mask: var(--mask);
mask: var(--mask)
}
/* just to make it obvious it works with semitrasparent background */
body {
background:
url(https://images.unsplash.com/photo-1693483923875-cdd9ef4a8046?w=800)
50%/ cover
}
<div class='circular-progress'></div>
--p
。
@property --p {
syntax: '<percentage>';
initial-value: 0%;
inherits: true
}
.circular-progress {
border: solid 1.5em hotpink;
width: 50vmin;
aspect-ratio: 1;
border-radius: 50%;
background: hsla(180, 100%, 50%, .5);
--mask:
linear-gradient(red, red) padding-box,
conic-gradient(red var(--p), transparent 0%) border-box;
-webkit-mask: var(--mask);
mask: var(--mask);
animation: p 4s linear infinite
}
@keyframes p { to { --p: 100% } }
/* just to make it obvious it works with semitrasparent background */
body {
background:
url(https://images.unsplash.com/photo-1693483923875-cdd9ef4a8046?w=800)
50%/ cover
}
<div class='circular-progress'></div>
是的,这是可能的 - 参见以下内容:
.circle {
position: relative;
margin: 7em auto;
width: 16em;
height: 16em;
border-radius: 50%;
background: lightblue;
}
.arc {
overflow: hidden;
position: absolute;
/* make sure top & left values are - the width of the border */
/* the bottom right corner is the centre of the parent circle */
top: -1em;
right: 50%;
bottom: 50%;
left: -1em;
/* the transform origin is the bottom right corner */
transform-origin: 100% 100%;
/* rotate by any angle */
/* the skew angle is 90deg - the angle you want for the arc */
transform: rotate(45deg) skewX(30deg);
}
.arc:before {
box-sizing: border-box;
display: block;
border: solid 1em navy;
width: 200%;
height: 200%;
border-radius: 50%;
transform: skewX(-30deg);
content: '';
}
<div class='circle'>
<div class='arc'></div>
</div>
90度-弧线角度
。但是为了填满整个圆,需要使用多个元素。 - Ana有可能。
border-radius
绘制两个圆,在上方放置一个圆。border-color
使两个圆的一个或多个弧形透明。transform
旋转第二个圆,这样你就会得到所需大小的弧形。这里是演示: http://jsfiddle.net/kJXwZ/2/
.wrapper {
position: relative;
margin: 20px;
}
.arc {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: 100%;
border: 1px solid;
}
.arc_start {
border-color: transparent red red red;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.arc_end {
border-color: red red red transparent;
-webkit-transform: rotate(75deg);
-moz-transform: rotate(75deg);
-ms-transform: rotate(75deg);
-o-transform: rotate(75deg);
transform: rotate(75deg);
}
<div class="wrapper">
<div class="arc arc_start"></div>
<div class="arc arc_end"></div>
</div>
这也使用了JavaScript,因此它与原始要求不符 :(
但是它确实实现了目标。
这里有一个 >> 演示 <<
@gkond 谢谢,我从您的回答中得出了这个。
// create a circle using HTML5 / CSS3 / JS which has a border that only goes part-way around
// the circle .. and which can be smoothly animated from 0% to 100% around the circle
// this solution allows for animation and still results in relatively clean code
// we use four quarter-circles, all hidden away behind a white square to start with..
// all four are rotated out clockwise, and each quarter will stop at it's own maximum:
// q1 at 25%, q2 at 50% .. etc. once we reach a value at or over 25%, all four quarters
// should be out from behind the white square, and we can hide it.. it needs to be
// hidden if we display a value over 75%, or else q4 will end up going in behind it again
// .. also, since the top border will usually sit between the angles of -45 to 45, we
// rotate everything by an extra -45 to make it all line up with the top nicely
var fromHidden = -90;
// utility function to align 0 degrees with top
// takes degrees and returns degrees - 45
function topAlign(degrees) {
return degrees - 45
};
// utility function to rotate a jQuery element
// takes element and the degree of rotation (from the top)
function rotate(el, degrees) {
var degrees = topAlign(degrees || 0);
el.css(
'transform', 'rotate(' + degrees + 'deg)',
'-webkit-transform', 'rotate(' + degrees + 'deg)',
'-moz-transform', 'rotate(' + degrees + 'deg)',
'-ms-transform', 'rotate(' + degrees + 'deg)',
'-o-transform', 'rotate(' + degrees + 'deg)'
)
}
// function to draw semi-circle
// takes a jQuery element and a value (between 0 and 1)
// element must contain four .arc_q elements
function circle(el, normalisedValue) {
var degrees = normalisedValue * 360; // turn normalised value into degrees
var counter = 1; // keeps track of which quarter we're working with
el.find('.arc_q').each(function() { // loop over quarters..
var angle = Math.min(counter * 90, degrees); // limit angle to maximum allowed for this quarter
rotate($(this), fromHidden + angle); // rotate from the hiding place
counter++; // track which quarter we'll be working with in next pass over loop
});
if (degrees > 90) { // hide the cover-up square soon as we can
el.find('.arc_cover').css('display', 'none');
}
}
// uses the the circle function to 'animate' drawing of the semi-circle
// incrementally increses the value passed by 0.01 up to the value required
function animate(el, normalisedValue, current) {
var current = current || 0;
circle(el, current);
if (current < normalisedValue) {
current += 0.01;
setTimeout(function() {
animate(el, normalisedValue, current);
}, 1);
}
}
// kick things off ..
animate($('.circle'), 0.69);
.circle {
position: relative;
margin: 20px;
width: 120px;
height: 120px;
}
.arc_q {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: 50%;
border: 10px solid;
border-color: transparent green transparent transparent;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
}
.arc_cover {
position: absolute;
top: 0;
left: 0;
width: 60px;
height: 60px;
background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="circle">
<div class="arc_q"></div>
<div class="arc_q"></div>
<div class="arc_q"></div>
<div class="arc_q"></div>
<div class="arc_cover"></div>
</div>
锥形渐变解决方案(适用于任何角度):
:root{
--degree:80deg;
--smoothing:0.5deg;
--color:red;
}
.a{
height:200px;
width:200px;
border-radius:50%;
background: conic-gradient(
var(--color) var(--degree), transparent calc(var(--degree) + var(--smoothing)) 100%);
}
.b{
height:84%;
width:84%;
top:8%;
left:8%;
position:relative;
border-radius:50%;
background:#D3D3D3;
}
<div class ="a">
<div class="b">
</div>
要实现这个,您可以使用简单的盒子边框属性、一个元素和一个类。这将是一个内联、内联块或块级处理,具体取决于您放置 easy-circle 类的位置以及如何/是否设置样式位置。
<!DOCTYPE html>
<html>
<head>
<style>
.easy-circle {
background: transparent;
border: 1em solid black; /* color not required, may show device fail */
border-color: red green blue transparent;
height: 10em;
width: 10em;
-moz-border-radius: 6em; /* height/2 + border thickness */
-webkit-border-radius: 6em;
border-radius: 50%; /* more than 50, shape-size adjustment irrelevant */
-ms-transform: rotate(45deg); /* IE 9 */
-webkit-transform: rotate(45deg); /* Chrome, Safari, Opera */
transform: rotate(45deg); /* transform optional */
}
</style>
</head>
<body>
<div class="easy-circle">
</div>
</body>
</html>
可以通过在透明圆周围设置透明边框,并使用 border-top-color: ;
为圆的一部分边框着色来实现此目标。
background-color:transparent;
border:3px solid transparent;
border-top-color: green;
border-bottom-color:green;
除此之外,还可以使用左右边框来区分圆的周长的不同部分。
这里有一个示例,展示了在三个部分圆内相互交替地旋转,以显示其效果的加载器。
最简单的动画方式是使用CSS关键帧。
http://jsfiddle.net/8SUPX/644/
/**
* HTML5 / CSS3 Circle with Partial Border
* https://dev59.com/Mmcs5IYBdhLWcg3wMhCz
*/
* { margin: 0; padding: 0; }
.circle {
position: relative;
margin: 6em auto;
width: 12em; height: 12em;
border-radius: 50%;
background: transparent;
border:20px solid #efefef;
border-top-color: #efefef;
border-right-color: #efefef;
border-bottom-color: #efefef;
border-left-color: #efefef;
-webkit-transition:.5s;-moz-transition:.5s;transition:.5s;
}
.circle:hover{
-webkit-animation: animix 0.5s 1;
-webkit-animation-fill-mode: forwards;
-moz-animation: animix 0.5s 1;
-moz-animation-fill-mode: forwards;
animation: animix 0.5s 1;
animation-fill-mode: forwards;
}
//Animate
@-webkit-keyframes animix {
0% {
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
25% {
border-top-color: red;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
50% {
border-top-color: red;
border-right-color: red;
border-bottom-color: transparent;
border-left-color: transparent;
}
75% {
border-top-color: red;
border-right-color: red;
border-bottom-color: red;
border-left-color: transparent;
}
100% {
border-top-color: red;
border-right-color: red;
border-bottom-color: red;
border-left-color: red;
}
}
@keyframes animix {
0% {
border-top-color: transparent;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
25% {
border-top-color: red;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}
50% {
border-top-color: red;
border-right-color: red;
border-bottom-color: transparent;
border-left-color: transparent;
}
75% {
border-top-color: red;
border-right-color: red;
border-bottom-color: red;
border-left-color: transparent;
}
100% {
border-top-color: red;
border-right-color: red;
border-bottom-color: red;
border-left-color: red;
}
}
<div class="circle"> </div>
if you want double border you can use it also
div
{
background-color: #ddd;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
font-size: 30px;
margin: 40px auto;
color: black;
width: 200px;
height: 200px;
border-radius: 50%;
position: relative;
}
div::before
{
content: "";
width: 200px;
height: 200px;
border-radius: 50%;
position: absolute;
left: 0;
top: 0;
transform: translate(-10px, -10px);
z-index: -1;
border: 10px solid;
border-color: red red red transparent;
}
body ::after
{
content: "";
width: 220px;
height: 220px;
border-radius: 50%;
position: absolute;
left: 0;
top: 0;
transform: translate(-21px, -22px);
z-index: -8;
border: 12px solid;
background: transparent;
border-color: blue transparent blue blue;
}
<div> </div>