SVG 组件在浏览器之间的渲染不一致

问题描述 投票:0回答:1

我正在开发一个 SVG 仪表组件,该组件在 Chrome 中完美运行,但在 Safari 和 Firefox 中存在渲染问题。仪表使用渐变填充和旋转指针显示进度。在 Chrome 中,一切都会正确呈现,但在 Safari 和 Firefox 中,仪表样式不正确。

我已经尝试过:

  1. 调整
    transform-box
    transform-origin
    CSS 属性。
  2. 修改SVG结构并使用JavaScript计算路径。

这是我的组件:https://codesandbox.io/p/sandbox/falling-meadow-n7jtxr?file=%2Fsrc%2FGauge.jsx%3A6%2C31

在 Safari 和 Firefox 中,仪表的样式不正确,并且进度和指针旋转未按预期应用。我尝试了多种解决方案但没有成功。任何有关使该仪表组件在所有浏览器上正确呈现的帮助将不胜感激。

编辑:

正如@RobertLongson所说,“Firefox尚不支持clipPath元素上的transform-origin。”,我能够通过将transform属性直接应用于路径元素来解决我的问题。

查看更新:https://codesandbox.io/p/sandbox/falling-meadow-n7jtxr?file=%2Fsrc%2FGauge.jsx%3A6%2C31

问题:

  • 这是处理此问题的明智方法吗?
  • 我的路径上的过渡在 Firefox 或 Safari 上没有动画效果。有谁知道问题可能是什么?这是一个错误吗?
javascript html css reactjs svg
1个回答
0
投票

这是一个我不依赖CSS transform-box 和transform-origin 的解决方案。

不知道是否解决了其他问题。请发表评论,我会尽力改进/回答。

document.forms.form01.range.addEventListener('input', e => {
  let val = e.target.valueAsNumber;
  let val_deg = 180 / 100 * val;
  let svg = document.getElementById('svg');
  svg.querySelector('.gauge1').setAttribute('transform', `rotate(${val_deg})`);
  svg.querySelector('.gauge2').setAttribute('transform', `rotate(${val_deg})`);
  let val_extra = (val > 99) ? 110 : val;
  svg.querySelector('.meter1').setAttribute('stroke-dasharray', `${val_extra + 50} 200`);
  svg.querySelector('.meter2').setAttribute('stroke-dasharray', `${val + 2} 200`);
  svg.querySelector('.text').textContent = `${val}%`;
});
<div style="width: 300px; margin: 0px auto;">
  <div class="container undefined">
    <div class="svg-container">
      <svg id="svg" viewBox="0 0 172 95">
        <defs>
          <linearGradient id="lg1" x1="0" y1="75" x2="0" y2="-75"
            gradientUnits="userSpaceOnUse">
            <stop stop-color="#BC0117" offset="0"></stop>
            <stop stop-color="#FF8A35" offset="0.225"></stop>
            <stop stop-color="#FFBF0B" offset="0.47"></stop>
            <stop stop-color="#C3B30C" offset="0.735"></stop>
            <stop stop-color="#008A10" offset="0.96"></stop>
          </linearGradient>
          <mask id="m1">
            <circle transform="rotate(180)" r="74" fill="none"
              stroke="white" stroke-width="20" stroke-dasharray="100 200"
              pathLength="200" stroke-linecap="round" />
          </mask>
          <mask id="m2">
            <circle r="60" fill="none" stroke="white" stroke-width="4"
              stroke-dasharray=".4 9.6" pathLength="300" />
          </mask>
          <mask id="m3">
            <g transform="rotate(90)">
              <rect class="gauge1" transform="rotate(45)" fill="white"
                x="63.5" y="-2.5" width="21" height="6" rx="2" ry="2" />
            </g>
          </mask>
        </defs>
        <g transform="translate(86 85)">
          <g mask="url(#m1)">
            <circle r="74" fill="none" stroke="#ddd" stroke-width="20" />
            <circle class="meter1" r="74" fill="none" stroke="url(#lg1)"
              stroke-width="20" transform="rotate(90)"
              stroke-dasharray="100 200" stroke-dashoffset="0"
              pathLength="200"/>
          </g>
          <g mask="url(#m2)" transform="rotate(180)">
            <circle r="60" fill="none" stroke="#999" stroke-width="5"
              pathLength="200" />
            <circle class="meter2" r="60" fill="none" stroke="black"
              stroke-width="5" pathLength="200" stroke-dasharray="50 200" />
          </g>
          <circle transform="rotate(90)" mask="url(#m3)" r="74"
            fill="none" stroke="url(#lg1)" stroke-width="20" />
          <g transform="rotate(180)">
            <rect class="gauge2" transform="rotate(90)" stroke-width="1"
              stroke="#ffe40d" fill="black" fill-opacity=".2" x="63.5"
              y="-2.5" width="21" height="6" rx="2" ry="2" />
          </g>
        </g>
        <text x="50%" y="50%" dominant-baseline="middle"
          text-anchor="middle" font-size="15" class="text">50%</text>
      </svg>
    </div>
  </div>
  <form name="form01">
    <input name="range" type="range" min="0" max="100"
      style="width: 300px; margin: 20px auto; display: block;" value="50">
  </form>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.