精华内容
下载资源
问答
  • wxcharts.js

    2019-01-24 11:25:22
    微信小程序图表插件,微信小程序图表插件wxcharts使用,使用地址参考https://blog.csdn.net/weixin_43923231/article/details/86594183
  • 基于wxcharts绘制报表

    2019-07-29 10:38:24
    前言 微信小程序图表插件(wx-charts)是基于canvas绘制,体积小巧,支持图表...如上图所示,我们基于wxcharts.js 来实现订单统计报表。 导入wxcharts.js 3.pic.jpg 将wxcharts.js 存放在utils目录 column.w...

    前言

    微信小程序图表插件(wx-charts)是基于canvas绘制,体积小巧,支持图表类型饼图、线图、柱状图 、区域图等图表图形绘制,目前wx-charts是微信小程序图表插件中比较强大好使的一个。

    如上图所示,我们基于wxcharts.js 来实现订单统计报表。

    导入wxcharts.js

    3.pic.jpg

    将wxcharts.js 存放在utils目录

    column.wxml

    <view class="container">
            <!--标题-->
        <view class="title">
            {{chartTitle}}
        </view>
        <!--绘制canvas-->
        <canvas canvas-id="columnCanvas" class="canvas" bindtouchstart="touchHandler"></canvas>
    </view>
    

    coumn.js

    引入wxcharts.js

    var wxCharts = require('../../../utils/wxcharts.js');
    

    初始化数据

    var app = getApp();
    var columnChart = null;
    var chartData = {
        main: {
            title: '订单统计',
            data: [23, 28, 35, 54, 95],
            categories: ['2013', '2014', '2015', '2016', '2017']
        }    
    };
    

    加载报表数据

    Page({
        data: {
            chartTitle: '总订单',
            isMainChartDisplay: true
        },
        onReady: function (e) {
            var windowWidth = 320;
            try {
              var res = wx.getSystemInfoSync();
              windowWidth = res.windowWidth;
            } catch (e) {
              console.error('getSystemInfoSync failed!');
            }
    
            columnChart = new wxCharts({
                canvasId: 'columnCanvas',
                type: 'column',
                animation: true,
                categories: chartData.main.categories,
                series: [{
                    name: '订单量',
                    color:'#188df0',
                    data: chartData.main.data,
                    format: function (val, name) {
                        return val.toFixed(2) + '万';
                    }
                }],
                yAxis: {
                    format: function (val) {
                        return val + '万';
                    },
                    min: 0
                },
                xAxis: {
                    disableGrid: false,
                    type: 'calibration'
                },
                extra: {
                    column: {
                        width: 15,
                    },
                    legendTextColor: '#000000'
                },
                width: windowWidth,
                height: 200,
            });
        }
    });
    

    直接copy以上代码就可以查看效果哦~~~

    wx-charts更多特性

    支持报表类型

    1. 饼图 pie
    2. 圆环图 ring
    3. 线图 line
    4. 柱状图 column
    5. 区域图 area
    6. 雷达图 radar

    参数说明

    opts                         Object
    opts.canvasId                String required                    微信小程序canvas-id
    opts.width                   Number required                canvas宽度,单位为px
    opts.height                  Number required                canvas高度,单位为px
    opts.title                   Object           (only for ring chart)
    opts.title.name              String           标题内容
    opts.title.fontSize          Number            标题字体大小(可选,单位为px)
    opts.title.color             String           标题颜色(可选)
    opts.subtitle                Object         (only for ring chart)
    opts.subtitle.name           String           副标题内容
    opts.subtitle.fontSize       Number          副标题字体大小(可选,单位为px)
    opts.subtitle.color          String          副标题颜色(可选)
    opts.animation               Boolean default true         是否动画展示
    opts.legend                  Boolen default true       是否显示图表下方各类别的标识
    opts.type                    String required 图表类型,可选值为pie, line, column, area……
    opts.categories              Array required       (饼图、圆环图不需要) 数据类别分类
    opts.dataLabel               Boolean default true     是否在图表中显示数据内容值
    opts.dataPointShape          Boolean default true   是否在图表中显示数据点图形标识
    opts.xAxis                   Object       X轴配置
    opts.xAxis.disableGrid       Boolean default false      不绘制X轴网格
    opts.yAxis                   Object    Y轴配置
    opts.yAxis.format            Function           自定义Y轴文案显示
    opts.yAxis.min               Number        Y轴起始值
    opts.yAxis.max               Number           Y轴终止值
    opts.yAxis.title             String       Y轴title
    opts.yAxis.disabled          Boolean default false        不绘制Y轴
    opts.series                  Array required        数据列表
    

    结构定义

    dataItem                      Object
    dataItem.data                 Array required (饼图、圆环图为Number) 数据
    dataItem.color                String 例如#7cb5ec 不传入则使用系统默认配色方案
    dataItem.name                 String 数据名称
    dateItem.format               Function 自定义显示数据内容

    饼图pie chart

    复制代码

    var Charts = require('charts.js');
    new Charts({
        canvasId: 'pieCanvas',
        type: 'pie',
        series: [{
            name: '成交量1',
            data: 15,
        }, {
            name: '成交量2',
            data: 35,
        }, {
            name: '成交量3',
            data: 78,
        }, {
            name: '成交量4',
            data: 63,
        }],
        width: 640,
        height: 400,
        dataLabel: false
    });

    复制代码

    线图line chart

    复制代码

    new Charts({
        canvasId: 'lineCanvas',
        type: 'line',
        categories: ['2012', '2013', '2014', '2015', '2016', '2017'],
        series: [{
            name: '成交量1',
            data: [0.15, 0.2, 0.45, 0.37, 0.4, 0.8],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }, {
            name: '成交量2',
            data: [0.30, 0.37, 0.65, 0.78, 0.69, 0.94],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }],
        yAxis: {
            title: '成交金额 (万元)',
            format: function (val) {
                return val.toFixed(2);
            },
            min: 0
        },
        width: 640,
        height: 400
    });

    复制代码

    柱状图columnChart

    复制代码

    new Charts({
        canvasId: 'columnCanvas',
        type: 'column',
        categories: ['2016-08', '2016-09', '2016-10', '2016-11', '2016-12', '2017'],
        series: [{
            name: '成交量1',
            data: [15, 20, 45, 37, 4, 80]
        }, {
            name: '成交量2',
            data: [70, 40, 65, 100, 34, 18]
        }, {
            name: '成交量3',
            data: [70, 40, 65, 100, 34, 18]
        }, {
            name: '成交量4',
            data: [70, 40, 65, 100, 34, 18]
        }],
        yAxis: {
            format: function (val) {
                return val + '万';
            }
        },
        width: 640,
        height: 400,
        dataLabel: false
    });

    复制代码

    区域图areaChart

    复制代码

    new Charts({
        canvasId: 'areaCanvas',
        type: 'area',
        categories: ['2016-08', '2016-09', '2016-10', '2016-11', '2016-12', '2017'],
        series: [{
            name: '成交量1',
            data: [70, 40, 65, 100, 34, 18],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }, {
            name: '成交量2',
            data: [15, 20, 45, 37, 4, 80],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }],
        yAxis: {
            format: function (val) {
                return val + '万';
            }
        },
        width: 640,
        height: 400
    });

    复制代码

    雷达图radar Chart

    复制代码

    new wxCharts({
       canvasId: 'radarCanvas',
        type: 'radar',
        categories: ['1', '2', '3', '4', '5', '6'],
        series: [{
            name: '成交量1',
            data: [90, 110, 125, 95, 87, 122]
        }],
        width: windowWidth,
        height: 200,
        extra: {
            radar: {
                max: 150
            }
        }
    });

    复制代码

    下面是自己项目中的代码,先上效果图

    wxml

    <!-- 折线区域 -->
    <view class='chart'>
      <!-- 图形 -->
      <view class='chart-info'>
        <canvas canvas-id="lineCanvas" disable-scroll="true" class="canvas" bindtouchstart="touchHandler"></canvas>
      </view>
      <!-- 折线图统计最近六个月家长给教师的好评情况 -->
    </view>

     

    wxss

     

    /* 折线 */
    .chart{
      width: 95%;
      height: 550rpx;
      margin: 0 auto;
      padding-top: 50rpx;
      background: #fff;
    }
    
    .chart-info{
      height: 500rpx;
    }
    
    .canvas {
        width: 380px;
        height: 400px;
    }

     

    js

     

    let Charts = require('../../../utils/wxcharts.js');   //引入wxChart文件
    var app = getApp();
    var lineChart = null;
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        date:''
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        //获取系统当前时间
        let that = this
        var myDate = new Date();
        var date = myDate.toLocaleDateString();
        console.log(date)
        that.setData({
          date: date,  //选择时间
        })
    
        // 折线图
        var windowWidth = '', windowHeight = '';    //定义宽高
        try {
          var res = wx.getSystemInfoSync();    //试图获取屏幕宽高数据
          windowWidth = res.windowWidth / 750 * 700   //以设计图750为主进行比例算换
          windowHeight = res.windowWidth / 750 * 500    //以设计图750为主进行比例算换
        } catch (e) {
          console.error('getSystemInfoSync failed!');   //如果获取失败
        }
    
        lineChart = new Charts({
          canvasId: 'lineCanvas',
          type: 'line',
          animation: true,  //是否开启动画
          categories: ['06', '07', '08', '09', '10', '11', '12'],
          series: [{
            name: '月教师好评情况',
            data: [15, 20, 45, 37, 40, 80, 25],
            format: function (val) {
              return val.toFixed(2) + '分';
            }
          }],
          xAxis: {   //是否隐藏x轴分割线
            disableGrid: true,
          },
          yAxis: {
            title: '教师好评总分数',
            format: function (val) {
              return val.toFixed(2);
            },
          },
          width: windowWidth, //图表展示内容宽度
          height: windowHeight, //图表展示内容高度
          dataLabel: true,    //是否在图表上直接显示数据
          dataPointShape: true, //是否在图标上显示数据点标志
          extra: {  
            lineStyle: 'curve'  //曲线
          },
        });
      },
      /**
       * 点击数据点显示对应的数据
       */
      touchHandler: function (e) {
        lineChart.showToolTip(e, {
          // background: '#7cb5ec',
          format: function (item, category) {
            return category + ' ' + item.name + ':' + item.data
          }
        });
      },
    
    })

     

    展开全文
  • var wxCharts = require('wxcharts.js'); new wxCharts({ canvasId: 'pieCanvas', type: 'pie', series: [{ name: 'cat1', data: 50, }, { name: 'cat2', data...
  • 小程序wxcharts绘制曲线图

    千次阅读 2020-03-30 16:18:19
    1.新建一个文件夹用来存放js, ...https://sucai.suoluomei.cn/sucai_zs/file/20200330161542-wxcharts-min.js https://sucai.suoluomei.cn/sucai_zs/file/20200330161601-wxcharts.js 页面粘贴内容 <view class...

    在这里插入图片描述
    1.新建一个文件夹用来存放js,
    在这里插入图片描述
    下载源码放到对应的js文件中(下面有源码)

    https://sucai.suoluomei.cn/sucai_zs/file/20200330161542-wxcharts-min.js
    https://sucai.suoluomei.cn/sucai_zs/file/20200330161601-wxcharts.js
    

    页面粘贴内容

        <view class='echart'>
          <canvas canvas-id="lineCanvas" disable-scroll="true" class="canvas"></canvas>
        </view>
    
    .echart{
      background: white;
      border-radius: 25rpx;
      padding: 20rpx 0;
      margin-top: 40rpx;
      height: 550rpx
    }
    canvas {
      margin: 0 auto;
       height: 600rpx
    }
    
    const Charts = require('../dist/wxcharts.js')
    
      onShow: function () {
        new Charts({
          canvasId: 'lineCanvas',
          type: 'line',
          categories: ['1月', '2月', '3月', '4月', '5月', '6月', '7月'],
          series: [{
            name: '测试成绩',
            color: '#BDE1F3', // 配色,不传入则使用系统默认配色方案
            background: '#1F9CEC',
            data: [20, 100, 20, 10, 90,100, 91],
            format: function (val) {
              return val.toFixed(2);
            }
          }],
          dataLabel: false,
          yAxis: {
            max: 100,
            min: 0, // Y轴起始值,
            disableGrid: true
          },
          extra: {
            lineStyle: 'curve' // (仅对line, area图表有效) 可选值:curve曲线,straight直线 (默认)
          },
          dataPointShape: true,
          width: 320,
          height: 275
        });
      },
    

    完毕

    wxcharts-min.js源码:

    /*
     * charts for WeChat small app v1.0
     *
     * https://github.com/xiaolin3303/wx-charts
     * 2016-11-28
     *
     * Designed and built with all the love of Web
     */
     
    "use strict";function assign(t,e){if(null==t)throw new TypeError("Cannot convert undefined or null to object");for(var i=Object(t),a=1;a<arguments.length;a++){var n=arguments[a];if(null!=n)for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(i[o]=n[o])}return i}function findRange(t,e,i){if(isNaN(t))throw new Error("[wxCharts] unvalid series data!");i=i||10,e=e||"upper";for(var a=1;i<1;)i*=10,a*=10;for(t="upper"===e?Math.ceil(t*a):Math.floor(t*a);t%i!=0;)"upper"===e?t++:t--;return t/a}function calValidDistance(t,e,i,a){var n=a.width-i.padding-e.xAxisPoints[0],o=e.eachSpacing*a.categories.length,r=t;return t>=0?r=0:Math.abs(t)>=o-n&&(r=n-o),r}function isInAngleRange(t,e,i){function a(t){for(;t<0;)t+=2*Math.PI;for(;t>2*Math.PI;)t-=2*Math.PI;return t}return t=a(t),e=a(e),i=a(i),e>i&&(i+=2*Math.PI,t<e&&(t+=2*Math.PI)),t>=e&&t<=i}function calRotateTranslate(t,e,i){var a=t,n=i-e,o=a+(i-n-a)/Math.sqrt(2);return o*=-1,{transX:o,transY:(i-n)*(Math.sqrt(2)-1)-(i-n-a)/Math.sqrt(2)}}function createCurveControlPoints(t,e){function i(t,e){return!(!t[e-1]||!t[e+1])&&(t[e].y>=Math.max(t[e-1].y,t[e+1].y)||t[e].y<=Math.min(t[e-1].y,t[e+1].y))}var a=null,n=null,o=null,r=null;if(e<1?(a=t[0].x+.2*(t[1].x-t[0].x),n=t[0].y+.2*(t[1].y-t[0].y)):(a=t[e].x+.2*(t[e+1].x-t[e-1].x),n=t[e].y+.2*(t[e+1].y-t[e-1].y)),e>t.length-3){var s=t.length-1;o=t[s].x-.2*(t[s].x-t[s-1].x),r=t[s].y-.2*(t[s].y-t[s-1].y)}else o=t[e+1].x-.2*(t[e+2].x-t[e].x),r=t[e+1].y-.2*(t[e+2].y-t[e].y);return i(t,e+1)&&(r=t[e+1].y),i(t,e)&&(n=t[e].y),{ctrA:{x:a,y:n},ctrB:{x:o,y:r}}}function convertCoordinateOrigin(t,e,i){return{x:i.x+t,y:i.y-e}}function avoidCollision(t,e){if(e)for(;util.isCollision(t,e);)t.start.x>0?t.start.y--:t.start.x<0?t.start.y++:t.start.y>0?t.start.y++:t.start.y--;return t}function fillSeriesColor(t,e){var i=0;return t.map(function(t){return t.color||(t.color=e.colors[i],i=(i+1)%e.colors.length),t})}function getDataRange(t,e){var i=0,a=e-t;return i=a>=1e4?1e3:a>=1e3?100:a>=100?10:a>=10?5:a>=1?1:a>=.1?.1:.01,{minRange:findRange(t,"lower",i),maxRange:findRange(e,"upper",i)}}function measureText(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:10;t=String(t);var t=t.split(""),i=0;return t.forEach(function(t){/[a-zA-Z]/.test(t)?i+=7:/[0-9]/.test(t)?i+=5.5:/\./.test(t)?i+=2.7:/-/.test(t)?i+=3.25:/[\u4e00-\u9fa5]/.test(t)?i+=10:/\(|\)/.test(t)?i+=3.73:/\s/.test(t)?i+=2.5:/%/.test(t)?i+=8:i+=10}),i*e/10}function dataCombine(t){return t.reduce(function(t,e){return(t.data?t.data:t).concat(e.data)},[])}function getSeriesDataItem(t,e){var i=[];return t.forEach(function(t){if(null!==t.data[e]&&void 0!==t.data[e]){var a={};a.color=t.color,a.name=t.name,a.data=t.format?t.format(t.data[e]):t.data[e],i.push(a)}}),i}function getMaxTextListLength(t){var e=t.map(function(t){return measureText(t)});return Math.max.apply(null,e)}function getRadarCoordinateSeries(t){for(var e=2*Math.PI/t,i=[],a=0;a<t;a++)i.push(e*a);return i.map(function(t){return-1*t+Math.PI/2})}function getToolTipData(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{},o=t.map(function(t){return{text:n.format?n.format(t,a[i]):t.name+": "+t.data,color:t.color}}),r=[],s={x:0,y:0};return e.forEach(function(t){void 0!==t[i]&&null!==t[i]&&r.push(t[i])}),r.forEach(function(t){s.x=Math.round(t.x),s.y+=t.y}),s.y/=r.length,{textList:o,offset:s}}function findCurrentIndex(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:0,o=-1;return isInExactChartArea(t,i,a)&&e.forEach(function(e,i){t.x+n>e&&(o=i)}),o}function isInExactChartArea(t,e,i){return t.x<e.width-i.padding&&t.x>i.padding+i.yAxisWidth+i.yAxisTitleWidth&&t.y>i.padding&&t.y<e.height-i.legendHeight-i.xAxisHeight-i.padding}function findRadarChartCurrentIndex(t,e,i){var a=2*Math.PI/i,n=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var o=function(t){return t<0&&(t+=2*Math.PI),t>2*Math.PI&&(t-=2*Math.PI),t},r=Math.atan2(e.center.y-t.y,t.x-e.center.x);r*=-1,r<0&&(r+=2*Math.PI);e.angleList.map(function(t){return t=o(-1*t)}).forEach(function(t,e){var i=o(t-a/2),s=o(t+a/2);s<i&&(s+=2*Math.PI),(r>=i&&r<=s||r+2*Math.PI>=i&&r+2*Math.PI<=s)&&(n=e)})}return n}function findPieChartCurrentIndex(t,e){var i=-1;if(isInExactPieChartArea(t,e.center,e.radius)){var a=Math.atan2(e.center.y-t.y,t.x-e.center.x);a=-a;for(var n=0,o=e.series.length;n<o;n++){var r=e.series[n];if(isInAngleRange(a,r._start_,r._start_+2*r._proportion_*Math.PI)){i=n;break}}}return i}function isInExactPieChartArea(t,e,i){return Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)<=Math.pow(i,2)}function splitPoints(t){var e=[],i=[];return t.forEach(function(t,a){null!==t?i.push(t):(i.length&&e.push(i),i=[])}),i.length&&e.push(i),e}function calLegendData(t,e,i){if(!1===e.legend)return{legendList:[],legendHeight:0};var a=[],n=0,o=[];return t.forEach(function(t){var i=30+measureText(t.name||"undefined");n+i>e.width?(a.push(o),n=i,o=[t]):(n+=i,o.push(t))}),o.length&&a.push(o),{legendList:a,legendHeight:a.length*(i.fontSize+8)+5}}function calCategoriesData(t,e,i){var a={angle:0,xAxisHeight:i.xAxisHeight},n=getXAxisPoints(t,e,i),o=n.eachSpacing,r=t.map(function(t){return measureText(t)}),s=Math.max.apply(this,r);return s+2*i.xAxisTextPadding>o&&(a.angle=45*Math.PI/180,a.xAxisHeight=2*i.xAxisTextPadding+s*Math.sin(a.angle)),a}function getRadarDataPoints(t,e,i,a,n){var o=arguments.length>5&&void 0!==arguments[5]?arguments[5]:1,r=n.extra.radar||{};r.max=r.max||0;var s=Math.max(r.max,Math.max.apply(null,dataCombine(a))),l=[];return a.forEach(function(a){var n={};n.color=a.color,n.data=[],a.data.forEach(function(a,r){var l={};l.angle=t[r],l.proportion=a/s,l.position=convertCoordinateOrigin(i*l.proportion*o*Math.cos(l.angle),i*l.proportion*o*Math.sin(l.angle),e),n.data.push(l)}),l.push(n)}),l}function getPieDataPoints(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,i=0,a=0;return t.forEach(function(t){t.data=null===t.data?0:t.data,i+=t.data}),t.forEach(function(t){t.data=null===t.data?0:t.data,t._proportion_=t.data/i*e}),t.forEach(function(t){t._start_=a,a+=2*t._proportion_*Math.PI}),t}function getPieTextMaxLength(t){t=getPieDataPoints(t);var e=0;return t.forEach(function(t){var i=t.format?t.format(+t._proportion_.toFixed(2)):util.toFixed(100*t._proportion_)+"%";e=Math.max(e,measureText(i))}),e}function fixColumeData(t,e,i,a,n,o){return t.map(function(t){return null===t?null:(t.width=(e-2*n.columePadding)/i,o.extra.column&&o.extra.column.width&&+o.extra.column.width>0?t.width=Math.min(t.width,+o.extra.column.width):t.width=Math.min(t.width,25),t.x+=(a+.5-i/2)*t.width,t)})}function getXAxisPoints(t,e,i){var a=i.yAxisWidth+i.yAxisTitleWidth,n=e.width-2*i.padding-a,o=e.enableScroll?Math.min(5,t.length):t.length,r=n/o,s=[],l=i.padding+a,h=e.width-i.padding;return t.forEach(function(t,e){s.push(l+e*r)}),!0===e.enableScroll?s.push(l+t.length*r):s.push(h),{xAxisPoints:s,startX:l,endX:h,eachSpacing:r}}function getDataPoints(t,e,i,a,n,o,r){var s=arguments.length>7&&void 0!==arguments[7]?arguments[7]:1,l=[],h=o.height-2*r.padding-r.xAxisHeight-r.legendHeight;return t.forEach(function(t,c){if(null===t)l.push(null);else{var d={};d.x=a[c]+Math.round(n/2);var x=h*(t-e)/(i-e);x*=s,d.y=o.height-r.xAxisHeight-r.legendHeight-Math.round(x)-r.padding,l.push(d)}}),l}function getYAxisTextList(t,e,i){var a=dataCombine(t);a=a.filter(function(t){return null!==t});var n=Math.min.apply(this,a),o=Math.max.apply(this,a);if("number"==typeof e.yAxis.min&&(n=Math.min(e.yAxis.min,n)),"number"==typeof e.yAxis.max&&(o=Math.max(e.yAxis.max,o)),n===o){var r=o||1;n-=r,o+=r}for(var s=getDataRange(n,o),l=s.minRange,h=s.maxRange,c=[],d=(h-l)/i.yAxisSplit,x=0;x<=i.yAxisSplit;x++)c.push(l+d*x);return c.reverse()}function calYAxisData(t,e,i){var a=getYAxisTextList(t,e,i),n=i.yAxisWidth,o=a.map(function(t){return t=util.toFixed(t,2),t=e.yAxis.format?e.yAxis.format(Number(t)):t,n=Math.max(n,measureText(t)+5),t});return!0===e.yAxis.disabled&&(n=0),{rangesFormat:o,ranges:a,yAxisWidth:n}}function drawPointShape(t,e,i,a){a.beginPath(),a.setStrokeStyle("#ffffff"),a.setLineWidth(1),a.setFillStyle(e),"diamond"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x,t.y-4.5),a.lineTo(t.x-4.5,t.y),a.lineTo(t.x,t.y+4.5),a.lineTo(t.x+4.5,t.y),a.lineTo(t.x,t.y-4.5))}):"circle"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x+3.5,t.y),a.arc(t.x,t.y,4,0,2*Math.PI,!1))}):"rect"===i?t.forEach(function(t,e){null!==t&&(a.moveTo(t.x-3.5,t.y-3.5),a.rect(t.x-3.5,t.y-3.5,7,7))}):"triangle"===i&&t.forEach(function(t,e){null!==t&&(a.moveTo(t.x,t.y-4.5),a.lineTo(t.x-4.5,t.y+4.5),a.lineTo(t.x+4.5,t.y+4.5),a.lineTo(t.x,t.y-4.5))}),a.closePath(),a.fill(),a.stroke()}function drawRingTitle(t,e,i){var a=t.title.fontSize||e.titleFontSize,n=t.subtitle.fontSize||e.subtitleFontSize,o=t.title.name||"",r=t.subtitle.name||"",s=t.title.color||e.titleColor,l=t.subtitle.color||e.subtitleColor,h=o?a:0,c=r?n:0;if(r){var d=measureText(r,n),x=(t.width-d)/2+(t.subtitle.offsetX||0),f=(t.height-e.legendHeight+n)/2;o&&(f-=(h+5)/2),i.beginPath(),i.setFontSize(n),i.setFillStyle(l),i.fillText(r,x,f),i.stroke(),i.closePath()}if(o){var u=measureText(o,a),g=(t.width-u)/2+(t.title.offsetX||0),p=(t.height-e.legendHeight+a)/2;r&&(p+=(c+5)/2),i.beginPath(),i.setFontSize(a),i.setFillStyle(s),i.fillText(o,g,p),i.stroke(),i.closePath()}}function drawPointText(t,e,i,a){var n=e.data;a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle("#666666"),t.forEach(function(t,i){if(null!==t){var o=e.format?e.format(n[i]):n[i];a.fillText(o,t.x-measureText(o)/2,t.y-2)}}),a.closePath(),a.stroke()}function drawRadarLabel(t,e,i,a,n,o){var r=a.extra.radar||{};e+=n.radarLabelTextMargin,o.beginPath(),o.setFontSize(n.fontSize),o.setFillStyle(r.labelColor||"#666666"),t.forEach(function(t,r){var s={x:e*Math.cos(t),y:e*Math.sin(t)},l=convertCoordinateOrigin(s.x,s.y,i),h=l.x,c=l.y;util.approximatelyEqual(s.x,0)?h-=measureText(a.categories[r]||"")/2:s.x<0&&(h-=measureText(a.categories[r]||"")),o.fillText(a.categories[r]||"",h,c+n.fontSize/2)}),o.stroke(),o.closePath()}function drawPieText(t,e,i,a,n,o){var r=n+i.pieChartLinePadding,s=[],l=null;t.map(function(t){return{arc:2*Math.PI-(t._start_+2*Math.PI*t._proportion_/2),text:t.format?t.format(+t._proportion_.toFixed(2)):util.toFixed(100*t._proportion_)+"%",color:t.color}}).forEach(function(t){var e=Math.cos(t.arc)*r,a=Math.sin(t.arc)*r,o=Math.cos(t.arc)*n,h=Math.sin(t.arc)*n,c=e>=0?e+i.pieChartTextPadding:e-i.pieChartTextPadding,d=a,x=measureText(t.text),f=d;l&&util.isSameXCoordinateArea(l.start,{x:c})&&(f=c>0?Math.min(d,l.start.y):e<0?Math.max(d,l.start.y):d>0?Math.max(d,l.start.y):Math.min(d,l.start.y)),c<0&&(c-=x);var u={lineStart:{x:o,y:h},lineEnd:{x:e,y:a},start:{x:c,y:f},width:x,height:i.fontSize,text:t.text,color:t.color};l=avoidCollision(u,l),s.push(l)}),s.forEach(function(t){var e=convertCoordinateOrigin(t.lineStart.x,t.lineStart.y,o),n=convertCoordinateOrigin(t.lineEnd.x,t.lineEnd.y,o),r=convertCoordinateOrigin(t.start.x,t.start.y,o);a.setLineWidth(1),a.setFontSize(i.fontSize),a.beginPath(),a.setStrokeStyle(t.color),a.setFillStyle(t.color),a.moveTo(e.x,e.y);var s=t.start.x<0?r.x+t.width:r.x,l=t.start.x<0?r.x-5:r.x+5;a.quadraticCurveTo(n.x,n.y,s,r.y),a.moveTo(e.x,e.y),a.stroke(),a.closePath(),a.beginPath(),a.moveTo(r.x+t.width,r.y),a.arc(s,r.y,2,0,2*Math.PI),a.closePath(),a.fill(),a.beginPath(),a.setFillStyle("#666666"),a.fillText(t.text,l,r.y+3),a.closePath(),a.stroke(),a.closePath()})}function drawToolTipSplitLine(t,e,i,a){var n=i.padding,o=e.height-i.padding-i.xAxisHeight-i.legendHeight;a.beginPath(),a.setStrokeStyle("#cccccc"),a.setLineWidth(1),a.moveTo(t,n),a.lineTo(t,o),a.stroke(),a.closePath()}function drawToolTip(t,e,i,a,n){var o=!1;e=assign({x:0,y:0},e),e.y-=8;var r=t.map(function(t){return measureText(t.text)}),s=9+4*a.toolTipPadding+Math.max.apply(null,r),l=2*a.toolTipPadding+t.length*a.toolTipLineHeight;e.x-Math.abs(i._scrollDistance_)+8+s>i.width&&(o=!0),n.beginPath(),n.setFillStyle(i.tooltip.option.background||a.toolTipBackground),n.setGlobalAlpha(a.toolTipOpacity),o?(n.moveTo(e.x,e.y+10),n.lineTo(e.x-8,e.y+10-5),n.lineTo(e.x-8,e.y+10+5),n.moveTo(e.x,e.y+10),n.fillRect(e.x-s-8,e.y,s,l)):(n.moveTo(e.x,e.y+10),n.lineTo(e.x+8,e.y+10-5),n.lineTo(e.x+8,e.y+10+5),n.moveTo(e.x,e.y+10),n.fillRect(e.x+8,e.y,s,l)),n.closePath(),n.fill(),n.setGlobalAlpha(1),t.forEach(function(t,i){n.beginPath(),n.setFillStyle(t.color);var r=e.x+8+2*a.toolTipPadding,l=e.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding;o&&(r=e.x-s-8+2*a.toolTipPadding),n.fillRect(r,l,4,a.fontSize),n.closePath()}),n.beginPath(),n.setFontSize(a.fontSize),n.setFillStyle("#ffffff"),t.forEach(function(t,i){var r=e.x+8+2*a.toolTipPadding+4+5;o&&(r=e.x-s-8+2*a.toolTipPadding+4+5);var l=e.y+(a.toolTipLineHeight-a.fontSize)/2+a.toolTipLineHeight*i+a.toolTipPadding;n.fillText(t.text,r,l+a.fontSize)}),n.stroke(),n.closePath()}function drawYAxisTitle(t,e,i,a){var n=i.xAxisHeight+(e.height-i.xAxisHeight-measureText(t))/2;a.save(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.yAxis.titleFontColor||"#333333"),a.translate(0,e.height),a.rotate(-90*Math.PI/180),a.fillText(t,n,i.padding+.5*i.fontSize),a.stroke(),a.closePath(),a.restore()}function drawColumnDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift();return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),t.forEach(function(o,r){var s=o.data,x=getDataPoints(s,c,d,l,h,e,i,n);x=fixColumeData(x,h,t.length,r,i,e),a.beginPath(),a.setFillStyle(o.color),x.forEach(function(t,n){if(null!==t){var o=t.x-t.width/2+1,r=e.height-t.y-i.padding-i.xAxisHeight-i.legendHeight;a.moveTo(o,t.y),a.rect(o,t.y,t.width-2,r)}}),a.closePath(),a.fill()}),t.forEach(function(o,r){var s=o.data,x=getDataPoints(s,c,d,l,h,e,i,n);x=fixColumeData(x,h,t.length,r,i,e),!1!==e.dataLabel&&1===n&&drawPointText(x,o,i,a)}),a.restore(),{xAxisPoints:l,eachSpacing:h}}function drawAreaDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift(),x=e.height-i.padding-i.xAxisHeight-i.legendHeight,f=[];return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),e.tooltip&&e.tooltip.textList&&e.tooltip.textList.length&&1===n&&drawToolTipSplitLine(e.tooltip.offset.x,e,i,a),t.forEach(function(t,o){var r=t.data,s=getDataPoints(r,c,d,l,h,e,i,n);if(f.push(s),splitPoints(s).forEach(function(i){if(a.beginPath(),a.setStrokeStyle(t.color),a.setFillStyle(t.color),a.setGlobalAlpha(.6),a.setLineWidth(2),i.length>1){var n=i[0],o=i[i.length-1];a.moveTo(n.x,n.y),"curve"===e.extra.lineStyle?i.forEach(function(t,e){if(e>0){var n=createCurveControlPoints(i,e-1);a.bezierCurveTo(n.ctrA.x,n.ctrA.y,n.ctrB.x,n.ctrB.y,t.x,t.y)}}):i.forEach(function(t,e){e>0&&a.lineTo(t.x,t.y)}),a.lineTo(o.x,x),a.lineTo(n.x,x),a.lineTo(n.x,n.y)}else{var r=i[0];a.moveTo(r.x-h/2,r.y),a.lineTo(r.x+h/2,r.y),a.lineTo(r.x+h/2,x),a.lineTo(r.x-h/2,x),a.moveTo(r.x-h/2,r.y)}a.closePath(),a.fill(),a.setGlobalAlpha(1)}),!1!==e.dataPointShape){var u=i.dataPointShape[o%i.dataPointShape.length];drawPointShape(s,t.color,u,a)}}),!1!==e.dataLabel&&1===n&&t.forEach(function(t,o){drawPointText(getDataPoints(t.data,c,d,l,h,e,i,n),t,i,a)}),a.restore(),{xAxisPoints:l,calPoints:f,eachSpacing:h}}function drawLineDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=calYAxisData(t,e,i),r=o.ranges,s=getXAxisPoints(e.categories,e,i),l=s.xAxisPoints,h=s.eachSpacing,c=r.pop(),d=r.shift(),x=[];return a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&!0===e.enableScroll&&a.translate(e._scrollDistance_,0),e.tooltip&&e.tooltip.textList&&e.tooltip.textList.length&&1===n&&drawToolTipSplitLine(e.tooltip.offset.x,e,i,a),t.forEach(function(t,o){var r=t.data,s=getDataPoints(r,c,d,l,h,e,i,n);if(x.push(s),splitPoints(s).forEach(function(i,n){a.beginPath(),a.setStrokeStyle(t.color),a.setLineWidth(2),1===i.length?(a.moveTo(i[0].x,i[0].y),a.arc(i[0].x,i[0].y,1,0,2*Math.PI)):(a.moveTo(i[0].x,i[0].y),"curve"===e.extra.lineStyle?i.forEach(function(t,e){if(e>0){var n=createCurveControlPoints(i,e-1);a.bezierCurveTo(n.ctrA.x,n.ctrA.y,n.ctrB.x,n.ctrB.y,t.x,t.y)}}):i.forEach(function(t,e){e>0&&a.lineTo(t.x,t.y)}),a.moveTo(i[0].x,i[0].y)),a.closePath(),a.stroke()}),!1!==e.dataPointShape){var f=i.dataPointShape[o%i.dataPointShape.length];drawPointShape(s,t.color,f,a)}}),!1!==e.dataLabel&&1===n&&t.forEach(function(t,o){drawPointText(getDataPoints(t.data,c,d,l,h,e,i,n),t,i,a)}),a.restore(),{xAxisPoints:l,calPoints:x,eachSpacing:h}}function drawToolTipBridge(t,e,i,a){i.save(),t._scrollDistance_&&0!==t._scrollDistance_&&!0===t.enableScroll&&i.translate(t._scrollDistance_,0),t.tooltip&&t.tooltip.textList&&t.tooltip.textList.length&&1===a&&drawToolTip(t.tooltip.textList,t.tooltip.offset,t,e,i),i.restore()}function drawXAxis(t,e,i,a){var n=getXAxisPoints(t,e,i),o=n.xAxisPoints,r=(n.startX,n.endX,n.eachSpacing),s=e.height-i.padding-i.xAxisHeight-i.legendHeight,l=s+i.xAxisLineHeight;a.save(),e._scrollDistance_&&0!==e._scrollDistance_&&a.translate(e._scrollDistance_,0),a.beginPath(),a.setStrokeStyle(e.xAxis.gridColor||"#cccccc"),!0!==e.xAxis.disableGrid&&("calibration"===e.xAxis.type?o.forEach(function(t,e){e>0&&(a.moveTo(t-r/2,s),a.lineTo(t-r/2,s+4))}):o.forEach(function(t,e){a.moveTo(t,s),a.lineTo(t,l)})),a.closePath(),a.stroke();var h=e.width-2*i.padding-i.yAxisWidth-i.yAxisTitleWidth,c=Math.min(t.length,Math.ceil(h/i.fontSize/1.5)),d=Math.ceil(t.length/c);t=t.map(function(t,e){return e%d!=0?"":t}),0===i._xAxisTextAngle_?(a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.xAxis.fontColor||"#666666"),t.forEach(function(t,e){var n=r/2-measureText(t)/2;a.fillText(t,o[e]+n,s+i.fontSize+5)}),a.closePath(),a.stroke()):t.forEach(function(t,n){a.save(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.xAxis.fontColor||"#666666");var l=measureText(t),h=r/2-l,c=calRotateTranslate(o[n]+r/2,s+i.fontSize/2+5,e.height),d=c.transX,x=c.transY;a.rotate(-1*i._xAxisTextAngle_),a.translate(d,x),a.fillText(t,o[n]+h,s+i.fontSize+5),a.closePath(),a.stroke(),a.restore()}),a.restore()}function drawYAxisGrid(t,e,i){for(var a=t.height-2*e.padding-e.xAxisHeight-e.legendHeight,n=Math.floor(a/e.yAxisSplit),o=e.yAxisWidth+e.yAxisTitleWidth,r=e.padding+o,s=t.width-e.padding,l=[],h=0;h<e.yAxisSplit;h++)l.push(e.padding+n*h);l.push(e.padding+n*e.yAxisSplit+2),i.beginPath(),i.setStrokeStyle(t.yAxis.gridColor||"#cccccc"),i.setLineWidth(1),l.forEach(function(t,e){i.moveTo(r,t),i.lineTo(s,t)}),i.closePath(),i.stroke()}function drawYAxis(t,e,i,a){if(!0!==e.yAxis.disabled){var n=calYAxisData(t,e,i),o=n.rangesFormat,r=i.yAxisWidth+i.yAxisTitleWidth,s=e.height-2*i.padding-i.xAxisHeight-i.legendHeight,l=Math.floor(s/i.yAxisSplit),h=i.padding+r,c=e.width-i.padding,d=e.height-i.padding-i.xAxisHeight-i.legendHeight;a.setFillStyle(e.background||"#ffffff"),e._scrollDistance_<0&&a.fillRect(0,0,h,d+i.xAxisHeight+5),a.fillRect(c,0,e.width,d+i.xAxisHeight+5);for(var x=[],f=0;f<=i.yAxisSplit;f++)x.push(i.padding+l*f);a.stroke(),a.beginPath(),a.setFontSize(i.fontSize),a.setFillStyle(e.yAxis.fontColor||"#666666"),o.forEach(function(t,e){var n=x[e]?x[e]:d;a.fillText(t,i.padding+i.yAxisTitleWidth,n+i.fontSize/2)}),a.closePath(),a.stroke(),e.yAxis.title&&drawYAxisTitle(e.yAxis.title,e,i,a)}}function drawLegend(t,e,i,a){if(e.legend){var n=calLegendData(t,e,i),o=n.legendList;o.forEach(function(t,n){var o=0;t.forEach(function(t){t.name=t.name||"undefined",o+=15+measureText(t.name)+15});var r=(e.width-o)/2+5,s=e.height-i.padding-i.legendHeight+n*(i.fontSize+8)+5+8;a.setFontSize(i.fontSize),t.forEach(function(t){switch(e.type){case"line":a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(t.color),a.moveTo(r-2,s+5),a.lineTo(r+17,s+5),a.stroke(),a.closePath(),a.beginPath(),a.setLineWidth(1),a.setStrokeStyle("#ffffff"),a.setFillStyle(t.color),a.moveTo(r+7.5,s+5),a.arc(r+7.5,s+5,4,0,2*Math.PI),a.fill(),a.stroke(),a.closePath();break;case"pie":case"ring":a.beginPath(),a.setFillStyle(t.color),a.moveTo(r+7.5,s+5),a.arc(r+7.5,s+5,7,0,2*Math.PI),a.closePath(),a.fill();break;default:a.beginPath(),a.setFillStyle(t.color),a.moveTo(r,s),a.rect(r,s,15,10),a.closePath(),a.fill()}r+=20,a.beginPath(),a.setFillStyle(e.extra.legendTextColor||"#333333"),a.fillText(t.name,r,s+9),a.closePath(),a.stroke(),r+=measureText(t.name)+10})})}}function drawPieDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=e.extra.pie||{};t=getPieDataPoints(t,n);var r={x:e.width/2,y:(e.height-i.legendHeight)/2},s=Math.min(r.x-i.pieChartLinePadding-i.pieChartTextPadding-i._pieTextMaxLength_,r.y-i.pieChartLinePadding-i.pieChartTextPadding);if(e.dataLabel?s-=10:s-=2*i.padding,t=t.map(function(t){return t._start_+=(o.offsetAngle||0)*Math.PI/180,t}),t.forEach(function(t){a.beginPath(),a.setLineWidth(2),a.setStrokeStyle("#ffffff"),a.setFillStyle(t.color),a.moveTo(r.x,r.y),a.arc(r.x,r.y,s,t._start_,t._start_+2*t._proportion_*Math.PI),a.closePath(),a.fill(),!0!==e.disablePieStroke&&a.stroke()}),"ring"===e.type){var l=.6*s;"number"==typeof e.extra.ringWidth&&e.extra.ringWidth>0&&(l=Math.max(0,s-e.extra.ringWidth)),a.beginPath(),a.setFillStyle(e.background||"#ffffff"),a.moveTo(r.x,r.y),a.arc(r.x,r.y,l,0,2*Math.PI),a.closePath(),a.fill()}if(!1!==e.dataLabel&&1===n){for(var h=!1,c=0,d=t.length;c<d;c++)if(t[c].data>0){h=!0;break}h&&drawPieText(t,e,i,a,s,r)}return 1===n&&"ring"===e.type&&drawRingTitle(e,i,a),{center:r,radius:s,series:t}}function drawRadarDataPoints(t,e,i,a){var n=arguments.length>4&&void 0!==arguments[4]?arguments[4]:1,o=e.extra.radar||{},r=getRadarCoordinateSeries(e.categories.length),s={x:e.width/2,y:(e.height-i.legendHeight)/2},l=Math.min(s.x-(getMaxTextListLength(e.categories)+i.radarLabelTextMargin),s.y-i.radarLabelTextMargin);l-=i.padding,a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(o.gridColor||"#cccccc"),r.forEach(function(t){var e=convertCoordinateOrigin(l*Math.cos(t),l*Math.sin(t),s);a.moveTo(s.x,s.y),a.lineTo(e.x,e.y)}),a.stroke(),a.closePath();for(var h=1;h<=i.radarGridCount;h++)!function(t){var e={};a.beginPath(),a.setLineWidth(1),a.setStrokeStyle(o.gridColor||"#cccccc"),r.forEach(function(n,o){var r=convertCoordinateOrigin(l/i.radarGridCount*t*Math.cos(n),l/i.radarGridCount*t*Math.sin(n),s);0===o?(e=r,a.moveTo(r.x,r.y)):a.lineTo(r.x,r.y)}),a.lineTo(e.x,e.y),a.stroke(),a.closePath()}(h);return getRadarDataPoints(r,s,l,t,e,n).forEach(function(t,n){if(a.beginPath(),a.setFillStyle(t.color),a.setGlobalAlpha(.6),t.data.forEach(function(t,e){0===e?a.moveTo(t.position.x,t.position.y):a.lineTo(t.position.x,t.position.y)}),a.closePath(),a.fill(),a.setGlobalAlpha(1),!1!==e.dataPointShape){var o=i.dataPointShape[n%i.dataPointShape.length];drawPointShape(t.data.map(function(t){return t.position}),t.color,o,a)}}),drawRadarLabel(r,l,s,e,i,a),{center:s,radius:l,angleList:r}}function drawCanvas(t,e){e.draw()}function Animation(t){this.isStop=!1,t.duration=void 0===t.duration?1e3:t.duration,t.timing=t.timing||"linear";var e=function(){return"undefined"!=typeof requestAnimationFrame?requestAnimationFrame:"undefined"!=typeof setTimeout?function(t,e){setTimeout(function(){var e=+new Date;t(e)},e)}:function(t){t(null)}}(),i=null,a=function(n){if(null===n||!0===this.isStop)return t.onProcess&&t.onProcess(1),void(t.onAnimationFinish&&t.onAnimationFinish());if(null===i&&(i=n),n-i<t.duration){var o=(n-i)/t.duration;o=(0,Timing[t.timing])(o),t.onProcess&&t.onProcess(o),e(a,17)}else t.onProcess&&t.onProcess(1),t.onAnimationFinish&&t.onAnimationFinish()};a=a.bind(this),e(a,17)}function drawCharts(t,e,i,a){var n=this,o=e.series,r=e.categories;o=fillSeriesColor(o,i);var s=calLegendData(o,e,i),l=s.legendHeight;i.legendHeight=l;var h=calYAxisData(o,e,i),c=h.yAxisWidth;if(i.yAxisWidth=c,r&&r.length){var d=calCategoriesData(r,e,i),x=d.xAxisHeight,f=d.angle;i.xAxisHeight=x,i._xAxisTextAngle_=f}"pie"!==t&&"ring"!==t||(i._pieTextMaxLength_=!1===e.dataLabel?0:getPieTextMaxLength(o));var u=e.animation?1e3:0;switch(this.animationInstance&&this.animationInstance.stop(),t){case"line":this.animationInstance=new Animation({timing:"easeIn",duration:u,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawLineDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.calPoints,c=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.calPoints=h,n.chartData.eachSpacing=c,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawToolTipBridge(e,i,a,t),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger("renderComplete")}});break;case"column":this.animationInstance=new Animation({timing:"easeIn",duration:u,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawColumnDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.eachSpacing=h,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger("renderComplete")}});break;case"area":this.animationInstance=new Animation({timing:"easeIn",duration:u,onProcess:function(t){drawYAxisGrid(e,i,a);var s=drawAreaDataPoints(o,e,i,a,t),l=s.xAxisPoints,h=s.calPoints,c=s.eachSpacing;n.chartData.xAxisPoints=l,n.chartData.calPoints=h,n.chartData.eachSpacing=c,drawXAxis(r,e,i,a),drawLegend(e.series,e,i,a),drawYAxis(o,e,i,a),drawToolTipBridge(e,i,a,t),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger("renderComplete")}});break;case"ring":case"pie":this.animationInstance=new Animation({timing:"easeInOut",duration:u,onProcess:function(t){n.chartData.pieData=drawPieDataPoints(o,e,i,a,t),drawLegend(e.series,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger("renderComplete")}});break;case"radar":this.animationInstance=new Animation({timing:"easeInOut",duration:u,onProcess:function(t){n.chartData.radarData=drawRadarDataPoints(o,e,i,a,t),drawLegend(e.series,e,i,a),drawCanvas(e,a)},onAnimationFinish:function(){n.event.trigger("renderComplete")}})}}function Event(){this.events={}}var config={yAxisWidth:15,yAxisSplit:5,xAxisHeight:15,xAxisLineHeight:15,legendHeight:15,yAxisTitleWidth:15,padding:12,columePadding:3,fontSize:10,dataPointShape:["diamond","circle","triangle","rect"],colors:["#7cb5ec","#f7a35c","#434348","#90ed7d","#f15c80","#8085e9"],pieChartLinePadding:25,pieChartTextPadding:15,xAxisTextPadding:3,titleColor:"#333333",titleFontSize:20,subtitleColor:"#999999",subtitleFontSize:15,toolTipPadding:3,toolTipBackground:"#000000",toolTipOpacity:.7,toolTipLineHeight:14,radarGridCount:3,radarLabelTextMargin:15},util={toFixed:function(t,e){return e=e||2,this.isFloat(t)&&(t=t.toFixed(e)),t},isFloat:function(t){return t%1!=0},approximatelyEqual:function(t,e){return Math.abs(t-e)<1e-10},isSameSign:function(t,e){return Math.abs(t)===t&&Math.abs(e)===e||Math.abs(t)!==t&&Math.abs(e)!==e},isSameXCoordinateArea:function(t,e){return this.isSameSign(t.x,e.x)},isCollision:function(t,e){return t.end={},t.end.x=t.start.x+t.width,t.end.y=t.start.y-t.height,e.end={},e.end.x=e.start.x+e.width,e.end.y=e.start.y-e.height,!(e.start.x>t.end.x||e.end.x<t.start.x||e.end.y>t.start.y||e.start.y<t.end.y)}},Timing={easeIn:function(t){return Math.pow(t,3)},easeOut:function(t){return Math.pow(t-1,3)+1},easeInOut:function(t){return(t/=.5)<1?.5*Math.pow(t,3):.5*(Math.pow(t-2,3)+2)},linear:function(t){return t}};Animation.prototype.stop=function(){this.isStop=!0},Event.prototype.addEventListener=function(t,e){this.events[t]=this.events[t]||[],this.events[t].push(e)},Event.prototype.trigger=function(){for(var t=arguments.length,e=Array(t),i=0;i<t;i++)e[i]=arguments[i];var a=e[0],n=e.slice(1);this.events[a]&&this.events[a].forEach(function(t){try{t.apply(null,n)}catch(t){console.error(t)}})};var Charts=function(t){t.title=t.title||{},t.subtitle=t.subtitle||{},t.yAxis=t.yAxis||{},t.xAxis=t.xAxis||{},t.extra=t.extra||{},t.legend=!1!==t.legend,t.animation=!1!==t.animation;var e=assign({},config);e.yAxisTitleWidth=!0!==t.yAxis.disabled&&t.yAxis.title?e.yAxisTitleWidth:0,e.pieChartLinePadding=!1===t.dataLabel?0:e.pieChartLinePadding,e.pieChartTextPadding=!1===t.dataLabel?0:e.pieChartTextPadding,this.opts=t,this.config=e,this.context=wx.createCanvasContext(t.canvasId),this.chartData={},this.event=new Event,this.scrollOption={currentOffset:0,startTouchX:0,distance:0},drawCharts.call(this,t.type,t,e,this.context)};Charts.prototype.updateData=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};this.opts.series=t.series||this.opts.series,this.opts.categories=t.categories||this.opts.categories,this.opts.title=assign({},this.opts.title,t.title||{}),this.opts.subtitle=assign({},this.opts.subtitle,t.subtitle||{}),drawCharts.call(this,this.opts.type,this.opts,this.config,this.context)},Charts.prototype.stopAnimation=function(){this.animationInstance&&this.animationInstance.stop()},Charts.prototype.addEventListener=function(t,e){this.event.addEventListener(t,e)},Charts.prototype.getCurrentDataIndex=function(t){var e=t.touches&&t.touches.length?t.touches:t.changedTouches;if(e&&e.length){var i=e[0],a=i.x,n=i.y;return"pie"===this.opts.type||"ring"===this.opts.type?findPieChartCurrentIndex({x:a,y:n},this.chartData.pieData):"radar"===this.opts.type?findRadarChartCurrentIndex({x:a,y:n},this.chartData.radarData,this.opts.categories.length):findCurrentIndex({x:a,y:n},this.chartData.xAxisPoints,this.opts,this.config,Math.abs(this.scrollOption.currentOffset))}return-1},Charts.prototype.showToolTip=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if("line"===this.opts.type||"area"===this.opts.type){var i=this.getCurrentDataIndex(t),a=this.scrollOption.currentOffset,n=assign({},this.opts,{_scrollDistance_:a,animation:!1});if(i>-1){var o=getSeriesDataItem(this.opts.series,i);if(0!==o.length){var r=getToolTipData(o,this.chartData.calPoints,i,this.opts.categories,e),s=r.textList,l=r.offset;n.tooltip={textList:s,offset:l,option:e}}}drawCharts.call(this,n.type,n,this.config,this.context)}},Charts.prototype.scrollStart=function(t){t.touches[0]&&!0===this.opts.enableScroll&&(this.scrollOption.startTouchX=t.touches[0].x)},Charts.prototype.scroll=function(t){if(t.touches[0]&&!0===this.opts.enableScroll){var e=t.touches[0].x-this.scrollOption.startTouchX,i=this.scrollOption.currentOffset,a=calValidDistance(i+e,this.chartData,this.config,this.opts);this.scrollOption.distance=e=a-i;var n=assign({},this.opts,{_scrollDistance_:i+e,animation:!1});drawCharts.call(this,n.type,n,this.config,this.context)}},Charts.prototype.scrollEnd=function(t){if(!0===this.opts.enableScroll){var e=this.scrollOption,i=e.currentOffset,a=e.distance;this.scrollOption.currentOffset=i+a,this.scrollOption.distance=0}},module.exports=Charts;
    
    

    wxcharts.js源码

    /*
     * charts for WeChat small app v1.0
     *
     * https://github.com/xiaolin3303/wx-charts
     * 2016-11-28
     *
     * Designed and built with all the love of Web
     */
    
    'use strict';
    
    var config = {
        yAxisWidth: 15,
        yAxisSplit: 5,
        xAxisHeight: 15,
        xAxisLineHeight: 15,
        legendHeight: 15,
        yAxisTitleWidth: 15,
        padding: 12,
        columePadding: 3,
        fontSize: 10,
        dataPointShape: ['diamond', 'circle', 'triangle', 'rect'],
        colors: ['#7cb5ec', '#f7a35c', '#434348', '#90ed7d', '#f15c80', '#8085e9'],
        pieChartLinePadding: 25,
        pieChartTextPadding: 15,
        xAxisTextPadding: 3,
        titleColor: '#333333',
        titleFontSize: 20,
        subtitleColor: '#999999',
        subtitleFontSize: 15,
        toolTipPadding: 3,
        toolTipBackground: '#000000',
        toolTipOpacity: 0.7,
        toolTipLineHeight: 14,
        radarGridCount: 3,
        radarLabelTextMargin: 15
    };
    
    // Object.assign polyfill
    // https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
    function assign(target, varArgs) {
        if (target == null) {
            // TypeError if undefined or null
            throw new TypeError('Cannot convert undefined or null to object');
        }
    
        var to = Object(target);
    
        for (var index = 1; index < arguments.length; index++) {
            var nextSource = arguments[index];
    
            if (nextSource != null) {
                // Skip over if undefined or null
                for (var nextKey in nextSource) {
                    // Avoid bugs when hasOwnProperty is shadowed
                    if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                        to[nextKey] = nextSource[nextKey];
                    }
                }
            }
        }
        return to;
    }
    
    var util = {
        toFixed: function toFixed(num, limit) {
            limit = limit || 2;
            if (this.isFloat(num)) {
                num = num.toFixed(limit);
            }
            return num;
        },
        isFloat: function isFloat(num) {
            return num % 1 !== 0;
        },
        approximatelyEqual: function approximatelyEqual(num1, num2) {
            return Math.abs(num1 - num2) < 1e-10;
        },
        isSameSign: function isSameSign(num1, num2) {
            return Math.abs(num1) === num1 && Math.abs(num2) === num2 || Math.abs(num1) !== num1 && Math.abs(num2) !== num2;
        },
        isSameXCoordinateArea: function isSameXCoordinateArea(p1, p2) {
            return this.isSameSign(p1.x, p2.x);
        },
        isCollision: function isCollision(obj1, obj2) {
            obj1.end = {};
            obj1.end.x = obj1.start.x + obj1.width;
            obj1.end.y = obj1.start.y - obj1.height;
            obj2.end = {};
            obj2.end.x = obj2.start.x + obj2.width;
            obj2.end.y = obj2.start.y - obj2.height;
            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;
    
            return !flag;
        }
    };
    
    function findRange(num, type, limit) {
        if (isNaN(num)) {
            throw new Error('[wxCharts] unvalid series data!');
        }
        limit = limit || 10;
        type = type ? type : 'upper';
        var multiple = 1;
        while (limit < 1) {
            limit *= 10;
            multiple *= 10;
        }
        if (type === 'upper') {
            num = Math.ceil(num * multiple);
        } else {
            num = Math.floor(num * multiple);
        }
        while (num % limit !== 0) {
            if (type === 'upper') {
                num++;
            } else {
                num--;
            }
        }
    
        return num / multiple;
    }
    
    function calValidDistance(distance, chartData, config, opts) {
    
        var dataChartAreaWidth = opts.width - config.padding - chartData.xAxisPoints[0];
        var dataChartWidth = chartData.eachSpacing * opts.categories.length;
        var validDistance = distance;
        if (distance >= 0) {
            validDistance = 0;
        } else if (Math.abs(distance) >= dataChartWidth - dataChartAreaWidth) {
            validDistance = dataChartAreaWidth - dataChartWidth;
        }
        return validDistance;
    }
    
    function isInAngleRange(angle, startAngle, endAngle) {
        function adjust(angle) {
            while (angle < 0) {
                angle += 2 * Math.PI;
            }
            while (angle > 2 * Math.PI) {
                angle -= 2 * Math.PI;
            }
    
            return angle;
        }
    
        angle = adjust(angle);
        startAngle = adjust(startAngle);
        endAngle = adjust(endAngle);
        if (startAngle > endAngle) {
            endAngle += 2 * Math.PI;
            if (angle < startAngle) {
                angle += 2 * Math.PI;
            }
        }
    
        return angle >= startAngle && angle <= endAngle;
    }
    
    function calRotateTranslate(x, y, h) {
        var xv = x;
        var yv = h - y;
    
        var transX = xv + (h - yv - xv) / Math.sqrt(2);
        transX *= -1;
    
        var transY = (h - yv) * (Math.sqrt(2) - 1) - (h - yv - xv) / Math.sqrt(2);
    
        return {
            transX: transX,
            transY: transY
        };
    }
    
    function createCurveControlPoints(points, i) {
    
        function isNotMiddlePoint(points, i) {
            if (points[i - 1] && points[i + 1]) {
                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);
            } else {
                return false;
            }
        }
    
        var a = 0.2;
        var b = 0.2;
        var pAx = null;
        var pAy = null;
        var pBx = null;
        var pBy = null;
        if (i < 1) {
            pAx = points[0].x + (points[1].x - points[0].x) * a;
            pAy = points[0].y + (points[1].y - points[0].y) * a;
        } else {
            pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
            pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
        }
    
        if (i > points.length - 3) {
            var last = points.length - 1;
            pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
            pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
        } else {
            pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
            pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
        }
    
        // fix issue https://github.com/xiaolin3303/wx-charts/issues/79
        if (isNotMiddlePoint(points, i + 1)) {
            pBy = points[i + 1].y;
        }
        if (isNotMiddlePoint(points, i)) {
            pAy = points[i].y;
        }
    
        return {
            ctrA: { x: pAx, y: pAy },
            ctrB: { x: pBx, y: pBy }
        };
    }
    
    function convertCoordinateOrigin(x, y, center) {
        return {
            x: center.x + x,
            y: center.y - y
        };
    }
    
    function avoidCollision(obj, target) {
        if (target) {
            // is collision test
            while (util.isCollision(obj, target)) {
                if (obj.start.x > 0) {
                    obj.start.y--;
                } else if (obj.start.x < 0) {
                    obj.start.y++;
                } else {
                    if (obj.start.y > 0) {
                        obj.start.y++;
                    } else {
                        obj.start.y--;
                    }
                }
            }
        }
        return obj;
    }
    
    function fillSeriesColor(series, config) {
        var index = 0;
        return series.map(function (item) {
            if (!item.color) {
                item.color = config.colors[index];
                index = (index + 1) % config.colors.length;
            }
            return item;
        });
    }
    
    function getDataRange(minData, maxData) {
        var limit = 0;
        var range = maxData - minData;
        if (range >= 10000) {
            limit = 1000;
        } else if (range >= 1000) {
            limit = 100;
        } else if (range >= 100) {
            limit = 10;
        } else if (range >= 10) {
            limit = 5;
        } else if (range >= 1) {
            limit = 1;
        } else if (range >= 0.1) {
            limit = 0.1;
        } else {
            limit = 0.01;
        }
        return {
            minRange: findRange(minData, 'lower', limit),
            maxRange: findRange(maxData, 'upper', limit)
        };
    }
    
    function measureText(text) {
        var fontSize = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 10;
    
        // wx canvas 未实现measureText方法, 此处自行实现
        text = String(text);
        var text = text.split('');
        var width = 0;
        text.forEach(function (item) {
            if (/[a-zA-Z]/.test(item)) {
                width += 7;
            } else if (/[0-9]/.test(item)) {
                width += 5.5;
            } else if (/\./.test(item)) {
                width += 2.7;
            } else if (/-/.test(item)) {
                width += 3.25;
            } else if (/[\u4e00-\u9fa5]/.test(item)) {
                width += 10;
            } else if (/\(|\)/.test(item)) {
                width += 3.73;
            } else if (/\s/.test(item)) {
                width += 2.5;
            } else if (/%/.test(item)) {
                width += 8;
            } else {
                width += 10;
            }
        });
        return width * fontSize / 10;
    }
    
    function dataCombine(series) {
        return series.reduce(function (a, b) {
            return (a.data ? a.data : a).concat(b.data);
        }, []);
    }
    
    function getSeriesDataItem(series, index) {
        var data = [];
        series.forEach(function (item) {
            if (item.data[index] !== null && typeof item.data[index] !== 'undefined') {
                var seriesItem = {};
                seriesItem.color = item.color;
                seriesItem.name = item.name;
                seriesItem.data = item.format ? item.format(item.data[index]) : item.data[index];
                data.push(seriesItem);
            }
        });
    
        return data;
    }
    
    
    
    function getMaxTextListLength(list) {
        var lengthList = list.map(function (item) {
            return measureText(item);
        });
        return Math.max.apply(null, lengthList);
    }
    
    function getRadarCoordinateSeries(length) {
        var eachAngle = 2 * Math.PI / length;
        var CoordinateSeries = [];
        for (var i = 0; i < length; i++) {
            CoordinateSeries.push(eachAngle * i);
        }
    
        return CoordinateSeries.map(function (item) {
            return -1 * item + Math.PI / 2;
        });
    }
    
    function getToolTipData(seriesData, calPoints, index, categories) {
        var option = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : {};
    
        var textList = seriesData.map(function (item) {
            return {
                text: option.format ? option.format(item, categories[index]) : item.name + ': ' + item.data,
                color: item.color
            };
        });
        var validCalPoints = [];
        var offset = {
            x: 0,
            y: 0
        };
        calPoints.forEach(function (points) {
            if (typeof points[index] !== 'undefined' && points[index] !== null) {
                validCalPoints.push(points[index]);
            }
        });
        validCalPoints.forEach(function (item) {
            offset.x = Math.round(item.x);
            offset.y += item.y;
        });
    
        offset.y /= validCalPoints.length;
        return { textList: textList, offset: offset };
    }
    
    function findCurrentIndex(currentPoints, xAxisPoints, opts, config) {
        var offset = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
    
        var currentIndex = -1;
        if (isInExactChartArea(currentPoints, opts, config)) {
            xAxisPoints.forEach(function (item, index) {
                if (currentPoints.x + offset > item) {
                    currentIndex = index;
                }
            });
        }
    
        return currentIndex;
    }
    
    function isInExactChartArea(currentPoints, opts, config) {
        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;
    }
    
    function findRadarChartCurrentIndex(currentPoints, radarData, count) {
        var eachAngleArea = 2 * Math.PI / count;
        var currentIndex = -1;
        if (isInExactPieChartArea(currentPoints, radarData.center, radarData.radius)) {
            var fixAngle = function fixAngle(angle) {
                if (angle < 0) {
                    angle += 2 * Math.PI;
                }
                if (angle > 2 * Math.PI) {
                    angle -= 2 * Math.PI;
                }
                return angle;
            };
    
            var angle = Math.atan2(radarData.center.y - currentPoints.y, currentPoints.x - radarData.center.x);
            angle = -1 * angle;
            if (angle < 0) {
                angle += 2 * Math.PI;
            }
    
            var angleList = radarData.angleList.map(function (item) {
                item = fixAngle(-1 * item);
    
                return item;
            });
    
            angleList.forEach(function (item, index) {
                var rangeStart = fixAngle(item - eachAngleArea / 2);
                var rangeEnd = fixAngle(item + eachAngleArea / 2);
                if (rangeEnd < rangeStart) {
                    rangeEnd += 2 * Math.PI;
                }
                if (angle >= rangeStart && angle <= rangeEnd || angle + 2 * Math.PI >= rangeStart && angle + 2 * Math.PI <= rangeEnd) {
                    currentIndex = index;
                }
            });
        }
    
        return currentIndex;
    }
    
    function findPieChartCurrentIndex(currentPoints, pieData) {
        var currentIndex = -1;
        if (isInExactPieChartArea(currentPoints, pieData.center, pieData.radius)) {
            var angle = Math.atan2(pieData.center.y - currentPoints.y, currentPoints.x - pieData.center.x);
            angle = -angle;
            for (var i = 0, len = pieData.series.length; i < len; i++) {
                var item = pieData.series[i];
                if (isInAngleRange(angle, item._start_, item._start_ + item._proportion_ * 2 * Math.PI)) {
                    currentIndex = i;
                    break;
                }
            }
        }
    
        return currentIndex;
    }
    
    function isInExactPieChartArea(currentPoints, center, radius) {
        return Math.pow(currentPoints.x - center.x, 2) + Math.pow(currentPoints.y - center.y, 2) <= Math.pow(radius, 2);
    }
    
    function splitPoints(points) {
        var newPoints = [];
        var items = [];
        points.forEach(function (item, index) {
            if (item !== null) {
                items.push(item);
            } else {
                if (items.length) {
                    newPoints.push(items);
                }
                items = [];
            }
        });
        if (items.length) {
            newPoints.push(items);
        }
    
        return newPoints;
    }
    
    function calLegendData(series, opts, config) {
        if (opts.legend === false) {
            return {
                legendList: [],
                legendHeight: 0
            };
        }
        var padding = 5;
        var marginTop = 8;
        var shapeWidth = 15;
        var legendList = [];
        var widthCount = 0;
        var currentRow = [];
        series.forEach(function (item) {
            var itemWidth = 3 * padding + shapeWidth + measureText(item.name || 'undefined');
            if (widthCount + itemWidth > opts.width) {
                legendList.push(currentRow);
                widthCount = itemWidth;
                currentRow = [item];
            } else {
                widthCount += itemWidth;
                currentRow.push(item);
            }
        });
        if (currentRow.length) {
            legendList.push(currentRow);
        }
    
        return {
            legendList: legendList,
            legendHeight: legendList.length * (config.fontSize + marginTop) + padding
        };
    }
    
    function calCategoriesData(categories, opts, config) {
        var result = {
            angle: 0,
            xAxisHeight: config.xAxisHeight
        };
    
        var _getXAxisPoints = getXAxisPoints(categories, opts, config),
            eachSpacing = _getXAxisPoints.eachSpacing;
    
        // get max length of categories text
    
    
        var categoriesTextLenth = categories.map(function (item) {
            return measureText(item);
        });
    
        var maxTextLength = Math.max.apply(this, categoriesTextLenth);
    
        if (maxTextLength + 2 * config.xAxisTextPadding > eachSpacing) {
            result.angle = 45 * Math.PI / 180;
            result.xAxisHeight = 2 * config.xAxisTextPadding + maxTextLength * Math.sin(result.angle);
        }
    
        return result;
    }
    
    function getRadarDataPoints(angleList, center, radius, series, opts) {
        var process = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 1;
    
        var radarOption = opts.extra.radar || {};
        radarOption.max = radarOption.max || 0;
        var maxData = Math.max(radarOption.max, Math.max.apply(null, dataCombine(series)));
    
        var data = [];
        series.forEach(function (each) {
            var listItem = {};
            listItem.color = each.color;
            listItem.data = [];
            each.data.forEach(function (item, index) {
                var tmp = {};
                tmp.angle = angleList[index];
    
                tmp.proportion = item / maxData;
                tmp.position = convertCoordinateOrigin(radius * tmp.proportion * process * Math.cos(tmp.angle), radius * tmp.proportion * process * Math.sin(tmp.angle), center);
                listItem.data.push(tmp);
            });
    
            data.push(listItem);
        });
    
        return data;
    }
    
    function getPieDataPoints(series) {
        var process = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
    
        var count = 0;
        var _start_ = 0;
        series.forEach(function (item) {
            item.data = item.data === null ? 0 : item.data;
            count += item.data;
        });
        series.forEach(function (item) {
            item.data = item.data === null ? 0 : item.data;
            item._proportion_ = item.data / count * process;
        });
        series.forEach(function (item) {
            item._start_ = _start_;
            _start_ += 2 * item._proportion_ * Math.PI;
        });
    
        return series;
    }
    
    function getPieTextMaxLength(series) {
        series = getPieDataPoints(series);
        var maxLength = 0;
        series.forEach(function (item) {
            var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
            maxLength = Math.max(maxLength, measureText(text));
        });
    
        return maxLength;
    }
    
    function fixColumeData(points, eachSpacing, columnLen, index, config, opts) {
        return points.map(function (item) {
            if (item === null) {
                return null;
            }
            item.width = (eachSpacing - 2 * config.columePadding) / columnLen;
    
            if (opts.extra.column && opts.extra.column.width && +opts.extra.column.width > 0) {
                // customer column width
                item.width = Math.min(item.width, +opts.extra.column.width);
            } else {
                // default width should less tran 25px
                // don't ask me why, I don't know
                item.width = Math.min(item.width, 25);
            }
            item.x += (index + 0.5 - columnLen / 2) * item.width;
    
            return item;
        });
    }
    
    function getXAxisPoints(categories, opts, config) {
        var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
        var spacingValid = opts.width - 2 * config.padding - yAxisTotalWidth;
        var dataCount = opts.enableScroll ? Math.min(5, categories.length) : categories.length;
        var eachSpacing = spacingValid / dataCount;
    
        var xAxisPoints = [];
        var startX = config.padding + yAxisTotalWidth;
        var endX = opts.width - config.padding;
        categories.forEach(function (item, index) {
            xAxisPoints.push(startX + index * eachSpacing);
        });
        if (opts.enableScroll === true) {
            xAxisPoints.push(startX + categories.length * eachSpacing);
        } else {
            xAxisPoints.push(endX);
        }
    
        return { xAxisPoints: xAxisPoints, startX: startX, endX: endX, eachSpacing: eachSpacing };
    }
    
    function getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config) {
        var process = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 1;
    
        var points = [];
        var validHeight = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
        data.forEach(function (item, index) {
            if (item === null) {
                points.push(null);
            } else {
                var point = {};
                point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
                var height = validHeight * (item - minRange) / (maxRange - minRange);
                height *= process;
                point.y = opts.height - config.xAxisHeight - config.legendHeight - Math.round(height) - config.padding;
                points.push(point);
            }
        });
    
        return points;
    }
    
    function getYAxisTextList(series, opts, config) {
        var data = dataCombine(series);
        // remove null from data
        data = data.filter(function (item) {
            return item !== null;
        });
        var minData = Math.min.apply(this, data);
        var maxData = Math.max.apply(this, data);
        if (typeof opts.yAxis.min === 'number') {
            minData = Math.min(opts.yAxis.min, minData);
        }
        if (typeof opts.yAxis.max === 'number') {
            maxData = Math.max(opts.yAxis.max, maxData);
        }
    
        // fix issue https://github.com/xiaolin3303/wx-charts/issues/9
        if (minData === maxData) {
            var rangeSpan = maxData || 1;
            minData -= rangeSpan;
            maxData += rangeSpan;
        }
    
        var dataRange = getDataRange(minData, maxData);
        var minRange = dataRange.minRange;
        var maxRange = dataRange.maxRange;
    
        var range = [];
        var eachRange = (maxRange - minRange) / config.yAxisSplit;
    
        for (var i = 0; i <= config.yAxisSplit; i++) {
            range.push(minRange + eachRange * i);
        }
        return range.reverse();
    }
    
    function calYAxisData(series, opts, config) {
    
        var ranges = getYAxisTextList(series, opts, config);
        var yAxisWidth = config.yAxisWidth;
        var rangesFormat = ranges.map(function (item) {
            item = util.toFixed(item, 2);
            item = opts.yAxis.format ? opts.yAxis.format(Number(item)) : item;
            yAxisWidth = Math.max(yAxisWidth, measureText(item) + 5);
            return item;
        });
        if (opts.yAxis.disabled === true) {
            yAxisWidth = 0;
        }
    
        return { rangesFormat: rangesFormat, ranges: ranges, yAxisWidth: yAxisWidth };
    }
    
    function drawPointShape(points, color, shape, context) {
        context.beginPath();
        context.setStrokeStyle("#ffffff");
        context.setLineWidth(1);
        context.setFillStyle(color);
    
        if (shape === 'diamond') {
            points.forEach(function (item, index) {
                if (item !== null) {
                    context.moveTo(item.x, item.y - 4.5);
                    context.lineTo(item.x - 4.5, item.y);
                    context.lineTo(item.x, item.y + 4.5);
                    context.lineTo(item.x + 4.5, item.y);
                    context.lineTo(item.x, item.y - 4.5);
                }
            });
        } else if (shape === 'circle') {
            points.forEach(function (item, index) {
                if (item !== null) {
                    context.moveTo(item.x + 3.5, item.y);
                    context.arc(item.x, item.y, 4, 0, 2 * Math.PI, false);
                }
            });
        } else if (shape === 'rect') {
            points.forEach(function (item, index) {
                if (item !== null) {
                    context.moveTo(item.x - 3.5, item.y - 3.5);
                    context.rect(item.x - 3.5, item.y - 3.5, 7, 7);
                }
            });
        } else if (shape === 'triangle') {
            points.forEach(function (item, index) {
                if (item !== null) {
                    context.moveTo(item.x, item.y - 4.5);
                    context.lineTo(item.x - 4.5, item.y + 4.5);
                    context.lineTo(item.x + 4.5, item.y + 4.5);
                    context.lineTo(item.x, item.y - 4.5);
                }
            });
        }
        context.closePath();
        context.fill();
        context.stroke();
    }
    
    function drawRingTitle(opts, config, context) {
        var titlefontSize = opts.title.fontSize || config.titleFontSize;
        var subtitlefontSize = opts.subtitle.fontSize || config.subtitleFontSize;
        var title = opts.title.name || '';
        var subtitle = opts.subtitle.name || '';
        var titleFontColor = opts.title.color || config.titleColor;
        var subtitleFontColor = opts.subtitle.color || config.subtitleColor;
        var titleHeight = title ? titlefontSize : 0;
        var subtitleHeight = subtitle ? subtitlefontSize : 0;
        var margin = 5;
        if (subtitle) {
            var textWidth = measureText(subtitle, subtitlefontSize);
            var startX = (opts.width - textWidth) / 2 + (opts.subtitle.offsetX || 0);
            var startY = (opts.height - config.legendHeight + subtitlefontSize) / 2;
            if (title) {
                startY -= (titleHeight + margin) / 2;
            }
            context.beginPath();
            context.setFontSize(subtitlefontSize);
            context.setFillStyle(subtitleFontColor);
            context.fillText(subtitle, startX, startY);
            context.stroke();
            context.closePath();
        }
        if (title) {
            var _textWidth = measureText(title, titlefontSize);
            var _startX = (opts.width - _textWidth) / 2 + (opts.title.offsetX || 0);
            var _startY = (opts.height - config.legendHeight + titlefontSize) / 2;
            if (subtitle) {
                _startY += (subtitleHeight + margin) / 2;
            }
            context.beginPath();
            context.setFontSize(titlefontSize);
            context.setFillStyle(titleFontColor);
            context.fillText(title, _startX, _startY);
            context.stroke();
            context.closePath();
        }
    }
    
    function drawPointText(points, series, config, context) {
        // 绘制数据文案
        var data = series.data;
    
        context.beginPath();
        context.setFontSize(config.fontSize);
        context.setFillStyle('#666666');
        points.forEach(function (item, index) {
            if (item !== null) {
                var formatVal = series.format ? series.format(data[index]) : data[index];
                context.fillText(formatVal, item.x - measureText(formatVal) / 2, item.y - 2);
            }
        });
        context.closePath();
        context.stroke();
    }
    
    function drawRadarLabel(angleList, radius, centerPosition, opts, config, context) {
        var radarOption = opts.extra.radar || {};
        radius += config.radarLabelTextMargin;
        context.beginPath();
        context.setFontSize(config.fontSize);
        context.setFillStyle(radarOption.labelColor || '#666666');
        angleList.forEach(function (angle, index) {
            var pos = {
                x: radius * Math.cos(angle),
                y: radius * Math.sin(angle)
            };
            var posRelativeCanvas = convertCoordinateOrigin(pos.x, pos.y, centerPosition);
            var startX = posRelativeCanvas.x;
            var startY = posRelativeCanvas.y;
            if (util.approximatelyEqual(pos.x, 0)) {
                startX -= measureText(opts.categories[index] || '') / 2;
            } else if (pos.x < 0) {
                startX -= measureText(opts.categories[index] || '');
            }
            context.fillText(opts.categories[index] || '', startX, startY + config.fontSize / 2);
        });
        context.stroke();
        context.closePath();
    }
    
    function drawPieText(series, opts, config, context, radius, center) {
        var lineRadius = radius + config.pieChartLinePadding;
        var textObjectCollection = [];
        var lastTextObject = null;
    
        var seriesConvert = series.map(function (item) {
            var arc = 2 * Math.PI - (item._start_ + 2 * Math.PI * item._proportion_ / 2);
            var text = item.format ? item.format(+item._proportion_.toFixed(2)) : util.toFixed(item._proportion_ * 100) + '%';
            var color = item.color;
            return { arc: arc, text: text, color: color };
        });
        seriesConvert.forEach(function (item) {
            // line end
            var orginX1 = Math.cos(item.arc) * lineRadius;
            var orginY1 = Math.sin(item.arc) * lineRadius;
    
            // line start
            var orginX2 = Math.cos(item.arc) * radius;
            var orginY2 = Math.sin(item.arc) * radius;
    
            // text start
            var orginX3 = orginX1 >= 0 ? orginX1 + config.pieChartTextPadding : orginX1 - config.pieChartTextPadding;
            var orginY3 = orginY1;
    
            var textWidth = measureText(item.text);
            var startY = orginY3;
    
            if (lastTextObject && util.isSameXCoordinateArea(lastTextObject.start, { x: orginX3 })) {
                if (orginX3 > 0) {
                    startY = Math.min(orginY3, lastTextObject.start.y);
                } else if (orginX1 < 0) {
                    startY = Math.max(orginY3, lastTextObject.start.y);
                } else {
                    if (orginY3 > 0) {
                        startY = Math.max(orginY3, lastTextObject.start.y);
                    } else {
                        startY = Math.min(orginY3, lastTextObject.start.y);
                    }
                }
            }
    
            if (orginX3 < 0) {
                orginX3 -= textWidth;
            }
    
            var textObject = {
                lineStart: {
                    x: orginX2,
                    y: orginY2
                },
                lineEnd: {
                    x: orginX1,
                    y: orginY1
                },
                start: {
                    x: orginX3,
                    y: startY
                },
                width: textWidth,
                height: config.fontSize,
                text: item.text,
                color: item.color
            };
    
            lastTextObject = avoidCollision(textObject, lastTextObject);
            textObjectCollection.push(lastTextObject);
        });
    
        textObjectCollection.forEach(function (item) {
            var lineStartPoistion = convertCoordinateOrigin(item.lineStart.x, item.lineStart.y, center);
            var lineEndPoistion = convertCoordinateOrigin(item.lineEnd.x, item.lineEnd.y, center);
            var textPosition = convertCoordinateOrigin(item.start.x, item.start.y, center);
            context.setLineWidth(1);
            context.setFontSize(config.fontSize);
            context.beginPath();
            context.setStrokeStyle(item.color);
            context.setFillStyle(item.color);
            context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
            var curveStartX = item.start.x < 0 ? textPosition.x + item.width : textPosition.x;
            var textStartX = item.start.x < 0 ? textPosition.x - 5 : textPosition.x + 5;
            context.quadraticCurveTo(lineEndPoistion.x, lineEndPoistion.y, curveStartX, textPosition.y);
            context.moveTo(lineStartPoistion.x, lineStartPoistion.y);
            context.stroke();
            context.closePath();
            context.beginPath();
            context.moveTo(textPosition.x + item.width, textPosition.y);
            context.arc(curveStartX, textPosition.y, 2, 0, 2 * Math.PI);
            context.closePath();
            context.fill();
            context.beginPath();
            context.setFillStyle('#666666');
            context.fillText(item.text, textStartX, textPosition.y + 3);
            context.closePath();
            context.stroke();
    
            context.closePath();
        });
    }
    
    function drawToolTipSplitLine(offsetX, opts, config, context) {
        var startY = config.padding;
        var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
        context.beginPath();
        context.setStrokeStyle('#cccccc');
        context.setLineWidth(1);
        context.moveTo(offsetX, startY);
        context.lineTo(offsetX, endY);
        context.stroke();
        context.closePath();
    }
    
    function drawToolTip(textList, offset, opts, config, context) {
        var legendWidth = 4;
        var legendMarginRight = 5;
        var arrowWidth = 8;
        var isOverRightBorder = false;
        offset = assign({
            x: 0,
            y: 0
        }, offset);
        offset.y -= 8;
        var textWidth = textList.map(function (item) {
            return measureText(item.text);
        });
    
        var toolTipWidth = legendWidth + legendMarginRight + 4 * config.toolTipPadding + Math.max.apply(null, textWidth);
        var toolTipHeight = 2 * config.toolTipPadding + textList.length * config.toolTipLineHeight;
    
        // if beyond the right border
        if (offset.x - Math.abs(opts._scrollDistance_) + arrowWidth + toolTipWidth > opts.width) {
            isOverRightBorder = true;
        }
    
        // draw background rect
        context.beginPath();
        context.setFillStyle(opts.tooltip.option.background || config.toolTipBackground);
        context.setGlobalAlpha(config.toolTipOpacity);
        if (isOverRightBorder) {
            context.moveTo(offset.x, offset.y + 10);
            context.lineTo(offset.x - arrowWidth, offset.y + 10 - 5);
            context.lineTo(offset.x - arrowWidth, offset.y + 10 + 5);
            context.moveTo(offset.x, offset.y + 10);
            context.fillRect(offset.x - toolTipWidth - arrowWidth, offset.y, toolTipWidth, toolTipHeight);
        } else {
            context.moveTo(offset.x, offset.y + 10);
            context.lineTo(offset.x + arrowWidth, offset.y + 10 - 5);
            context.lineTo(offset.x + arrowWidth, offset.y + 10 + 5);
            context.moveTo(offset.x, offset.y + 10);
            context.fillRect(offset.x + arrowWidth, offset.y, toolTipWidth, toolTipHeight);
        }
    
        context.closePath();
        context.fill();
        context.setGlobalAlpha(1);
    
        // draw legend
        textList.forEach(function (item, index) {
            context.beginPath();
            context.setFillStyle(item.color);
            var startX = offset.x + arrowWidth + 2 * config.toolTipPadding;
            var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding;
            if (isOverRightBorder) {
                startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding;
            }
            context.fillRect(startX, startY, legendWidth, config.fontSize);
            context.closePath();
        });
    
        // draw text list
        context.beginPath();
        context.setFontSize(config.fontSize);
        context.setFillStyle('#ffffff');
        textList.forEach(function (item, index) {
            var startX = offset.x + arrowWidth + 2 * config.toolTipPadding + legendWidth + legendMarginRight;
            if (isOverRightBorder) {
                startX = offset.x - toolTipWidth - arrowWidth + 2 * config.toolTipPadding + +legendWidth + legendMarginRight;
            }
            var startY = offset.y + (config.toolTipLineHeight - config.fontSize) / 2 + config.toolTipLineHeight * index + config.toolTipPadding;
            context.fillText(item.text, startX, startY + config.fontSize);
        });
        context.stroke();
        context.closePath();
    }
    
    function drawYAxisTitle(title, opts, config, context) {
        var startX = config.xAxisHeight + (opts.height - config.xAxisHeight - measureText(title)) / 2;
        context.save();
        context.beginPath();
        context.setFontSize(config.fontSize);
        context.setFillStyle(opts.yAxis.titleFontColor || '#333333');
        context.translate(0, opts.height);
        context.rotate(-90 * Math.PI / 180);
        context.fillText(title, startX, config.padding + 0.5 * config.fontSize);
        context.stroke();
        context.closePath();
        context.restore();
    }
    
    function drawColumnDataPoints(series, opts, config, context) {
        var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
    
        var _calYAxisData = calYAxisData(series, opts, config),
            ranges = _calYAxisData.ranges;
    
        var _getXAxisPoints = getXAxisPoints(opts.categories, opts, config),
            xAxisPoints = _getXAxisPoints.xAxisPoints,
            eachSpacing = _getXAxisPoints.eachSpacing;
    
        var minRange = ranges.pop();
        var maxRange = ranges.shift();
        context.save();
        if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
            context.translate(opts._scrollDistance_, 0);
        }
    
        series.forEach(function (eachSeries, seriesIndex) {
            var data = eachSeries.data;
            var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
            points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
    
            // 绘制柱状数据图
            context.beginPath();
            context.setFillStyle(eachSeries.color);
            points.forEach(function (item, index) {
                if (item !== null) {
                    var startX = item.x - item.width / 2 + 1;
                    var height = opts.height - item.y - config.padding - config.xAxisHeight - config.legendHeight;
                    context.moveTo(startX, item.y);
                    context.rect(startX, item.y, item.width - 2, height);
                }
            });
            context.closePath();
            context.fill();
        });
        series.forEach(function (eachSeries, seriesIndex) {
            var data = eachSeries.data;
            var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
            points = fixColumeData(points, eachSpacing, series.length, seriesIndex, config, opts);
            if (opts.dataLabel !== false && process === 1) {
                drawPointText(points, eachSeries, config, context);
            }
        });
        context.restore();
        return {
            xAxisPoints: xAxisPoints,
            eachSpacing: eachSpacing
        };
    }
    
    function drawAreaDataPoints(series, opts, config, context) {
        var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
    
        var _calYAxisData2 = calYAxisData(series, opts, config),
            ranges = _calYAxisData2.ranges;
    
        var _getXAxisPoints2 = getXAxisPoints(opts.categories, opts, config),
            xAxisPoints = _getXAxisPoints2.xAxisPoints,
            eachSpacing = _getXAxisPoints2.eachSpacing;
    
        var minRange = ranges.pop();
        var maxRange = ranges.shift();
        var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
        var calPoints = [];
    
        context.save();
        if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
            context.translate(opts._scrollDistance_, 0);
        }
    
        if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
            drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
        }
    
        series.forEach(function (eachSeries, seriesIndex) {
            var data = eachSeries.data;
            var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
            calPoints.push(points);
    
            var splitPointList = splitPoints(points);
    
            splitPointList.forEach(function (points) {
                // 绘制区域数据
                context.beginPath();
                context.setStrokeStyle(eachSeries.color);
                context.setFillStyle(eachSeries.color);
                context.setGlobalAlpha(0.6);
                context.setLineWidth(2);
                if (points.length > 1) {
                    var firstPoint = points[0];
                    var lastPoint = points[points.length - 1];
    
                    context.moveTo(firstPoint.x, firstPoint.y);
                    if (opts.extra.lineStyle === 'curve') {
                        points.forEach(function (item, index) {
                            if (index > 0) {
                                var ctrlPoint = createCurveControlPoints(points, index - 1);
                                context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
                            }
                        });
                    } else {
                        points.forEach(function (item, index) {
                            if (index > 0) {
                                context.lineTo(item.x, item.y);
                            }
                        });
                    }
    
                    context.lineTo(lastPoint.x, endY);
                    context.lineTo(firstPoint.x, endY);
                    context.lineTo(firstPoint.x, firstPoint.y);
                } else {
                    var item = points[0];
                    context.moveTo(item.x - eachSpacing / 2, item.y);
                    context.lineTo(item.x + eachSpacing / 2, item.y);
                    context.lineTo(item.x + eachSpacing / 2, endY);
                    context.lineTo(item.x - eachSpacing / 2, endY);
                    context.moveTo(item.x - eachSpacing / 2, item.y);
                }
                context.closePath();
                context.fill();
                context.setGlobalAlpha(1);
            });
    
            if (opts.dataPointShape !== false) {
                var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
                drawPointShape(points, eachSeries.color, shape, context);
            }
        });
        if (opts.dataLabel !== false && process === 1) {
            series.forEach(function (eachSeries, seriesIndex) {
                var data = eachSeries.data;
                var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
                drawPointText(points, eachSeries, config, context);
            });
        }
    
        context.restore();
    
        return {
            xAxisPoints: xAxisPoints,
            calPoints: calPoints,
            eachSpacing: eachSpacing
        };
    }
    
    function drawLineDataPoints(series, opts, config, context) {
        var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
    
        var _calYAxisData3 = calYAxisData(series, opts, config),
            ranges = _calYAxisData3.ranges;
    
        var _getXAxisPoints3 = getXAxisPoints(opts.categories, opts, config),
            xAxisPoints = _getXAxisPoints3.xAxisPoints,
            eachSpacing = _getXAxisPoints3.eachSpacing;
    
        var minRange = ranges.pop();
        var maxRange = ranges.shift();
        var calPoints = [];
    
        context.save();
        if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
            context.translate(opts._scrollDistance_, 0);
        }
    
        if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
            drawToolTipSplitLine(opts.tooltip.offset.x, opts, config, context);
        }
    
        series.forEach(function (eachSeries, seriesIndex) {
            var data = eachSeries.data;
            var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
            calPoints.push(points);
            var splitPointList = splitPoints(points);
    
            splitPointList.forEach(function (points, index) {
                context.beginPath();
                context.setStrokeStyle(eachSeries.color);
                context.setLineWidth(2);
                if (points.length === 1) {
                    context.moveTo(points[0].x, points[0].y);
                    context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
                } else {
                    context.moveTo(points[0].x, points[0].y);
                    if (opts.extra.lineStyle === 'curve') {
                        points.forEach(function (item, index) {
                            if (index > 0) {
                                var ctrlPoint = createCurveControlPoints(points, index - 1);
                                context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x, item.y);
                            }
                        });
                    } else {
                        points.forEach(function (item, index) {
                            if (index > 0) {
                                context.lineTo(item.x, item.y);
                            }
                        });
                    }
                    context.moveTo(points[0].x, points[0].y);
                }
                context.closePath();
                context.stroke();
            });
    
            if (opts.dataPointShape !== false) {
                var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
                drawPointShape(points, eachSeries.color, shape, context);
            }
        });
        if (opts.dataLabel !== false && process === 1) {
            series.forEach(function (eachSeries, seriesIndex) {
                var data = eachSeries.data;
                var points = getDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, process);
                drawPointText(points, eachSeries, config, context);
            });
        }
    
        context.restore();
    
        return {
            xAxisPoints: xAxisPoints,
            calPoints: calPoints,
            eachSpacing: eachSpacing
        };
    }
    
    function drawToolTipBridge(opts, config, context, process) {
        context.save();
        if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
            context.translate(opts._scrollDistance_, 0);
        }
        if (opts.tooltip && opts.tooltip.textList && opts.tooltip.textList.length && process === 1) {
            drawToolTip(opts.tooltip.textList, opts.tooltip.offset, opts, config, context);
        }
        context.restore();
    }
    
    function drawXAxis(categories, opts, config, context) {
        var _getXAxisPoints4 = getXAxisPoints(categories, opts, config),
            xAxisPoints = _getXAxisPoints4.xAxisPoints,
            startX = _getXAxisPoints4.startX,
            endX = _getXAxisPoints4.endX,
            eachSpacing = _getXAxisPoints4.eachSpacing;
    
        var startY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
        var endY = startY + config.xAxisLineHeight;
    
        context.save();
        if (opts._scrollDistance_ && opts._scrollDistance_ !== 0) {
            context.translate(opts._scrollDistance_, 0);
        }
    
        context.beginPath();
        context.setStrokeStyle(opts.xAxis.gridColor || "#cccccc");
    
        if (opts.xAxis.disableGrid !== true) {
            if (opts.xAxis.type === 'calibration') {
                xAxisPoints.forEach(function (item, index) {
                    if (index > 0) {
                        context.moveTo(item - eachSpacing / 2, startY);
                        context.lineTo(item - eachSpacing / 2, startY + 4);
                    }
                });
            } else {
                xAxisPoints.forEach(function (item, index) {
                    context.moveTo(item, startY);
                    context.lineTo(item, endY);
                });
            }
        }
        context.closePath();
        context.stroke();
    
        // 对X轴列表做抽稀处理
        var validWidth = opts.width - 2 * config.padding - config.yAxisWidth - config.yAxisTitleWidth;
        var maxXAxisListLength = Math.min(categories.length, Math.ceil(validWidth / config.fontSize / 1.5));
        var ratio = Math.ceil(categories.length / maxXAxisListLength);
    
        categories = categories.map(function (item, index) {
            return index % ratio !== 0 ? '' : item;
        });
    
        if (config._xAxisTextAngle_ === 0) {
            context.beginPath();
            context.setFontSize(config.fontSize);
            context.setFillStyle(opts.xAxis.fontColor || '#666666');
            categories.forEach(function (item, index) {
                var offset = eachSpacing / 2 - measureText(item) / 2;
                context.fillText(item, xAxisPoints[index] + offset, startY + config.fontSize + 5);
            });
            context.closePath();
            context.stroke();
        } else {
            categories.forEach(function (item, index) {
                context.save();
                context.beginPath();
                context.setFontSize(config.fontSize);
                context.setFillStyle(opts.xAxis.fontColor || '#666666');
                var textWidth = measureText(item);
                var offset = eachSpacing / 2 - textWidth;
    
                var _calRotateTranslate = calRotateTranslate(xAxisPoints[index] + eachSpacing / 2, startY + config.fontSize / 2 + 5, opts.height),
                    transX = _calRotateTranslate.transX,
                    transY = _calRotateTranslate.transY;
    
                context.rotate(-1 * config._xAxisTextAngle_);
                context.translate(transX, transY);
                context.fillText(item, xAxisPoints[index] + offset, startY + config.fontSize + 5);
                context.closePath();
                context.stroke();
                context.restore();
            });
        }
    
        context.restore();
    }
    
    function drawYAxisGrid(opts, config, context) {
        var spacingValid = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
        var eachSpacing = Math.floor(spacingValid / config.yAxisSplit);
        var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
        var startX = config.padding + yAxisTotalWidth;
        var endX = opts.width - config.padding;
    
        var points = [];
        for (var i = 0; i < config.yAxisSplit; i++) {
            points.push(config.padding + eachSpacing * i);
        }
        points.push(config.padding + eachSpacing * config.yAxisSplit + 2);
    
        context.beginPath();
        context.setStrokeStyle(opts.yAxis.gridColor || "#cccccc");
        context.setLineWidth(1);
        points.forEach(function (item, index) {
            context.moveTo(startX, item);
            context.lineTo(endX, item);
        });
        context.closePath();
        context.stroke();
    }
    
    function drawYAxis(series, opts, config, context) {
        if (opts.yAxis.disabled === true) {
            return;
        }
    
        var _calYAxisData4 = calYAxisData(series, opts, config),
            rangesFormat = _calYAxisData4.rangesFormat;
    
        var yAxisTotalWidth = config.yAxisWidth + config.yAxisTitleWidth;
    
        var spacingValid = opts.height - 2 * config.padding - config.xAxisHeight - config.legendHeight;
        var eachSpacing = Math.floor(spacingValid / config.yAxisSplit);
        var startX = config.padding + yAxisTotalWidth;
        var endX = opts.width - config.padding;
        var endY = opts.height - config.padding - config.xAxisHeight - config.legendHeight;
    
        // set YAxis background
        context.setFillStyle(opts.background || '#ffffff');
        if (opts._scrollDistance_ < 0) {
            context.fillRect(0, 0, startX, endY + config.xAxisHeight + 5);
        }
        context.fillRect(endX, 0, opts.width, endY + config.xAxisHeight + 5);
    
        var points = [];
        for (var i = 0; i <= config.yAxisSplit; i++) {
            points.push(config.padding + eachSpacing * i);
        }
    
        context.stroke();
        context.beginPath();
        context.setFontSize(config.fontSize);
        context.setFillStyle(opts.yAxis.fontColor || '#666666');
        rangesFormat.forEach(function (item, index) {
            var pos = points[index] ? points[index] : endY;
            context.fillText(item, config.padding + config.yAxisTitleWidth, pos + config.fontSize / 2);
        });
        context.closePath();
        context.stroke();
    
        if (opts.yAxis.title) {
            drawYAxisTitle(opts.yAxis.title, opts, config, context);
        }
    }
    
    function drawLegend(series, opts, config, context) {
        if (!opts.legend) {
            return;
        }
        // each legend shape width 15px
        // the spacing between shape and text in each legend is the `padding`
        // each legend spacing is the `padding`
        // legend margin top `config.padding`
    
        var _calLegendData = calLegendData(series, opts, config),
            legendList = _calLegendData.legendList;
    
        var padding = 5;
        var marginTop = 8;
        var shapeWidth = 15;
        legendList.forEach(function (itemList, listIndex) {
            var width = 0;
            itemList.forEach(function (item) {
                item.name = item.name || 'undefined';
                width += 3 * padding + measureText(item.name) + shapeWidth;
            });
            var startX = (opts.width - width) / 2 + padding;
            var startY = opts.height - config.padding - config.legendHeight + listIndex * (config.fontSize + marginTop) + padding + marginTop;
    
            context.setFontSize(config.fontSize);
            itemList.forEach(function (item) {
                switch (opts.type) {
                    case 'line':
                        context.beginPath();
                        context.setLineWidth(1);
                        context.setStrokeStyle(item.color);
                        context.moveTo(startX - 2, startY + 5);
                        context.lineTo(startX + 17, startY + 5);
                        context.stroke();
                        context.closePath();
                        context.beginPath();
                        context.setLineWidth(1);
                        context.setStrokeStyle('#ffffff');
                        context.setFillStyle(item.color);
                        context.moveTo(startX + 7.5, startY + 5);
                        context.arc(startX + 7.5, startY + 5, 4, 0, 2 * Math.PI);
                        context.fill();
                        context.stroke();
                        context.closePath();
                        break;
                    case 'pie':
                    case 'ring':
                        context.beginPath();
                        context.setFillStyle(item.color);
                        context.moveTo(startX + 7.5, startY + 5);
                        context.arc(startX + 7.5, startY + 5, 7, 0, 2 * Math.PI);
                        context.closePath();
                        context.fill();
                        break;
                    default:
                        context.beginPath();
                        context.setFillStyle(item.color);
                        context.moveTo(startX, startY);
                        context.rect(startX, startY, 15, 10);
                        context.closePath();
                        context.fill();
                }
                startX += padding + shapeWidth;
                context.beginPath();
                context.setFillStyle(opts.extra.legendTextColor || '#333333');
                context.fillText(item.name, startX, startY + 9);
                context.closePath();
                context.stroke();
                startX += measureText(item.name) + 2 * padding;
            });
        });
    }
    function drawPieDataPoints(series, opts, config, context) {
        var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
    
        var pieOption = opts.extra.pie || {};
        series = getPieDataPoints(series, process);
        var centerPosition = {
            x: opts.width / 2,
            y: (opts.height - config.legendHeight) / 2
        };
        var radius = Math.min(centerPosition.x - config.pieChartLinePadding - config.pieChartTextPadding - config._pieTextMaxLength_, centerPosition.y - config.pieChartLinePadding - config.pieChartTextPadding);
        if (opts.dataLabel) {
            radius -= 10;
        } else {
            radius -= 2 * config.padding;
        }
        series = series.map(function (eachSeries) {
            eachSeries._start_ += (pieOption.offsetAngle || 0) * Math.PI / 180;
            return eachSeries;
        });
        series.forEach(function (eachSeries) {
            context.beginPath();
            context.setLineWidth(2);
            context.setStrokeStyle('#ffffff');
            context.setFillStyle(eachSeries.color);
            context.moveTo(centerPosition.x, centerPosition.y);
            context.arc(centerPosition.x, centerPosition.y, radius, eachSeries._start_, eachSeries._start_ + 2 * eachSeries._proportion_ * Math.PI);
            context.closePath();
            context.fill();
            if (opts.disablePieStroke !== true) {
                context.stroke();
            }
        });
    
        if (opts.type === 'ring') {
            var innerPieWidth = radius * 0.6;
            if (typeof opts.extra.ringWidth === 'number' && opts.extra.ringWidth > 0) {
                innerPieWidth = Math.max(0, radius - opts.extra.ringWidth);
            }
            context.beginPath();
            context.setFillStyle(opts.background || '#ffffff');
            context.moveTo(centerPosition.x, centerPosition.y);
            context.arc(centerPosition.x, centerPosition.y, innerPieWidth, 0, 2 * Math.PI);
            context.closePath();
            context.fill();
        }
    
        if (opts.dataLabel !== false && process === 1) {
            // fix https://github.com/xiaolin3303/wx-charts/issues/132
            var valid = false;
            for (var i = 0, len = series.length; i < len; i++) {
                if (series[i].data > 0) {
                    valid = true;
                    break;
                }
            }
    
            if (valid) {
                drawPieText(series, opts, config, context, radius, centerPosition);
            }
        }
    
        if (process === 1 && opts.type === 'ring') {
            drawRingTitle(opts, config, context);
        }
    
        return {
            center: centerPosition,
            radius: radius,
            series: series
        };
    }
    
    function drawRadarDataPoints(series, opts, config, context) {
        var process = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
    
        var radarOption = opts.extra.radar || {};
        var coordinateAngle = getRadarCoordinateSeries(opts.categories.length);
        var centerPosition = {
            x: opts.width / 2,
            y: (opts.height - config.legendHeight) / 2
        };
    
        var radius = Math.min(centerPosition.x - (getMaxTextListLength(opts.categories) + config.radarLabelTextMargin), centerPosition.y - config.radarLabelTextMargin);
    
        radius -= config.padding;
    
        // draw grid
        context.beginPath();
        context.setLineWidth(1);
        context.setStrokeStyle(radarOption.gridColor || "#cccccc");
        coordinateAngle.forEach(function (angle) {
            var pos = convertCoordinateOrigin(radius * Math.cos(angle), radius * Math.sin(angle), centerPosition);
            context.moveTo(centerPosition.x, centerPosition.y);
            context.lineTo(pos.x, pos.y);
        });
        context.stroke();
        context.closePath();
    
        // draw split line grid
    
        var _loop = function _loop(i) {
            var startPos = {};
            context.beginPath();
            context.setLineWidth(1);
            context.setStrokeStyle(radarOption.gridColor || "#cccccc");
            coordinateAngle.forEach(function (angle, index) {
                var pos = convertCoordinateOrigin(radius / config.radarGridCount * i * Math.cos(angle), radius / config.radarGridCount * i * Math.sin(angle), centerPosition);
                if (index === 0) {
                    startPos = pos;
                    context.moveTo(pos.x, pos.y);
                } else {
                    context.lineTo(pos.x, pos.y);
                }
            });
            context.lineTo(startPos.x, startPos.y);
            context.stroke();
            context.closePath();
        };
    
        for (var i = 1; i <= config.radarGridCount; i++) {
            _loop(i);
        }
    
        var radarDataPoints = getRadarDataPoints(coordinateAngle, centerPosition, radius, series, opts, process);
        radarDataPoints.forEach(function (eachSeries, seriesIndex) {
            // 绘制区域数据
            context.beginPath();
            context.setFillStyle(eachSeries.color);
            context.setGlobalAlpha(0.6);
            eachSeries.data.forEach(function (item, index) {
                if (index === 0) {
                    context.moveTo(item.position.x, item.position.y);
                } else {
                    context.lineTo(item.position.x, item.position.y);
                }
            });
            context.closePath();
            context.fill();
            context.setGlobalAlpha(1);
    
            if (opts.dataPointShape !== false) {
                var shape = config.dataPointShape[seriesIndex % config.dataPointShape.length];
                var points = eachSeries.data.map(function (item) {
                    return item.position;
                });
                drawPointShape(points, eachSeries.color, shape, context);
            }
        });
        // draw label text
        drawRadarLabel(coordinateAngle, radius, centerPosition, opts, config, context);
    
        return {
            center: centerPosition,
            radius: radius,
            angleList: coordinateAngle
        };
    }
    
    function drawCanvas(opts, context) {
        context.draw();
    }
    
    var Timing = {
        easeIn: function easeIn(pos) {
            return Math.pow(pos, 3);
        },
    
        easeOut: function easeOut(pos) {
            return Math.pow(pos - 1, 3) + 1;
        },
    
        easeInOut: function easeInOut(pos) {
            if ((pos /= 0.5) < 1) {
                return 0.5 * Math.pow(pos, 3);
            } else {
                return 0.5 * (Math.pow(pos - 2, 3) + 2);
            }
        },
    
        linear: function linear(pos) {
            return pos;
        }
    };
    
    function Animation(opts) {
        this.isStop = false;
        opts.duration = typeof opts.duration === 'undefined' ? 1000 : opts.duration;
        opts.timing = opts.timing || 'linear';
    
        var delay = 17;
    
        var createAnimationFrame = function createAnimationFrame() {
            if (typeof requestAnimationFrame !== 'undefined') {
                return requestAnimationFrame;
            } else if (typeof setTimeout !== 'undefined') {
                return function (step, delay) {
                    setTimeout(function () {
                        var timeStamp = +new Date();
                        step(timeStamp);
                    }, delay);
                };
            } else {
                return function (step) {
                    step(null);
                };
            }
        };
        var animationFrame = createAnimationFrame();
        var startTimeStamp = null;
        var _step = function step(timestamp) {
            if (timestamp === null || this.isStop === true) {
                opts.onProcess && opts.onProcess(1);
                opts.onAnimationFinish && opts.onAnimationFinish();
                return;
            }
            if (startTimeStamp === null) {
                startTimeStamp = timestamp;
            }
            if (timestamp - startTimeStamp < opts.duration) {
                var process = (timestamp - startTimeStamp) / opts.duration;
                var timingFunction = Timing[opts.timing];
                process = timingFunction(process);
                opts.onProcess && opts.onProcess(process);
                animationFrame(_step, delay);
            } else {
                opts.onProcess && opts.onProcess(1);
                opts.onAnimationFinish && opts.onAnimationFinish();
            }
        };
        _step = _step.bind(this);
    
        animationFrame(_step, delay);
    }
    
    // stop animation immediately
    // and tigger onAnimationFinish
    Animation.prototype.stop = function () {
        this.isStop = true;
    };
    
    function drawCharts(type, opts, config, context) {
        var _this = this;
    
        var series = opts.series;
        var categories = opts.categories;
        series = fillSeriesColor(series, config);
    
        var _calLegendData = calLegendData(series, opts, config),
            legendHeight = _calLegendData.legendHeight;
    
        config.legendHeight = legendHeight;
    
        var _calYAxisData = calYAxisData(series, opts, config),
            yAxisWidth = _calYAxisData.yAxisWidth;
    
        config.yAxisWidth = yAxisWidth;
        if (categories && categories.length) {
            var _calCategoriesData = calCategoriesData(categories, opts, config),
                xAxisHeight = _calCategoriesData.xAxisHeight,
                angle = _calCategoriesData.angle;
    
            config.xAxisHeight = xAxisHeight;
            config._xAxisTextAngle_ = angle;
        }
        if (type === 'pie' || type === 'ring') {
            config._pieTextMaxLength_ = opts.dataLabel === false ? 0 : getPieTextMaxLength(series);
        }
    
        var duration = opts.animation ? 1000 : 0;
        this.animationInstance && this.animationInstance.stop();
        switch (type) {
            case 'line':
                this.animationInstance = new Animation({
                    timing: 'easeIn',
                    duration: duration,
                    onProcess: function onProcess(process) {
                        drawYAxisGrid(opts, config, context);
    
                        var _drawLineDataPoints = drawLineDataPoints(series, opts, config, context, process),
                            xAxisPoints = _drawLineDataPoints.xAxisPoints,
                            calPoints = _drawLineDataPoints.calPoints,
                            eachSpacing = _drawLineDataPoints.eachSpacing;
    
                        _this.chartData.xAxisPoints = xAxisPoints;
                        _this.chartData.calPoints = calPoints;
                        _this.chartData.eachSpacing = eachSpacing;
                        drawXAxis(categories, opts, config, context);
                        drawLegend(opts.series, opts, config, context);
                        drawYAxis(series, opts, config, context);
                        drawToolTipBridge(opts, config, context, process);
                        drawCanvas(opts, context);
                    },
                    onAnimationFinish: function onAnimationFinish() {
                        _this.event.trigger('renderComplete');
                    }
                });
                break;
            case 'column':
                this.animationInstance = new Animation({
                    timing: 'easeIn',
                    duration: duration,
                    onProcess: function onProcess(process) {
                        drawYAxisGrid(opts, config, context);
    
                        var _drawColumnDataPoints = drawColumnDataPoints(series, opts, config, context, process),
                            xAxisPoints = _drawColumnDataPoints.xAxisPoints,
                            eachSpacing = _drawColumnDataPoints.eachSpacing;
    
                        _this.chartData.xAxisPoints = xAxisPoints;
                        _this.chartData.eachSpacing = eachSpacing;
                        drawXAxis(categories, opts, config, context);
                        drawLegend(opts.series, opts, config, context);
                        drawYAxis(series, opts, config, context);
                        drawCanvas(opts, context);
                    },
                    onAnimationFinish: function onAnimationFinish() {
                        _this.event.trigger('renderComplete');
                    }
                });
                break;
            case 'area':
                this.animationInstance = new Animation({
                    timing: 'easeIn',
                    duration: duration,
                    onProcess: function onProcess(process) {
                        drawYAxisGrid(opts, config, context);
    
                        var _drawAreaDataPoints = drawAreaDataPoints(series, opts, config, context, process),
                            xAxisPoints = _drawAreaDataPoints.xAxisPoints,
                            calPoints = _drawAreaDataPoints.calPoints,
                            eachSpacing = _drawAreaDataPoints.eachSpacing;
    
                        _this.chartData.xAxisPoints = xAxisPoints;
                        _this.chartData.calPoints = calPoints;
                        _this.chartData.eachSpacing = eachSpacing;
                        drawXAxis(categories, opts, config, context);
                        drawLegend(opts.series, opts, config, context);
                        drawYAxis(series, opts, config, context);
                        drawToolTipBridge(opts, config, context, process);
                        drawCanvas(opts, context);
                    },
                    onAnimationFinish: function onAnimationFinish() {
                        _this.event.trigger('renderComplete');
                    }
                });
                break;
            case 'ring':
            case 'pie':
                this.animationInstance = new Animation({
                    timing: 'easeInOut',
                    duration: duration,
                    onProcess: function onProcess(process) {
                        _this.chartData.pieData = drawPieDataPoints(series, opts, config, context, process);
                        drawLegend(opts.series, opts, config, context);
                        drawCanvas(opts, context);
                    },
                    onAnimationFinish: function onAnimationFinish() {
                        _this.event.trigger('renderComplete');
                    }
                });
                break;
            case 'radar':
                this.animationInstance = new Animation({
                    timing: 'easeInOut',
                    duration: duration,
                    onProcess: function onProcess(process) {
                        _this.chartData.radarData = drawRadarDataPoints(series, opts, config, context, process);
                        drawLegend(opts.series, opts, config, context);
                        drawCanvas(opts, context);
                    },
                    onAnimationFinish: function onAnimationFinish() {
                        _this.event.trigger('renderComplete');
                    }
                });
                break;
        }
    }
    
    // simple event implement
    
    function Event() {
    	this.events = {};
    }
    
    Event.prototype.addEventListener = function (type, listener) {
    	this.events[type] = this.events[type] || [];
    	this.events[type].push(listener);
    };
    
    Event.prototype.trigger = function () {
    	for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
    		args[_key] = arguments[_key];
    	}
    
    	var type = args[0];
    	var params = args.slice(1);
    	if (!!this.events[type]) {
    		this.events[type].forEach(function (listener) {
    			try {
    				listener.apply(null, params);
    			} catch (e) {
    				console.error(e);
    			}
    		});
    	}
    };
    
    var Charts = function Charts(opts) {
        opts.title = opts.title || {};
        opts.subtitle = opts.subtitle || {};
        opts.yAxis = opts.yAxis || {};
        opts.xAxis = opts.xAxis || {};
        opts.extra = opts.extra || {};
        opts.legend = opts.legend === false ? false : true;
        opts.animation = opts.animation === false ? false : true;
        var config$$1 = assign({}, config);
        config$$1.yAxisTitleWidth = opts.yAxis.disabled !== true && opts.yAxis.title ? config$$1.yAxisTitleWidth : 0;
        config$$1.pieChartLinePadding = opts.dataLabel === false ? 0 : config$$1.pieChartLinePadding;
        config$$1.pieChartTextPadding = opts.dataLabel === false ? 0 : config$$1.pieChartTextPadding;
    
        this.opts = opts;
        this.config = config$$1;
        this.context = wx.createCanvasContext(opts.canvasId);
        // store calcuated chart data
        // such as chart point coordinate
        this.chartData = {};
        this.event = new Event();
        this.scrollOption = {
            currentOffset: 0,
            startTouchX: 0,
            distance: 0
        };
    
        drawCharts.call(this, opts.type, opts, config$$1, this.context);
    };
    
    Charts.prototype.updateData = function () {
        var data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
    
        this.opts.series = data.series || this.opts.series;
        this.opts.categories = data.categories || this.opts.categories;
    
        this.opts.title = assign({}, this.opts.title, data.title || {});
        this.opts.subtitle = assign({}, this.opts.subtitle, data.subtitle || {});
    
        drawCharts.call(this, this.opts.type, this.opts, this.config, this.context);
    };
    
    Charts.prototype.stopAnimation = function () {
        this.animationInstance && this.animationInstance.stop();
    };
    
    Charts.prototype.addEventListener = function (type, listener) {
        this.event.addEventListener(type, listener);
    };
    
    Charts.prototype.getCurrentDataIndex = function (e) {
        var touches = e.touches && e.touches.length ? e.touches : e.changedTouches;
        if (touches && touches.length) {
            var _touches$ = touches[0],
                x = _touches$.x,
                y = _touches$.y;
    
            if (this.opts.type === 'pie' || this.opts.type === 'ring') {
                return findPieChartCurrentIndex({ x: x, y: y }, this.chartData.pieData);
            } else if (this.opts.type === 'radar') {
                return findRadarChartCurrentIndex({ x: x, y: y }, this.chartData.radarData, this.opts.categories.length);
            } else {
                return findCurrentIndex({ x: x, y: y }, this.chartData.xAxisPoints, this.opts, this.config, Math.abs(this.scrollOption.currentOffset));
            }
        }
        return -1;
    };
    
    Charts.prototype.showToolTip = function (e) {
        var option = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
    
        if (this.opts.type === 'line' || this.opts.type === 'area') {
            var index = this.getCurrentDataIndex(e);
            var currentOffset = this.scrollOption.currentOffset;
    
            var opts = assign({}, this.opts, {
                _scrollDistance_: currentOffset,
                animation: false
            });
            if (index > -1) {
                var seriesData = getSeriesDataItem(this.opts.series, index);
                if (seriesData.length !== 0) {
                    var _getToolTipData = getToolTipData(seriesData, this.chartData.calPoints, index, this.opts.categories, option),
                        textList = _getToolTipData.textList,
                        offset = _getToolTipData.offset;
    
                    opts.tooltip = {
                        textList: textList,
                        offset: offset,
                        option: option
                    };
                }
            }
            drawCharts.call(this, opts.type, opts, this.config, this.context);
        }
    };
    
    Charts.prototype.scrollStart = function (e) {
        if (e.touches[0] && this.opts.enableScroll === true) {
            this.scrollOption.startTouchX = e.touches[0].x;
        }
    };
    
    Charts.prototype.scroll = function (e) {
        // TODO throtting...
        if (e.touches[0] && this.opts.enableScroll === true) {
            var _distance = e.touches[0].x - this.scrollOption.startTouchX;
            var currentOffset = this.scrollOption.currentOffset;
    
            var validDistance = calValidDistance(currentOffset + _distance, this.chartData, this.config, this.opts);
    
            this.scrollOption.distance = _distance = validDistance - currentOffset;
            var opts = assign({}, this.opts, {
                _scrollDistance_: currentOffset + _distance,
                animation: false
            });
    
            drawCharts.call(this, opts.type, opts, this.config, this.context);
        }
    };
    
    Charts.prototype.scrollEnd = function (e) {
        if (this.opts.enableScroll === true) {
            var _scrollOption = this.scrollOption,
                currentOffset = _scrollOption.currentOffset,
                distance = _scrollOption.distance;
    
            this.scrollOption.currentOffset = currentOffset + distance;
            this.scrollOption.distance = 0;
        }
    };
    
    module.exports = Charts;
    
    
    展开全文
  • 大神们,请问一下,微信小程序的图表插件wxcharts,怎么样让同一图表中的两条数据,一条数据用折线显示,另一条数据用柱形显示?
  • 小程序图表-wxcharts

    2019-09-17 17:27:09
    小程序-wxcharts 百度找以下文件下载放入项目使用 **必须搭配canvas标签使用 <view class="day {{index==0?'show':'hidden'}}"> <canvas canvas-id="ringCanvas" class="ringCanvas"></canvas&...

    小程序-wxcharts

    在这里插入图片描述

    百度找以下文件下载放入项目使用
    在这里插入图片描述

     **必须搭配canvas标签使用
      <view class="day {{index==0?'show':'hidden'}}">
           <canvas canvas-id="ringCanvas" class="ringCanvas"></canvas>
      </view>
      <view class="month {{index==1?'show':'hidden'}}">
           <canvas canvas-id="monthRingCanvas" class="ringCanvas"></canvas>
      </view>
    
    //引入文件,声明变量
    var wxCharts = require('../../utils/wxcharts.js');
    var lineChart = null;
    var ringChart = null;
    
    
    //js部分代码
    
    //线形图点击显示提示每个月的数量
       touchHandler: function(e) {
        lineChart.showToolTip(e, {
          format: function(item, category) {
            return category + ' ' + item.name + ':' + item.data
          }
        });
      },
        // 创建数据
      createData: function() {
        //月份
         var categories =[]
         //月份对应数据
         var data = [11, 50, 56, 48, 180, 22, 76, 88, 209, 800, 63, 610];
         for (var i = 0; i < 12; i++) {
           categories.push((i + 1) + '月');
         }
        return {
          categories: categories,
          data: data
        }
      },
       // 创建线形图
      creatLine() {
       var windowWidth = 320;
        var res = wx.getSystemInfoSync();
        windowWidth = res.windowWidth;
        var linearData = this.createData();
        // 创建图表
        lineChart = new wxCharts({
          canvasId: 'lineCanvas',
          // 图表类型  line线形图 ring圆环图 pie饼状图 column柱状图 area radar
          type: 'line',
          //  数据类别分类
          categories: linearData .categories,
        
          // 动画
          animation: true,
          // 数据列表
          series: [{
            name: '来访人数',
            //  数据,如果传入null图表该处出现断点
            data: linearData .data,
            // 自定义显示数据内容
            format: function(val, name) {
              return val + '个';
            }
          }, ],
          // X轴
          xAxis: {
            disableGrid: true //不绘制X轴网格 
          },
          // Y轴
          yAxis: {
    
            title: '人数/个',
            // 文案显示
            format: function(val) {
              return val;
            },
            min: 0,
          },
          width: windowWidth,
          height: 200,
          dataLabel: false, //是否在图表中显示数据内容值
          dataPointShape: true, //是否在图表中显示数据点图形标识
          // 其他通用配置项
          extra: {
            lineStyle: 'straight' //curve曲线,straight直线
          }
        });
      },
      // 创建圆环图
      creatRing() {
       var windowWidth = 320;
        var res = wx.getSystemInfoSync();
        windowWidth = res.windowWidth;
        ringChart = new wxCharts({
          animation: true,
          canvasId: 'ringCanvas',
          type: 'ring',
          extra: {
            ringWidth: 25,
            pie: {
              offsetAngle: -45
            }
          },
          series:{
                    name: '一厂',
                    data: 15,
                    color:'pink',
                    stroke: false
                }, {
                    name: '二厂',
                    data: 35,
                     color:'red',
                     stroke: false
                } ,
          disablePieStroke: false,
          width: windowWidth,
          //图表的高度
          height: 225,
          dataLabel: true,
          legend: true,
          background: '#f5f5f5',
          padding: 0
        });
        ringChart.addEventListener('renderComplete', () => {
          console.log('renderComplete');
        });
        setTimeout(() => {
          ringChart.stopAnimation();
        }, 500);
      },
    
    展开全文
  • 微信小程序图表插件 wxcharts 的使用 使用前需要先导入 var wxCharts = require('../../common/wxcharts'); 1.扇形图 在js文件中调用 new wxCharts({ canvasId: 'pieCanvas', type: 'pie', series: [{ name: '...

    微信小程序图表插件 wxcharts 的使用

    使用前需要先导入

    var wxCharts = require('../../common/wxcharts');
    

    1.扇形图

    在js文件中调用

     new wxCharts({
            canvasId: 'pieCanvas',
            type: 'pie',
            series: [{
                name: 'p1',
                data: 50,
            }, {
                name: 'p2',
                data: 30,
            }, {
                name: 'p3',
                data: 1,
            }, {
                name: 'p4',
                data: 1,
            }, {
                name: 'p5',
                data: 46,
            }],
            width: 360,
            height: 300,
            dataLabel: true
        });
        new wxCharts({
          canvasId: 'ringCanvas',
          type: 'ring',
          series: [{
              name: '成交量1',
              data: 15,
          }, {
              name: '成交量2',
              data: 35,
          }, {
              name: '成交量3',
              data: 78,
          }, {
              name: '成交量4',
              data: 63,
          }],
          width: 320,
          height: 200,
          dataLabel: false
      });
    

    效果图

    在这里插入图片描述

    2.圆环图

    js文件

    new wxCharts({
          canvasId: 'ringCanvas',
          type: 'ring',
          series: [{
              name: 'p1',
              data: 15,
          }, {
              name: 'p2',
              data: 35,
          }, {
              name: 'p3',
              data: 78,
          }, {
              name: 'p4',
              data: 63,
          }],
          width: 320,
          height: 200,
          dataLabel: false
      });
    

    效果图

    在这里插入图片描述

    3.折线图

    new wxCharts({
        canvasId: 'lineCanvas',
        type: 'line',
        categories: ['2012', '2013', '2014', '2015', '2016', '2017'],
        series: [{
            name: 'p1',
            data: [0.15, 0.2, 0.45, 0.37, 0.4, 0.8],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }, {
            name: 'p2',
            data: [0.30, 0.37, 0.65, 0.78, 0.69, 0.94],
            format: function (val) {
                return val.toFixed(2) + '万';
            }
        }],
        yAxis: {
            title: '成交金额 (万元)',
            format: function (val) {
                return val.toFixed(2);
            },
            min: 0
        },
        width: 320,
        height: 200
    });
    

    效果图

    在这里插入图片描述

    4.柱形图

    new wxCharts({
      canvasId: 'columnCanvas',
      type: 'column',
      categories: ['2012', '2013', '2014', '2015', '2016', '2017'],
      series: [{
          name: 'p1',
          data: [15, 20, 45, 37, 4, 80]
      }, {
          name: 'p2',
          data: [70, 40, 65, 100, 34, 18]
      }],
      yAxis: {
          format: function (val) {
              return val + '万';
          }
      },
      width: 320,
      height: 200
    });
    

    效果图

    在这里插入图片描述

    5.区域图

    new wxCharts({
      canvasId: 'areaCanvas',
      type: 'area',
      categories: ['2016-08', '2016-09', '2016-10', '2016-11', '2016-12', '2017'],
      series: [{
          name: 'p1',
          data: [70, 40, 65, 100, 34, 18],
          format: function (val) {
              return val.toFixed(2) + '万';
          }
      }, {
          name: 'p2',
          data: [15, 20, 45, 37, 4, 80],
          format: function (val) {
              return val.toFixed(2) + '万';
          }
      }],
      yAxis: {
          format: function (val) {
              return val + '万';
          }
      },
      width: 320,
      height: 200
    });
    

    效果图

    在这里插入图片描述

    6.雷达图

    new wxCharts({
      canvasId: 'radarCanvas',
      type: 'radar',
      categories: ['1', '2', '3', '4', '5', '6'],
      series: [{
          name: 'p1',
          data: [90, 110, 125, 95, 87, 122]
      }],
      width: 320,
      height: 200,
      extra: {
          radar: {
              max: 150
          }
      }
    });
    

    效果图

    在这里插入图片描述

    展开全文
  • <div><h1>方法 ... new wxCharts(...); chart.addEventListener('renderComplete', () => { // your code here }); </code></pre>该提问来源于开源项目:xiaolin3303/wx-charts</p></div>
  • wxcharts.zip

    2019-07-11 17:51:32
    wx.charts.js jar包下载,希望能帮助大家,找了好久才找到的
  • 微信小程序图表插件wxcharts使用

    千次阅读 2019-01-22 14:35:10
    1.wxml &...--pages/wxcharts/wxcharts.wxml--&amp;amp;amp;gt; &amp;amp;amp;lt;canvas canvas-id=&amp;amp;quot;pieCanvas&amp;amp;quot; disable-scroll=&amp;amp;quot;tru
  • 小程序之wxcharts(图表)

    千次阅读 2018-02-02 13:23:56
    一、wxml canvas canvas-id="lineCanvas" disable-scroll="true" class="canvas" hidden='{{canvaShow}}'>canvas> ...wxCharts = require('../../utils/wxcharts.js'); var s
  • 微信小程序中的股票分时图、K线图wxCharts-master.zip
  • 使用说明:Example - wxCharts使用说明 参数说明:参数说明 - wxCharts使用文档 Demo:https://github.com/xiaolin3303/wx-charts-demo 前两天做人脸对比小程序页面,要求用圆环图显示,中间显示相似度,效果...
  • 尝试使用wx-charts来使用图表显示各类数据,主要留意<canvas></canvas>中的id写法不是id="ringCanvas",而是canvas-id="ringCanvas"。 参考博客:... wxcharts.js下载地址:https...
  • 使用wxcharts.js绘图的层级问题

    千次阅读 2018-11-05 19:42:18
    最近在学习微信小程序使用wxcharts.js绘图时遇到了一个问题, 因为在最终绘制完成的页面要进行判断,会有一个弹出框,在微信开发者工具上运行是是没有任何问题的,但到了真机预览时遇到了问题,绘制完成的图形总是在...
  • wxCharts修改X轴或者Y轴上的字体颜色

    千次阅读 2018-11-13 10:31:01
    自己摸索了wxCharts,最后发现网上有很多,但都解决不了我的需求。所以去看了官方文档,本来不想看的(嫌太多了)。后知后觉,看文档才是真的省时间。附上url:官方-wxCharts使用文档 代码: xAxis: { //是否隐藏x...
  • 前言微信小程序图表插件(wx-charts)是基于canvas绘制,体积小巧,支持图表类型饼图、线图、柱状图 、区域图等图表图形绘制,目前...导入wxcharts.js将wxcharts.js 存放在utils目录column.wxml<view class="container"
  • 谈一次使用wxcharts做微信小程序图表功能采到的坑 铃木千夏—前端小白 第一次写博客,记录自己采到的坑,希望下次再遇到类似的不会这么头疼,也希望你们能少走些弯路。 wxcharts柱状图 从网上找了wxcharts.js插件并...
  • 1.要自己设置容器的宽度,在页面onload时,setData, windowWidth: wx.getSystemInfoSync().windowWidth - 15, 这里的15是你想要的左右边距 ...2.当传入areaChart = new wxCharts({})中的data为空时,会...
  • 然后将wxcharts粘贴在自己项目的目录中; 2.在需要使用图表的js页面引入wxcharts.js 在.wpy页面中使用 官方定义的三个函数在js中使用即可; (我使用的是滚动的)这三个函数在methods中定义 3.创建图表注意:this....
  • wxCharts-master.zip

    2020-03-13 12:03:28
    这是一个关于股票分析的小程序,可以查看分时图和K线图,自定义时间查看,运行图详见作者其他博客。有问题可以评论交流也可以私信,看到就会回。
  • 一、wxcharts.js 参考地址:https://github.com/xiaolin3303/wx-charts/issues/58 参数含义参考:https://www.cnblogs.com/zxf100/p/9956415.html 1.1.wxml <!--pages/wxcharts/wxcharts.wxml--> <...
  • 简单 使用
  • wxCharts-for-stock.zip

    2021-01-11 14:22:08
    基于echarts使用微信小程序绘制股票分时图、k线图
  • 解决微信小程序使用wxcharts在屏幕不固定问题-开发工具里也显示好了布局,为啥到真机就是乱的 .chart{ width: 100%; text-align: center; } .canvas{ /* position: absolute; top: 10%; */ width: 100%; height: 600...
  • 1.把wxcharts.js拷贝进项目,放好位置,我一般放在utils下面(js百度可以自己搜下载)2.从后台获取数据(括号自己部全)页面引入这句即可&lt;canvas canvas-id="columnCanvas" class="canvas&...
  • <div><h1>参数说明 <p><code>opts</code> Object <p><code>opts.canvasId</code> String <strong>required</strong> 微信小程序canvas-id <p><code>opts.width</code> Number <strong>required</strong> canvas宽度&...
  • <p>1、创建的时候一个柱状图,默认填入30日考勤数据如下图 ... <p>2、我想让图生成的时候直接显示30前几天的数据,如下图 ... 还有就是,为什么数据多了中间的日期 就不显示了呢,...

空空如也

空空如也

1 2 3 4 5 6
收藏数 113
精华内容 45
关键字:

wxcharts