美文网首页
Flutter自定义组件(绘制五角星组件)

Flutter自定义组件(绘制五角星组件)

作者: android不是安卓 | 来源:发表于2022-05-10 16:50 被阅读0次

    何用canvas绘制我们任何想要任意图案的组件,这篇文章用自定义一个五角星组件来说明。

    CsutomPaint

    自定义组件,建议用官方的CustomPaint来实现,先新建一个pantagram的类

    class Pentagram extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        final paint = Paint()..color = Colors.black;
        final rect = Offset.zero & size;
        canvas.drawRect(rect, paint);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        return false;
      }
    }
    

    它是继承CustomPainter这个类,有两个方法,shouldRepaint先写死返回false,paint方法就是真实绘制的地方,这里先绘制一个黑色的矩形
    然后在页面引用这个类

    return Scaffold(              
      appBar: AppBar(             
        title: Text('Demo Page'), 
      ),                           
      body: Center(               
        child: CustomPaint(       
          painter: Pentagram(),   
        ),                         
      ),                           
    );    
    

    运行后,发现页面是空白的,查看了下它的源码,发现是size的问题

    const CustomPaint({            
      Key? key,                    
      this.painter,                
      this.foregroundPainter,      
      this.size = Size.zero, //尺寸默认是0       
    

    size默认的尺寸是0,重新设置size后,显示正常了(个人觉得,默认的size用size.infinite更合理,充满父布局)


    使用自定义组件,绘制出了一块黑色的矩形了

    绘制path

    由于五角星属于特殊的图案,需要手动设置path,为了验证path的可行性,先绘制一个菱形来做验证

    void paint(Canvas canvas, Size size) {       
      //把画笔设置成stroke模式                           
      final paint = Paint()                      
        ..color = Colors.black                   
        ..style = PaintingStyle.stroke           
        ..strokeWidth = 2;                       
      var rect = Offset.zero & size;             
      var center = rect.center;                  
      // 连接好菱形的四个顶点                              
      final path = Path();                       
      path.moveTo(center.dx, 0);                 
      path.lineTo(rect.right, center.dy);        
      path.lineTo(center.dx, rect.bottom);       
      path.lineTo(0, center.dy);                 
      path.close(); //最后用close的方式把path封闭起来       
      // 调用canvas绘制path                          
      canvas.drawPath(path, paint);              
    }             
    

    先把画笔设置成stroke模式,然后path连接好菱形的四个顶点,最后直接绘制即可,效果如下:

    菱形绘制好了,说明path的方案可行

    绘制五角星

    既然path方案可行,接来下就是确定五角星的五个顶点,用path连接起来,代码如下:

    Path getPentagramPath(double radius) {                         
      var initDegreen = 180;                                       
      // 连接五角星的五个顶点                                                
      final path = Path();                                         
      var posOne = getOffsetPosition(initDegreen, radius);         
      path.moveTo(posOne.dx, posOne.dy);                           
      // 360/5,每个是72度                                              
      var posTwo = getOffsetPosition(72 + initDegreen, radius);    
      path.lineTo(posTwo.dx, posTwo.dy);                           
      var posThree = getOffsetPosition(144 + initDegreen, radius); 
      path.lineTo(posThree.dx, posThree.dy);                       
      var posfour = getOffsetPosition(216 + initDegreen, radius);  
      path.lineTo(posfour.dx, posfour.dy);                         
      var posFive = getOffsetPosition(288 + initDegreen, radius);  
      path.lineTo(posFive.dx, posFive.dy);                         
      //最后用close的方式把path封闭起来                                       
      path.close();                                                
      return path;                                                 
    }                                                              
                                                                   
    Offset getOffsetPosition(int degreen, double radius) {         
      //角度转成弧度                                                     
      var radian = degreen * pi / 180;                             
      var dx = sin(radian) * radius;                               
      var dy = cos(radian) * radius;                               
      return Offset(dx + radius, dy + radius);                     
    }                 
    
    看下效果图:

    结果变成五边形了,不是我们要的五角星,需要把path的线条连接方式修改下:

    var initDegreen = 180;                                      
    // 连接五角星的五个顶点,360/5,每个是72度                                  
    final path = Path();                                        
    var posOne = getOffsetPosition(initDegreen, radius);        
    var posTwo = getOffsetPosition(72 + initDegreen, radius);   
    var posThree = getOffsetPosition(144 + initDegreen, radius);
    var posfour = getOffsetPosition(216 + initDegreen, radius); 
    var posFive = getOffsetPosition(288 + initDegreen, radius); 
    path.moveTo(posOne.dx, posOne.dy);                          
    path.lineTo(posfour.dx, posfour.dy);                        
    path.lineTo(posTwo.dx, posTwo.dy);                          
    path.lineTo(posFive.dx, posFive.dy);                        
    path.lineTo(posThree.dx, posThree.dy);                      
    //最后用close的方式把path封闭起来                                      
    path.close();              
    

    这次终于看到我们需要的效果:

    这个五角星,如果要用填充的方式展示,只需要把画笔style设置成fill即可.

    final paint = Paint()            
      ..color = Colors.black         
      ..style = PaintingStyle.fill;  
    

    效果如下:

    传参

    对于自定义组件,想要一些参数,是可以外部控制的,比如五角星的颜色,可以用外部传进来。

    class Pentagram extends CustomPainter {
      Pentagram(this.color);
      //画笔的颜色
      final Color color;
    

    先定义好需要外部设置的参数,外部在使用的地方,把颜色设置进来

    child: CustomPaint(                  
      size: Size(150, 150),          
      painter: Pentagram(Colors.black),  
    ),             
    

    包括动态调整颜色和其他熟悉,也都可以实现了。

    转载自作者:韦东锏
    https://mp.weixin.qq.com/s/XV_FdANJWQijuzKKpJffkw

    相关文章

      网友评论

          本文标题:Flutter自定义组件(绘制五角星组件)

          本文链接:https://www.haomeiwen.com/subject/ggglurtx.html