精华内容
下载资源
问答
  • 本文实例讲述了jQuery圆形统计图开发的方法。分享给大家供大家参考。具体分析如下:这里我们要给大家介绍一款圆形统计图circliful,它基于HTML5的画布和jQuery,无需使用图像轻松实现圆形统计图,而且有很多属性设置...

    5268f80b9b1e01f982625ef6fac83ca1.png

    本文实例讲述了jQuery圆形统计图开发的方法。分享给大家供大家参考。具体分析如下:

    这里我们要给大家介绍一款圆形统计图circliful,它基于HTML5的画布和jQuery,无需使用图像轻松实现圆形统计图,而且有很多属性设置,使用起来非常方便。效果图如下:

    ef52997d923f26972194babb948831e3.png

    首先我们需要将jquery库文件和jquery.circliful.min.js引入到页面中。

    代码如下:

    所需的Jquery文件引入后,现在我们就可以自定义圆形统计图的基本样式了:

    代码如下:

    .circliful {

    position: relative;

    }

    .circle-text, .circle-info, .circle-text-half, .circle-info-half {

    width: 100%;

    position: absolute;

    text-align: center;

    display: inline-block;

    }

    .circle-info, .circle-info-half {

    color: #999;

    }

    .circliful .fa {

    margin: -10px 3px 0 3px;

    position: relative;

    bottom: 4px;

    }

    样式初步定义好之后,只需要在需要统计图的地方,添加如下样式代码:

    代码如下:

    data-width="30" data-fontsize="38" data-percent="35" data-fgcolor="#61a9dc"

    data-bgcolor="#eee" data-fill="#ddd">

    区域块填写完之后,我们现在需要初始化它了:

    代码如下:

    $( document ).ready(function() {

    $('#myStat').circliful();

    });

    就这么简单,只需轻松几部就可以完成帅气的统计图了。

    下面是插件的基本属性说明:

    Circliful提供了丰富的属性选项设置,基于html5的data属性,以下是设置清单。

    参数

    描述

    默认值

    data-dimension

    圆形图的宽度和高度px

    250

    data-text

    显示在圆圈内侧的文字内容

    empty

    data-info

    显示在data-text下的说明信息

    empty

    data-width

    圆圈的厚度px

    15

    data-fontsize

    圈内文字大小px

    15

    data-percent

    圆圈统计百分比%,1-100

    50

    data-fgcolor

    圆圈的前景色

    #556b2f

    data-bgcolor

    圆圈的背景色

    #eeeeee

    data-fill

    圆形的填充背景色

    empty

    data-type

    圆形统计类型,可以是”half”或”full”

    full

    data-total

    数据总量,和data-part配合使用

    empty

    data-part

    数据量,与data-total配合使用

    empty

    data-border

    圆形样式,可以加边框,如inline或outline

    empty

    data-icon

    Fontawesome图标样式,详情可参照:Fontawesome Website – Icons

    empty

    data-icon-size

    图标大小

    empty

    data-icon-color

    图标颜色

    empty

    希望本文所述对大家的jQuery程序设计有所帮助。

    1428d0e076c3959ab11d28a39bc84fab.png

    5268f80b9b1e01f982625ef6fac83ca1.png

    本条技术文章来源于互联网,如果无意侵犯您的权益请点击此处反馈版权投诉

    本文系统来源:php中文网

    展开全文
  • 用Java语言编写的圆盘画法 可用于统计图 用循环实现 替换过于迅速
  • 饼图,应该是大家比较熟悉的图形了吧,作为用来展示定性数据比例分布特征的经典统计图形,通过饼图,你可以很直观的看到各组数据的占比情况哦,上次已经和大家探讨了如何用Python来绘制经典的阶梯,今天呢,咱们...

    饼图,应该是大家比较熟悉的图形了吧,作为用来展示定性数据比例分布特征的经典统计图形,通过饼图,你可以很直观的看到各组数据的占比情况哦,上次已经和大家探讨了如何用Python来绘制经典的阶梯图,今天呢,咱们继续深入聊聊哦,看看在Python中如何绘制更为经典和常用的饼图呢。

    好啦,咱们就开始吧!

    作为Python数据可视化的经典库,matplotlib库一直是Python青睐者的首选调用库,那在matplotlib库中该调用哪个函数绘制饼图呢?它就是今天咱们要讨论的pie()函数。

    下面,咱们还是老习惯,先举个“栗子”看看pie()绘制饼图的效果吧,先熟悉一点它是如何操作的!

    举个“栗子”哦:

    上面就是咱们所编写的程序哦,其中红色方框中所标识的是关于pie()函数的调用哦,下面呢,咱们先仔细研究一下绘制饼图的这个pie()函数吧!

    plt.pie(percents,explode=explode,labels=labels,autopct='%3.1f%%',startangle=45,shadow=True,colors=colors)

    首先说一下pie()函数中各个参数的含义哦,只有了解了各个参数的含义才能随意的调用pie()函数绘制自己要想的饼图哦!

    第1个参数percents代表的是饼图的各个组成饼片所占的百分比哦,在上面第12行可以看到咱们给它赋值了一个序列哦!

    第2个参数explode代表的是饼图的各个组成饼片偏离饼图半径的百分比哦。可以看到上面第18行,咱们给各个饼片设置了相同的偏离百分比哦,均为10%。

    第3个参数labels,顾名思义,当然是代表饼图中各个组成饼片的名字哦,我们在第9行对该参数进行了赋值哦!

    第4个参数autopct表示的是饼图中各个组成饼片所添加的标签内容对应的数值百分比的样式哦,这个参数大家已经要理解哦!

    第5个参数startangle代表的是起始旋转角度哦,程序中咱们给该参数赋值为45,表示的意思是从x轴作为起始位置,第一个所组成饼片逆时针旋转的角度为45度哦!

    第6个参数shadow表示的是咱们所绘制的饼图的各个组成饼片是否需要阴影显示哦,咱们赋值为True表示的是需要哦!

    第7个参数color则表示的是饼图的各个组成饼片的颜色设置哦,咱们在上面程序第15行对其用序列的方式进行了赋值哦!

    好啦,说完了上面该pie()函数的各个参数的含义,下面咱们就调用Python解释器来运行一下咱们所编写的程序看看咱们所绘制的饼图的效果吧!

    运行上面指令,就会输出下面咱们所绘制的饼图哦:

    怎么样,是不是感觉很漂亮,立体感十足呢,这是因为咱们加入了阴影和偏离所带来的显示效果哦!

    好啦,对于调用matplotlib库的pie()函数绘制饼图,今天咱们就聊这些哦,希望大家能够学会在Python中绘制饼图的正确方式哦,当然啦,在此小编只是抛砖引玉了,希望大家能够自己亲自实践一下,并进行灵活调用来绘制自己的饼图哦!

    好啦,今天就聊到这吧!下次再见哦!

    展开全文
  • 小程序统计进度条及环形 wxml <!--pages/statistical/statistical.wxml--> <view> <view class="stater"> <!-- 标题 --> <view class="sta_title"> 直播观看数据汇总 &...

    小程序统计进度条及环形图

    在这里插入图片描述

    wxml

    <!--pages/statistical/statistical.wxml-->
    <view>
    	<view class="stater">
    		<!-- 标题 -->
    		<view class="sta_title">
    			直播观看数据汇总
    		</view>
    		<view class="content-box">
    			<block wx:for="{{resList}}" wx:key="index">
    				<view class="progress-box">
    					<view style="color:{{item.color}}" class="top-area"><text>{{item.name}}</text></view>
    					<view class="bottom-area">
    						<view class="progress-item">
    							<view style="background:{{item.color}};width:{{(item.has/item.total)*100}}%;" class="progress-line">
    								<view style="color:{{item.color}}" class="progress-val {{(item.has/item.total)*100>92?'text-over':''}}">{{item.hasLabel}}{{item.unit}}</view>
    							</view>
    						</view>
    						<view style="color:{{item.color}}" class="total-box"><text>{{item.totalLabel}}{{item.unit}}</text></view>
    					</view>
    				</view>
    			</block>
    		</view>
    		<view class="sta_title">
    			区域数据分析
    		</view>
    		<view class="content-box">
    			<scroll-view wx:if="{{classifyList.length}}" scroll-x="true" class="classify-box">
    				<block wx:for="{{classifyList}}" wx:key="index" >
    					<view bindtap="changeFilter" data-index="{{index}}" class="classify-item {{selectIndex==index?'active-item':''}}">
    						<view style="background:{{item.bgColor}}" class="classify-inner">
    							<text>{{item.name}}</text>
    						</view>
    					</view>
    				</block>
    			</scroll-view>
    			<view class="canvas-box">
    				<view class='weui'>
    			<view class="weui1">
    				<view class="weui2">
    					<canvas class='oneCan' canvas-id='school'></canvas>
    					<view>学校占比</view>
    				</view>
    			</view>
    			<view class="weui1">
    				<view class="weui2">
    					<canvas class='oneCan' canvas-id='teacher'></canvas>
    					<view>老师人数占比</view>
    				</view>
    			</view>
    			<view class="weui1">
    				<view class="weui2">
    					<canvas class='oneCan' canvas-id='parents'></canvas>
    					<view>家长人数占比</view>
    				</view>
    			</view>
    			<view class="weui1">
    				<view class="weui2">
    					<canvas class='oneCan' canvas-id='other'></canvas>
    					<view>其他占比</view>
    				</view>
    			</view>
    		</view>
    			</view>
    		</view>
    	</view>
    </view>
    

    wxss

    page {
      background: rgba(60, 83, 163, 1);
    }
    
    .stater {
      margin: 30rpx 26rpx;
    }
    
    /* 标题 */
    .sta_title {
      font-size: 30rpx;
      font-family: Source Han Sans CN;
      font-weight: 500;
      color: rgba(169, 238, 255, 1);
      line-height: 38px;
    }
    
    
    .content-box {
      padding-top: 30rpx;
    }
    
    .progress-box {
      margin-bottom: 30rpx;
    }
    
    .progress-box .top-area {
      margin-bottom: 8rpx;
    }
    .top-area text{
      font-size:28rpx;
      font-family:Source Han Sans CN;
      font-weight:500;
      line-height:38rpx;
    }
    
    .progress-box .bottom-area {
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    
    .progress-box .progress-item,
    .progress-box .progress-line {
      height: 36rpx;
      border-radius: 30rpx;
    }
    
    .progress-box .progress-item {
      width: 590rpx;
      background: #2d3d82;
      position: relative;
      box-shadow: 0 4rpx 4rpx 0 rgba(45, 60, 130, 0.8);
    }
    
    .progress-item .progress-line {
      position: absolute;
      left: 0;
      top: 0;
      position: relative;
      display: flex;
      justify-content: flex-end;
      align-items: center;
    }
    
    .progress-box .total-box {
      text-align: right;
      line-height: 30rpx;
    }
    
    .total-box text {
      font-size: 28rpx;
      font-family: Source Han Sans CN;
      font-weight: 500;
      line-height: 38rpx;
    }
    
    .progress-item .progress-val {
      box-sizing: border-box;
      padding-left: 10rpx;
      width: 100rpx;
      font-size: 24rpx;
      /* color:red!important; */
      position: relative;
      left: 100rpx;
    }
    
    .progress-val.text-over {
      left: 0 !important;
      text-shadow: 1rpx 1rpx 2rpx #000;
    }
    /* 环形图 */
    .classify-box {
    	height: 80rpx;
    	white-space: nowrap;
    }
    
    .classify-box .classify-item {
    	width: 200rpx;
    	height: 80rpx;
    	box-sizing: border-box;
    	border: 1rpx solid transparent;
    	padding: 3rpx;
    	border-radius: 10rpx;
    	margin-left: 6rpx;
    	display: inline-flex;
    }
    
    .classify-box .classify-item:first-child {
    	margin-left: 0;
    }
    
    .classify-box .classify-item.active-item {
    	border-color: #fff;
    }
    
    .classify-box .classify-inner {
    	width: 100%;
    	border-radius: 10rpx;
    	display: flex;
    	justify-content: center;
    	align-items: center;
    	font-size: 28rpx;
    	color: #fff;
    }
    
    .canvas-box {
    	/* width: 100%;
    	height: 400rpx; */
    	margin-top: 60rpx;
    }
    
    canvas {
    	width: 300px;
    	height: 150px;
    }
    
    .weui {
      margin: 20rpx;
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
    }
    
    .weui1 {
      width: 50%;
    }
    
    canvas {
      width: 240rpx;
      margin: 0 auto;
      text-align: center;
    }
    
    .weui2 {
      text-align: center;
      margin: 20rpx 0;
    }
    
    .weui2 view {
      font-size: 28rpx;
      font-family: Source Han Sans CN;
      font-weight: 500;
      color: rgba(255, 255, 255, 1);
      line-height: 38rpx;
    }
    
    

    js

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        resList: [],
        selectIndex: 0,
        classifyList: [{
            id: 1,
            name: '武侯区',
            bgColor: '#7f98ff',
            percent: 50,
            percent1: 20,
            percent2: 23,
            percent3: 25
          },
          {
            id: 2,
            name: '青羊区',
            bgColor: '#6d9ff8',
            percent: 50,
            percent1: 20,
            percent2: 23,
            percent3: 25
          },
          {
            id: 3,
            name: '金牛区',
            bgColor: '#71affb'
          },
          {
            id: 4,
            name: '锦江区',
            bgColor: '#6285eb'
          }
        ],
        yuan: {
          height: 110
        }
      },
      changeFilter(e) {
        console.log('changeFilter:::', this.data.classifyList)
        console.log('changeFilter:::', e.currentTarget.dataset.index)
        this.setData({
          selectIndex: e.currentTarget.dataset.index
        })
      },
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      /**
       * 生命周期函数--监听页面加载
       */
      // 进度条
      progressbar() {
        let resList = [{
            color: '#b1dcff',
            name: '学校',
            total: 100,
            has: 75,
            unit: '所',
            totalLabel: '',
            hasLabel: ''
          },
          {
            color: '#adb6ff',
            name: '老师',
            total: 3000,
            has: 2400,
            unit: '人',
            totalLabel: '',
            hasLabel: ''
          }, {
            color: '#89a6f0',
            name: '家长',
            total: 40000,
            has: 29000,
            unit: '人',
            totalLabel: '',
            hasLabel: ''
          }, {
            color: '#a496f5',
            name: '其他',
            total: 20000,
            has: 14000,
            unit: '人',
            totalLabel: '',
            hasLabel: ''
          }
        ]
        // 处理进度条显示的文字
        resList.forEach((item, index) => {
          if (item.total > 9999) {
            item.totalLabel = item.total / 10000 + '万'
          } else if (item.total > 999) {
            item.totalLabel = item.total / 1000 + '千'
          } else {
            item.totalLabel = item.total
          }
          if (item.has > 9999) {
            item.hasLabel = item.has / 10000 + '万'
          } else if (item.has > 999) {
            item.hasLabel = item.has / 1000 + '千'
          } else {
            item.hasLabel = item.has
          }
        })
        this.setData({
          resList: resList
        })
      },
      // 环形图
      diagram() {
        var windowidth = 400;
        var colw = windowidth / 3;
        this.setData({
          yuan: {
            height: colw
          }
        })
        console.log(this.data.classifyList);
        this.createCanvas('school', colw / 2, '#63BBE9', '第一', this.data.classifyList[0].percent, 100);
        this.createCanvas('teacher', colw / 2, '#7D80FF', '第一', this.data.classifyList[0].percent1, 100);
        this.createCanvas('parents', colw / 2, '#5F84EE', '第一', this.data.classifyList[0].percent2, 100);
        this.createCanvas('other', colw / 2, '#A091F6', '第一', this.data.classifyList[0].percent3, 100);
      },
    
      createCanvas: function (id, xy, color, txt, val, total) {
        var ctx = wx.createCanvasContext(id);
        ctx.setLineWidth(8);
        ctx.setStrokeStyle('#ffffff');
        ctx.setLineCap('round');
        ctx.beginPath();
        ctx.arc(xy, xy, 0.75 * xy, 0, 2 * Math.PI, false);
        ctx.stroke();
    
        ctx.setLineWidth(8);
        ctx.setStrokeStyle(color);
        ctx.setLineCap('round');
        var p = val / total;
    
        ctx.beginPath(xy);
        ctx.arc(xy, xy, 0.75 * xy, -90 * Math.PI / 180, (p * 360 - 90) * Math.PI / 180, false);
        ctx.textAlign = "center";
        ctx.font = '14rpx Arial';
        ctx.fillText('', xy, 1.4 * xy, xy);
        ctx.font = '28rpx Arial';
        ctx.fillStyle = color;
        ctx.fillText(val + '%', xy, 1.1 * xy, xy);
        ctx.stroke(); //对当前路径进行描边
        ctx.draw();
    
      },
      onLoad: function (options) {
        // 进度条
        this.progressbar();
        // 环形图
        this.diagram();
      },
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
    
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
    
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
    
      },
    
      /**
       * 用户点击右上角分享
       */
      onShareAppMessage: function () {
    
      }
    })
    
    展开全文
  • 小程序统计图,各种统计,想要的都有,欢迎下载.........
  • Android 手撸一个圆环信息统计控件

    千次阅读 2018-05-03 17:25:43
    对于很多应用来说都可能需要做一些数据的统计与展示,通常使用的也就是圆盘统计图和直线统计图以及折线统计图,由于android原生系统中不提供这类的控件,通常需要自己手撸一个或者使用第三方框架,有很多第三方框架...

    目录

    前言

    对于很多应用来说都可能需要做一些数据的统计与展示,通常使用的也就是圆盘统计图和直线统计图以及折线统计图,由于android原生系统中不提供这类的控件,通常需要自己手撸一个或者使用第三方框架,有很多第三方框架做的很好很炫酷,功能也很全面,但是如果让你自己手写一个改怎么实现呢?今天我来展示一下我的小思路吧。

    设计

    统计控件有很多种,我这次只写了圆环信息统计控件,首先的设计一下这个控件的样式和功能,在参考支付宝账单的圆环统计控件后,我觉得这个样式很有特色的有特殊的美感。

    效果

    设计与实现的效果如下:

    控件效果

    编写

    首先加载一个圆环统计信息必须按照每一个子项来进行加载,定义一个bean类DataItem,其中包括属性:

        /**
         * 所占值
         */
        private int value;
        /**
         * 顶部文本
         */
        private String topText;
        /**
         * 底部文本
         */
        private String bottomText;
        /**
         * 颜色
         */
        private int color;

    现在开始我们的重头戏,那就是自定义控件的工作,首先看了效果图,我们要先画圆环,由于整个大圆环由不同数据子项构成,即把每个子项进行比例运算画出每个子项对应的圆弧最后达到画出整个圆环的效果。不过第一步还是进行大小的测量,即先获得控件所占的高度和宽度,按照圆半径占控件高度比例和圆心半径所占控件高度比例,得出圆环大圆和圆心的半径。代码如下:

        /**
         * 圆半径所占控件高度比例
         */
        private float radiusRatio = 7.0f/24.0f;
        /**
         * 圆心半径所占控件高度比例
         */
        private float centerRadiusRatio = 1.0f/6.0f;
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int widthSize  = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            radius = (int) (radiusRatio*heightSize);
            centerRadius = (int) (heightSize*centerRadiusRatio);
            setMeasuredDimension(widthSize,heightSize);
        }

    确定好控件的大小之后开始重写onDraw方法

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            drawItem(canvas);
            drawCenter(canvas);
            drawItemInfo(canvas);
        }

    onDraw方法中有三个方法第一绘制每个子项对应的圆弧,第二绘制环形中心颜色第三绘制每个数据子项对应的数据线和数据信息。首先看画弧:

        private void drawItem(Canvas canvas) {
            float start = 0;
            float need = 0;
            canvas.translate(getWidth()/ 2, getHeight()/ 2);
            discRect = new RectF(-radius,-radius,radius,radius);
            for (DataItem item : items) {
                mPaint.setColor(item.getColor());
                start += need;
                need = item.getValue()*1.0f/total*360.0f;
                canvas.drawArc(discRect,start,need,true,mPaint);
            }
        }

    其中start表示每个子项开始绘制的圆弧起始度数,need表示每个子项圆弧所占的度数,然后画圆弧,每个子项对应圆弧所占的度数由value和total的比例决定。
    画完圆弧之后即可绘制中心

        private void drawCenter(Canvas canvas) {
            mPaint.setColor(centerColor);
            canvas.drawCircle(0,0,centerRadius,mPaint);
        }

    代码简单即根据设定的颜色覆盖圆心区域,最后最大的难点到了,即是绘制每个子项对应的数据线和数据信息。先看效果图,每个子项对应的数据线先是一个小圆然后对应一线,如果没有数据重叠是不需要画折线的,当数据点位于顶边上圆弧的时候画折线要和画直线更好看,底部圆弧同理。当数据子项挨的很近的时候这个时候可以进行数据位置的移动让其不重叠在一起,为了简单起见,我们先写一个函数只负责根据起点和终点绘制数据线。把起点和终点确定的方法留给之后一个函数来计算和确定

    private void drawDataLine(Point start,Point end,Canvas canvas,DataItem item){
            mPaint.setColor(item.getColor());
            canvas.drawCircle(start.x,start.y,radius/20,mPaint);
            if (start.y != end.y){
                Point temp = new Point(0,end.y);
                int distance = Math.abs(start.y-end.y);
                if (distance>itemHeight){
                    distance = itemHeight;
                }
                if (start.x>0){
                    temp.x = start.x+distance;
                }else {
                    temp.x = start.x-distance;
                }
                canvas.drawLine(start.x,start.y,temp.x,temp.y,mPaint);
                start = temp;
            }
            drawText(canvas,end,item);
            canvas.drawLine(start.x,start.y,end.x,end.y,mPaint);
        }

    代码如上所述,根据起点和终点画数据线,如果线的起点和终点在一条水平线上即可画一条直线,若不在一条水平线上即画一条折线。当线条画好自然对应的文本也可绘制完成

        private void drawText(Canvas canvas,Point point,DataItem item) {
            drawText(canvas,point,item.getTopText(),true);
            drawText(canvas,point,item.getBottomText(),false);
        }
    
        private void drawText(Canvas canvas,Point point,String text,boolean isTop) {
            if (text!=null){
                float x = point.x +(point.x>0?-getAlignLength(text):0);
                float y ;
                if (isTop){
                    y = point.y - (itemHeight-textSize)/2;
                }else {
                    y = point.y + (itemHeight+textSize)/2;
                }
                canvas.drawText(text,x,y,textPaint);
            }
        }
    
        private float getAlignLength(String text){
            return textPaint.measureText(text);
        }

    绘制数据线的功能函数已经实现那么现在只需要明确好起点和终点集合,对于起点很好确定,即将圆弧对应的中线延长一点即可获取的数据线的起点,即获取圆弧的中心点的角度。按照半径的8/7获取到起点,代码如下:

        private Point getPointByAngle(float angle) {
            Point point = new Point();
            point.x = (int) (Math.cos(Math.toRadians(angle))*radius*8/7);
            point.y = (int) (Math.sin(Math.toRadians(angle))*radius*8/7);
            return point;
        }

    起点确定了,就得获取到终点,所限终点可以为起点平移到左右两侧边缘的点,但是可能会导致多个数据项的终点距离太近导致数据项信息的重叠,所以必须要进行终点位置的调整,先看代码:

        private void drawItemInfo(Canvas canvas) {
            float angle[] = new float[items.size()];
            Point point[] = new Point[items.size()];
            Stack<Point> stack = new Stack<>();
            Point endPoint = null;
            for (int i = 0; i < items.size(); i++) {
                angle[i] = items.get(i).getValue()*1.0f/total*360.0f;
                point[i] = getPointByAngle(angle[i]/2+(i>0?angle[i-1]:0));
                endPoint = getEndPoint(point[i],endPoint);
                if (i>0) angle[i] += angle[i-1];
                if ((point[i].x<0&&point[i].y>0)||(point[i].x>0&&point[i].y<0)){
                    if (!stack.isEmpty()&&!isSameQuadrant(stack.peek(),point[i])){
                        reverseDrawItemInfo(stack,i-1,canvas,null);
                        endPoint = point[i-1];
                    }
                    stack.push(point[i]);
                    if (i==items.size()-1){
                        reverseDrawItemInfo(stack,i,canvas,point[0]);
                    }
                    continue;
                }else if (!stack.isEmpty()){
                    reverseDrawItemInfo(stack,i-1,canvas,null);
                    endPoint = getEndPoint(point[i],point[i-1]);
                }
                drawDataLine(point[i],endPoint,canvas,items.get(i));
            }
        }
    
        private boolean isSameQuadrant(Point point,Point prePoint) {
            return point.x*prePoint.x>=0&&point.y*prePoint.y>=0;
        }

    这段代码中首先确定了每个数据子项的起点(point[i]),然后根据数据子项的起点来确定终点。首先我们我们看一张图:
    这里写图片描述
    圆弧绘制的起点为蓝色小点,我们可以简单的比较当前点和前一个点的终点,如果当前点与前一个点挨的太近即将当前点的终点Y坐标下移使得两点高度距离适中,但是由于绘制的方向是从第四象限开始一直到第一象限结束,所以当绘制到第三象限和第二象限时会导致数据线的重叠,应该反向绘制,这个时候采取一个Stack的数据结构即可实现,让我们先来看一下确定终点的方法,如下所示,如果距离相差不会导致重叠即可直接返回水平线对应的终点,反之距离相差太近或者终点靠近底部或顶部就就行终点位置的调整。

     private Point getEndPoint(Point point,Point prePoint) {
            if (prePoint != null&&point.x*prePoint.x>=0){
                int distance = Math.abs(prePoint.y - point.y);
                if (distance < 3*itemHeight/2||(point.y>=0
                        &&prePoint.y>point.y)||(point.y<0&&prePoint.y<point.y)){
                    Point endPoint = new Point();
                    endPoint.x = point.x>0?getWidth()/2-margin:-getWidth()/2+margin;
                    endPoint.y = point.y>=0?prePoint.y+2*itemHeight:prePoint.y-2*itemHeight;
                    return endPoint;
                }
            }
            return getEndPoint(point);
        }
    
     private Point getEndPoint(Point point){
            Point endPoint = new Point();
            endPoint.x = point.x>0?getWidth()/2-margin:-getWidth()/2+margin;
            if (Math.abs(point.y)> 5*radius/6){
                endPoint.y = point.y+(point.y>0?itemHeight:-itemHeight);
            }else {
                endPoint.y = point.y;
            }
            return endPoint;
        }

    对于二三象限即可反向绘制,代码如下:

     private void reverseDrawItemInfo(Stack<Point> stack
                ,int position,Canvas canvas,Point nextPoint){
            Point curPoint;
            while (!stack.isEmpty()){
                curPoint = stack.pop();
                nextPoint = getEndPoint(curPoint,nextPoint);
                drawDataLine(curPoint,nextPoint,canvas,items.get(position--));
            }
        }

    最后提供数据加载方法,将传入的数据,输入到List数据集合中,再更新界面即可

        public void setItems(List<DataItem> items) {
            this.items = items;
            total = 0;
            for (DataItem item : items) {
                total += item.getValue();
            }
            invalidate();
        }

    使用

    在自定义好控件之后,在Activity中配置使用,首先在xml里面添加控件

    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false"
        tools:context="com.disc.MainActivity">
        <com.disc.DiscView
            android:id="@+id/disc"
            android:layout_width="match_parent"
            android:layout_height="250dp" />
    </android.support.constraint.ConstraintLayout>
    

    然后在Activity中加载模拟数据,示例如下:

            DiscView discView = findViewById(R.id.disc);
            List<DataItem> items = new ArrayList<>();
            items.add(new DataItem(1,"百度","26.56",getColor(R.color.red)));
            items.add(new DataItem(1,"腾讯","32.45",getColor(R.color.green)));
            items.add(new DataItem(1,"美团","12.36",getColor(R.color.red)));
            items.add(new DataItem(23,"Google","56.23",getColor(R.color.black)));
            items.add(new DataItem(1,"沃尔玛","45.56",getColor(R.color.red)));
            items.add(new DataItem(35,"阿里巴巴","45.56",getColor(R.color.blue)));
            items.add(new DataItem(2,"华为","45.56",getColor(R.color.black)));
            items.add(new DataItem(3,"斗鱼","45.56",getColor(R.color.blue)));
            items.add(new DataItem(4,"虎牙","45.56",getColor(R.color.yellow)));
            items.add(new DataItem(24,"京东","35.56",getColor(R.color.green)));
            items.add(new DataItem(23,"Windows","37.25",getColor(R.color.yellow)));
            items.add(new DataItem(12,"头条","334.25",getColor(R.color.blue)));
            items.add(new DataItem(13,"IBM","37.25",getColor(R.color.black)));
            items.add(new DataItem(2,"甲骨文","30.25",getColor(R.color.yellow)));
            discView.setItems(items);
    

    然后运行即可看到效果图所示效果

    源码

    如果有想需要查看源码的小伙伴可以点击这里
    因为时间问题里面还有一些小问题,并不能像开源框架一样适用各类项目如果有需要的朋友可以自行修改参数加入到自己的项目当中。如果感觉有用,请帮忙star,谢谢。

    总结

    很多人很喜欢用开源框架,其有利也有弊,为了适用于各类的项目开源框架会进行扩展提供适应于各种情形的设置,如果只是需要一些基本功能或者特定功能的轻量级控件,建议自行定义。在编写之前必须考虑各项功能的设计,在实现上可以让每个方法分工明确把关于逻辑控制操作留在一个方法中做统一处理,更有利于思路的清晰。

    展开全文
  • MPAndroidChart统计图开发总结

    千次阅读 2017-07-26 11:39:58
    前段时间公司要求要给项目里面用统计图来统计数据的直观信息。之后在GitHub上找到了 MPAndroidChart这个库, 今天不对其原理进行解剖。指记录其用法以及常用的属性设置。围绕柱状图、折线图、和饼状图来给大家解析。...
  • vue用echarts写环形统计

    2021-06-10 14:56:41
    1.代码 <template> <div> <el-card class="Ratio-card" shadow="hover"> <div id="myChart" :style="{width: '100%', height: '400px'}"></div> <.../el-ca
  • plt.pie(size,explode,labels,autopct='%1.1f%%',shadow=True,startangle=35) (定义阴影及角度) plt.axis('equal') plt.show() 经过数据调整,我们可以得出下面的小圆盘,这个东西可以拿来统计自己的运动量,开销...
  • 给出若干互不相交的同心圆盘(圆盘的中心按页的边缘计算),计算出各轴像素密度(各圆环内“on”象素的个数)作为图形的特征向量.在页面的特征向量之间,建立一种距离,再进行聚类分析以识别文档的摹本.对从网下载的批量...
  • 对图像的处理,求出图像的面积,对灰度进行统计
  • 圆形比例(饼状

    千次阅读 2017-10-24 16:28:53
    项目中经常用圆形统计图来显示收益占比,消费占比等数据,像支付宝账单那样,感觉挺有意思,那么动手来自己撸一个,先来看一下最终效果图: 这个东西,想一下思路挺清晰的,就是算一下各个数据的比例,然后根据...
  • MPAndroidChart开源图表库之饼状

    千次阅读 2016-08-02 16:35:20
    今天做的项目一个需求是做一个饼图的统计图,于是查找资料,最后发现MPAndroidChart是一款基于Android的开源图表库,MPAndroidChart不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,...
  • python绘制多层饼状

    千次阅读 2017-12-08 11:10:42
    s={'S0': 3, 'S1': 19, 'S2': 6, 'S3': 2} ...将上面两个字典绘制在同一张饼状中: 代码如下: s={'S0': 3, 'S1': 19, 'S2': 6, 'S3': 2} s_labels=list(sorted(s.keys())) s_fracs=[s.get
  • echarts实现环形进度

    千次阅读 2015-03-14 12:09:35
    //环形进度 TgsChartsUtil.drawCircleLoadingChart = function(cfg){ var myChart = TgsChartsUtil.getChart(cfg); if(!TgsChartsUtil.isPageLoad()){ cfg.chartType = "circleLoading"; ...
  • 轻松搞定各种柱状

    千次阅读 2020-12-24 18:32:52
    graphpad prism是一款集生物统计、曲线拟合和科技绘图于一体的超级好用的医学绘图软件,深受生物、医学等科研人员喜爱,使用graphpad可以搞定大部分生物、医学研究所需的统计与作图,今天小编就以柱形为例,教大家...
  • } 二、环形 .loading { margin: 100px auto; width: 8em; height: 8em; position: relative; } .loading .progress { position: absolute; width: 6em; height: 6em; background-color: white; border-radius: 50...
  • 基于自相关函数的自然纹理图像分形维数的估计提出了一种估计分形维数的新方法 ,并利用该方法估计自然...在二阶统计特征基础上,引入高阶统计量作为纹理图像的特征参数,并与人工神经网...(本文共4页)阅读全文>&g...
  • Bootstrap系列之实现圆形图片效果

    千次阅读 2016-08-19 17:20:25
    安装Bootstrap环境,下载框架文档和core代码 您可以从http://getbootstrap.com/上下载 Bootstrap 的最新版本。当您点击这个链接时,您将看到如下所示... 您会看到两个按钮: ...Download Bootstrap:下载 Bootstrap。...
  • 模拟单位圆盘上的分数布朗场,Hurst 参数为“H”; 请注意,协方差函数是各向同性的,请参阅下面的参考资料。 输入: - 'H' 是高斯过程的 Hurst 参数- 'n' 是网格点的数量,其中 'n' 是 2 的幂; 如果提供的“n”...
  • 目录:1....直方反向投影一、绘制直方直方统计每个像素在图像矩阵中出现的次数或概率。OpenCV函数:绘制直方cv2.calcHist(images, channels, mask, histSize, ranges, hist=None, accum...
  • HSV图示: cv2:calcHist(images; channels; mask; histSize; ranges[; hist[; accumulate]]) ...channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅 像的直方。如果输入图像是灰...
  • 扇形统计图,显示百分比 ShanView自定义类: package com.wonder.collectionsystem.view; import java.util.List; import com.wonder.collectionsystem.bean.ShanData; import android.content.Conte...
  • 球形参数和几何图像[62],[63]和[64]为最常用的参数化方法,但它们只适合0形(genus-0)和近似圆盘的表面,任意拓扑的表面需要分成像圆盘的几部分,然后展开成一个二维域。这样它适合重建属于同一类外形的物体重建,...
  • android roundView(android 环形转盘按钮)

    热门讨论 2013-12-31 15:20:16
    自定义UI,实现了转盘样式按钮,多功能按钮。 此控件可以设置 按钮的图片,按钮的数量,还有背景,样式,分割线的宽度,还有对称轴。
  • 无参考图像清晰度评价

    万次阅读 2016-03-16 13:07:17
    实验表明,基于圆盘模型的均值滤波器和高斯模型的平滑滤波器都可以取得较好的效果,为了更好的与成像系统匹配,建议采用   7x7  大小且   的高 斯平滑滤波器。在需要实时处理的工 程应用中 7x7 均值滤波器并不会...
  •  一种较为蛮干的解决方法就是遍历图像统计,检索到1个白点,然后以它的8邻域扩展来搜索区域,当搜索的区域不在扩大时,说明该区域搜索完毕,计数加1,继续寻找下一个新的点,重复操作,直到执行完整副图片。...
  • 彩色图像中的像素值由RGB三个分量决定,每个分量都有0-255(256种)选择,这样一个像素点的像素值可以有1600万种可能(256256256),而灰度的像素点的像素值是RGB三个分量值相同的一种特殊的彩色图像, 只有256种...
  • S3.3.2:统计梯度幅度VG中,划分像素值最大的1%的那部分点的分界阈值high,划分像素值最小的1%的那部分点的分界阈值low;把所有像素值大于high的点,重置为high;把所有像素值小于low的点,重置为low;该步骤...
  • 》》 imshow(I) 2、估计图像背景: 图像中心位置背景亮度强于其他部分亮度,用imopen函数和一个半径为15的圆盘结构元素对输入的图像I进行形态学开操作,去掉那些不完全包括在圆盘中的对象,从而实现对背景亮度的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,376
精华内容 950
关键字:

圆盘统计图