flutter 版能力图

话不多说,先上图

先说下大概思路:

1,根据半径画最外圈的最浅色的那个背景,然后半径一次减少,画颜色比较深的背景+

(1)先计算渐变色背景的各个点的坐标,公式:x = R * cos(角度 - Π/2),y = R * sin(角度 - Π/2),这里减Π/2是为了符合x,y坐标的变化规律,因为原点是取在图形中心

(2)再使用paint画出各个颜色的背景,记得save和restore一下,保存画的效果(这里如果是用安卓的话,会有UI过度绘制的问题,按理说应该要每块区域每块区域地画,但是那样计算量太大了,于是放弃)

2,利用上面计算出来的最外圈的一组点坐标,将中间的分割白线画好,如果渐变色背景画在白线前,会出现白线被覆盖的情况,所以要注意绘图顺序

3,使用公式:x = (R +d)* cos(角度 - Π/2),y = (R +d) * sin(角度 - Π/2)计算出文字距离中心的距离,其中d为自己调节的值,想文字远一点就大一点,否则小一点,即为这一段,上面两个map是求出能力值的点坐标,下面两个是求出文字点的坐标,具体距离中心要多少距离,自己将代码中的60和50根据需要自己调节即可,这里在i=0的情况下是因为这两组点的坐标只需要计算一次

(1)计算

(2)画出文字,这里注意一下,文字是根据你计算的点作为文字左上角开始绘制,所以在绘制的时候,Offset的x坐标要根据pc的宽度进行减少一半以便文字居中,y坐标可以根据实际情况进行微调

4,计算出能力值线条的各个点坐标,进行绘制

(1)使用公式,x = (能力值/100)* (R +d)*cos(角度 - Π/2),y = (能力值/100)* (R +d) * sin(角度 - Π/2), 计算出能力值线条的各个点坐标

(2)绘制能力值线条,记得在path确定好后要close一下,这样是为了将最后一个点和第一个点进行连接

5,最后在view中进行调用即可,第一个参数是渐变色背景板半径,第二个数组是各能力的数值,第三个数组是各能力的名称,这两个数组的长度一定要是一样的!!!想要增加能力的种类,只需要在数组里面各加上对应的值即可。

这里map是可以用list代替的,写完了就懒得改了,反正调用写法都一样(→_→)

最后附上源码,如有不对,希望不吝赐教,

PS:如果有帮助,打个赏呗...XD

import 'dart:ui';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'dart:math';

class AbilityView extends CustomPainter{
  final List<int> _ab;//各能力的数值list,100为满分
  final double _r;//最外圈的半径
  final List<String> _abName;//能力名称list

  AbilityView(this._r, this._ab, this._abName);

  @override
  void paint(Canvas canvas, Size size) {
    _paintBack(canvas,size);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }

  void _paintBack(Canvas canvas,Size size) {
    canvas.translate(size.width/2, size.height/2 + 15);//移动到图中心,纵坐标根据需求微调
    var _angle = pi * 2 / _ab.length;
    List<Color> _colorList = [Color.fromARGB(255, 235, 235, 235),Color.fromARGB(255, 218, 215, 217),Color.fromARGB(255, 189, 176, 185),Color.fromARGB(255, 167, 144, 159),Color.fromARGB(255, 148, 120, 138),Color.fromARGB(255, 122, 90, 111),Color.fromARGB(255, 111, 77, 99)];
    List<Map<int,double>> _xPointList = [];//每层的各个点x坐标
    List<Map<int,double>> _yPointList = [];//每层的各个点y坐标
    Map<int,double> _xPointMap = {};//int--能力值索引,double--能力值x坐标
    Map<int,double> _yPointMap = {};//int--能力值索引,double--能力值y坐标
    Map<int,double> _xTextMap = {};//int--能力值文字索引,double--能力值文字x坐标
    Map<int,double> _yTextMap = {};//int--能力值文字索引,double--能力值文字y坐标

    var _dividerPaint = Paint()..color = Colors.white..style = PaintingStyle.stroke..strokeWidth = 1.5..strokeCap = StrokeCap.round;
    for(int i = 0; i < _colorList.length;i++){
      Map<int,double> _xMap = {};//int--点索引,double--点x坐标
      Map<int,double> _yMap = {};//int--点索引,double--点y坐标
      for(int j = 0; j < _ab.length;j++){
        double r = _r * (_colorList.length - 1 - i)/_colorList.length;
        var _x = (r+30) * cos(j*_angle - pi /2);//加30是让最中间的圈大一点
        var _y = (r+30) * sin(j*_angle - pi /2);//加30是让最中间的圈大一点
        _xMap[j] = _x;
        _yMap[j] = _y;
        if(i == 0){
          _xPointMap[j] = _ab[j]/100 * ((r+30)*cos(j*_angle - pi /2));//这边加30是为了和上面的半径保持一致
          _yPointMap[j] = _ab[j]/100 * ((r+30)*sin(j*_angle - pi /2));//这边加30是为了和上面的半径保持一致
          _xTextMap[j] = (r+60)*cos(j*_angle - pi /2);//字只需要延长半径即可
          _yTextMap[j] = (r+50)*sin(j*_angle - pi /2);//字只需要延长半径即可
        }
      }
      _xPointList.add(_xMap);
      _yPointList.add(_yMap);
    }

    var _paint = Paint()
        ..style = PaintingStyle.fill
        ..isAntiAlias = true;
    //画出渐变色背景板
    for(int i = 0;i < _xPointList.length;i++){
      canvas.save();
      Map<int,double> xMap = _xPointList[i];
      Map<int,double> yMap = _yPointList[i];
      Path bg = Path();
      bg.moveTo(xMap[0], yMap[0]);
      for(int j = 1;j < _ab.length;j++){
        bg.lineTo(xMap[j], yMap[j]);
      }
      canvas.drawPath(bg,_paint..color = _colorList[i]);
      canvas.restore();
    }
    //画出白色分割线
    for(int i = 0;i < _ab.length;i++){
      canvas.drawLine(Offset(0, 0), Offset(_xPointList[0][i], _yPointList[0][i]), _dividerPaint);
    }
    //画出文字
    var pc = ParagraphConstraints(width: 70);//根据文字数量微调
    for(int i = 0;i < _ab.length;i++){
      ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
        textAlign: TextAlign.center,
        fontStyle: FontStyle.normal,
        fontSize: 12
      ))
        ..pushStyle(ui.TextStyle(color: Color.fromARGB(255, 96, 63, 84)))
        ..addText('${_abName[i]}\n${_ab[i]}');
      var paragraph = pb.build()..layout(pc);
      canvas.drawParagraph(paragraph, Offset(_xTextMap[i]-35, _yTextMap[i]-15));//根据需求微调
    }

    Path point = Path();//能力值的线条
    point.moveTo(_xPointMap[0], _yPointMap[0]);
    for(int i = 1;i < _xPointMap.length;i++){
      point.lineTo(_xPointMap[i], _yPointMap[i]);
    }
    point.close();
    canvas.drawPath(point, _paint..color = Color.fromARGB(177, 96, 63, 84));

    var _linePaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2.0
      ..isAntiAlias = true;
    canvas.drawPath(point, _linePaint..color = Color.fromARGB(255, 96, 63, 84));

    canvas.save();
    canvas.restore();
  }
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter开发者是指拥有使用Flutter框架进行移动应用开发的技能和经验的人。Flutter是由Google开发的一种跨平台移动应用开发框架,可以用于同时在iOS和Android平台上构建高性能、美观的应用程序。 作为一个Flutter开发者,我具备以下技能和特点: 1. 扎实的Dart编程语言基础:Flutter使用Dart作为开发语言,所以熟悉Dart语法和常用库对于开发者来说是必备的。 2. 了解Flutter框架:熟悉Flutter框架的各种组件和功能,能够运用这些组件构建界面、处理用户输入、管理状态等。 3. 跨平台开发能力Flutter可以实现一次编写,多平台运行,我能够使用Flutter开发跨平台应用,减少了开发周期和成本。 4. UI设计和交互设计能力:通过使用Flutter的强大UI组件库,我可以创建精美的用户界面,并且能够与用户进行良好的交互。 5. 掌握RESTful API集成:在应用中使用Web服务进行数据获取和交互是常见的需求,我具备使用Dart的http库进行RESTful API集成的经验。 6. 熟悉本控制工具:如Git,能够与团队协作、管理代码库,并且有解决代码冲突和分支管理的经验。 7. 热爱学习和探索新技术:作为一个Flutter开发者,我时刻关注Flutter的最新动态,学习并应用新的技术和框架。 总结来说,作为一个Flutter开发者,我具备扎实的编程基础,熟练掌握Flutter框架和Dart编程语言,能够构建高性能、美观的跨平台移动应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值