audioVisualizerShapes function
The shapes style draws for levels, one level per band from 0 to 1, in
a box of width by height whose top-left corner is the origin.
barFill is how much of its share a bar fills; see
LayerAudioVisualizer.barFill. null takes the style's own, as does a
value outside above 0 to 1, which the native renderers never receive.
The Android, iOS and macOS renderers compute the same shapes from the same numbers; a change here has to be made there too.
Implementation
AudioVisualizerShapes audioVisualizerShapes({
required AudioVisualizerStyle style,
required double width,
required double height,
required List<double> levels,
double? barFill,
}) {
final count = levels.length;
if (count == 0 || width <= 0 || height <= 0) {
return const AudioVisualizerShapes();
}
double level(int band) => audioVisualizerUnitLevel(levels[band]);
final fill = barFill != null && barFill > 0 && barFill <= 1 ? barFill : null;
switch (style) {
case AudioVisualizerStyle.bars:
case AudioVisualizerStyle.mirroredBars:
final slot = width / count;
final barWidth = slot * (fill ?? audioVisualizerBarFill);
// A silent bar is a dot as wide as the bar.
final minHeight = math.min(barWidth, height);
return AudioVisualizerShapes(
bars: [
for (var band = 0; band < count; band++)
_bar(
left: band * slot + (slot - barWidth) / 2,
width: barWidth,
height: math.min(
height,
math.max(minHeight, level(band) * height),
),
boxHeight: height,
mirrored: style == AudioVisualizerStyle.mirroredBars,
),
],
);
case AudioVisualizerStyle.circle:
final radius = math.min(width, height) / 2;
final bars = count * 2;
final ring = radius * audioVisualizerCircleInnerRadius;
final barWidth = math.min(
2 * math.pi * ring / bars * (fill ?? audioVisualizerCircleBarFill),
(radius - ring) / 2,
);
final maxLength = math.max(0.0, radius - ring - barWidth);
return AudioVisualizerShapes(
bars: [
for (var bar = 0; bar < bars; bar++)
AudioVisualizerBar(
left: -barWidth / 2,
// The bands run from the top down both sides of the ring.
top:
-(ring +
barWidth +
level(bar < count ? bar : bars - 1 - bar) * maxLength),
right: barWidth / 2,
bottom: -ring,
radius: barWidth / 2,
pivotX: width / 2,
pivotY: height / 2,
rotation: 2 * math.pi * (bar + 0.5) / bars,
),
],
);
case AudioVisualizerStyle.wave:
return AudioVisualizerShapes(wave: _waveOutline(width, height, levels));
}
}