【问题标题】:Progress circle - draw a small arc at the end tip of the circle + more进度圆 - 在圆的末端画一个小圆弧 + 更多
【发布时间】:2016-05-10 01:00:14
【问题描述】:

如何在进度圈的末端画一个小圆圈,并在其下方/上方添加一个小文本块?

img 示例:

<div class="radial-progress" data-progress="0">
    <div class="circle">
    <div class="img"></div>
        <div class="mask full">
            <div class="fill"></div>
        </div>
        <div class="mask half">
            <div class="fill"></div>
            <div class="fill fix"></div>
        </div>
        <div class="shadow"></div>
    </div>
    <div class="inset">
        <div class="percentage">
            <div class="numbers"><span>-</span><span>0%</span><span>1%</span> <!--- lots of spans --->
        </div>
    </div>
</div>

感谢 Andre 的 medium.com 文章,我已经稍微编辑了他的版本 - 更新的版本说明了我想要动态实现给定的 % 值:http://codepen.io/Inlesco/pen/pgKXeG

但是,编译后的 CSS 太多了。对于 100 个中的每一个 %,将有太多的 CSS 用于定位。当前的 CSS(@codepen 示例)已经重约 50 KB。不是最佳做法。

我已经在基于 JS Canvas 的变体上取得了一些进展,将 vert&horz 居中的 img 定位在画布上方。但这真的是打造好看的响应式网站的唯一方法和最佳实践吗?

【问题讨论】:

  • 您为提出这个问题所付出的努力值得称赞,但(至少)我觉得它令人困惑和不清楚。对于初学者来说,图像的完整版本会有所帮助,而不是其中的一部分。其次,CodePen 更像是一个馅饼而不是进度条/圆圈,所以我真的不明白你所说的 tip 是什么意思。
  • 我已经用一个固定百分比值的示例更新了 codepen,现在可能更清楚了 :) “tip”可能是指弧的终点。

标签: css canvas responsive-design geometry css-shapes


【解决方案1】:

CSS 绝对不是执行此操作的正确工具,我强烈建议您放弃这个想法。 Canvas 绝对是一个不错的选择,但对于响应式网站,我建议您使用 SVG。使用 SVG,可以很容易地根据用户输入绘制进度圈,并在其尖端添加圆圈/点。

以下是首先创建进度圈必须执行的步骤:

  • 获取进度圆的用户输入(0 到 100),然后根据它计算圆弧的角度。公式将是 (输入 * 360/100),因为一个圆有 360 度。
  • SVG 弧线通常从时钟中 3 的位置开始,因此计算出的弧线角度必须负 90 度偏移。也就是说,弧度必须在 -90 度到 270 度之间。
  • 使用公式 -(以度为单位的角度 * PI / 180)将计算出的角度转换为弧度。
  • 计算出弧度角后,使用简单的三角函数根据角度在圆上找到一个点:

    • X 坐标 = Cos(以弧度为单位的角度)* 半径 + 中心点的 X 坐标。
    • Y 坐标 = Sin(以弧度为单位的角度)* 半径 + 中心点的 Y 坐标。
  • 找到点后,我们需要创建路径,使其从上一步中找到的点开始,到达圆心,然后到达圆弧的起点,然后从该点再次将弧线绘制到原始点。以这种方式创建路径是因为我们需要在所需点结束路径(因为我们会将标记附加到终点)。

  • 创建圆弧时要注意的一点是,任何大于 180 度的角度都需要两个圆弧命令来创建。第一个弧将是 12 的时钟位置到 6 的位置,下一个弧将是其余的。因此,我们使用了 if/else 循环。

要在其尖端添加点/圆,需要执行以下操作:

  • marker 元素被添加到 SVG,并使用circle 元素创建圆形标记。 circle 元素具有 3 个属性 - cx、cy 是圆点的中心点,r 是圆点的半径。
  • 使用marker-end 属性,然后将此标记添加到path。设置此属性将意味着创建的任何路径都会在其终点自动附加此点。不需要为此进行其他编码,因为 SVG 会自动处理定位。

也可以使用text 元素添加文本,然后可以使用xy 属性设置其位置。 (这点还需要在下面的 sn-p 中调优。

演示:

下面是一个非常粗略的实现演示。

window.onload = function() {
  var btn = document.querySelector('button'),
    inp = document.querySelector('#progress'),
    path = document.querySelector('#p'),
    text = document.querySelector('#val'),
    rect = document.querySelector('rect'),
    output = document.querySelector('#path-output');
  var x = 0,
    y = 0,
    r = 30,
    cx = 50,
    cy = 50,
    d = '',
    fill = 'yellowgreen',
    stroke = 'transparent';
  btn.addEventListener('click', function() {
    progress = (inp.value == '') ? 0 : inp.value;
    arcRad = ((progress * 360 / 100) - 90) * Math.PI / 180;

    x = Math.cos(arcRad) * r + cx;
    y = Math.sin(arcRad) * r + cy;

    if (progress > 0 && progress <= 50) {
      d = 'M' + x + ',' + y + ' L' + cx + ',' + cy + ' L' + cx + ',' + (cy - r) + ' A' + r + ',' + r + ' 0 0,1' + x + ',' + y;
      setColors(fill, stroke);
      setOutput();
    } else if (progress > 50 && progress <= 100) {
      d = 'M' + x + ',' + y + ' L' + cx + ',' + cy + ' L' + cx + ',' + (cy - r) + ' A' + r + ',' + r + ' 0 0,1' + cx + ',' + (cy + r) + ' A' + r + ',' + r + ' 0 0,1' + x + ',' + y;
      setColors(fill, stroke);
      setOutput();
    } else {
      text.innerHTML = '';
      path.setAttribute('d', '');
      output.innerHTML = 'Enter a value between 0 and 100';
      setColors('transparent', 'transparent');
    }

    if (progress > 0 && progress <= 10) {
      rect.setAttribute('x', x);
      rect.setAttribute('y', y + 7.5);
      text.setAttribute('x', x + 2);
      text.setAttribute('y', y + 15);
    } else if (progress > 10 && progress <= 62) {
      rect.setAttribute('x', x - 5);
      rect.setAttribute('y', y + 7.5);
      text.setAttribute('x', x - 3.5);
      text.setAttribute('y', y + 15);
    } else if (progress > 62 && progress <= 100) {
      rect.setAttribute('x', x - 5);
      rect.setAttribute('y', y - 15);
      text.setAttribute('x', x - 3.5);
      text.setAttribute('y', y - 7.5);
    }

  });

  function setColors(fill, stroke) {
    rect.setAttribute('fill', fill);
    rect.setAttribute('stroke', stroke);
    path.setAttribute('fill', fill);
    path.setAttribute('stroke', stroke);
  }

  function setOutput() {
    path.setAttribute('d', d);
    text.innerHTML = progress;
    output.innerHTML = 'Angle in Radians: ' + arcRad + '<br/>';
    output.innerHTML += 'Point in Circle: ' + x + ',' + y + '<br/>';
    output.innerHTML += 'Path d attribute: ' + d;
  }
}
svg {
  width: 200px;
  height: 200px;
}
.output {
  min-height: 20px;
}
h4 {
  border-bottom: 1px solid;
}
<input id='progress' type='number' />
<button>Generate</button>
<br/>
<svg viewBox='0 0 100 100'>
  <defs>
    <marker id='dot' viewBox='0 0 10 10' markerHeight='10' markerWidth='10' refX='5' refY='5'>
      <circle cx='5' cy='5' r='2' />
    </marker>
  </defs>
  <path d='' marker-end='url(#dot)' id='p' stroke='transparent' fill='transparent' />
  <rect height='10' width='10' x='10' y='10' stroke='transparent' fill='transparent' />
  <text x='10' y='10' id='val' font-family='Arial' font-size='6'></text>
</svg>
<div class='output'>
  <h4>Output:</h4>
  <output id='path-output'></output>
</div>

进一步阅读:

您可以在以下链接中阅读有关 SVG、其元素和属性的更多信息:

SVG Paths | Marker element | Text element | Circle element

【讨论】:

  • 很棒的例子和解释!非常感谢!既然我走在正确的道路上,我会在晚上回来提供解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-08
  • 1970-01-01
  • 2020-03-19
  • 1970-01-01
相关资源
最近更新 更多