166 lines
4.7 KiB
Dart
166 lines
4.7 KiB
Dart
// Author: fruit.com.cn
|
|
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
/// 首页右上角搜索/礼物图标的自定义样式:
|
|
/// 搜索为粗线条放大镜(Material 图标无法调线条粗细),礼物为 emoji 红金礼盒。
|
|
|
|
/// 粗线条白色放大镜,圆环在左上、手柄朝右下。
|
|
class SearchGlyph extends StatelessWidget {
|
|
const SearchGlyph({super.key, required this.size, required this.color});
|
|
|
|
final double size;
|
|
final Color color;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return CustomPaint(
|
|
size: Size.square(size),
|
|
painter: _SearchPainter(color: color),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _SearchPainter extends CustomPainter {
|
|
const _SearchPainter({required this.color});
|
|
|
|
final Color color;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final stroke = size.width * 0.09;
|
|
final paint = Paint()
|
|
..color = color
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = stroke
|
|
..strokeCap = StrokeCap.round;
|
|
|
|
final circleDiameter = size.width * 0.7;
|
|
final direction = math.pi / 4;
|
|
// 图形只占画布左上角,先平移让它视觉居中,否则会比文字基线偏高。
|
|
final drawnExtent =
|
|
circleDiameter / 2 +
|
|
(circleDiameter / 2 + size.width * 0.12) * math.sin(direction) +
|
|
stroke / 2;
|
|
final centering = (size.width - drawnExtent) / 2;
|
|
canvas.translate(centering, centering);
|
|
|
|
final center = Offset(circleDiameter / 2, circleDiameter / 2);
|
|
canvas.drawCircle(center, circleDiameter / 2 - stroke / 2, paint);
|
|
|
|
final start =
|
|
center +
|
|
Offset.fromDirection(direction, circleDiameter / 2 - stroke * 0.2);
|
|
final end =
|
|
center +
|
|
Offset.fromDirection(direction, circleDiameter / 2 + size.width * 0.12);
|
|
canvas.drawLine(start, end, paint);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant _SearchPainter oldDelegate) =>
|
|
oldDelegate.color != color;
|
|
}
|
|
|
|
/// YMB 品牌礼盒静态图标,使用玫红礼盒与金色丝带。
|
|
class GiftGlyph extends StatelessWidget {
|
|
const GiftGlyph({super.key, required this.size});
|
|
|
|
final double size;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return CustomPaint(size: Size.square(size), painter: _GiftPainter());
|
|
}
|
|
}
|
|
|
|
class _GiftPainter extends CustomPainter {
|
|
const _GiftPainter();
|
|
|
|
static const double _designSize = 26;
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
canvas.save();
|
|
canvas.scale(size.width / _designSize);
|
|
_paintBox(canvas);
|
|
_paintRibbon(canvas);
|
|
_paintBow(canvas);
|
|
canvas.restore();
|
|
}
|
|
|
|
void _paintBox(Canvas canvas) {
|
|
final body = RRect.fromRectAndRadius(
|
|
const Rect.fromLTRB(4, 13, 22, 23),
|
|
const Radius.circular(2),
|
|
);
|
|
canvas.drawRRect(
|
|
body,
|
|
Paint()
|
|
..shader = const LinearGradient(
|
|
begin: Alignment.topLeft,
|
|
end: Alignment.bottomRight,
|
|
colors: [Color(0xFFFF5C82), Color(0xFFEF315D)],
|
|
).createShader(const Rect.fromLTRB(4, 13, 22, 23)),
|
|
);
|
|
canvas.drawRRect(
|
|
RRect.fromRectAndRadius(
|
|
const Rect.fromLTRB(3, 10, 23, 14),
|
|
const Radius.circular(1.5),
|
|
),
|
|
Paint()
|
|
..shader = const LinearGradient(
|
|
colors: [Color(0xFFFF7190), Color(0xFFF52E5C)],
|
|
).createShader(const Rect.fromLTRB(3, 10, 23, 14)),
|
|
);
|
|
}
|
|
|
|
void _paintRibbon(Canvas canvas) {
|
|
final ribbon = Paint()
|
|
..shader = const LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [Color(0xFFFFFFA8), Color(0xFFFFD52F), Color(0xFFFFB900)],
|
|
).createShader(const Rect.fromLTRB(10.5, 10, 15.5, 23));
|
|
canvas.drawRect(const Rect.fromLTRB(10.5, 13, 15.5, 23), ribbon);
|
|
canvas.drawRect(const Rect.fromLTRB(3, 10.5, 23, 14), ribbon);
|
|
canvas.drawLine(
|
|
const Offset(11, 14),
|
|
const Offset(11, 22),
|
|
Paint()
|
|
..color = const Color(0xFFFFFFAE)
|
|
..strokeWidth = 0.6,
|
|
);
|
|
}
|
|
|
|
void _paintBow(Canvas canvas) {
|
|
final gold = Paint()
|
|
..shader = const LinearGradient(
|
|
colors: [Color(0xFFFFFFA8), Color(0xFFFFD52F), Color(0xFFFFB900)],
|
|
).createShader(const Rect.fromLTRB(5, 1, 21, 12));
|
|
final tails = Path()
|
|
..moveTo(11.8, 7)
|
|
..lineTo(15, 7)
|
|
..lineTo(17, 13)
|
|
..lineTo(14.1, 12)
|
|
..lineTo(12.6, 14)
|
|
..lineTo(10.8, 8)
|
|
..close();
|
|
canvas.drawPath(tails, gold);
|
|
final bow = Path()
|
|
..moveTo(13, 7)
|
|
..cubicTo(5.2, 0, 5.2, 4.8, 7.5, 6.7)
|
|
..cubicTo(9, 8, 11.5, 8, 13, 7)
|
|
..cubicTo(14.5, 8, 17, 8, 18.5, 6.7)
|
|
..cubicTo(20.8, 4.8, 20.8, 0, 13, 7)
|
|
..close();
|
|
canvas.drawPath(bow, gold);
|
|
canvas.drawCircle(const Offset(13, 7), 1.55, gold);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant _GiftPainter oldDelegate) => false;
|
|
}
|