# SVG 数值指示器
const POSITIVE_NUM = "#FF5140";
const NEGATIVE_NUM = "#00CE7D";
const HALF_ALARM = "#F2AC34";
const GREEN_DOT = "#00B69B";
// 参数:当前值、阈值、起始位置
const cancelRatioCell = (val, thre, startX = 15) => {
const _val = parseInt(val);
const _thre = parseInt(thre);
const angle =
_val > _thre || _thre === 0
? 180
: parseInt((_val / _thre) * 180);
const R1 = 17;
const R2 = 13;
const startY = 25;
const stopX = startX + 2 * R1;
let [endX, endY] = getPointsOfEllipse(startX, startY, R1, R2, angle);
return (
<span style={{ position: "relative" }}>
<svg
width="100%"
height="30px"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<linearGradient id="linearRed" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#FF9A7B" />
<stop offset="108%" stopColor="#F93C65" />
</linearGradient>
<linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor={NEGATIVE_NUM} />
<stop offset="108%" stopColor="#73D070" />
</linearGradient>
<linearGradient id="linearYellow" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stopColor="#FFD460" />
<stop offset="108%" stopColor="#FF9A7B" />
</linearGradient>
</defs>
<path
d={`M${startX},${startY} A${R1},${R2} 0,0,1 ${stopX},${startY}`}
fill="green"
stroke="#272B36"
strokeWidth="5"
fillOpacity="0"
/>
{_val != 0 && (
<path
d={`M${startX},${startY} A${R1},${R2} 0,0,1 ${endX},${endY}`}
fill="green"
strokeWidth="5"
stroke={
_val >= _thre
? "url(#linearRed)"
: _thre - _val <= 5
? "url(#linearYellow)"
: "url(#linear)"
}
fillOpacity="0"
/>
)}
<g
fontSize="11"
font="sans-serif"
fill="rgba(255,255,255,0.8)"
stroke="none"
textAnchor="right"
>
<text x={stopX} y={startY} dx="8" dy="2">
{_thre}
</text>
</g>
<g
fontSize="11"
font="sans-serif"
fill={
_val >= _thre
? POSITIVE_NUM
: _thre - _val <= 5
? HALF_ALARM
: NEGATIVE_NUM
}
stroke="none"
textAnchor="middle"
>
<text x={startX + R1} y={startY} dx="0" dy="2">
{_val}
</text>
</g>
</svg>
</span>
);
};
// 根据角度获取椭圆上点的位置
function getPointsOfEllipse(startX, startY, R1, R2, angle) {
angle = 180 - angle;
var theta = ((Math.PI * 2) / 360) * angle;
var commonBottom = Math.sqrt(R1 * R1 * Math.tan(theta) ** 2 + R2 * R2);
var x = (R1 * R2) / commonBottom;
var y = (R1 * R2 * Math.tan(theta)) / commonBottom;
if (angle > 90) {
x = -x;
}
return [startX + x + R1, startY - Math.abs(y)];
}
效果图: