osx 安装 mariadb

安装

1
brew install mariadb

启动/停止

启动/停止 mariadb 有两种方式,按需选择其中一种就可以:

  1. 方式一: 通过brew启动/停止,
    这种方法可以跟随系统启动(改plist那些操作麻烦并且会造成不稳定因素)
    启动:brew services start mariadb
    停止:brew services stop mariadb
  2. 方式二: 通过mysql.server,这个不能够跟随系统启动,每次重启MAC需要手动运行
    启动:mysql.server start
    停止:mysql.server stop

查看更多

分享到 评论

关于flutter图表控件fl_chart折线图不显示数据的问题

目前正在带领app团队使用flutter重构公司的app,我负责其中一部分,其中有需要使用图表的组件,经过调研后决定使用fl_chart,功能强大且开发人员也比较活跃。但是发现折线图不能显示当前点的数据…没问题,clone下来自己修改下。

line_chart的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
LineChartBarData _createLineChatBarData(List<FlSpot> spots, List<int> xAxisIndex) {
return LineChartBarData(
showingIndicators: xAxisIndex,
barWidth: 2, // 折线图折线宽度
spots: spots,
colors: [lineChartColor], //多个颜色会有渐变效果
isCurved: true, //平滑曲线,一般配合curveSmoothness使用
curveSmoothness: 0,
isStepLineChart: false,
dotData: FlDotData(
show: true,
dotSize: 3,
strokeWidth: 0,
showText: true, // 添加自己的属性
getTextStyle: (FlSpot spot) { // 添加自己的方法
return TextStyle(color: Colors.green);
},
getStrokeColor: (FlSpot spot, double xPercentage, LineChartBarData bar) {
return Colors.red;
},
getDotColor: (FlSpot _, double xPercentage, LineChartBarData bar) {
return Colors.red;
}
),
);
}

LineChart _chartChild() {
List<int> spotsNum = [];
widget.spotsArray.forEach((item) {
item.forEach((spot) {
spotsNum.add(spot.y.toInt());
});
});

spotsNum.addAll(widget.extraLines);
int yAxisMax = ArrayUtil.getArrMaxNum(spotsNum);
int yAxisMin = ArrayUtil.getArrMinNum(spotsNum);
List<int> xAxisIndex = widget.xAxis.asMap().keys.toList();
List<LineChartBarData> lineBarsData = widget.spotsArray.asMap().keys.map((index) {
return _createLineChatBarData(widget.spotsArray[index], xAxisIndex);
}).toList();


return LineChart(LineChartData(
maxY: yAxisMax.toDouble(), // y轴最大值
minY: yAxisMin.toDouble(), // y轴最小值
titlesData: FlTitlesData(
//标题
leftTitles: SideTitles( // Y轴
//左侧标题
margin: 15.w,
showTitles: true, //展示标题
reservedSize: 15, //标题宽度(不足会换行)
textStyle: chartTitleStyle, //标题样式
// interval: 7,
getTitles: (val) {
return null;
}
),
bottomTitles: SideTitles( // X轴
//底部标题
margin: 20.h,
showTitles: true, //展示标题
textStyle: chartTitleStyle,
getTitles: (val) {
int index = xAxisIndex.length - 1 - int.parse((val - 1).toStringAsFixed(0));
var dateString = widget.xAxis[index];
return dateString;
},
),
),
lineBarsData: lineBarsData,
borderData: FlBorderData( // 图表边框
show: false,
),
extraLinesData: ExtraLinesData( // 图表上额外的线(标准值标注)
extraLinesOnTop: true,
horizontalLines: widget.extraLines.map((line) {
return _createExternalHLine(line.toDouble());
}).toList(),
verticalLines: [],
),
gridData: FlGridData( // 图表的珊格控制
show: false,
drawHorizontalLine: false,
drawVerticalLine: false,
verticalInterval: 3
),
// showingTooltipIndicators: xAxisIndex.map((index) { // 显示tooltip的点
// return ShowingTooltipIndicators(index, lineBarsData.asMap().keys.map((idx) {
// return LineBarSpot(
// lineBarsData[idx], idx, lineBarsData[idx].spots[index]
// );
// }).toList());
// }).toList(),
// lineTouchData: LineTouchData( 图表触控控制系统(和showingTooltipIndicators搭配使用)
// enabled: false, // 设置为true则触控显示tooltip,false一直显示
//// fullHeightTouchLine: true,
// getTouchedSpotIndicator: (LineChartBarData barData, List<int> spotIndexes) {
// return spotIndexes.map((index) {
// return TouchedSpotIndicatorData(
// FlLine(
// color: Colors.transparent,
// ),
// FlDotData(
// show: true,
// dotSize: 0,
// strokeWidth: 3,
// getStrokeColor: (spot, percent, barData) => _getCurColorByIndex(widget.status, index),
// ),
// );
// }).toList();
// },
// touchTooltipData: LineTouchTooltipData( // tooltip样式控制
// tooltipBgColor: Colors.transparent,
// tooltipRoundedRadius: 0,
// tooltipBottomMargin: 0,
// getTooltipItems: (List<LineBarSpot> touchedSpots) {
//// if (touchedSpots == null) {
//// return null;
//// }
// return touchedSpots.map((LineBarSpot touchedSpot) {
//// if (touchedSpot == null) {
//// return null;
//// }
// final TextStyle textStyle = TextStyle(
// color: Colors.red,
// fontWeight: FontWeight.bold,
// fontSize: 10,
// );
// return LineTooltipItem(touchedSpot.y.toString(), textStyle);
// }).toList();
// }
// ),
// ),
}

单折线使用showingTooltipIndicators和lineTouchData配合即可实现显示点的数值,效果大致如下:

single

但是如果为多折线,所有数据会显示在最上,效果如下:

multi

显然和我们期待的不一致,所以需要另辟蹊径…

解决方法

查阅Fl_Chart的源码后发现,折线图文件分为“line_chart.dart”,”line_chart_data.dart”和“line_chart_painter.dart”三个文件,其中line_chart调用另两个文件,line_chart_data提供数据结构,也就是各种类文件,line_chart_painter负责具体绘制。

而我们需要做的就是在绘制图表上的点的同时,把当前点的y轴数值绘制上就可以了,经过一番查找,line_chart_data中 FlDotData负责定义点的数据,line_chart_painter中 _drawDots负责绘制,修改如下:

  1. 首先将fl_chart图表库放入plugins文件夹中,使用本地库引用。

  2. 在FlDotData的类中加入三个新属性:

    1
    2
    3
    4
    5

    @required bool showText, // 控制是否显示数值
    GetTextStyleCallback getTextStyle, // 数值样式
    Offset textOffset, // 数值偏移 (没用,还没实现)

  3. 在line_chart_painter的_drawDots中的

    1
    for (int i = 0; i < barData.spots.length; i++) {}

    循环最后加入绘制当前点的代码即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    // 修改:在每个点上面显示数值  = =
    void _drawDots(Canvas canvas, Size viewSize, LineChartBarData barData) {
    if (!barData.dotData.show || barData.spots == null || barData.spots.isEmpty) {
    return;
    }
    viewSize = getChartUsableDrawSize(viewSize);

    final barXDelta = _getBarLineXLength(barData, viewSize);

    for (int i = 0; i < barData.spots.length; i++) {
    final FlSpot spot = barData.spots[i];
    if (barData.dotData.checkToShowDot(spot, barData)) {
    final double x = getPixelX(spot.x, viewSize);
    final double y = getPixelY(spot.y, viewSize);

    final double xPercentInLine = ((x - getLeftOffsetDrawSize()) / barXDelta) * 100;

    final dotColor = barData.dotData.getDotColor(spot, xPercentInLine, barData);

    if (barData.dotData.getStrokeColor != null && barData.dotData.strokeWidth != null) {
    canvas.drawCircle(
    Offset(x, y),
    barData.dotData.dotSize + (barData.dotData.strokeWidth / 2),
    _dotPaint
    ..color = barData.dotData.getStrokeColor(spot, xPercentInLine, barData)
    ..strokeWidth = barData.dotData.strokeWidth
    ..style = PaintingStyle.stroke);
    }
    canvas.drawCircle(
    Offset(x, y),
    barData.dotData.dotSize,
    _dotPaint
    ..color = dotColor
    ..style = PaintingStyle.fill);
    // print("barData.dotData.show ${barData.dotData.show}");
    // print("barData.dotData.dotSize ${barData.dotData.dotSize}");
    // print("barData.dotData.showText ${barData.dotData.showText}");

    if (barData.dotData.showText) {
    TextStyle _defaultStyle = TextStyle(color: Colors.red, fontSize: 12, fontWeight: FontWeight.bold);
    Offset _defaultOffset = Offset(x - 8, y - 20);
    // 绘制spot点y轴数值
    final TextSpan span = TextSpan(
    style: barData.dotData.getTextStyle(spot),
    text: "${spot.y.toInt()}",
    );
    final TextPainter tp = TextPainter(
    text: span,
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
    textScaleFactor: textScale);
    tp.layout();
    final drawOffset = _defaultOffset;
    tp.paint(canvas, drawOffset);
    }
    }
    }
    }

最后效果如图:

final

分享到 评论

使用travis仓库公钥替换自己主机公钥

每次重装完电脑,自己本机的密钥就没了,在去配置blog的密钥登陆也是一大麻烦,当然也可以重装前备份,那么有没有别的办法,不用每次这么麻烦呢?

看这里,可以获得仓库的公钥,然后将其添加到 authorized_keys 即可。

获取仓库公钥

1
travis pubkey -r wxrbwran/wxrbwran.github.io

输出如下。

1
2
3
Public key for wxrbwran/wxrbwran.github.io

ssh-rsa ......

将公钥添加到 authorized_keys

1
2
3
4
5
mkdir .ssh
chmod 700 .ssh
touch .ssh/authorized_keys
chmod 600 .ssh/authorized_keys
vim .ssh/authorized_keys # 添加上面的公钥

使用该方案,无需方案一的添加 before_install 的步骤。

然后分别加入到github中和腾讯云主机中,这样travis就可以自主登录操作了。

分享到 评论

nextjs项目的部署

常规部署

Export静态资源

提到发布页面,就不能不提到Next提供的这个功能了,前面也减少过,但是很简单的介绍的,正好这个Demo全是静态页,没有任何数据获取操作~
Export的功能就是通过配置,将对应的pages下的路由页面导出成静态html文件。

查看更多

分享到 评论

pm2简易手册

PM2 使用手册

对于线上项目,如果直接通过 node app 来启动,如果报错了可能直接停止导致整个服务崩溃,一般监控 node 有几种方案。

  • supervisor: 一般用作开发环境的使用。
  • forever: 管理多个站点,一般每个站点的访问量不大的情况,不需要监控。
  • PM2: 网站的访问量比较大,需要完整的监控页面。

开发是使用的是nodemon,部署是后端人员操作,一直没有深入使用过pm2,这次部署next项目,正好熟习一下。


查看更多

分享到 评论