Skip to content

Instantly share code, notes, and snippets.

@derekedelaney
Last active December 21, 2022 00:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save derekedelaney/cba2c97d4d25244e1de0708d6a3f1eac to your computer and use it in GitHub Desktop.
Save derekedelaney/cba2c97d4d25244e1de0708d6a3f1eac to your computer and use it in GitHub Desktop.
A CustomCliper dart pad example
import 'dart:math';
import 'package:flutter/material.dart';
class FirstClipper extends CustomClipper<Path> {
FirstClipper();
@override
Path getClip(Size size) {
final path = Path();
final width = size.width;
final height = size.height;
final halfHeight = height / 2;
path.moveTo(0, 0);
path.lineTo(width - halfHeight, 0);
path.lineTo(width, height / 2);
path.lineTo(width - halfHeight, height);
path.lineTo(0, height);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
class SecondClipper extends CustomClipper<Path> {
SecondClipper();
@override
Path getClip(Size size) {
final path = Path();
final width = size.width;
final height = size.height;
final halfHeight = height / 2;
path.moveTo(0, 0);
path.lineTo(width - halfHeight, 0);
path.lineTo(width, height / 2);
path.lineTo(width - halfHeight, height);
path.lineTo(0, height);
path.lineTo(halfHeight, height / 2);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
class ThirdClipper extends CustomClipper<Path> {
ThirdClipper();
@override
Path getClip(Size size) {
final path = Path();
final width = size.width;
final height = size.height;
final halfHeight = height / 2;
path.moveTo(0, 0);
path.lineTo(width - halfHeight, 0);
path.arcToPoint(
Offset(width, height / 2),
radius: Radius.circular(height / 2),
);
path.arcToPoint(
Offset(width - halfHeight, height),
radius: Radius.circular(height / 2),
);
path.lineTo(0, height);
path.lineTo(halfHeight, height / 2);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
class CircleClipper1 extends CustomClipper<Path> {
CircleClipper1({required this.thickness});
final double thickness;
@override
Path getClip(Size size) {
final height = size.height;
final width = size.width;
final innerCircle = width - thickness;
final path = Path();
path.moveTo(0, height);
path.lineTo(thickness, height);
path.arcToPoint(
Offset(width, thickness),
radius: Radius.circular(innerCircle),
);
path.lineTo(width, 0);
path.arcToPoint(
Offset(0, height),
radius: Radius.circular(width),
clockwise: false,
);
path.close();
return path;
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
class CircleClipper2 extends CustomClipper<Path> {
CircleClipper2({required this.thickness});
final double thickness;
@override
Path getClip(Size size) {
final height = size.height;
final width = size.width;
final innerCircle = width - thickness;
const endingDegree = 305.0;
final path = Path();
final center = Point<double>(width, 0);
path.moveTo(0, 0);
path.lineTo(thickness, 0);
path.arcToPoint(
getOffsetOnCircle(center, innerCircle, 295),
radius: Radius.circular(innerCircle),
clockwise: false,
);
path.arcToPoint(
getOffsetOnCircle(center, innerCircle + 15, endingDegree),
radius: const Radius.circular(15),
);
path.lineTo(
getOffsetOnCircle(center, width, endingDegree).dx,
getOffsetOnCircle(center, width, endingDegree).dy,
);
path.arcToPoint(
const Offset(0, 0),
radius: Radius.circular(width),
);
path.close();
return path;
}
Offset getOffsetOnCircle(Point<double> c, double r, double deg) {
final x = c.x + r * sin(deg * pi / 180);
final y = c.y + r * cos(deg * pi / 180);
return Offset(x, y);
}
@override
bool shouldReclip(CustomClipper<Path> oldClipper) {
return false;
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: LayoutBuilder(builder: (context, constraints) {
const numberOfSections = 5;
const height = 70.0;
const spaceBetween = 10;
const overlapDistance = (height / 2) - spaceBetween;
final width = (constraints.maxWidth / numberOfSections) +
overlapDistance -
spaceBetween;
return Column(
children: [
SizedBox(
height: height,
child: Stack(
children: <Widget>[
Positioned(
left: 0,
child: SizedBox(
width: width,
child: ClipPath(
clipper: FirstClipper(),
child: Container(
height: height,
color: Colors.blue,
child: const Center(child: Text("Some Text")),
),
),
),
),
Positioned(
left: width - overlapDistance,
child: SizedBox(
width: width,
child: ClipPath(
clipper: SecondClipper(),
child: Container(
height: height,
color: Colors.green,
child: const Center(child: Text("Some Text")),
),
),
),
),
Positioned(
left: (width - overlapDistance) * 2,
child: SizedBox(
width: width * 2,
child: ClipPath(
clipper: SecondClipper(),
child: Container(
height: height,
color: Colors.green,
child: const Center(child: Text("Some Text")),
),
),
),
),
Positioned(
left: (width - overlapDistance) * 4 + overlapDistance,
child: SizedBox(
width: width,
child: ClipPath(
clipper: ThirdClipper(),
child: Container(
height: height,
color: Colors.green,
child: const Center(child: Text("Some Text")),
),
),
),
),
],
),
),
const SizedBox(height: 5),
Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
ClipPath(
clipper: CircleClipper1(thickness: 35),
child: Container(
height: 100,
width: 100,
color: Colors.green,
),
),
const SizedBox(width: 5),
Transform.scale(
scaleX: -1,
child: ClipPath(
clipper: CircleClipper1(thickness: 35),
child: Container(
height: 100,
width: 100,
color: Colors.green,
),
),
),
],
),
const SizedBox(height: 5),
Row(
mainAxisSize: MainAxisSize.min,
children: [
ClipPath(
clipper: CircleClipper2(thickness: 35),
child: Container(
height: 100,
width: 100,
color: Colors.blue,
),
),
const SizedBox(width: 5),
Transform.scale(
scaleX: -1,
child: ClipPath(
clipper: CircleClipper2(thickness: 35),
child: Container(
height: 100,
width: 100,
color: Colors.green,
),
),
),
],
),
],
),
const Positioned(
right: 0,
left: 0,
top: 0,
bottom: 0,
child: Icon(
Icons.check_circle,
size: 56,
color: Colors.green,
),
),
],
),
],
);
}),
),
);
}
}
@derekedelaney
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment