提交 7406558ce60b9031a949cd967375769861e954ce

作者 wangyu
1 个父辈 86c008b8

迭代

@@ -126,7 +126,8 @@ App({ @@ -126,7 +126,8 @@ App({
126 onshow_count: 0, 126 onshow_count: 0,
127 // baseUrl: "http://47.99.47.16:20000/", 127 // baseUrl: "http://47.99.47.16:20000/",
128 // baseUrl: "http://47.96.75.229:20000/", 128 // baseUrl: "http://47.96.75.229:20000/",
129 - baseUrl: "https://api.workai.com.cn/", 129 + baseUrl: "http://192.144.144.220:20000/",
  130 + // baseUrl: "https://api.workai.com.cn/",
130 OSSUrl: "",//"https://oss.workai.com.cn/", 131 OSSUrl: "",//"https://oss.workai.com.cn/",
131 userInfo: null, 132 userInfo: null,
132 hasLogin: false, 133 hasLogin: false,
@@ -14,6 +14,8 @@ @@ -14,6 +14,8 @@
14 "pages/main/advancepayment/home", 14 "pages/main/advancepayment/home",
15 15
16 "pages/main/finalpayment/home", 16 "pages/main/finalpayment/home",
  17 + "pages/main/finalpayment/inputinfo/inputinfo",
  18 + "pages/main/finalpayment/historydetail/historydetail",
17 "pages/login/login" 19 "pages/login/login"
18 ], 20 ],
19 "window": { 21 "window": {
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 47
48 .text_333_28 { 48 .text_333_28 {
49 font-family: PingFangSC-Regular; 49 font-family: PingFangSC-Regular;
50 - font-size: 26rpx; 50 + font-size: 28rpx;
51 color: #333; 51 color: #333;
52 text-align: right; 52 text-align: right;
53 line-height: 80rpx; 53 line-height: 80rpx;
@@ -57,6 +57,14 @@ @@ -57,6 +57,14 @@
57 font-family: PingFangSC-Regular; 57 font-family: PingFangSC-Regular;
58 font-size: 30rpx; 58 font-size: 30rpx;
59 color: #666; 59 color: #666;
  60 + text-align: right;
  61 +}
  62 +
  63 +.text_blue_28 {
  64 + font-family: PingFangSC-Regular;
  65 + font-size: 28rpx;
  66 + color: #3795ff;
  67 + text-align: right;
60 } 68 }
61 69
62 .text_333_30_bold { 70 .text_333_30_bold {
@@ -67,7 +75,7 @@ @@ -67,7 +75,7 @@
67 75
68 .text_999_28 { 76 .text_999_28 {
69 font-family: PingFangSC-Regular; 77 font-family: PingFangSC-Regular;
70 - font-size: 26rpx; 78 + font-size: 28rpx;
71 color: #999; 79 color: #999;
72 text-align: right; 80 text-align: right;
73 line-height: 80rpx; 81 line-height: 80rpx;
1 <!--pages/main/advancepayment/home.wxml--> 1 <!--pages/main/advancepayment/home.wxml-->
2 <view class='page'> 2 <view class='page'>
3 - <scroll-view> 3 + <scroll-view style='margin-bottom:40rpx'>
4 <view style='padding:30rpx;background:#ffffff'> 4 <view style='padding:30rpx;background:#ffffff'>
5 <view> 5 <view>
6 <text class='text_gray_32'>当前选择月份</text> 6 <text class='text_gray_32'>当前选择月份</text>
@@ -45,16 +45,61 @@ @@ -45,16 +45,61 @@
45 <text class='text_333_30_bold float_right'>32983000.00</text> 45 <text class='text_333_30_bold float_right'>32983000.00</text>
46 </view> 46 </view>
47 </view> 47 </view>
48 - <view style='padding:30rpx;positive:relative;width:92%;height:312rpx'> 48 + <view style='margin:30rpx;positive:relative;width:92%;height:312rpx'>
49 <image class=' payment_img_bg ' src='/images/payment_bg.png ' style='position:absolute;z-index: 1;'></image> 49 <image class=' payment_img_bg ' src='/images/payment_bg.png ' style='position:absolute;z-index: 1;'></image>
50 <view> 50 <view>
51 - <view style='position:absolute;z-index: 2'>  
52 - <text >38382738</text>  
53 - <!-- <text >38382739</text>  
54 - <text >38382730</text> --> 51 + <view class='view_bg_wrap' style='margin-top: 44rpx;'>
  52 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  53 + <text class='text_num_wrap'>3838.9</text>
  54 + <text class='text_text_wrap'>本期应预扣预缴税额</text>
  55 + </view>
  56 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  57 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  58 + <text class='text_num_wrap'>10398.01</text>
  59 + <text class='text_text_wrap'>已预扣预缴税额</text>
  60 + </view>
  61 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  62 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  63 + <text class='text_num_wrap'>133.09</text>
  64 + <text class='text_text_wrap'>本期应预扣预缴税额</text>
  65 + </view>
  66 + </view>
  67 +
  68 + <view class='view_bg_wrap' style='margin-top: 180rpx;'>
  69 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  70 + <text class='text_num_wrap'>30.8%</text>
  71 + <text class='text_text_wrap'>使用税率</text>
  72 + </view>
  73 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  74 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  75 + <text class='text_num_wrap'>19106.91</text>
  76 + <text class='text_text_wrap'>速算扣除数</text>
  77 + </view>
55 </view> 78 </view>
56 -  
57 </view> 79 </view>
58 </view> 80 </view>
  81 +
  82 + <view style='padding-left:30rpx;background:#ffffff'>
  83 + <image class='icon_wrap' src="/images/rectangle_icon.png"></image>
  84 + <text style='padding-left:20rpx' class='text_gray_32'>工资明细</text>
  85 + </view>
  86 + <view style='margin-top:2rpx;background:#ffffff;padding-bottom:30rpx'>
  87 + <view style='padding:30rpx'>
  88 + <text class='text_wrap_left'>公司名称</text>
  89 + <text class='text_wrap_right'>400000.00</text>
  90 + </view>
  91 + <view style='padding:30rpx'>
  92 + <text class='text_wrap_left'>计薪时间</text>
  93 + <text class='text_wrap_right'>400000.00</text>
  94 + </view>
  95 + <view style='padding:30rpx'>
  96 + <text class='text_wrap_left'>发薪时间</text>
  97 + <text class='text_wrap_right'>400000.00</text>
  98 + </view>
  99 + <view style='padding:30rpx'>
  100 + <text class='text_wrap_left'>实发工资</text>
  101 + <text class='text_wrap_right'>400000.00</text>
  102 + </view>
  103 + </view>
59 </scroll-view> 104 </scroll-view>
60 -</view>  
  105 + </view>
1 /* pages/main/advancepayment/home.wxss */ 1 /* pages/main/advancepayment/home.wxss */
2 -.page{ 2 +
  3 +.page {
3 background-color: #fcfcfc; 4 background-color: #fcfcfc;
4 } 5 }
5 6
6 .text_gray_32 { 7 .text_gray_32 {
7 font-size: 32rpx; 8 font-size: 32rpx;
8 - color: #6C7596 ; 9 + color: #6c7596;
9 font-family: PingFangSC-Semibold; 10 font-family: PingFangSC-Semibold;
10 line-height: 100rpx; 11 line-height: 100rpx;
11 } 12 }
@@ -15,10 +16,52 @@ @@ -15,10 +16,52 @@
15 width: 40rpx; 16 width: 40rpx;
16 height: 40rpx; 17 height: 40rpx;
17 margin-top: 30rpx; 18 margin-top: 30rpx;
18 - align-self: center 19 + align-self: center;
19 } 20 }
20 21
21 -.payment_img_bg{ 22 +.payment_img_bg {
22 width: 92%; 23 width: 92%;
23 height: 312rpx; 24 height: 312rpx;
24 -}  
  25 +}
  26 +
  27 +.icon_wrap {
  28 + width: 8rpx;
  29 + height: 28rpx;
  30 +}
  31 +
  32 +.view_bg_wrap {
  33 + position: absolute;
  34 + z-index: 2;
  35 + display: flex;
  36 + width: 690rpx;
  37 + flex-wrap: nowrap;
  38 +}
  39 +
  40 +.text_num_wrap {
  41 + font-family: PingFangSC-Semibold;
  42 + font-size: 18px;
  43 + color: #fff;
  44 + text-align: center;
  45 +}
  46 +
  47 +.text_text_wrap {
  48 + font-family: PingFang-SC-Medium;
  49 + font-size: 11px;
  50 + color: #fff;
  51 + text-align: center;
  52 +}
  53 +
  54 +.text_wrap_left {
  55 + font-family: PingFang-SC-Medium;
  56 + font-size: 30rpx;
  57 + color: #999;
  58 + float: left
  59 +}
  60 +
  61 +.text_wrap_right {
  62 + font-family: PingFang-SC-Medium;
  63 + font-size: 30rpx;
  64 + color: #000;
  65 + text-align: right;
  66 + float: right
  67 +}
  1 +// pages/main/finalpayment/historydetail/historydetail.js
  2 +var wxCharts = require('../../../../utils/wxcharts.js');
  3 +var app = getApp();
  4 +var pieChart = null;
  5 +Page({
  6 +
  7 + /**
  8 + * Page initial data
  9 + */
  10 + data: {
  11 +
  12 + },
  13 +
  14 + /**
  15 + * Lifecycle function--Called when page load
  16 + */
  17 + onLoad: function (options) {
  18 + var windowWidth = 320;
  19 + try {
  20 + var res = wx.getSystemInfoSync();
  21 + windowWidth = res.windowWidth;
  22 + } catch (e) {
  23 + console.error('getSystemInfoSync failed!');
  24 + }
  25 +
  26 + pieChart = new wxCharts({
  27 + animation: false,
  28 + canvasId: 'pieCanvas',
  29 + type: 'pie',
  30 + series: [{
  31 + name: '成交量2',
  32 + data: 35,
  33 + }, {
  34 + name: '成交量3',
  35 + data: 78,
  36 + }, {
  37 + name: '成交量4',
  38 + data: 63,
  39 + }, {
  40 + name: '成交量2',
  41 + data: 35,
  42 + }, {
  43 + name: '成交量3',
  44 + data: 78,
  45 + }],
  46 + width: windowWidth,
  47 + height: 280,
  48 + dataLabel: true,
  49 + });
  50 + },
  51 +
  52 + /**
  53 + * Lifecycle function--Called when page is initially rendered
  54 + */
  55 + onReady: function () {
  56 +
  57 + },
  58 +
  59 + /**
  60 + * Lifecycle function--Called when page show
  61 + */
  62 + onShow: function () {
  63 +
  64 + },
  65 +
  66 + /**
  67 + * Lifecycle function--Called when page hide
  68 + */
  69 + onHide: function () {
  70 +
  71 + },
  72 +
  73 + /**
  74 + * Lifecycle function--Called when page unload
  75 + */
  76 + onUnload: function () {
  77 +
  78 + },
  79 +
  80 + /**
  81 + * Page event handler function--Called when user drop down
  82 + */
  83 + onPullDownRefresh: function () {
  84 +
  85 + },
  86 +
  87 + /**
  88 + * Called when page reach bottom
  89 + */
  90 + onReachBottom: function () {
  91 +
  92 + },
  93 +
  94 + /**
  95 + * Called when user click on the top right corner to share
  96 + */
  97 + onShareAppMessage: function () {
  98 +
  99 + }
  100 +})
  1 +{
  2 + "navigationBarTitleText": "历史缴纳明细"
  3 +}
  1 +<!--pages/main/finalpayment/historydetail/historydetail.wxml-->
  2 +<view class='page'>
  3 + <view style='padding:30rpx;'>
  4 + <text class='text_gray_32'>当前选择月份</text>
  5 + <view class='float_right'>
  6 + <text class='text_gray_32'>2018年</text>
  7 + <image class='arrow_wrap' style='margin-top: 8rpx' src='/images/arrow_right.png'></image>
  8 + </view>
  9 + </view>
  10 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  11 +
  12 + <view style='padding-left:30rpx;background:#ffffff;height:100rpx;'>
  13 + <image class='icon_wrap' src="/images/rectangle_icon.png"></image>
  14 + <text style='padding-left:20rpx;line-height:100rpx' class='text_gray_32'>专项附加扣除概览</text>
  15 + </view>
  16 + <view class='divide_line_f5f5f5'></view>
  17 +
  18 + <view class="container_wrap">
  19 + <canvas canvas-id="pieCanvas" class="canvas" style="height:560rpx" bindtouchstart="touchHandler"></canvas>
  20 + </view>
  21 +
  22 + <view class='divide_line_f5f5f5'></view>
  23 +
  24 + <view style='display: flex;flex-wrap: nowrap;height:144rpx'>
  25 + <view style='flex-grow: 1;justify-content:center;display: flex;flex-direction: column;'>
  26 + <text class='text_num_wrap'>24138.2</text>
  27 + <text class='text_text_wrap'>所得(元)</text>
  28 + </view>
  29 + <view style='width:2rpx;height:84rpx;background:#f5f5f5;'></view>
  30 + <view style='flex-grow: 1;justify-content:center;display: flex;flex-direction: column;'>
  31 + <text class='text_num_wrap'>5861.8</text>
  32 + <text class='text_text_wrap'>应纳税额(元)</text>
  33 + </view>
  34 + </view>
  35 +
  36 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  37 + <view style='padding:0 30rpx;height:100rpx'>
  38 + <text class='text_333_28_bold ' style='line-height:100rpx'>专项扣除</text>
  39 + </view>
  40 +
  41 + <view>
  42 + <view style='height:2rpx;width:94%;background:#f5f5f5;align-self:center'></view>
  43 + <view style='padding:0 30rpx;height:80rpx'>
  44 + <text class='text_333_28 float_left'>基本养老保险</text>
  45 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  46 + </view>
  47 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  48 + <view style='padding:0 30rpx;height:80rpx'>
  49 + <text class='text_333_28 float_left'>基本失业保险</text>
  50 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  51 + </view>
  52 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  53 + <view style='padding:0 30rpx;height:80rpx'>
  54 + <text class='text_333_28 float_left'>基本医疗保险</text>
  55 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  56 + </view>
  57 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  58 + <view style='padding:0 30rpx;height:80rpx'>
  59 + <text class='text_333_28 float_left'>住房公积金</text>
  60 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  61 + </view>
  62 + </view>
  63 +
  64 +</view>
  1 +/* pages/main/finalpayment/historydetail/historydetail.wxss */
  2 +.text_gray_32 {
  3 + font-size: 32rpx;
  4 + color: #6c7596;
  5 + font-family: PingFangSC-Semibold;
  6 +}
  7 +
  8 +.icon_wrap {
  9 + width: 8rpx;
  10 + height: 28rpx;
  11 +}
  12 +
  13 +.text_num_wrap {
  14 + font-family: PingFangSC-Semibold;
  15 + font-size: 15px;
  16 + color: #333;
  17 + text-align: center;
  18 +}
  19 +
  20 +.text_text_wrap {
  21 + font-family: PingFang-SC-Medium;
  22 + font-size: 11px;
  23 + color: #333;
  24 + text-align: center;
  25 +}
  26 +
  27 +.container_wrap {
  28 + height: 560rpx;
  29 + display: flex;
  30 + flex-direction: column;
  31 + box-sizing: border-box;
  32 + -webkit-text-size-adjust:none;
  33 + -webkit-user-select: none;
  34 + font-size: 24rpx;
  35 + color: #6c7596;
  36 + font-family: PingFang-SC-Medium;
  37 +}
  38 +.canvas {
  39 + width: 100%;
  40 + height: 280;
  41 +}
  42 +
1 // pages/main/finalpayment/home.js 1 // pages/main/finalpayment/home.js
  2 +var wxCharts = require('../../../utils/wxcharts.js');
  3 +var app = getApp();
  4 +var pieChart = null;
2 Page({ 5 Page({
3 6
4 /** 7 /**
@@ -11,56 +14,99 @@ Page({ @@ -11,56 +14,99 @@ Page({
11 /** 14 /**
12 * Lifecycle function--Called when page load 15 * Lifecycle function--Called when page load
13 */ 16 */
14 - onLoad: function (options) {  
15 - 17 + onLoad: function(options) {
  18 + var windowWidth = 320;
  19 + try {
  20 + var res = wx.getSystemInfoSync();
  21 + windowWidth = res.windowWidth;
  22 + } catch (e) {
  23 + console.error('getSystemInfoSync failed!');
  24 + }
  25 +
  26 + pieChart = new wxCharts({
  27 + animation: false,
  28 + canvasId: 'pieCanvas',
  29 + type: 'pie',
  30 + series: [ {
  31 + name: '成交量2',
  32 + data: 35,
  33 + }, {
  34 + name: '成交量3',
  35 + data: 78,
  36 + }, {
  37 + name: '成交量4',
  38 + data: 63,
  39 + }, {
  40 + name: '成交量2',
  41 + data: 35,
  42 + }, {
  43 + name: '成交量3',
  44 + data: 78,
  45 + }],
  46 + width: windowWidth,
  47 + height: 260,
  48 + dataLabel: true,
  49 + });
16 }, 50 },
17 51
18 /** 52 /**
19 * Lifecycle function--Called when page is initially rendered 53 * Lifecycle function--Called when page is initially rendered
20 */ 54 */
21 - onReady: function () { 55 + onReady: function() {
22 56
23 }, 57 },
24 58
25 /** 59 /**
26 * Lifecycle function--Called when page show 60 * Lifecycle function--Called when page show
27 */ 61 */
28 - onShow: function () { 62 + onShow: function() {
  63 +
  64 + },
  65 +
  66 + addinfo: function(e) {
  67 + wx.navigateTo({
  68 + url: 'inputinfo/inputinfo',
  69 + })
  70 + },
29 71
  72 + gohistory: function (e) {
  73 + wx.navigateTo({
  74 + url: 'historydetail/historydetail',
  75 + })
30 }, 76 },
31 77
32 /** 78 /**
33 * Lifecycle function--Called when page hide 79 * Lifecycle function--Called when page hide
34 */ 80 */
35 - onHide: function () { 81 + onHide: function() {
36 82
37 }, 83 },
38 84
39 /** 85 /**
40 * Lifecycle function--Called when page unload 86 * Lifecycle function--Called when page unload
41 */ 87 */
42 - onUnload: function () { 88 + onUnload: function() {
43 89
44 }, 90 },
45 91
46 /** 92 /**
47 * Page event handler function--Called when user drop down 93 * Page event handler function--Called when user drop down
48 */ 94 */
49 - onPullDownRefresh: function () { 95 + onPullDownRefresh: function() {
50 96
51 }, 97 },
52 98
53 /** 99 /**
54 * Called when page reach bottom 100 * Called when page reach bottom
55 */ 101 */
56 - onReachBottom: function () { 102 + onReachBottom: function() {
57 103
58 }, 104 },
59 105
60 /** 106 /**
61 * Called when user click on the top right corner to share 107 * Called when user click on the top right corner to share
62 */ 108 */
63 - onShareAppMessage: function () { 109 + onShareAppMessage: function() {
64 110
65 } 111 }
66 }) 112 })
1 <!--pages/main/finalpayment/home.wxml--> 1 <!--pages/main/finalpayment/home.wxml-->
2 -<text>pages/main/finalpayment/home.wxml</text> 2 +<view class='page'>
  3 + <scroll-view style='margin-bottom:40rpx'>
  4 + <view style='background:#ffffff'>
  5 + <view style='padding:30rpx;'>
  6 + <text class='text_gray_32'>当前选择月份</text>
  7 + <view class='float_right'>
  8 + <text class='text_gray_32'>2018年11月</text>
  9 + <image class='arrow_wrap' src='/images/arrow_right.png'></image>
  10 + </view>
  11 + </view>
  12 + <view class='divide_line_f5f5f5'></view>
  13 + <view style='margin: 30rpx;positive:relative;width:92%;height:434rpx'>
  14 + <image class=' payment_img_bg ' src='/images/payment_bg.png ' style='position:absolute;z-index: 1;'></image>
  15 + <view>
  16 + <view class='view_bg_wrap' style='margin-top: 48rpx;'>
  17 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  18 + <text class='text_num_wrap'>261609.90</text>
  19 + <text class='text_text_wrap'>累计收入额</text>
  20 + </view>
  21 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  22 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  23 + <text class='text_num_wrap'>19106.91</text>
  24 + <text class='text_text_wrap'>累计缴纳个税</text>
  25 + </view>
  26 + </view>
  27 + <view class='view_bg_wrap' style='margin-top: 206rpx;'>
  28 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  29 + <text class='text_num_wrap'>3838.9</text>
  30 + <text class='text_text_wrap'>累计专项扣除</text>
  31 + </view>
  32 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  33 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  34 + <text class='text_num_wrap'>10398.01</text>
  35 + <text class='text_text_wrap'>累计专项附加扣除</text>
  36 + </view>
  37 + <view style='width:2rpx;height:74rpx;background:#ffffff;'></view>
  38 + <view style='flex-grow: 1;text-align:center;display: flex;flex-direction: column;'>
  39 + <text class='text_num_wrap'>133.09</text>
  40 + <text class='text_text_wrap'>汇算补差</text>
  41 + </view>
  42 + </view>
  43 + <view style='position: absolute;z-index: 2;display: flex;margin-top:370rpx;width:100%;justify-content: center;' bindtap='gohistory'>
  44 + <text class='text_blue_wrap_28' style=''>查看历史缴税信息</text>
  45 + </view>
  46 + </view>
  47 + </view>
  48 + <view class='divide_line_f5f5f5'></view>
  49 + <view style='padding-left:30rpx;background:#ffffff;height:100rpx;'>
  50 + <image class='icon_wrap' src="/images/rectangle_icon.png"></image>
  51 + <text style='padding-left:20rpx;line-height:100rpx' class='text_gray_32'>专项附加扣除概览</text>
  52 + </view>
  53 + </view>
  54 + <view class="container_wrap">
  55 + <canvas canvas-id="pieCanvas" class="canvas" style="height:300px" bindtouchstart="touchHandler"></canvas>
  56 + </view>
  57 + </scroll-view>
  58 +
  59 + <view>
  60 + <button class="btn_bottom" bindtap='addinfo'>录入信息</button>
  61 + </view>
  62 +</view>
1 -/* pages/main/finalpayment/home.wxss */  
  1 +/* pages/main/finalpayment/home.wxss */
  2 +.arrow_wrap {
  3 + position: relative;
  4 + width: 40rpx;
  5 + height: 40rpx;
  6 + align-self: center;
  7 + margin-top: 8rpx
  8 +}
  9 +
  10 +.text_gray_32 {
  11 + font-size: 32rpx;
  12 + color: #6c7596;
  13 + font-family: PingFangSC-Semibold;
  14 +}
  15 +
  16 +.payment_img_bg {
  17 + width: 92%;
  18 + height: 360rpx;
  19 +}
  20 +
  21 +.view_bg_wrap {
  22 + position: absolute;
  23 + z-index: 2;
  24 + display: flex;
  25 + width: 690rpx;
  26 + flex-wrap: nowrap;
  27 +}
  28 +
  29 +.text_num_wrap {
  30 + font-family: PingFangSC-Semibold;
  31 + font-size: 18px;
  32 + color: #fff;
  33 + text-align: center;
  34 +}
  35 +
  36 +.text_text_wrap {
  37 + font-family: PingFang-SC-Medium;
  38 + font-size: 11px;
  39 + color: #fff;
  40 + text-align: center;
  41 +}
  42 +
  43 +.text_blue_wrap_28{
  44 +font-size: 28rpx;
  45 +color: #357AEB;
  46 +letter-spacing: 0;
  47 +}
  48 +
  49 +.icon_wrap {
  50 + width: 8rpx;
  51 + height: 28rpx;
  52 +}
  53 +
  54 +.container_wrap {
  55 + display: flex;
  56 + flex-direction: column;
  57 + box-sizing: border-box;
  58 + -webkit-text-size-adjust:none;
  59 + -webkit-user-select: none;
  60 + font-size: 35rpx;
  61 + color: #333;
  62 + font-family: Helvetica,Arial,"Helvetica Neue","Droid Sans","Microsoft YaHei",sans-serif;
  63 +}
  64 +.canvas {
  65 + width: 100%;
  66 + height: 200px;
  67 +}
  1 +// pages/main/finalpayment/inputinfo/inputinfo.js
  2 +Page({
  3 +
  4 + /**
  5 + * Page initial data
  6 + */
  7 + data: {
  8 +
  9 + },
  10 +
  11 + /**
  12 + * Lifecycle function--Called when page load
  13 + */
  14 + onLoad: function (options) {
  15 +
  16 + },
  17 +
  18 + /**
  19 + * Lifecycle function--Called when page is initially rendered
  20 + */
  21 + onReady: function () {
  22 +
  23 + },
  24 +
  25 + /**
  26 + * Lifecycle function--Called when page show
  27 + */
  28 + onShow: function () {
  29 +
  30 + },
  31 +
  32 + /**
  33 + * Lifecycle function--Called when page hide
  34 + */
  35 + onHide: function () {
  36 +
  37 + },
  38 +
  39 + /**
  40 + * Lifecycle function--Called when page unload
  41 + */
  42 + onUnload: function () {
  43 +
  44 + },
  45 +
  46 + /**
  47 + * Page event handler function--Called when user drop down
  48 + */
  49 + onPullDownRefresh: function () {
  50 +
  51 + },
  52 +
  53 + /**
  54 + * Called when page reach bottom
  55 + */
  56 + onReachBottom: function () {
  57 +
  58 + },
  59 +
  60 + /**
  61 + * Called when user click on the top right corner to share
  62 + */
  63 + onShareAppMessage: function () {
  64 +
  65 + }
  66 +})
  1 +{
  2 +"navigationBarTitleText": "录入信息"
  3 +}
  1 +<!--pages/main/finalpayment/inputinfo/inputinfo.wxml-->
  2 +<view class='page'>
  3 + <view style='padding:30rpx;'>
  4 + <text class='text_gray_32'>当前选择月份</text>
  5 + <view class='float_right'>
  6 + <text class='text_gray_32'>2018年</text>
  7 + <image class='arrow_wrap' style='margin-top: 8rpx'src='/images/arrow_right.png'></image>
  8 + </view>
  9 + </view>
  10 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  11 + <view style='padding:0 30rpx;height:100rpx'>
  12 + <text class='text_333_28_bold ' style='line-height:100rpx'>专项扣除</text>
  13 + <text class='text_blue_28 float_right' style='line-height:100rpx'>编辑</text>
  14 + </view>
  15 +
  16 + <view>
  17 + <view style='height:2rpx;width:94%;background:#f5f5f5;align-self:center'></view>
  18 + <view style='padding:0 30rpx;height:80rpx'>
  19 + <text class='text_333_28 float_left'>基本养老保险</text>
  20 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  21 + </view>
  22 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  23 + <view style='padding:0 30rpx;height:80rpx'>
  24 + <text class='text_333_28 float_left'>基本失业保险</text>
  25 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  26 + </view>
  27 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  28 + <view style='padding:0 30rpx;height:80rpx'>
  29 + <text class='text_333_28 float_left'>基本医疗保险</text>
  30 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  31 + </view>
  32 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  33 + <view style='padding:0 30rpx;height:80rpx'>
  34 + <text class='text_333_28 float_left'>住房公积金</text>
  35 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  36 + </view>
  37 + </view>
  38 +
  39 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  40 + <view style='padding:0 30rpx;height:100rpx'>
  41 + <text class='text_333_28_bold ' style='line-height:100rpx'>法定扣除</text>
  42 + <text class='text_blue_28 float_right' style='line-height:100rpx'>编辑</text>
  43 + </view>
  44 + <view>
  45 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  46 + <view style='padding:0 30rpx;height:80rpx'>
  47 + <text class='text_333_28 float_left'>捐赠</text>
  48 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  49 + </view>
  50 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  51 + <view style='padding:0 30rpx;height:80rpx'>
  52 + <text class='text_333_28 float_left'>总额</text>
  53 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  54 + </view>
  55 + </view>
  56 +
  57 +
  58 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  59 + <view style='padding:0 30rpx;height:100rpx'>
  60 + <text class='text_333_28_bold ' style='line-height:100rpx'>专项附加扣除</text>
  61 + <text class='text_blue_28 float_right' style='line-height:100rpx'>编辑</text>
  62 + </view>
  63 + <view>
  64 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  65 + <view style='padding:0 30rpx;height:80rpx'>
  66 + <text class='text_333_28 float_left'>继续教育</text>
  67 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  68 + </view>
  69 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  70 + <view style='padding:0 30rpx;height:80rpx'>
  71 + <text class='text_333_28 float_left'>子女教育</text>
  72 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  73 + </view>
  74 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  75 + <view style='padding:0 30rpx;height:80rpx'>
  76 + <text class='text_333_28 float_left'>大病医疗</text>
  77 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  78 + </view>
  79 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  80 + <view style='padding:0 30rpx;height:80rpx'>
  81 + <text class='text_333_28 float_left'>住房租金</text>
  82 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  83 + </view>
  84 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  85 + <view style='padding:0 30rpx;height:80rpx'>
  86 + <text class='text_333_28 float_left'>赡养老人</text>
  87 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  88 + </view>
  89 + </view>
  90 +
  91 + <view style='height:20rpx;width:100%;background:#f5f5f5'></view>
  92 + <view style='padding:0 30rpx;height:100rpx'>
  93 + <text class='text_333_28_bold ' style='line-height:100rpx'>收入及个税</text>
  94 + <text class='text_blue_28 float_right' style='line-height:100rpx'>编辑</text>
  95 + </view>
  96 + <view>
  97 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  98 + <view style='padding:0 30rpx;height:80rpx'>
  99 + <text class='text_333_28 float_left'>收入类型</text>
  100 + <image class='arrow_wrap' src='/images/arrow_right.png'></image>
  101 + <text class='text_333_28 float_right'>工作</text>
  102 + </view>
  103 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  104 + <view style='padding:0 30rpx;height:80rpx'>
  105 + <text class='text_333_28 float_left'>收入金额(含免税部分)</text>
  106 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  107 + </view>
  108 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  109 + <view style='padding:0 30rpx;height:80rpx'>
  110 + <text class='text_333_28 float_left'>已申报个税</text>
  111 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  112 + </view>
  113 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  114 + <view style='padding:0 30rpx;height:80rpx'>
  115 + <text class='text_333_28 float_left'>申报单位</text>
  116 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='北京小爱智能科技'> </input>
  117 + </view>
  118 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  119 + <view style='padding:0 30rpx;height:80rpx'>
  120 + <text class='text_333_28 float_left'>申报地</text>
  121 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='北京 朝阳'> </input>
  122 + </view>
  123 + <view style='height:2rpx;width:94%;background:#f5f5f5'></view>
  124 + <view style='padding:0 30rpx;height:80rpx'>
  125 + <text class='text_333_28 float_left'>总额</text>
  126 + <input class='text_999_28 float_right' style='margin-top:12rpx' value='500.00'> </input>
  127 + </view>
  128 + </view>
  129 +</view>
  1 +/* pages/main/finalpayment/inputinfo/inputinfo.wxss */
  2 +.text_gray_32 {
  3 + font-size: 32rpx;
  4 + color: #6c7596;
  5 + font-family: PingFangSC-Semibold;
  6 +}
  7 +
  8 +.text_333_28_bold {
  9 + font-family: PingFangSC-Semibold;
  10 + font-size: 28rpx;
  11 + color: #333;
  12 + text-align: left;
  13 +}
  14 +
  15 +.arrow_wrap {
  16 + position: relative;
  17 + width: 40rpx;
  18 + height: 40rpx;
  19 + align-self: center;
  20 +}
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 "ignore": [] 4 "ignore": []
5 }, 5 },
6 "setting": { 6 "setting": {
7 - "urlCheck": true, 7 + "urlCheck": false,
8 "es6": true, 8 "es6": true,
9 "postcss": true, 9 "postcss": true,
10 "minified": true, 10 "minified": true,
  1 +/*
  2 + * charts for WeChat small app v1.0
  3 + *
  4 + * https://github.com/xiaolin3303/wx-charts
  5 + * 2016-11-28
  6 + *
  7 + * Designed and built with all the love of Web
  8 + */
  9 +
  10 +'use strict';
  11 +
  12 +var config = {
  13 + yAxisWidth: 15,
  14 + yAxisSplit: 5,
  15 + xAxisHeight: 15,
  16 + xAxisLineHeight: 15,
  17 + legendHeight: 15,
  18 + yAxisTitleWidth: 15,
  19 + padding: 12,
  20 + columePadding: 3,
  21 + fontSize: 10,
  22 + dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
  23 + colors: ['#7cb5ec', '#f7a35c', '#434348', '#90ed7d', '#f15c80', '#8085e9'],
  24 + pieChartLinePadding: 25,
  25 + pieChartTextPadding: 15,
  26 + xAxisTextPadding: 3,
  27 + titleColor: '#333333',
  28 + titleFontSize: 20,
  29 + subtitleColor: '#999999',
  30 + subtitleFontSize: 15,
  31 + toolTipPadding: 3,
  32 + toolTipBackground: '#000000',
  33 + toolTipOpacity: 0.7,
  34 + toolTipLineHeight: 14,
  35 + radarGridCount: 3,
  36 + radarLabelTextMargin: 15
  37 +};
  38 +
  39 +// Object.assign polyfill
  40 +// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
  41 +function assign(target, varArgs) {
  42 + if (target == null) {
  43 + // TypeError if undefined or null
  44 + throw new TypeError('Cannot convert undefined or null to object');
  45 + }
  46 +
  47 + var to = Object(target);
  48 +
  49 + for (var index = 1; index < arguments.length; index++) {
  50 + var nextSource = arguments[index];
  51 +
  52 + if (nextSource != null) {
  53 + // Skip over if undefined or null
  54 + for (var nextKey in nextSource) {
  55 + // Avoid bugs when hasOwnProperty is shadowed
  56 + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
  57 + to[nextKey] = nextSource[nextKey];
  58 + }
  59 + }
  60 + }
  61 + }
  62 + return to;
  63 +}
  64 +
  65 +var util = {
  66 + toFixed: function toFixed(num, limit) {
  67 + limit = limit || 2;
  68 + if (this.isFloat(num)) {
  69 + num = num.toFixed(limit);
  70 + }
  71 + return num;
  72 + },
  73 + isFloat: function isFloat(num) {
  74 + return num % 1 !== 0;
  75 + },
  76 + approximatelyEqual: function approximatelyEqual(num1, num2) {
  77 + return Math.abs(num1 - num2) < 1e-10;
  78 + },
  79 + isSameSign: function isSameSign(num1, num2) {
  80 + return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
  81 + },
  82 + isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
  83 + return this.isSameSign(p1.x, p2.x);
  84 + },
  85 + isCollision: function isCollision(obj1, obj2) {
  86 + obj1.end = {};
  87 + obj1.end.x = obj1.start.x + obj1.width;
  88 + obj1.end.y = obj1.start.y - obj1.height;
  89 + obj2.end = {};
  90 + obj2.end.x = obj2.start.x + obj2.width;
  91 + obj2.end.y = obj2.start.y - obj2.height;
  92 + var flag = obj2.start.x > obj1.end.x || obj2.end.x < obj1.start.x || obj2.end.y > obj1.start.y || obj2.start.y < obj1.end.y;
  93 +
  94 + return !flag;
  95 + }
  96 +};
  97 +
  98 +function findRange(num, type, limit) {
  99 + if (isNaN(num)) {
  100 + throw new Error('[wxCharts] unvalid series data!');
  101 + }
  102 + limit = limit || 10;
  103 + type = type ? type : 'upper';
  104 + var multiple = 1;
  105 + while (limit < 1) {
  106 + limit *= 10;
  107 + multiple *= 10;
  108 + }
  109 + if (type === 'upper') {
  110 + num = Math.ceil(num * multiple);
  111 + } else {
  112 + num = Math.floor(num * multiple);
  113 + }
  114 + while (num % limit !== 0) {
  115 + if (type === 'upper') {
  116 + num++;
  117 + } else {
  118 + num--;
  119 + }
  120 + }
  121 +
  122 + return num / multiple;
  123 +}
  124 +
  125 +function calValidDistance(distance, chartData, config, opts) {
  126 +
  127 + var dataChartAreaWidth = opts.width - config.padding - chartData.xAxisPoints[0];
  128 + var dataChartWidth = chartData.eachSpacing * opts.categories.length;
  129 + var validDistance = distance;
  130 + if (distance >= 0) {
  131 + validDistance = 0;
  132 + } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
  133 + validDistance = dataChartAreaWidth - dataChartWidth;
  134 + }
  135 + return validDistance;
  136 +}
  137 +
  138 +function isInAngleRange(angle, startAngle, endAngle) {
  139 + function adjust(angle) {
  140 + while (angle < 0) {
  141 + angle += 2 * Math.PI;
  142 + }
  143 + while (angle > 2 * Math.PI) {
  144 + angle -= 2 * Math.PI;
  145 + }
  146 +
  147 + return angle;
  148 + }
  149 +
  150 + angle = adjust(angle);
  151 + startAngle = adjust(startAngle);
  152 + endAngle = adjust(endAngle);
  153 + if (startAngle > endAngle) {
  154 + endAngle += 2 * Math.PI;
  155 + if (angle < startAngle) {
  156 + angle += 2 * Math.PI;
  157 + }
  158 + }
  159 +
  160 + return angle >= startAngle && angle <= endAngle;
  161 +}
  162 +
  163 +function calRotateTranslate(x, y, h) {
  164 + var xv = x;
  165 + var yv = h - y;
  166 +
  167 + var transX = xv + (h - yv - xv) / Math.sqrt(2);
  168 + transX *= -1;
  169 +
  170 + var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
  171 +
  172 + return {
  173 + transX: transX,
  174 + transY: transY
  175 + };
  176 +}
  177 +
  178 +function createCurveControlPoints(points, i) {
  179 +
  180 + function isNotMiddlePoint(points, i) {
  181 + if (points[i - 1] && points[i + 1]) {
  182 + return points[i].y >= Math.max(points[i - 1].y, points[i + 1].y) || points[i].y <= Math.min(points[i - 1].y, points[i + 1].y);
  183 + } else {
  184 + return false;
  185 + }
  186 + }
  187 +
  188 + var a = 0.2;
  189 + var b = 0.2;
  190 + var pAx = null;
  191 + var pAy = null;
  192 + var pBx = null;
  193 + var pBy = null;
  194 + if (i < 1) {
  195 + pAx = points[0].x + (points[1].x - points[0].x) * a;
  196 + pAy = points[0].y + (points[1].y - points[0].y) * a;
  197 + } else {
  198 + pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
  199 + pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
  200 + }
  201 +
  202 + if (i > points.length - 3) {
  203 + var last = points.length - 1;
  204 + pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
  205 + pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
  206 + } else {
  207 + pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
  208 + pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
  209 + }
  210 +
  211 + // fix issue https://github.com/xiaolin3303/wx-charts/issues/79
  212 + if (isNotMiddlePoint(points, i + 1)) {
  213 + pBy = points[i + 1].y;
  214 + }
  215 + if (isNotMiddlePoint(points, i)) {
  216 + pAy = points[i].y;
  217 + }
  218 +
  219 + return {
  220 + ctrA: { x: pAx, y: pAy },
  221 + ctrB: { x: pBx, y: pBy }
  222 + };
  223 +}
  224 +
  225 +function convertCoordinateOrigin(x, y, center) {
  226 + return {
  227 + x: center.x + x,
  228 + y: center.y - y
  229 + };
  230 +}
  231 +
  232 +function avoidCollision(obj, target) {
  233 + if (target) {
  234 + // is collision test
  235 + while (util.isCollision(obj, target)) {
  236 + if (obj.start.x > 0) {
  237 + obj.start.y--;
  238 + } else if (obj.start.x < 0) {
  239 + obj.start.y++;
  240 + } else {
  241 + if (obj.start.y > 0) {
  242 + obj.start.y++;
  243 + } else {
  244 + obj.start.y--;
  245 + }
  246 + }
  247 + }
  248 + }
  249 + return obj;
  250 +}
  251 +
  252 +function fillSeriesColor(series, config) {
  253 + var index = 0;
  254 + return series.map(function (item) {
  255 + if (!item.color) {
  256 + item.color = config.colors[index];
  257 + index = (index + 1) % config.colors.length;
  258 + }
  259 + return item;
  260 + });
  261 +}
  262 +
  263 +function getDataRange(minData, maxData) {
  264 + var limit = 0;
  265 + var range = maxData - minData;
  266 + if (range >= 10000) {
  267 + limit = 1000;
  268 + } else if (range >= 1000) {
  269 + limit = 100;
  270 + } else if (range >= 100) {
  271 + limit = 10;
  272 + } else if (range >= 10) {
  273 + limit = 5;
  274 + } else if (range >= 1) {
  275 + limit = 1;
  276 + } else if (range >= 0.1) {
  277 + limit = 0.1;
  278 + } else {
  279 + limit = 0.01;
  280 + }
  281 + return {
  282 + minRange: findRange(minData, 'lower', limit),
  283 + maxRange: findRange(maxData, 'upper', limit)
  284 + };
  285 +}
  286 +
  287 +function measureText(text) {
  288 + var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
  289 +
  290 + // wx canvas 未实现measureText方法, 此处自行实现
  291 + text = String(text);
  292 + var text = text.split('');
  293 + var width = 0;
  294 + text.forEach(function (item) {
  295 + if (/[a-zA-Z]/.test(item)) {
  296 + width += 7;
  297 + } else if (/[0-9]/.test(item)) {
  298 + width += 5.5;
  299 + } else if (/\./.test(item)) {
  300 + width += 2.7;
  301 + } else if (/-/.test(item)) {
  302 + width += 3.25;
  303 + } else if (/[\u4e00-\u9fa5]/.test(item)) {
  304 + width += 10;
  305 + } else if (/\(|\)/.test(item)) {
  306 + width += 3.73;
  307 + } else if (/\s/.test(item)) {
  308 + width += 2.5;
  309 + } else if (/%/.test(item)) {
  310 + width += 8;
  311 + } else {
  312 + width += 10;
  313 + }
  314 + });
  315 + return width * fontSize / 10;
  316 +}
  317 +
  318 +function dataCombine(series) {
  319 + return series.reduce(function (a, b) {
  320 + return (a.data ? a.data : a).concat(b.data);
  321 + }, []);
  322 +}
  323 +
  324 +function getSeriesDataItem(series, index) {
  325 + var data = [];
  326 + series.forEach(function (item) {
  327 + if (item.data[index] !== null && typeof item.data[index] !== 'undefinded') {
  328 + var seriesItem = {};
  329 + seriesItem.color = item.color;
  330 + seriesItem.name = item.name;
  331 + seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
  332 + data.push(seriesItem);
  333 + }
  334 + });
  335 +
  336 + return data;
  337 +}
  338 +
  339 +
  340 +
  341 +function getMaxTextListLength(list) {
  342 + var lengthList = list.map(function (item) {
  343 + return measureText(item);
  344 + });
  345 + return Math.max.apply(null, lengthList);
  346 +}
  347 +
  348 +function getRadarCoordinateSeries(length) {
  349 + var eachAngle = 2 * Math.PI / length;
  350 + var CoordinateSeries = [];
  351 + for (var i = 0; i < length; i++) {
  352 + CoordinateSeries.push(eachAngle * i);
  353 + }
  354 +
  355 + return CoordinateSeries.map(function (item) {
  356 + return -1 * item + Math.PI / 2;
  357 + });
  358 +}
  359 +
  360 +function getToolTipData(seriesData, calPoints, index, categories) {
  361 + var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
  362 +
  363 + var textList = seriesData.map(function (item) {
  364 + return {
  365 + text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data,
  366 + color: item.color
  367 + };
  368 + });
  369 + var validCalPoints = [];
  370 + var offset = {
  371 + x: 0,
  372 + y: 0
  373 + };
  374 + calPoints.forEach(function (points) {
  375 + if (typeof points[index] !== 'undefinded' && points[index] !== null) {
  376 + validCalPoints.push(points[index]);
  377 + }
  378 + });
  379 + validCalPoints.forEach(function (item) {
  380 + offset.x = Math.round(item.x);
  381 + offset.y += item.y;
  382 + });
  383 +
  384 + offset.y /= validCalPoints.length;
  385 + return { textList: textList, offset: offset };
  386 +}
  387 +
  388 +function findCurrentIndex(currentPoints, xAxisPoints, opts, config) {
  389 + var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
  390 +
  391 + var currentIndex = -1;
  392 + if (isInExactChartArea(currentPoints, opts, config)) {
  393 + xAxisPoints.forEach(function (item, index) {
  394 + if (currentPoints.x + offset > item) {
  395 + currentIndex = index;
  396 + }
  397 + });
  398 + }
  399 +
  400 + return currentIndex;
  401 +}
  402 +
  403 +function isInExactChartArea(currentPoints, opts, config) {
  404 + return currentPoints.x < opts.width - config.padding && currentPoints.x > config.padding + config.yAxisWidth + config.yAxisTitleWidth && currentPoints.y > config.padding && currentPoints.y < opts.height - config.legendHeight - config.xAxisHeight - config.padding;
  405 +}
  406 +
  407 +function findRadarChartCurrentIndex(currentPoints, radarData, count) {
  408 + var eachAngleArea = 2 * Math.PI / count;
  409 + var currentIndex = -1;
  410 + if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
  411 + var fixAngle = function fixAngle(angle) {
  412 + if (angle < 0) {
  413 + angle += 2 * Math.PI;
  414 + }
  415 + if (angle > 2 * Math.PI) {
  416 + angle -= 2 * Math.PI;
  417 + }
  418 + return angle;
  419 + };
  420 +
  421 + var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
  422 + angle = -1 * angle;
  423 + if (angle < 0) {
  424 + angle += 2 * Math.PI;
  425 + }
  426 +
  427 + var angleList = radarData.angleList.map(function (item) {
  428 + item = fixAngle(-1 * item);
  429 +
  430 + return item;
  431 + });
  432 +
  433 + angleList.forEach(function (item, index) {
  434 + var rangeStart = fixAngle(item - eachAngleArea / 2);
  435 + var rangeEnd = fixAngle(item + eachAngleArea / 2);
  436 + if (rangeEnd < rangeStart) {
  437 + rangeEnd += 2 * Math.PI;
  438 + }
  439 + if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= rangeEnd) {
  440 + currentIndex = index;
  441 + }
  442 + });
  443 + }
  444 +
  445 + return currentIndex;
  446 +}
  447 +
  448 +function findPieChartCurrentIndex(currentPoints, pieData) {
  449 + var currentIndex = -1;
  450 + if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
  451 + var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
  452 + angle = -angle;
  453 + for (var i = 0, len = pieData.series.length; i < len; i++) {
  454 + var item = pieData.series[i];
  455 + if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) {
  456 + currentIndex = i;
  457 + break;
  458 + }
  459 + }
  460 + }
  461 +
  462 + return currentIndex;
  463 +}
  464 +
  465 +function isInExactPieChartArea(currentPoints, center, radius) {
  466 + return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
  467 +}
  468 +
  469 +function splitPoints(points) {
  470 + var newPoints = [];
  471 + var items = [];
  472 + points.forEach(function (item, index) {
  473 + if (item !== null) {
  474 + items.push(item);
  475 + } else {
  476 + if (items.length) {
  477 + newPoints.push(items);
  478 + }
  479 + items = [];
  480 + }
  481 + });
  482 + if (items.length) {
  483 + newPoints.push(items);
  484 + }
  485 +
  486 + return newPoints;
  487 +}
  488 +
  489 +function calLegendData(series, opts, config) {
  490 + if (opts.legend === false) {
  491 + return {
  492 + legendList: [],
  493 + legendHeight: 0
  494 + };
  495 + }
  496 + var padding = 5;
  497 + var marginTop = 8;
  498 + var shapeWidth = 15;
  499 + var legendList = [];
  500 + var widthCount = 0;
  501 + var currentRow = [];
  502 + series.forEach(function (item) {
  503 + var itemWidth = 3 * padding + shapeWidth + measureText(item.name || 'undefinded');
  504 + if (widthCount + itemWidth > opts.width) {
  505 + legendList.push(currentRow);
  506 + widthCount = itemWidth;
  507 + currentRow = [item];
  508 + } else {
  509 + widthCount += itemWidth;
  510 + currentRow.push(item);
  511 + }
  512 + });
  513 + if (currentRow.length) {
  514 + legendList.push(currentRow);
  515 + }
  516 +
  517 + return {
  518 + legendList: legendList,
  519 + legendHeight: legendList.length * (config.fontSize + marginTop) + padding
  520 + };
  521 +}
  522 +
  523 +function calCategoriesData(categories, opts, config) {
  524 + var result = {
  525 + angle: 0,
  526 + xAxisHeight: config.xAxisHeight
  527 + };
  528 +
  529 + var _getXAxisPoints = getXAxisPoints(categories, opts, config),
  530 + eachSpacing = _getXAxisPoints.eachSpacing;
  531 +
  532 + // get max length of categories text
  533 +
  534 +
  535 + var categoriesTextLenth = categories.map(function (item) {
  536 + return measureText(item);
  537 + });
  538 +
  539 + var maxTextLength = Math.max.apply(this, categoriesTextLenth);
  540 +
  541 + if (maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
  542 + result.angle = 45 * Math.PI / 180;
  543 + result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
  544 + }
  545 +
  546 + return result;
  547 +}
  548 +
  549 +function getRadarDataPoints(angleList, center, radius, series, opts) {
  550 + var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
  551 +
  552 + var radarOption = opts.extra.radar || {};
  553 + radarOption.max = radarOption.max || 0;
  554 + var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
  555 +
  556 + var data = [];
  557 + series.forEach(function (each) {
  558 + var listItem = {};
  559 + listItem.color = each.color;
  560 + listItem.data = [];
  561 + each.data.forEach(function (item, index) {
  562 + var tmp = {};
  563 + tmp.angle = angleList[index];
  564 +
  565 + tmp.proportion = item / maxData;
  566 + tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * process * Math.sin(tmp.angle), center);
  567 + listItem.data.push(tmp);
  568 + });
  569 +
  570 + data.push(listItem);
  571 + });
  572 +
  573 + return data;
  574 +}
  575 +
  576 +function getPieDataPoints(series) {
  577 + var process = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  578 +
  579 + var count = 0;
  580 + var _start_ = 0;
  581 + series.forEach(function (item) {
  582 + item.data = item.data === null ? 0 : item.data;
  583 + count += item.data;
  584 + });
  585 + series.forEach(function (item) {
  586 + item.data = item.data === null ? 0 : item.data;
  587 + item._proportion_ = item.data / count * process;
  588 + });
  589 + series.forEach(function (item) {
  590 + item._start_ = _start_;
  591 + _start_ += 2 * item._proportion_ * Math.PI;
  592 + });
  593 +
  594 + return series;
  595 +}
  596 +
  597 +function getPieTextMaxLength(series) {
  598 + series = getPieDataPoints(series);
  599 + var maxLength = 0;
  600 + series.forEach(function (item) {
  601 + var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
  602 + maxLength = Math.max(maxLength, measureText(text));
  603 + });
  604 +
  605 + return maxLength;
  606 +}
  607 +
  608 +function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
  609 + return points.map(function (item) {
  610 + if (item === null) {
  611 + return null;
  612 + }
  613 + item.width = (eachSpacing - 2 * config.columePadding) / columnLen;
  614 +
  615 + if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
  616 + // customer column width
  617 + item.width = Math.min(item.width, +opts.extra.column.width);
  618 + } else {
  619 + // default width should less tran 25px
  620 + // don't ask me why, I don't know
  621 + item.width = Math.min(item.width, 25);
  622 + }
  623 + item.x += (index + 0.5 - columnLen / 2) * item.width;
  624 +
  625 + return item;
  626 + });
  627 +}
  628 +
  629 +function getXAxisPoints(categories, opts, config) {
  630 + var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
  631 + var spacingValid = opts.width - 2 * config.padding - yAxisTotalWidth;
  632 + var dataCount = opts.enableScroll ? Math.min(5, categories.length) : categories.length;
  633 + var eachSpacing = spacingValid / dataCount;
  634 +
  635 + var xAxisPoints = [];
  636 + var startX = config.padding + yAxisTotalWidth;
  637 + var endX = opts.width - config.padding;
  638 + categories.forEach(function (item, index) {
  639 + xAxisPoints.push(startX + index * eachSpacing);
  640 + });
  641 + if (opts.enableScroll === true) {
  642 + xAxisPoints.push(startX + categories.length * eachSpacing);
  643 + } else {
  644 + xAxisPoints.push(endX);
  645 + }
  646 +
  647 + return { xAxisPoints: xAxisPoints, startX: startX, endX: endX, eachSpacing: eachSpacing };
  648 +}
  649 +
  650 +function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
  651 + var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
  652 +
  653 + var points = [];
  654 + var validHeight = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
  655 + data.forEach(function (item, index) {
  656 + if (item === null) {
  657 + points.push(null);
  658 + } else {
  659 + var point = {};
  660 + point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
  661 + var height = validHeight * (item - minRange) / (maxRange - minRange);
  662 + height *= process;
  663 + point.y = opts.height - config.xAxisHeight - config.legendHeight - Math.round(height) - config.padding;
  664 + points.push(point);
  665 + }
  666 + });
  667 +
  668 + return points;
  669 +}
  670 +
  671 +function getYAxisTextList(series, opts, config) {
  672 + var data = dataCombine(series);
  673 + // remove null from data
  674 + data = data.filter(function (item) {
  675 + return item !== null;
  676 + });
  677 + var minData = Math.min.apply(this, data);
  678 + var maxData = Math.max.apply(this, data);
  679 + if (typeof opts.yAxis.min === 'number') {
  680 + minData = Math.min(opts.yAxis.min, minData);
  681 + }
  682 + if (typeof opts.yAxis.max === 'number') {
  683 + maxData = Math.max(opts.yAxis.max, maxData);
  684 + }
  685 +
  686 + // fix issue https://github.com/xiaolin3303/wx-charts/issues/9
  687 + if (minData === maxData) {
  688 + var rangeSpan = maxData || 1;
  689 + minData -= rangeSpan;
  690 + maxData += rangeSpan;
  691 + }
  692 +
  693 + var dataRange = getDataRange(minData, maxData);
  694 + var minRange = dataRange.minRange;
  695 + var maxRange = dataRange.maxRange;
  696 +
  697 + var range = [];
  698 + var eachRange = (maxRange - minRange) / config.yAxisSplit;
  699 +
  700 + for (var i = 0; i <= config.yAxisSplit; i++) {
  701 + range.push(minRange + eachRange * i);
  702 + }
  703 + return range.reverse();
  704 +}
  705 +
  706 +function calYAxisData(series, opts, config) {
  707 +
  708 + var ranges = getYAxisTextList(series, opts, config);
  709 + var yAxisWidth = config.yAxisWidth;
  710 + var rangesFormat = ranges.map(function (item) {
  711 + item = util.toFixed(item, 2);
  712 + item = opts.yAxis.format ? opts.yAxis.format(Number(item)) : item;
  713 + yAxisWidth = Math.max(yAxisWidth, measureText(item) + 5);
  714 + return item;
  715 + });
  716 + if (opts.yAxis.disabled === true) {
  717 + yAxisWidth = 0;
  718 + }
  719 +
  720 + return { rangesFormat: rangesFormat, ranges: ranges, yAxisWidth: yAxisWidth };
  721 +}
  722 +
  723 +function drawPointShape(points, color, shape, context) {
  724 + context.beginPath();
  725 + context.setStrokeStyle("#ffffff");
  726 + context.setLineWidth(1);
  727 + context.setFillStyle(color);
  728 +
  729 + if (shape === 'diamond') {
  730 + points.forEach(function (item, index) {
  731 + if (item !== null) {
  732 + context.moveTo(item.x, item.y - 4.5);
  733 + context.lineTo(item.x - 4.5, item.y);
  734 + context.lineTo(item.x, item.y + 4.5);
  735 + context.lineTo(item.x + 4.5, item.y);
  736 + context.lineTo(item.x, item.y - 4.5);
  737 + }
  738 + });
  739 + } else if (shape === 'circle') {
  740 + points.forEach(function (item, index) {
  741 + if (item !== null) {
  742 + context.moveTo(item.x + 3.5, item.y);
  743 + context.arc(item.x, item.y, 4, 0, 2 * Math.PI, false);
  744 + }
  745 + });
  746 + } else if (shape === 'rect') {
  747 + points.forEach(function (item, index) {
  748 + if (item !== null) {
  749 + context.moveTo(item.x - 3.5, item.y - 3.5);
  750 + context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
  751 + }
  752 + });
  753 + } else if (shape === 'triangle') {
  754 + points.forEach(function (item, index) {
  755 + if (item !== null) {
  756 + context.moveTo(item.x, item.y - 4.5);
  757 + context.lineTo(item.x - 4.5, item.y + 4.5);
  758 + context.lineTo(item.x + 4.5, item.y + 4.5);
  759 + context.lineTo(item.x, item.y - 4.5);
  760 + }
  761 + });
  762 + }
  763 + context.closePath();
  764 + context.fill();
  765 + context.stroke();
  766 +}
  767 +
  768 +function drawRingTitle(opts, config, context) {
  769 + var titlefontSize = opts.title.fontSize || config.titleFontSize;
  770 + var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize;
  771 + var title = opts.title.name || '';
  772 + var subtitle = opts.subtitle.name || '';
  773 + var titleFontColor = opts.title.color || config.titleColor;
  774 + var subtitleFontColor = opts.subtitle.color || config.subtitleColor;
  775 + var titleHeight = title ? titlefontSize : 0;
  776 + var subtitleHeight = subtitle ? subtitlefontSize : 0;
  777 + var margin = 5;
  778 + if (subtitle) {
  779 + var textWidth = measureText(subtitle, subtitlefontSize);
  780 + var startX = (opts.width - textWidth) / 2 + (opts.subtitle.offsetX || 0);
  781 + var startY = (opts.height - config.legendHeight + subtitlefontSize) / 2;
  782 + if (title) {
  783 + startY -= (titleHeight + margin) / 2;
  784 + }
  785 + context.beginPath();
  786 + context.setFontSize(subtitlefontSize);
  787 + context.setFillStyle(subtitleFontColor);
  788 + context.fillText(subtitle, startX, startY);
  789 + context.stroke();
  790 + context.closePath();
  791 + }
  792 + if (title) {
  793 + var _textWidth = measureText(title, titlefontSize);
  794 + var _startX = (opts.width - _textWidth) / 2 + (opts.title.offsetX || 0);
  795 + var _startY = (opts.height - config.legendHeight + titlefontSize) / 2;
  796 + if (subtitle) {
  797 + _startY += (subtitleHeight + margin) / 2;
  798 + }
  799 + context.beginPath();
  800 + context.setFontSize(titlefontSize);
  801 + context.setFillStyle(titleFontColor);
  802 + context.fillText(title, _startX, _startY);
  803 + context.stroke();
  804 + context.closePath();
  805 + }
  806 +}
  807 +
  808 +function drawPointText(points, series, config, context) {
  809 + // 绘制数据文案
  810 + var data = series.data;
  811 +
  812 + context.beginPath();
  813 + context.setFontSize(config.fontSize);
  814 + context.setFillStyle('#666666');
  815 + points.forEach(function (item, index) {
  816 + if (item !== null) {
  817 + var formatVal = series.format ? series.format(data[index]) : data[index];
  818 + context.fillText(formatVal, item.x - measureText(formatVal) / 2, item.y - 2);
  819 + }
  820 + });
  821 + context.closePath();
  822 + context.stroke();
  823 +}
  824 +
  825 +function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
  826 + var radarOption = opts.extra.radar || {};
  827 + radius += config.radarLabelTextMargin;
  828 + context.beginPath();
  829 + context.setFontSize(config.fontSize);
  830 + context.setFillStyle(radarOption.labelColor || '#666666');
  831 + angleList.forEach(function (angle, index) {
  832 + var pos = {
  833 + x: radius * Math.cos(angle),
  834 + y: radius * Math.sin(angle)
  835 + };
  836 + var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
  837 + var startX = posRelativeCanvas.x;
  838 + var startY = posRelativeCanvas.y;
  839 + if (util.approximatelyEqual(pos.x, 0)) {
  840 + startX -= measureText(opts.categories[index] || '') / 2;
  841 + } else if (pos.x < 0) {
  842 + startX -= measureText(opts.categories[index] || '');
  843 + }
  844 + context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
  845 + });
  846 + context.stroke();
  847 + context.closePath();
  848 +}
  849 +
  850 +function drawPieText(series, opts, config, context, radius, center) {
  851 + var lineRadius = radius + config.pieChartLinePadding;
  852 + var textObjectCollection = [];
  853 + var lastTextObject = null;
  854 +
  855 + var seriesConvert = series.map(function (item) {
  856 + var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
  857 + var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
  858 + var color = item.color;
  859 + return { arc: arc, text: text, color: color };
  860 + });
  861 + seriesConvert.forEach(function (item) {
  862 + // line end
  863 + var orginX1 = Math.cos(item.arc) * lineRadius;
  864 + var orginY1 = Math.sin(item.arc) * lineRadius;
  865 +
  866 + // line start
  867 + var orginX2 = Math.cos(item.arc) * radius;
  868 + var orginY2 = Math.sin(item.arc) * radius;
  869 +
  870 + // text start
  871 + var orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
  872 + var orginY3 = orginY1;
  873 +
  874 + var textWidth = measureText(item.text);
  875 + var startY = orginY3;
  876 +
  877 + if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, { x: orginX3 })) {
  878 + if (orginX3 > 0) {
  879 + startY = Math.min(orginY3, lastTextObject.start.y);
  880 + } else if (orginX1 < 0) {
  881 + startY = Math.max(orginY3, lastTextObject.start.y);
  882 + } else {
  883 + if (orginY3 > 0) {
  884 + startY = Math.max(orginY3, lastTextObject.start.y);
  885 + } else {
  886 + startY = Math.min(orginY3, lastTextObject.start.y);
  887 + }
  888 + }
  889 + }
  890 +
  891 + if (orginX3 < 0) {
  892 + orginX3 -= textWidth;
  893 + }
  894 +
  895 + var textObject = {
  896 + lineStart: {
  897 + x: orginX2,
  898 + y: orginY2
  899 + },
  900 + lineEnd: {
  901 + x: orginX1,
  902 + y: orginY1
  903 + },
  904 + start: {
  905 + x: orginX3,
  906 + y: startY
  907 + },
  908 + width: textWidth,
  909 + height: config.fontSize,
  910 + text: item.text,
  911 + color: item.color
  912 + };
  913 +
  914 + lastTextObject = avoidCollision(textObject, lastTextObject);
  915 + textObjectCollection.push(lastTextObject);
  916 + });
  917 +
  918 + textObjectCollection.forEach(function (item) {
  919 + var lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
  920 + var lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
  921 + var textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
  922 + context.setLineWidth(1);
  923 + context.setFontSize(config.fontSize);
  924 + context.beginPath();
  925 + context.setStrokeStyle(item.color);
  926 + context.setFillStyle(item.color);
  927 + context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
  928 + var curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
  929 + var textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
  930 + context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
  931 + context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
  932 + context.stroke();
  933 + context.closePath();
  934 + context.beginPath();
  935 + context.moveTo(textPosition.x + item.width, textPosition.y);
  936 + context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
  937 + context.closePath();
  938 + context.fill();
  939 + context.beginPath();
  940 + context.setFillStyle('#666666');
  941 + context.fillText(item.text, textStartX, textPosition.y + 3);
  942 + context.closePath();
  943 + context.stroke();
  944 +
  945 + context.closePath();
  946 + });
  947 +}
  948 +
  949 +function drawToolTipSplitLine(offsetX, opts, config, context) {
  950 + var startY = config.padding;
  951 + var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
  952 + context.beginPath();
  953 + context.setStrokeStyle('#cccccc');
  954 + context.setLineWidth(1);
  955 + context.moveTo(offsetX, startY);
  956 + context.lineTo(offsetX, endY);
  957 + context.stroke();
  958 + context.closePath();
  959 +}
  960 +
  961 +function drawToolTip(textList, offset, opts, config, context) {
  962 + var legendWidth = 4;
  963 + var legendMarginRight = 5;
  964 + var arrowWidth = 8;
  965 + var isOverRightBorder = false;
  966 + offset = assign({
  967 + x: 0,
  968 + y: 0
  969 + }, offset);
  970 + offset.y -= 8;
  971 + var textWidth = textList.map(function (item) {
  972 + return measureText(item.text);
  973 + });
  974 +
  975 + var toolTipWidth = legendWidth + legendMarginRight + 4 * config.toolTipPadding + Math.max.apply(null, textWidth);
  976 + var toolTipHeight = 2 * config.toolTipPadding + textList.length * config.toolTipLineHeight;
  977 +
  978 + // if beyond the right border
  979 + if (offset.x - Math.abs(opts._scrollDistance_) + arrowWidth + toolTipWidth > opts.width) {
  980 + isOverRightBorder = true;
  981 + }
  982 +
  983 + // draw background rect
  984 + context.beginPath();
  985 + context.setFillStyle(opts.tooltip.option.background || config.toolTipBackground);
  986 + context.setGlobalAlpha(config.toolTipOpacity);
  987 + if (isOverRightBorder) {
  988 + context.moveTo(offset.x, offset.y + 10);
  989 + context.lineTo(offset.x - arrowWidth, offset.y + 10 - 5);
  990 + context.lineTo(offset.x - arrowWidth, offset.y + 10 + 5);
  991 + context.moveTo(offset.x, offset.y + 10);
  992 + context.fillRect(offset.x - toolTipWidth - arrowWidth, offset.y, toolTipWidth, toolTipHeight);
  993 + } else {
  994 + context.moveTo(offset.x, offset.y + 10);
  995 + context.lineTo(offset.x + arrowWidth, offset.y + 10 - 5);
  996 + context.lineTo(offset.x + arrowWidth, offset.y + 10 + 5);
  997 + context.moveTo(offset.x, offset.y + 10);
  998 + context.fillRect(offset.x + arrowWidth, offset.y, toolTipWidth, toolTipHeight);
  999 + }
  1000 +
  1001 + context.closePath();
  1002 + context.fill();
  1003 + context.setGlobalAlpha(1);
  1004 +
  1005 + // draw legend
  1006 + textList.forEach(function (item, index) {
  1007 + context.beginPath();
  1008 + context.setFillStyle(item.color);
  1009 + var startX = offset.x + arrowWidth + 2 * config.toolTipPadding;
  1010 + var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding;
  1011 + if (isOverRightBorder) {
  1012 + startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
  1013 + }
  1014 + context.fillRect(startX, startY, legendWidth, config.fontSize);
  1015 + context.closePath();
  1016 + });
  1017 +
  1018 + // draw text list
  1019 + context.beginPath();
  1020 + context.setFontSize(config.fontSize);
  1021 + context.setFillStyle('#ffffff');
  1022 + textList.forEach(function (item, index) {
  1023 + var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight;
  1024 + if (isOverRightBorder) {
  1025 + startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight;
  1026 + }
  1027 + var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding;
  1028 + context.fillText(item.text, startX, startY + config.fontSize);
  1029 + });
  1030 + context.stroke();
  1031 + context.closePath();
  1032 +}
  1033 +
  1034 +function drawYAxisTitle(title, opts, config, context) {
  1035 + var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2;
  1036 + context.save();
  1037 + context.beginPath();
  1038 + context.setFontSize(config.fontSize);
  1039 + context.setFillStyle(opts.yAxis.titleFontColor || '#333333');
  1040 + context.translate(0, opts.height);
  1041 + context.rotate(-90 * Math.PI / 180);
  1042 + context.fillText(title, startX, config.padding + 0.5 * config.fontSize);
  1043 + context.stroke();
  1044 + context.closePath();
  1045 + context.restore();
  1046 +}
  1047 +
  1048 +function drawColumnDataPoints(series, opts, config, context) {
  1049 + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  1050 +
  1051 + var _calYAxisData = calYAxisData(series, opts, config),
  1052 + ranges = _calYAxisData.ranges;
  1053 +
  1054 + var _getXAxisPoints = getXAxisPoints(opts.categories, opts, config),
  1055 + xAxisPoints = _getXAxisPoints.xAxisPoints,
  1056 + eachSpacing = _getXAxisPoints.eachSpacing;
  1057 +
  1058 + var minRange = ranges.pop();
  1059 + var maxRange = ranges.shift();
  1060 + context.save();
  1061 + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  1062 + context.translate(opts._scrollDistance_, 0);
  1063 + }
  1064 +
  1065 + series.forEach(function (eachSeries, seriesIndex) {
  1066 + var data = eachSeries.data;
  1067 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1068 + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
  1069 +
  1070 + // 绘制柱状数据图
  1071 + context.beginPath();
  1072 + context.setFillStyle(eachSeries.color);
  1073 + points.forEach(function (item, index) {
  1074 + if (item !== null) {
  1075 + var startX = item.x - item.width / 2 + 1;
  1076 + var height = opts.height - item.y - config.padding - config.xAxisHeight - config.legendHeight;
  1077 + context.moveTo(startX, item.y);
  1078 + context.rect(startX, item.y, item.width - 2, height);
  1079 + }
  1080 + });
  1081 + context.closePath();
  1082 + context.fill();
  1083 + });
  1084 + series.forEach(function (eachSeries, seriesIndex) {
  1085 + var data = eachSeries.data;
  1086 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1087 + points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
  1088 + if (opts.dataLabel !== false && process === 1) {
  1089 + drawPointText(points, eachSeries, config, context);
  1090 + }
  1091 + });
  1092 + context.restore();
  1093 + return {
  1094 + xAxisPoints: xAxisPoints,
  1095 + eachSpacing: eachSpacing
  1096 + };
  1097 +}
  1098 +
  1099 +function drawAreaDataPoints(series, opts, config, context) {
  1100 + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  1101 +
  1102 + var _calYAxisData2 = calYAxisData(series, opts, config),
  1103 + ranges = _calYAxisData2.ranges;
  1104 +
  1105 + var _getXAxisPoints2 = getXAxisPoints(opts.categories, opts, config),
  1106 + xAxisPoints = _getXAxisPoints2.xAxisPoints,
  1107 + eachSpacing = _getXAxisPoints2.eachSpacing;
  1108 +
  1109 + var minRange = ranges.pop();
  1110 + var maxRange = ranges.shift();
  1111 + var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
  1112 + var calPoints = [];
  1113 +
  1114 + context.save();
  1115 + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  1116 + context.translate(opts._scrollDistance_, 0);
  1117 + }
  1118 +
  1119 + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  1120 + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
  1121 + }
  1122 +
  1123 + series.forEach(function (eachSeries, seriesIndex) {
  1124 + var data = eachSeries.data;
  1125 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1126 + calPoints.push(points);
  1127 +
  1128 + var splitPointList = splitPoints(points);
  1129 +
  1130 + splitPointList.forEach(function (points) {
  1131 + // 绘制区域数据
  1132 + context.beginPath();
  1133 + context.setStrokeStyle(eachSeries.color);
  1134 + context.setFillStyle(eachSeries.color);
  1135 + context.setGlobalAlpha(0.6);
  1136 + context.setLineWidth(2);
  1137 + if (points.length > 1) {
  1138 + var firstPoint = points[0];
  1139 + var lastPoint = points[points.length - 1];
  1140 +
  1141 + context.moveTo(firstPoint.x, firstPoint.y);
  1142 + if (opts.extra.lineStyle === 'curve') {
  1143 + points.forEach(function (item, index) {
  1144 + if (index > 0) {
  1145 + var ctrlPoint = createCurveControlPoints(points, index - 1);
  1146 + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  1147 + }
  1148 + });
  1149 + } else {
  1150 + points.forEach(function (item, index) {
  1151 + if (index > 0) {
  1152 + context.lineTo(item.x, item.y);
  1153 + }
  1154 + });
  1155 + }
  1156 +
  1157 + context.lineTo(lastPoint.x, endY);
  1158 + context.lineTo(firstPoint.x, endY);
  1159 + context.lineTo(firstPoint.x, firstPoint.y);
  1160 + } else {
  1161 + var item = points[0];
  1162 + context.moveTo(item.x - eachSpacing / 2, item.y);
  1163 + context.lineTo(item.x + eachSpacing / 2, item.y);
  1164 + context.lineTo(item.x + eachSpacing / 2, endY);
  1165 + context.lineTo(item.x - eachSpacing / 2, endY);
  1166 + context.moveTo(item.x - eachSpacing / 2, item.y);
  1167 + }
  1168 + context.closePath();
  1169 + context.fill();
  1170 + context.setGlobalAlpha(1);
  1171 + });
  1172 +
  1173 + if (opts.dataPointShape !== false) {
  1174 + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
  1175 + drawPointShape(points, eachSeries.color, shape, context);
  1176 + }
  1177 + });
  1178 + if (opts.dataLabel !== false && process === 1) {
  1179 + series.forEach(function (eachSeries, seriesIndex) {
  1180 + var data = eachSeries.data;
  1181 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1182 + drawPointText(points, eachSeries, config, context);
  1183 + });
  1184 + }
  1185 +
  1186 + context.restore();
  1187 +
  1188 + return {
  1189 + xAxisPoints: xAxisPoints,
  1190 + calPoints: calPoints,
  1191 + eachSpacing: eachSpacing
  1192 + };
  1193 +}
  1194 +
  1195 +function drawLineDataPoints(series, opts, config, context) {
  1196 + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  1197 +
  1198 + var _calYAxisData3 = calYAxisData(series, opts, config),
  1199 + ranges = _calYAxisData3.ranges;
  1200 +
  1201 + var _getXAxisPoints3 = getXAxisPoints(opts.categories, opts, config),
  1202 + xAxisPoints = _getXAxisPoints3.xAxisPoints,
  1203 + eachSpacing = _getXAxisPoints3.eachSpacing;
  1204 +
  1205 + var minRange = ranges.pop();
  1206 + var maxRange = ranges.shift();
  1207 + var calPoints = [];
  1208 +
  1209 + context.save();
  1210 + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  1211 + context.translate(opts._scrollDistance_, 0);
  1212 + }
  1213 +
  1214 + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  1215 + drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
  1216 + }
  1217 +
  1218 + series.forEach(function (eachSeries, seriesIndex) {
  1219 + var data = eachSeries.data;
  1220 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1221 + calPoints.push(points);
  1222 + var splitPointList = splitPoints(points);
  1223 +
  1224 + splitPointList.forEach(function (points, index) {
  1225 + context.beginPath();
  1226 + context.setStrokeStyle(eachSeries.color);
  1227 + context.setLineWidth(2);
  1228 + if (points.length === 1) {
  1229 + context.moveTo(points[0].x, points[0].y);
  1230 + context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
  1231 + } else {
  1232 + context.moveTo(points[0].x, points[0].y);
  1233 + if (opts.extra.lineStyle === 'curve') {
  1234 + points.forEach(function (item, index) {
  1235 + if (index > 0) {
  1236 + var ctrlPoint = createCurveControlPoints(points, index - 1);
  1237 + context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
  1238 + }
  1239 + });
  1240 + } else {
  1241 + points.forEach(function (item, index) {
  1242 + if (index > 0) {
  1243 + context.lineTo(item.x, item.y);
  1244 + }
  1245 + });
  1246 + }
  1247 + context.moveTo(points[0].x, points[0].y);
  1248 + }
  1249 + context.closePath();
  1250 + context.stroke();
  1251 + });
  1252 +
  1253 + if (opts.dataPointShape !== false) {
  1254 + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
  1255 + drawPointShape(points, eachSeries.color, shape, context);
  1256 + }
  1257 + });
  1258 + if (opts.dataLabel !== false && process === 1) {
  1259 + series.forEach(function (eachSeries, seriesIndex) {
  1260 + var data = eachSeries.data;
  1261 + var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
  1262 + drawPointText(points, eachSeries, config, context);
  1263 + });
  1264 + }
  1265 +
  1266 + context.restore();
  1267 +
  1268 + return {
  1269 + xAxisPoints: xAxisPoints,
  1270 + calPoints: calPoints,
  1271 + eachSpacing: eachSpacing
  1272 + };
  1273 +}
  1274 +
  1275 +function drawToolTipBridge(opts, config, context, process) {
  1276 + context.save();
  1277 + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
  1278 + context.translate(opts._scrollDistance_, 0);
  1279 + }
  1280 + if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
  1281 + drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context);
  1282 + }
  1283 + context.restore();
  1284 +}
  1285 +
  1286 +function drawXAxis(categories, opts, config, context) {
  1287 + var _getXAxisPoints4 = getXAxisPoints(categories, opts, config),
  1288 + xAxisPoints = _getXAxisPoints4.xAxisPoints,
  1289 + startX = _getXAxisPoints4.startX,
  1290 + endX = _getXAxisPoints4.endX,
  1291 + eachSpacing = _getXAxisPoints4.eachSpacing;
  1292 +
  1293 + var startY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
  1294 + var endY = startY + config.xAxisLineHeight;
  1295 +
  1296 + context.save();
  1297 + if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
  1298 + context.translate(opts._scrollDistance_, 0);
  1299 + }
  1300 +
  1301 + context.beginPath();
  1302 + context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
  1303 +
  1304 + if (opts.xAxis.disableGrid !== true) {
  1305 + if (opts.xAxis.type === 'calibration') {
  1306 + xAxisPoints.forEach(function (item, index) {
  1307 + if (index > 0) {
  1308 + context.moveTo(item - eachSpacing / 2, startY);
  1309 + context.lineTo(item - eachSpacing / 2, startY + 4);
  1310 + }
  1311 + });
  1312 + } else {
  1313 + xAxisPoints.forEach(function (item, index) {
  1314 + context.moveTo(item, startY);
  1315 + context.lineTo(item, endY);
  1316 + });
  1317 + }
  1318 + }
  1319 + context.closePath();
  1320 + context.stroke();
  1321 +
  1322 + // 对X轴列表做抽稀处理
  1323 + var validWidth = opts.width - 2 * config.padding - config.yAxisWidth - config.yAxisTitleWidth;
  1324 + var maxXAxisListLength = Math.min(categories.length, Math.ceil(validWidth / config.fontSize / 1.5));
  1325 + var ratio = Math.ceil(categories.length / maxXAxisListLength);
  1326 +
  1327 + categories = categories.map(function (item, index) {
  1328 + return index % ratio !== 0 ? '' : item;
  1329 + });
  1330 +
  1331 + if (config._xAxisTextAngle_ === 0) {
  1332 + context.beginPath();
  1333 + context.setFontSize(config.fontSize);
  1334 + context.setFillStyle(opts.xAxis.fontColor || '#666666');
  1335 + categories.forEach(function (item, index) {
  1336 + var offset = eachSpacing / 2 - measureText(item) / 2;
  1337 + context.fillText(item, xAxisPoints[index] + offset, startY + config.fontSize + 5);
  1338 + });
  1339 + context.closePath();
  1340 + context.stroke();
  1341 + } else {
  1342 + categories.forEach(function (item, index) {
  1343 + context.save();
  1344 + context.beginPath();
  1345 + context.setFontSize(config.fontSize);
  1346 + context.setFillStyle(opts.xAxis.fontColor || '#666666');
  1347 + var textWidth = measureText(item);
  1348 + var offset = eachSpacing / 2 - textWidth;
  1349 +
  1350 + var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + config.fontSize / 2 + 5, opts.height),
  1351 + transX = _calRotateTranslate.transX,
  1352 + transY = _calRotateTranslate.transY;
  1353 +
  1354 + context.rotate(-1 * config._xAxisTextAngle_);
  1355 + context.translate(transX, transY);
  1356 + context.fillText(item, xAxisPoints[index] + offset, startY + config.fontSize + 5);
  1357 + context.closePath();
  1358 + context.stroke();
  1359 + context.restore();
  1360 + });
  1361 + }
  1362 +
  1363 + context.restore();
  1364 +}
  1365 +
  1366 +function drawYAxisGrid(opts, config, context) {
  1367 + var spacingValid = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
  1368 + var eachSpacing = Math.floor(spacingValid / config.yAxisSplit);
  1369 + var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
  1370 + var startX = config.padding + yAxisTotalWidth;
  1371 + var endX = opts.width - config.padding;
  1372 +
  1373 + var points = [];
  1374 + for (var i = 0; i < config.yAxisSplit; i++) {
  1375 + points.push(config.padding + eachSpacing * i);
  1376 + }
  1377 + points.push(config.padding + eachSpacing * config.yAxisSplit + 2);
  1378 +
  1379 + context.beginPath();
  1380 + context.setStrokeStyle(opts.yAxis.gridColor || "#cccccc");
  1381 + context.setLineWidth(1);
  1382 + points.forEach(function (item, index) {
  1383 + context.moveTo(startX, item);
  1384 + context.lineTo(endX, item);
  1385 + });
  1386 + context.closePath();
  1387 + context.stroke();
  1388 +}
  1389 +
  1390 +function drawYAxis(series, opts, config, context) {
  1391 + if (opts.yAxis.disabled === true) {
  1392 + return;
  1393 + }
  1394 +
  1395 + var _calYAxisData4 = calYAxisData(series, opts, config),
  1396 + rangesFormat = _calYAxisData4.rangesFormat;
  1397 +
  1398 + var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
  1399 +
  1400 + var spacingValid = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
  1401 + var eachSpacing = Math.floor(spacingValid / config.yAxisSplit);
  1402 + var startX = config.padding + yAxisTotalWidth;
  1403 + var endX = opts.width - config.padding;
  1404 + var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
  1405 +
  1406 + // set YAxis background
  1407 + context.setFillStyle(opts.background || '#ffffff');
  1408 + if (opts._scrollDistance_ < 0) {
  1409 + context.fillRect(0, 0, startX, endY + config.xAxisHeight + 5);
  1410 + }
  1411 + context.fillRect(endX, 0, opts.width, endY + config.xAxisHeight + 5);
  1412 +
  1413 + var points = [];
  1414 + for (var i = 0; i <= config.yAxisSplit; i++) {
  1415 + points.push(config.padding + eachSpacing * i);
  1416 + }
  1417 +
  1418 + context.stroke();
  1419 + context.beginPath();
  1420 + context.setFontSize(config.fontSize);
  1421 + context.setFillStyle(opts.yAxis.fontColor || '#666666');
  1422 + rangesFormat.forEach(function (item, index) {
  1423 + var pos = points[index] ? points[index] : endY;
  1424 + context.fillText(item, config.padding + config.yAxisTitleWidth, pos + config.fontSize / 2);
  1425 + });
  1426 + context.closePath();
  1427 + context.stroke();
  1428 +
  1429 + if (opts.yAxis.title) {
  1430 + drawYAxisTitle(opts.yAxis.title, opts, config, context);
  1431 + }
  1432 +}
  1433 +
  1434 +function drawLegend(series, opts, config, context) {
  1435 + if (!opts.legend) {
  1436 + return;
  1437 + }
  1438 + // each legend shape width 15px
  1439 + // the spacing between shape and text in each legend is the `padding`
  1440 + // each legend spacing is the `padding`
  1441 + // legend margin top `config.padding`
  1442 +
  1443 + var _calLegendData = calLegendData(series, opts, config),
  1444 + legendList = _calLegendData.legendList;
  1445 +
  1446 + var padding = 5;
  1447 + var marginTop = 8;
  1448 + var shapeWidth = 15;
  1449 + legendList.forEach(function (itemList, listIndex) {
  1450 + var width = 0;
  1451 + itemList.forEach(function (item) {
  1452 + item.name = item.name || 'undefined';
  1453 + width += 3 * padding + measureText(item.name) + shapeWidth;
  1454 + });
  1455 + var startX = (opts.width - width) / 2 + padding;
  1456 + var startY = opts.height - config.padding - config.legendHeight + listIndex * (config.fontSize + marginTop) + padding + marginTop;
  1457 +
  1458 + context.setFontSize(config.fontSize);
  1459 + itemList.forEach(function (item) {
  1460 + switch (opts.type) {
  1461 + case 'line':
  1462 + context.beginPath();
  1463 + context.setLineWidth(1);
  1464 + context.setStrokeStyle(item.color);
  1465 + context.moveTo(startX - 2, startY + 5);
  1466 + context.lineTo(startX + 17, startY + 5);
  1467 + context.stroke();
  1468 + context.closePath();
  1469 + context.beginPath();
  1470 + context.setLineWidth(1);
  1471 + context.setStrokeStyle('#ffffff');
  1472 + context.setFillStyle(item.color);
  1473 + context.moveTo(startX + 7.5, startY + 5);
  1474 + context.arc(startX + 7.5, startY + 5, 4, 0, 2 * Math.PI);
  1475 + context.fill();
  1476 + context.stroke();
  1477 + context.closePath();
  1478 + break;
  1479 + case 'pie':
  1480 + case 'ring':
  1481 + context.beginPath();
  1482 + context.setFillStyle(item.color);
  1483 + context.moveTo(startX + 7.5, startY + 5);
  1484 + context.arc(startX + 7.5, startY + 5, 7, 0, 2 * Math.PI);
  1485 + context.closePath();
  1486 + context.fill();
  1487 + break;
  1488 + default:
  1489 + context.beginPath();
  1490 + context.setFillStyle(item.color);
  1491 + context.moveTo(startX, startY);
  1492 + context.rect(startX, startY, 15, 10);
  1493 + context.closePath();
  1494 + context.fill();
  1495 + }
  1496 + startX += padding + shapeWidth;
  1497 + context.beginPath();
  1498 + context.setFillStyle(opts.extra.legendTextColor || '#333333');
  1499 + context.fillText(item.name, startX, startY + 9);
  1500 + context.closePath();
  1501 + context.stroke();
  1502 + startX += measureText(item.name) + 2 * padding;
  1503 + });
  1504 + });
  1505 +}
  1506 +function drawPieDataPoints(series, opts, config, context) {
  1507 + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  1508 +
  1509 + var pieOption = opts.extra.pie || {};
  1510 + series = getPieDataPoints(series, process);
  1511 + var centerPosition = {
  1512 + x: opts.width / 2,
  1513 + y: (opts.height - config.legendHeight) / 2
  1514 + };
  1515 + var radius = Math.min(centerPosition.x - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, centerPosition.y - config.pieChartLinePadding - config.pieChartTextPadding);
  1516 + if (opts.dataLabel) {
  1517 + radius -= 10;
  1518 + } else {
  1519 + radius -= 2 * config.padding;
  1520 + }
  1521 + series = series.map(function (eachSeries) {
  1522 + eachSeries._start_ += (pieOption.offsetAngle || 0) * Math.PI / 180;
  1523 + return eachSeries;
  1524 + });
  1525 + series.forEach(function (eachSeries) {
  1526 + context.beginPath();
  1527 + context.setLineWidth(2);
  1528 + context.setStrokeStyle('#ffffff');
  1529 + context.setFillStyle(eachSeries.color);
  1530 + context.moveTo(centerPosition.x, centerPosition.y);
  1531 + context.arc(centerPosition.x, centerPosition.y, radius, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
  1532 + context.closePath();
  1533 + context.fill();
  1534 + if (opts.disablePieStroke !== true) {
  1535 + context.stroke();
  1536 + }
  1537 + });
  1538 +
  1539 + if (opts.type === 'ring') {
  1540 + var innerPieWidth = radius * 0.6;
  1541 + if (typeof opts.extra.ringWidth === 'number' && opts.extra.ringWidth > 0) {
  1542 + innerPieWidth = Math.max(0, radius - opts.extra.ringWidth);
  1543 + }
  1544 + context.beginPath();
  1545 + context.setFillStyle(opts.background || '#ffffff');
  1546 + context.moveTo(centerPosition.x, centerPosition.y);
  1547 + context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
  1548 + context.closePath();
  1549 + context.fill();
  1550 + }
  1551 +
  1552 + if (opts.dataLabel !== false && process === 1) {
  1553 + // fix https://github.com/xiaolin3303/wx-charts/issues/132
  1554 + var valid = false;
  1555 + for (var i = 0, len = series.length; i < len; i++) {
  1556 + if (series[i].data > 0) {
  1557 + valid = true;
  1558 + break;
  1559 + }
  1560 + }
  1561 +
  1562 + if (valid) {
  1563 + drawPieText(series, opts, config, context, radius, centerPosition);
  1564 + }
  1565 + }
  1566 +
  1567 + if (process === 1 && opts.type === 'ring') {
  1568 + drawRingTitle(opts, config, context);
  1569 + }
  1570 +
  1571 + return {
  1572 + center: centerPosition,
  1573 + radius: radius,
  1574 + series: series
  1575 + };
  1576 +}
  1577 +
  1578 +function drawRadarDataPoints(series, opts, config, context) {
  1579 + var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  1580 +
  1581 + var radarOption = opts.extra.radar || {};
  1582 + var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
  1583 + var centerPosition = {
  1584 + x: opts.width / 2,
  1585 + y: (opts.height - config.legendHeight) / 2
  1586 + };
  1587 +
  1588 + var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin), centerPosition.y - config.radarLabelTextMargin);
  1589 +
  1590 + radius -= config.padding;
  1591 +
  1592 + // draw grid
  1593 + context.beginPath();
  1594 + context.setLineWidth(1);
  1595 + context.setStrokeStyle(radarOption.gridColor || "#cccccc");
  1596 + coordinateAngle.forEach(function (angle) {
  1597 + var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
  1598 + context.moveTo(centerPosition.x, centerPosition.y);
  1599 + context.lineTo(pos.x, pos.y);
  1600 + });
  1601 + context.stroke();
  1602 + context.closePath();
  1603 +
  1604 + // draw split line grid
  1605 +
  1606 + var _loop = function _loop(i) {
  1607 + var startPos = {};
  1608 + context.beginPath();
  1609 + context.setLineWidth(1);
  1610 + context.setStrokeStyle(radarOption.gridColor || "#cccccc");
  1611 + coordinateAngle.forEach(function (angle, index) {
  1612 + var pos = convertCoordinateOrigin(radius / config.radarGridCount * i * Math.cos(angle), radius / config.radarGridCount * i * Math.sin(angle), centerPosition);
  1613 + if (index === 0) {
  1614 + startPos = pos;
  1615 + context.moveTo(pos.x, pos.y);
  1616 + } else {
  1617 + context.lineTo(pos.x, pos.y);
  1618 + }
  1619 + });
  1620 + context.lineTo(startPos.x, startPos.y);
  1621 + context.stroke();
  1622 + context.closePath();
  1623 + };
  1624 +
  1625 + for (var i = 1; i <= config.radarGridCount; i++) {
  1626 + _loop(i);
  1627 + }
  1628 +
  1629 + var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
  1630 + radarDataPoints.forEach(function (eachSeries, seriesIndex) {
  1631 + // 绘制区域数据
  1632 + context.beginPath();
  1633 + context.setFillStyle(eachSeries.color);
  1634 + context.setGlobalAlpha(0.6);
  1635 + eachSeries.data.forEach(function (item, index) {
  1636 + if (index === 0) {
  1637 + context.moveTo(item.position.x, item.position.y);
  1638 + } else {
  1639 + context.lineTo(item.position.x, item.position.y);
  1640 + }
  1641 + });
  1642 + context.closePath();
  1643 + context.fill();
  1644 + context.setGlobalAlpha(1);
  1645 +
  1646 + if (opts.dataPointShape !== false) {
  1647 + var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
  1648 + var points = eachSeries.data.map(function (item) {
  1649 + return item.position;
  1650 + });
  1651 + drawPointShape(points, eachSeries.color, shape, context);
  1652 + }
  1653 + });
  1654 + // draw label text
  1655 + drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
  1656 +
  1657 + return {
  1658 + center: centerPosition,
  1659 + radius: radius,
  1660 + angleList: coordinateAngle
  1661 + };
  1662 +}
  1663 +
  1664 +function drawCanvas(opts, context) {
  1665 + context.draw();
  1666 +}
  1667 +
  1668 +var Timing = {
  1669 + easeIn: function easeIn(pos) {
  1670 + return Math.pow(pos, 3);
  1671 + },
  1672 +
  1673 + easeOut: function easeOut(pos) {
  1674 + return Math.pow(pos - 1, 3) + 1;
  1675 + },
  1676 +
  1677 + easeInOut: function easeInOut(pos) {
  1678 + if ((pos /= 0.5) < 1) {
  1679 + return 0.5 * Math.pow(pos, 3);
  1680 + } else {
  1681 + return 0.5 * (Math.pow(pos - 2, 3) + 2);
  1682 + }
  1683 + },
  1684 +
  1685 + linear: function linear(pos) {
  1686 + return pos;
  1687 + }
  1688 +};
  1689 +
  1690 +function Animation(opts) {
  1691 + this.isStop = false;
  1692 + opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
  1693 + opts.timing = opts.timing || 'linear';
  1694 +
  1695 + var delay = 17;
  1696 +
  1697 + var createAnimationFrame = function createAnimationFrame() {
  1698 + if (typeof requestAnimationFrame !== 'undefined') {
  1699 + return requestAnimationFrame;
  1700 + } else if (typeof setTimeout !== 'undefined') {
  1701 + return function (step, delay) {
  1702 + setTimeout(function () {
  1703 + var timeStamp = +new Date();
  1704 + step(timeStamp);
  1705 + }, delay);
  1706 + };
  1707 + } else {
  1708 + return function (step) {
  1709 + step(null);
  1710 + };
  1711 + }
  1712 + };
  1713 + var animationFrame = createAnimationFrame();
  1714 + var startTimeStamp = null;
  1715 + var _step = function step(timestamp) {
  1716 + if (timestamp === null || this.isStop === true) {
  1717 + opts.onProcess && opts.onProcess(1);
  1718 + opts.onAnimationFinish && opts.onAnimationFinish();
  1719 + return;
  1720 + }
  1721 + if (startTimeStamp === null) {
  1722 + startTimeStamp = timestamp;
  1723 + }
  1724 + if (timestamp - startTimeStamp < opts.duration) {
  1725 + var process = (timestamp - startTimeStamp) / opts.duration;
  1726 + var timingFunction = Timing[opts.timing];
  1727 + process = timingFunction(process);
  1728 + opts.onProcess && opts.onProcess(process);
  1729 + animationFrame(_step, delay);
  1730 + } else {
  1731 + opts.onProcess && opts.onProcess(1);
  1732 + opts.onAnimationFinish && opts.onAnimationFinish();
  1733 + }
  1734 + };
  1735 + _step = _step.bind(this);
  1736 +
  1737 + animationFrame(_step, delay);
  1738 +}
  1739 +
  1740 +// stop animation immediately
  1741 +// and tigger onAnimationFinish
  1742 +Animation.prototype.stop = function () {
  1743 + this.isStop = true;
  1744 +};
  1745 +
  1746 +function drawCharts(type, opts, config, context) {
  1747 + var _this = this;
  1748 +
  1749 + var series = opts.series;
  1750 + var categories = opts.categories;
  1751 + series = fillSeriesColor(series, config);
  1752 +
  1753 + var _calLegendData = calLegendData(series, opts, config),
  1754 + legendHeight = _calLegendData.legendHeight;
  1755 +
  1756 + config.legendHeight = legendHeight;
  1757 +
  1758 + var _calYAxisData = calYAxisData(series, opts, config),
  1759 + yAxisWidth = _calYAxisData.yAxisWidth;
  1760 +
  1761 + config.yAxisWidth = yAxisWidth;
  1762 + if (categories && categories.length) {
  1763 + var _calCategoriesData = calCategoriesData(categories, opts, config),
  1764 + xAxisHeight = _calCategoriesData.xAxisHeight,
  1765 + angle = _calCategoriesData.angle;
  1766 +
  1767 + config.xAxisHeight = xAxisHeight;
  1768 + config._xAxisTextAngle_ = angle;
  1769 + }
  1770 + if (type === 'pie' || type === 'ring') {
  1771 + config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(series);
  1772 + }
  1773 +
  1774 + var duration = opts.animation ? 1000 : 0;
  1775 + this.animationInstance && this.animationInstance.stop();
  1776 + switch (type) {
  1777 + case 'line':
  1778 + this.animationInstance = new Animation({
  1779 + timing: 'easeIn',
  1780 + duration: duration,
  1781 + onProcess: function onProcess(process) {
  1782 + drawYAxisGrid(opts, config, context);
  1783 +
  1784 + var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
  1785 + xAxisPoints = _drawLineDataPoints.xAxisPoints,
  1786 + calPoints = _drawLineDataPoints.calPoints,
  1787 + eachSpacing = _drawLineDataPoints.eachSpacing;
  1788 +
  1789 + _this.chartData.xAxisPoints = xAxisPoints;
  1790 + _this.chartData.calPoints = calPoints;
  1791 + _this.chartData.eachSpacing = eachSpacing;
  1792 + drawXAxis(categories, opts, config, context);
  1793 + drawLegend(opts.series, opts, config, context);
  1794 + drawYAxis(series, opts, config, context);
  1795 + drawToolTipBridge(opts, config, context, process);
  1796 + drawCanvas(opts, context);
  1797 + },
  1798 + onAnimationFinish: function onAnimationFinish() {
  1799 + _this.event.trigger('renderComplete');
  1800 + }
  1801 + });
  1802 + break;
  1803 + case 'column':
  1804 + this.animationInstance = new Animation({
  1805 + timing: 'easeIn',
  1806 + duration: duration,
  1807 + onProcess: function onProcess(process) {
  1808 + drawYAxisGrid(opts, config, context);
  1809 +
  1810 + var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
  1811 + xAxisPoints = _drawColumnDataPoints.xAxisPoints,
  1812 + eachSpacing = _drawColumnDataPoints.eachSpacing;
  1813 +
  1814 + _this.chartData.xAxisPoints = xAxisPoints;
  1815 + _this.chartData.eachSpacing = eachSpacing;
  1816 + drawXAxis(categories, opts, config, context);
  1817 + drawLegend(opts.series, opts, config, context);
  1818 + drawYAxis(series, opts, config, context);
  1819 + drawCanvas(opts, context);
  1820 + },
  1821 + onAnimationFinish: function onAnimationFinish() {
  1822 + _this.event.trigger('renderComplete');
  1823 + }
  1824 + });
  1825 + break;
  1826 + case 'area':
  1827 + this.animationInstance = new Animation({
  1828 + timing: 'easeIn',
  1829 + duration: duration,
  1830 + onProcess: function onProcess(process) {
  1831 + drawYAxisGrid(opts, config, context);
  1832 +
  1833 + var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
  1834 + xAxisPoints = _drawAreaDataPoints.xAxisPoints,
  1835 + calPoints = _drawAreaDataPoints.calPoints,
  1836 + eachSpacing = _drawAreaDataPoints.eachSpacing;
  1837 +
  1838 + _this.chartData.xAxisPoints = xAxisPoints;
  1839 + _this.chartData.calPoints = calPoints;
  1840 + _this.chartData.eachSpacing = eachSpacing;
  1841 + drawXAxis(categories, opts, config, context);
  1842 + drawLegend(opts.series, opts, config, context);
  1843 + drawYAxis(series, opts, config, context);
  1844 + drawToolTipBridge(opts, config, context, process);
  1845 + drawCanvas(opts, context);
  1846 + },
  1847 + onAnimationFinish: function onAnimationFinish() {
  1848 + _this.event.trigger('renderComplete');
  1849 + }
  1850 + });
  1851 + break;
  1852 + case 'ring':
  1853 + case 'pie':
  1854 + this.animationInstance = new Animation({
  1855 + timing: 'easeInOut',
  1856 + duration: duration,
  1857 + onProcess: function onProcess(process) {
  1858 + _this.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
  1859 + drawLegend(opts.series, opts, config, context);
  1860 + drawCanvas(opts, context);
  1861 + },
  1862 + onAnimationFinish: function onAnimationFinish() {
  1863 + _this.event.trigger('renderComplete');
  1864 + }
  1865 + });
  1866 + break;
  1867 + case 'radar':
  1868 + this.animationInstance = new Animation({
  1869 + timing: 'easeInOut',
  1870 + duration: duration,
  1871 + onProcess: function onProcess(process) {
  1872 + _this.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process);
  1873 + drawLegend(opts.series, opts, config, context);
  1874 + drawCanvas(opts, context);
  1875 + },
  1876 + onAnimationFinish: function onAnimationFinish() {
  1877 + _this.event.trigger('renderComplete');
  1878 + }
  1879 + });
  1880 + break;
  1881 + }
  1882 +}
  1883 +
  1884 +// simple event implement
  1885 +
  1886 +function Event() {
  1887 + this.events = {};
  1888 +}
  1889 +
  1890 +Event.prototype.addEventListener = function (type, listener) {
  1891 + this.events[type] = this.events[type] || [];
  1892 + this.events[type].push(listener);
  1893 +};
  1894 +
  1895 +Event.prototype.trigger = function () {
  1896 + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
  1897 + args[_key] = arguments[_key];
  1898 + }
  1899 +
  1900 + var type = args[0];
  1901 + var params = args.slice(1);
  1902 + if (!!this.events[type]) {
  1903 + this.events[type].forEach(function (listener) {
  1904 + try {
  1905 + listener.apply(null, params);
  1906 + } catch (e) {
  1907 + console.error(e);
  1908 + }
  1909 + });
  1910 + }
  1911 +};
  1912 +
  1913 +var Charts = function Charts(opts) {
  1914 + opts.title = opts.title || {};
  1915 + opts.subtitle = opts.subtitle || {};
  1916 + opts.yAxis = opts.yAxis || {};
  1917 + opts.xAxis = opts.xAxis || {};
  1918 + opts.extra = opts.extra || {};
  1919 + opts.legend = opts.legend === false ? false : true;
  1920 + opts.animation = opts.animation === false ? false : true;
  1921 + var config$$1 = assign({}, config);
  1922 + config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
  1923 + config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : config$$1.pieChartLinePadding;
  1924 + config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding;
  1925 +
  1926 + this.opts = opts;
  1927 + this.config = config$$1;
  1928 + this.context = wx.createCanvasContext(opts.canvasId);
  1929 + // store calcuated chart data
  1930 + // such as chart point coordinate
  1931 + this.chartData = {};
  1932 + this.event = new Event();
  1933 + this.scrollOption = {
  1934 + currentOffset: 0,
  1935 + startTouchX: 0,
  1936 + distance: 0
  1937 + };
  1938 +
  1939 + drawCharts.call(this, opts.type, opts, config$$1, this.context);
  1940 +};
  1941 +
  1942 +Charts.prototype.updateData = function () {
  1943 + var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  1944 +
  1945 + this.opts.series = data.series || this.opts.series;
  1946 + this.opts.categories = data.categories || this.opts.categories;
  1947 +
  1948 + this.opts.title = assign({}, this.opts.title, data.title || {});
  1949 + this.opts.subtitle = assign({}, this.opts.subtitle, data.subtitle || {});
  1950 +
  1951 + drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
  1952 +};
  1953 +
  1954 +Charts.prototype.stopAnimation = function () {
  1955 + this.animationInstance && this.animationInstance.stop();
  1956 +};
  1957 +
  1958 +Charts.prototype.addEventListener = function (type, listener) {
  1959 + this.event.addEventListener(type, listener);
  1960 +};
  1961 +
  1962 +Charts.prototype.getCurrentDataIndex = function (e) {
  1963 + var touches = e.touches && e.touches.length ? e.touches : e.changedTouches;
  1964 + if (touches && touches.length) {
  1965 + var _touches$ = touches[0],
  1966 + x = _touches$.x,
  1967 + y = _touches$.y;
  1968 +
  1969 + if (this.opts.type === 'pie' || this.opts.type === 'ring') {
  1970 + return findPieChartCurrentIndex({ x: x, y: y }, this.chartData.pieData);
  1971 + } else if (this.opts.type === 'radar') {
  1972 + return findRadarChartCurrentIndex({ x: x, y: y }, this.chartData.radarData, this.opts.categories.length);
  1973 + } else {
  1974 + return findCurrentIndex({ x: x, y: y }, this.chartData.xAxisPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
  1975 + }
  1976 + }
  1977 + return -1;
  1978 +};
  1979 +
  1980 +Charts.prototype.showToolTip = function (e) {
  1981 + var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  1982 +
  1983 + if (this.opts.type === 'line' || this.opts.type === 'area') {
  1984 + var index = this.getCurrentDataIndex(e);
  1985 + var currentOffset = this.scrollOption.currentOffset;
  1986 +
  1987 + var opts = assign({}, this.opts, {
  1988 + _scrollDistance_: currentOffset,
  1989 + animation: false
  1990 + });
  1991 + if (index > -1) {
  1992 + var seriesData = getSeriesDataItem(this.opts.series, index);
  1993 + if (seriesData.length === 0) {
  1994 + drawCharts.call(this, opts.type, opts, this.config, this.context);
  1995 + } else {
  1996 + var _getToolTipData = getToolTipData(seriesData, this.chartData.calPoints, index, this.opts.categories, option),
  1997 + textList = _getToolTipData.textList,
  1998 + offset = _getToolTipData.offset;
  1999 +
  2000 + opts.tooltip = {
  2001 + textList: textList,
  2002 + offset: offset,
  2003 + option: option
  2004 + };
  2005 + drawCharts.call(this, opts.type, opts, this.config, this.context);
  2006 + }
  2007 + } else {
  2008 + drawCharts.call(this, opts.type, opts, this.config, this.context);
  2009 + }
  2010 + }
  2011 +};
  2012 +
  2013 +Charts.prototype.scrollStart = function (e) {
  2014 + if (e.touches[0] && this.opts.enableScroll === true) {
  2015 + this.scrollOption.startTouchX = e.touches[0].x;
  2016 + }
  2017 +};
  2018 +
  2019 +Charts.prototype.scroll = function (e) {
  2020 + // TODO throtting...
  2021 + if (e.touches[0] && this.opts.enableScroll === true) {
  2022 + var _distance = e.touches[0].x - this.scrollOption.startTouchX;
  2023 + var currentOffset = this.scrollOption.currentOffset;
  2024 +
  2025 + var validDistance = calValidDistance(currentOffset + _distance, this.chartData, this.config, this.opts);
  2026 +
  2027 + this.scrollOption.distance = _distance = validDistance - currentOffset;
  2028 + var opts = assign({}, this.opts, {
  2029 + _scrollDistance_: currentOffset + _distance,
  2030 + animation: false
  2031 + });
  2032 +
  2033 + drawCharts.call(this, opts.type, opts, this.config, this.context);
  2034 + }
  2035 +};
  2036 +
  2037 +Charts.prototype.scrollEnd = function (e) {
  2038 + if (this.opts.enableScroll === true) {
  2039 + var _scrollOption = this.scrollOption,
  2040 + currentOffset = _scrollOption.currentOffset,
  2041 + distance = _scrollOption.distance;
  2042 +
  2043 + this.scrollOption.currentOffset = currentOffset + distance;
  2044 + this.scrollOption.distance = 0;
  2045 + }
  2046 +};
  2047 +
  2048 +module.exports = Charts;
注册登录 后发表评论