如何用 HTML CSS 创建 semi-circle/ellipse?喜欢 gauge/speedometer

How to create semi-circle/ellipse with HTML CSS? Like a gauge/speedometer

我正在尝试做这样的事情:

这不是一个完整的或半圆,边缘有一点半径。还需要包含一些点以百分比显示当前位置。有人可以告诉我如何将接近以下 3 个想法的东西放在一起吗?

.circle {
   display: flex;
   width: 200px;
   height: 100px;
   border-top-left-radius: 200px;
   border-top-right-radius: 200px;
   border: 10px solid gray;
   border-bottom: 0;
}

.circle>.text {
   font-size: 50px;
   margin: auto;
}

.circle.gradient {
   margin-top: 30px;
   border-image-slice: 1;
   border-width: 10px;
   border-bottom: 0;
   border-image-source: linear-gradient(to left, #6ECE34, #E6A749, #E5A749, #F71C1C);
}

.line {
   position: relative;
   margin-top: 30px;
   width: 220px;
   height: 10px;
   border-radius: 5px;
   background: linear-gradient(to left, #6ECE34, #E6A749, #E5A749, #F71C1C);
}

.line>.point {
   position: absolute;
   top: -3px;
   left: 21%;
   width: 8px;
   height: 16px;
   border-radius: 5px;
   border: 1px solid black;
   background: #FFF;
}
<!-- Just semi circle -->
<div class="circle">
   <div class="text">
      21
   </div>
</div>

<!-- With gradient border -->
<div class="circle gradient"></div>

<!-- Maybe strech in Y -->
<div class="line">
   <!-- Relative point -->
   <div class="point"></div>
</div>

您可以使用 CSS 外观和更新 CSS 指针变量 position/slope 来拼凑外观和功能,无论您使用什么语言来更新速度。

这是为演示设置 --pointerleft、--pointerright 和 --pointerdeg 的外观片段。在操作代码中,你需要做一些三角函数来计算这些给定的特定速度,然后设置 CSS 变量(例如在 JS 中)。

是否使用径向和圆锥渐变然后必须将小圆位定位在末端可以说是一个我不知道的推荐。 SO 不喜欢推荐,但我会冒险并建议这可行,但有点 hacky,SVG 可能更好。

注意,该代码段只有一个简单的 3 色圆锥渐变,您可以根据需要添加不同程度的 more/different 颜色。

.ring {
  position: relative;
  --pointerleft: 11%;
  --pointertop: 11%;
  --pointerdeg: -45deg;
  width: 50vmin;
  height: 50vmin;
  background-image: radial-gradient(red 0, red 50%, transparent 50%, transparent 100%), radial-gradient(green 0, green 50%, transparent 50%, transparent 100%), radial-gradient(white 0, white 60%, transparent 60%), conic-gradient(orange 0, green 130deg, white 130deg, white 230deg, red 230deg, orange 360deg);
  background-size: 11% 11%, 11% 11%, 100% 100%, 100% 100%;
  background-repeat: no-repeat;
  background-position: 9.2% 82.3%, 90.8% 82.3%, center center, center center;
  border-radius: 50%;
  border-style: none;
}

.ring::after {
  position: absolute;
  content: '';
  width: 5%;
  height: 15%;
  left: var(--pointerleft);
  top: var(--pointertop);
  transform: rotate(var(--pointerdeg));
  border-style: solid;
  border-width: 0.5vmin;
  border-radius: 2vmin;
  background-color: white;
}

.speed {
  display: inline-block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translateX(-50%) translateY(-50%);
  text-align: center;
  color: gray;
}

.speed .number {
  font-size: 6vw;
}

.speed .units {
  font-size: 3vw;
}
<div class="ring">
  <div class="speed">
    <div class="number">21</div>
    <div class="units" style=";">km/h</div>
  </div>
</div>

我修改了上面的代码,以便更容易动态配置百分比和颜色。

我也在这里留下另一个选择:

.gauge{
    height: 85px;
    /*overflow: hidden;*/
    position: relative;
    width: 170px;
}
.gauge .arc{
    background-image:
        radial-gradient(#fff 0, #fff 60%, transparent 60%),
        conic-gradient(red 0, orange 135deg, #ccc 135deg, #ccc 180deg, #fff 180deg, #fff 360deg);
    background-position: center center, center center;
    background-repeat: no-repeat;
    background-size: 100% 100%, 100% 100%;
    border-radius: 50%;
    border-style: none;
    height: 170px;
    position: relative;
    transform: rotate(-90deg);
    width: 100%;
}
.gauge .pointer{
    background: #fff;
    border: 1px solid #000;
    border-radius: 5px;
    bottom: 0;
    content: '';
    height: 6px;
    left: 0;
    position: absolute;
    transform: rotate(135deg) translateX(2px) translateY(-6px);
    transform-origin: 85px 0;
    width: 20px;
    z-index: 5;
}
.gauge .mask::before,
.gauge .mask::after{
    background-image: radial-gradient(transparent 0, transparent 50%, #fff 50%, #fff 100%);
    clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0% 100%);
    content: '';
    height: 18px;
    position: absolute;
    width: 18px;
}
.gauge .mask::before{
    left: -2px;
    bottom: 0;
}
.gauge .mask::after{
    bottom: 0;
    right: -2px;
}
.gauge .label{
    bottom: 20px;
    font-size: 16px;
    font-weight: 700;
    left: 0;
    line-height: 26px;
    position: absolute;
    text-align: center;
    width: 100%;
}
<div class="gauge">
    <div class="arc"></div>
    <div class="pointer"></div>
    <div class="mask"></div>
    <div class="label">75% (135°)</div>
</div>