Skip to content

Instantly share code, notes, and snippets.

@jogboms
Last active May 30, 2022 21:03
Show Gist options
  • Save jogboms/4b69fcd642e0179eb32dcd86dec87656 to your computer and use it in GitHub Desktop.
Save jogboms/4b69fcd642e0179eb32dcd86dec87656 to your computer and use it in GitHub Desktop.
Flutter guild presentation - RenderObject demo
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(const MaterialApp(home: App()));
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) => const Scaffold(body: Center(child: SliderWidget()));
}
class SliderWidget extends LeafRenderObjectWidget {
const SliderWidget({super.key});
@override
RenderObject createRenderObject(BuildContext context) => SliderRenderObject();
}
class SliderRenderObject extends RenderBox {
late final drag = HorizontalDragGestureRecognizer()
..onStart = _onDragStart
..onUpdate = _onDragUpdate;
late Rect knobRect;
double dragPosition = 0.0;
bool canDragKnob = false;
@override
void performLayout() {
size = Constants.size;
}
@override
bool get isRepaintBoundary => true;
@override
bool hitTestSelf(Offset position) => true;
@override
void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
if (event is PointerDownEvent) {
drag.addPointer(event);
}
}
@override
void paint(PaintingContext context, Offset offset) {
final canvas = context.canvas;
final knobTrackRect = offset.shift(Constants.knobToTrackPadding) & Constants.knobTrackSize;
canvas.drawRRect(
Constants.borderRadius.toRRect(knobTrackRect),
Paint()..shader = Constants.gradient.createShader(knobTrackRect),
);
final lowerLimit = knobTrackRect.left;
final upperLimit = knobTrackRect.right;
final knobLeftPosition = dragPosition.clamp(lowerLimit, upperLimit);
final knobColor = Constants.gradientColors.mix(lowerLimit, upperLimit, knobLeftPosition);
final knobCenter = Offset(knobLeftPosition, offset.dy + size.height / 2);
knobRect = Rect.fromCircle(center: knobCenter, radius: Constants.knobRadius);
canvas
..drawShadow(
Path()..addOval(Rect.fromCircle(center: knobCenter, radius: Constants.knobRadius)),
Constants.knobShadowColor,
Constants.knobElevation,
true,
)
..drawCircle(
knobCenter,
Constants.knobRadius,
Paint()..color = Constants.knobBackgroundColor,
)
..drawCircle(
knobCenter,
Constants.knobRadius - Constants.knobToTrackPadding,
Paint()..color = knobColor,
);
}
void _onDragStart(DragStartDetails details) {
canDragKnob = knobRect.contains(details.localPosition);
}
void _onDragUpdate(DragUpdateDetails details) {
if (!canDragKnob) {
return;
}
dragPosition += details.primaryDelta!;
markNeedsPaint();
}
}
class Constants {
Constants._();
static const size = Size(720, 120);
static final knobDimension = size.height;
static final knobSize = Size.square(knobDimension);
static final knobRadius = knobDimension / 2;
static final knobToTrackPadding = knobDimension * .15;
static final knobTrackSize = Size(size.width - knobToTrackPadding * 2, size.height - knobToTrackPadding * 2);
static const knobBackgroundColor = Colors.white;
static const knobElevation = 8.0;
static const knobShadowColor = Colors.black87;
static final borderRadius = BorderRadius.circular(size.height / 2);
static const gradientColors = [Colors.blueAccent, Colors.purpleAccent];
static const gradient = LinearGradient(colors: gradientColors);
}
// https://stackoverflow.com/a/55088673/8236404
double Function(double input) interpolate({
double inputMin = 0,
double inputMax = 1,
double outputMin = 0,
double outputMax = 1,
}) {
assert(inputMin != inputMax || outputMin != outputMax);
final diff = (outputMax - outputMin) / (inputMax - inputMin);
return (input) => ((input - inputMin) * diff) + outputMin;
}
extension ShiftExtension on Offset {
Offset shift(double delta) => translate(delta, delta);
}
extension MixGradientColor on List<Color> {
Color mix(double min, double max, double value) =>
Color.lerp(first, last, interpolate(inputMin: min, inputMax: max)(value))!;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment