我正在开发一个 SVG 仪表组件,该组件在 Chrome 中完美运行,但在 Safari 和 Firefox 中存在渲染问题。仪表使用渐变填充和旋转指针显示进度。在 Chrome 中,一切都会正确呈现,但在 Safari 和 Firefox 中,仪表样式不正确。
我已经尝试过:
transform-box
和 transform-origin
CSS 属性。这是我的组件: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
问题:
这是一个我不依赖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>