Flutter - 3D 标签云 效果实现

demo 地址: https://github.com/iotjin/jh_flutter_demo

Flutter伪3D旋转标签云(在此基础上改的)
Flutter 31: 图解 TextPainter 与 TextSpan 小尝试
Flutter 33: 图解自定义 View 之 Canvas (一)
Flutter实现3D球

效果图:

Flutter - 3D 标签云 效果实现_第1张图片

Flutter - 3D 标签云 效果实现_第2张图片

调用


import 'package:flutter/material.dart';
import 'package:jh_flutter_demo/base_appbar.dart';
import 'tag_cloud_widget.dart';

var _data = [
  {"ID": "111", "name": "1.这是文字", "num": "11"},
  {"ID": "222", "name": "2.这是文", "num": "22"},
  {"ID": "333", "name": "3.这是文字文字", "num": "33"},
  {"ID": "444", "name": "4.这是文字", "num": "44"},
  {"ID": "555", "name": "5.这是文字", "num": "55"},
  {"ID": "666", "name": "6.这是", "num": "66"},
  {"ID": "777", "name": "7.这是文字", "num": "77"},
  {"ID": "888", "name": "8.这是文字", "num": "88"},
];

class TagCloudPage extends StatefulWidget {
  @override
  _TagCloudPageState createState() => _TagCloudPageState();
}

class _TagCloudPageState extends State {

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: backAppBar(context, 'TagCloudWidget'),
        backgroundColor: Color(0xFFF8F8F8),
        body: Padding(
            padding: const EdgeInsets.all(30.0),
            child: TagCloudWidget(400, _data, rpm: 3)));
  }
}

样式 是 通过 TextPainter 和 canvas 组合实现的, TextPainter 展示的文字,canvas 添加的圆角矩形

一些样式的实现

TagCloudWidget使用的
      // TextPainter 富文本 加边框
      var text = TextPainter(
          textAlign: TextAlign.center,
          text: TextSpan(
              text: '${data['name']}\n',
              style: TextStyle(fontSize: _fontSize, color: _textColor_row1),
              children: [
                TextSpan(
                    text: data['num'],
                    style:
                        TextStyle(fontSize: _fontSize, color: _textColor_row2),
                    recognizer: TapGestureRecognizer()
                      ..onTap = () {
                        print('===测试暂时有误,待研究==');
                      }),
              ]),
          textDirection: TextDirection.ltr)
        ..layout(maxWidth: 200, minWidth: 80)
        ..paint(canvas, Offset(point.x, point.y));

      paintStyle.strokeWidth = _boderWidth;

      //  正方形
//      canvas.drawRect(Rect.fromCircle(center:Offset(point.x+text.width/2, point.y+20),radius:text.width/2), paintStyle);
      //长方形
//      canvas.drawRect(Rect.fromCenter(center:Offset(point.x+text.width/2, point.y+15),width: text.width,height: 50), paintStyle);

      //圆角矩形
      canvas.drawRRect(
          RRect.fromRectAndRadius(
              Rect.fromCenter(
                  center: Offset(point.x + text.width / 2, point.y + 15),
                  width: text.width,
                  height: 50),
              Radius.circular(_boderRadius)),
          paintStyle);

其他
     /********************************* canvas  绘制球 ********************************/
      // canvas  绘制球
      var opacity = _getOpacity(point.z / size.width * 2);
      paintStyle.color = point.color.withOpacity(opacity);
      paintStyle.style = PaintingStyle.fill;
      var r = _getScale(point.z / size.width * 2) * radius;
      canvas.drawCircle(Offset(point.x, point.y), r, paintStyle);

        /********************************* canvas  绘制文字 ********************************/
      // canvas  绘制文字
      ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
        textAlign: TextAlign.center,
        fontWeight: FontWeight.w300,
        fontStyle: FontStyle.normal,
        fontSize: 12.0,
      ));
      pb.pushStyle(
        ui.TextStyle(fontSize: 15, color: Colors.red),
      );
      pb.addText('ABCDE');
      ParagraphConstraints pc = ParagraphConstraints(width: 30);
//这里需要先layout, 后面才能获取到文字高度
      Paragraph paragraph = pb.build()..layout(pc);
      canvas.drawParagraph(paragraph, Offset(point.x, point.y));

      /********************************* TextPainter 富文本 ********************************/
      // TextPainter  富文本
      TextPainter(
          text: TextSpan(
              text: '这是文字',
              style: TextStyle(fontSize: 13.0, color: Colors.white)),
          textDirection: TextDirection.ltr)
        ..layout(maxWidth: 100, minWidth: 50)
        ..paint(canvas, Offset(point.x, point.y));

      /********************************* TextPainter 富文本 多个 ********************************/
      // TextPainter 富文本 多个
      TextPainter(
          text: TextSpan(
              text: '这是',
              style: TextStyle(fontSize: 13.0, color: Colors.white),
              children: [
                TextSpan(
                    text: '红色',
                    style: TextStyle(fontSize: 18.0, color: Colors.red)),
                TextSpan(
                    text: '黑色',
                    style: TextStyle(fontSize: 12.0, color: Colors.black),
//                    recognizer: TapGestureRecognizer()
//                      ..onTap = () {
//                        print('===测试暂时有误,待研究==');
//                      }
                    recognizer: new TapGestureRecognizer()..onTap = () => print('Tap Here onTap'),
                ),
              ]),
          textDirection: TextDirection.ltr)
        ..layout(maxWidth: 100, minWidth: 50)
        ..paint(canvas, Offset(point.x, point.y));

      /******************************** canvas 文字 加边框 长方形 *********************************/

      // canvas  绘制文字
      ParagraphBuilder pb = ParagraphBuilder(ParagraphStyle(
        textAlign: TextAlign.center,
        fontWeight: FontWeight.w300,
        fontStyle: FontStyle.normal,
        fontSize: 12.0,
      ));
      pb.pushStyle(
        ui.TextStyle(fontSize: 12, color: Colors.white),
      );
      pb.addText("这是文字文字 \n ");
      pb.addText('FF');
      ParagraphConstraints pc = ParagraphConstraints(width: 90);
      Paragraph paragraph = pb.build()..layout(pc);
      canvas.drawParagraph(paragraph, Offset(point.x, point.y));

      // 长方形
      canvas.drawRect(Rect.fromCenter(center:Offset(point.x+pc.width/2, point.y+15),width: pc.width,height: 50), paintStyle);

你可能感兴趣的:(Flutter)