|
const root = document.body; |
|
|
|
const Gauge = () => { |
|
return { |
|
view: ({ |
|
attrs: { |
|
/** Category colors */ |
|
colors = ["#fde7d0ff", "#fec48dff", "#fe952aff", "#e27000ff"], |
|
/** Margin around the gauge */ |
|
margin = 10, |
|
/** Inner radius */ |
|
r1 = 80, |
|
/** Outer radius */ |
|
r2 = 140, |
|
/** Value in degrees [0-180] of the gauge meter */ |
|
valueInDegrees = 0, |
|
/** Color of the gauge meter */ |
|
arrowColor = "grey", |
|
/** Base width of the gauge meter */ |
|
arrowThickness = 8, |
|
}, |
|
}) => { |
|
const arrow = r2 - arrowThickness; |
|
const count = colors.length; |
|
const width = 2 * (r2 + margin); |
|
const height = r2 + 2 * margin; |
|
const [x0, y0] = [r2 + margin, r2 + margin]; |
|
const alpha = Math.PI / count; |
|
|
|
const slices = []; |
|
let sinA0 = 0; |
|
let cosA0 = 1; |
|
let angle = alpha; |
|
for (let i = 0; i < count; i++) { |
|
let sinA1 = Math.sin(angle); |
|
let cosA1 = Math.cos(angle); |
|
const d = ` |
|
M ${x0 - r1 * cosA0} ${y0 - r1 * sinA0} |
|
A ${r1} ${r1} 0 0 1 ${x0 - r1 * cosA1} ${y0 - r1 * sinA1} |
|
L ${x0 - r2 * cosA1} ${y0 - r2 * sinA1} |
|
A ${r2} ${r2} 0 0 0 ${x0 - r2 * cosA0} ${y0 - r2 * sinA0} |
|
Z |
|
`; |
|
sinA0 = sinA1; |
|
cosA0 = cosA1; |
|
angle += alpha; |
|
slices.push(d); |
|
} |
|
|
|
return m("svg[xmlns=http://www.w3.org/2000/svg]", { width, height }, [ |
|
slices.map((d, i) => m("path", { d, fill: colors[i] })), |
|
m("path", { |
|
d: `M ${x0 - arrow} ${y0} L ${x0} ${y0 - arrowThickness} L ${x0} ${ |
|
y0 + arrowThickness |
|
} Z`, |
|
fill: arrowColor, |
|
transform: `rotate(${valueInDegrees} ${x0} ${y0})`, |
|
}), |
|
]); |
|
}, |
|
}; |
|
}; |
|
|
|
const eachFrame = cb => { |
|
cb() |
|
requestAnimationFrame(() => eachFrame(cb)) |
|
} |
|
|
|
let x = 0; |
|
eachFrame(() => { |
|
x += 0.02 |
|
const angle = 90 * (1 + Math.sin(x)) |
|
m.render(root, m(Gauge, { |
|
colors: ['#fde7d0ff', '#fec48dff', '#fe952aff', '#e27000ff'], |
|
margin: 10, |
|
r1: 80, |
|
r2: 140, |
|
arrowThickness: 8, |
|
valueInDegrees: angle |
|
})); |
|
}) |