精华内容
下载资源
问答
  • 仿金融APP收益曲线图

    千次阅读 2017-07-02 17:01:58
    转载请注明出处:http://blog.csdn.net/binbinqq86/article/details/74127768很多金融APP都会给我们呈现七天收益曲线图(貌似一开始是支付宝里面的余额宝先发明的),最近项目需要用到,之前也接触过图表相关的...

    转载请注明出处:http://blog.csdn.net/binbinqq86/article/details/74127768

    很多金融APP都会给我们呈现七天收益曲线图(貌似一开始是支付宝里面的余额宝先发明的),最近做项目需要用到,之前也接触过图表相关的开源库,比如hellocharts、MPChart等比较出名的两个,但是感觉就这么一个图表不需要去集成一个开源库,还是自己去实现一个吧!于是周末在家用了一天时间去实现并完善这个图表,看效果图:

    这里写图片描述

    怎么样,自我感觉良好~下面说说主要实现思路:

    1. 自定义view,去绘制这些坐标轴还有曲线
    2. 根据后台返回数据(这里用的模拟数据)计算相应坐标轴文本和曲线上的点的绘制位置
    3. 加入动画
    4. 完善一些配置信息,使图表可配置

    说起来就这么几步,先看一下数据model:

    package com.example.tianbin.myincomechart;
    
    /**
     * Created by TianBin on 2017/7/1 12:53.
     * Description :
     */
    
    public class Model {
        public String date;
        public float percent;
    }
    

    两个成员变量,一个是X轴日期,一个是Y轴收益百分比,然后就是我们的主角——自定义图表部分。先来分析一下:我们需要绘制的是X轴Y轴坐标系,并且有横向分割线,另外就是具体的坐标点。Y轴首先是分为6等份,有一份分给x轴坐标文本,另外5份是Y轴刻度值均分的结果(根据后台返回数据的最大最小值均分,算出每个刻度值),而在绘制的过程中,需要根据图表的高度以及总刻度值来计算每一份收益百分比所占像素,最后根据每个model的percent值来计算出应该绘制在屏幕的位置。然后用path方法把所有的点连在一起,绘制出最终的曲线,至于下面阴影部分的绘制,只需要让path闭合就可以了,来看这部分关键代码:

    //...代码省略
            //放大为整数,避免浮点运算
            min= (int) (datas.get(0).percent*100);
            max= (int) (datas.get(0).percent*100);
            if(datas.get(0).percent<0){
                negativePos=0;
            }
    
            for (int i = 1; i < datas.size(); i++) {
                int f= (int) (datas.get(i).percent*100);
                if(min>f){
                    min=f;
                }
                if(max<f){
                    max=f;
                }
                if(datas.get(i).percent<0){
                    negativePos=i;
                }
            }
    
    
            //转换比例,找出最大和最小进行换算每个梯度所占像素
            perPercent=(max-min)/(ySize-1);
    //        Log.e(TAG, "onDraw: "+perPercent+"@"+min+"#"+max );
            perHeight=getHeight()/(ySize+1);
    
            //坐标右对齐========Y轴处理
            String str=negativePos==-1?datas.get(0).percent+"%":datas.get(negativePos).percent+"%";
            xVertical=getPaddingLeft()+labelYPaint.measureText(str);
            xPadding= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics());
    
            //X轴处理和曲线绘制,居中对齐
            eachWidth=(getWidth()-getPaddingRight()-xVertical-xPadding)/xSize;
            bottomY=getHeight()-perHeight-labelYHeight/3f;//最低点坐标
            topY=perHeight-labelYHeight/3f;//最高点坐标
            perY=(bottomY-topY)/((max-min)/100f);//每个刻度所占坐标像素
    
            for (int i = 0; i < datas.size(); i++) {
                float x=i*eachWidth+xPadding+xVertical+eachWidth/2f;
                float y=bottomY-perY*(datas.get(i).percent-min/100f);
    //            Log.e(TAG, "onDraw: "+y+"#"+perY+"$"+bottomY+"$"+topY );
    
                points[i][0]=x;
                points[i][1]=y;
            }

    上面主要就是求出最大最小两个边界值,然后计算出后面绘制坐标轴和曲线需要的一些变量及数据集坐标集合,继续看代码:

    //...代码省略
            for (int i = 0; i < ySize; i++) {
                float eachy=(min+i*perPercent)/100f;
                String label=df.format(eachy)+"%";
                if(i==ySize-1){
                    label=df.format(max/100f)+"%";
                }
                float y=perHeight*(ySize-i);
    //            Log.e(TAG, "onDraw: "+y+"#"+label );
                //绘制y坐标轴
                canvas.drawText(label,xVertical,y,labelYPaint);
                //绘制横向分割线
                canvas.drawLine(xVertical+xPadding,y-labelYHeight/3,getWidth()-getPaddingRight(),y-labelYHeight/3,xSeparatePaint);
            }
    

    上面是绘制y轴相关的内容,包括坐标label,横向分割线,主要工作量就是计算绘制所需的坐标。这里max/100f是因为初始化数据的时候为了防止浮点运算,故意放大100倍为整数,所以这里要除回来。

            for (int i = 0; i < datas.size(); i++) {
                String label=datas.get(i).date;
                float x=i*eachWidth+xPadding+xVertical+eachWidth/2f;
                float y=bottomY-perY*(datas.get(i).percent-min/100f);
    //            Log.e(TAG, "onDraw: "+y+"#"+perY+"$"+bottomY+"$"+topY );
    
                //绘制x坐标轴
                canvas.drawText(label,x,getHeight()-labelXHeight*1.8f,labelXPaint);
            }
    

    同理y轴的绘制,上面的代码是x轴的相关内容绘制。

            //绘制曲线图
            if(playAnim){
                Path dst = new Path();
                //根据动画值从线段总长度不断截取绘制造成动画效果
                mPathMeasure.getSegment(mPathMeasure.getLength() * mAnimatorValue, mPathMeasure.getLength(), dst, true);
                canvas.drawPath(dst, linePaint);
    
                if(fillAreaHasAnim){
                    float currX=(points[datas.size()-1][0]-points[0][0]) * (1-mAnimatorValue)+points[0][0];
                    if(isFillArea){
                        dst.lineTo(points[0][0],bottomY);
                        dst.lineTo(currX,bottomY);
                        dst.close();
                        canvas.drawPath(dst,fillPaint);
                    }
                }
            }else{
                canvas.drawPath(path,linePaint);
            }
    
            if(isOver||!playAnim){
                if(isFillArea){
                    Path pa=new Path(path);
                    pa.lineTo(points[0][0],bottomY);
                    pa.lineTo(points[datas.size()-1][0],bottomY);
                    pa.close();
                    canvas.drawPath(pa,fillPaint);
                }
                //最后一个点上面绘制文本
                Bitmap bg= BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher);
                float lastX=points[datas.size()-1][0];
                float lastY=points[datas.size()-1][1];
                canvas.drawBitmap(bg,lastX-bg.getWidth(),lastY-bg.getHeight(),new Paint());
                String tip=datas.get(datas.size()-1).percent+"%";
                canvas.drawText(tip,lastX-labelValuePaint.measureText(tip)/2f,lastY-labelValueHeight/2f,labelValuePaint);
    
                float pointRadius= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,3,getResources().getDisplayMetrics());
                if(drawPoints){
                    for (float[] f:points) {
                        canvas.drawCircle(f[0],f[1],pointRadius,pointPaint);
                    }
                }
            }
    
        }

    上面就是根据变量来判断绘制的方式和内容,还有动画方式。可以让曲线从左到右动态绘制,还可以控制曲线下面的区域是否填充,以及坐标点的绘制与否。下面的代码是所需绘制路径的初始化:

    private void initPath(){
            path.moveTo(points[points.length-1][0],points[points.length-1][1]);
            for (int i = points.length-1; i >=0; i--) {
                path.lineTo(points[i][0],points[i][1]);
            }
            mPathMeasure=new PathMeasure(path,false);
        }

    核心代码就是上面这些,已经加入了很详细的注释,下面说一下动画:主要采用的PathMeasure这个类,结合ValueAnimator,注意上面代码构造path路径,加入的顺序是倒序,为什么这样呢?看onDraw方法里面第37行,PathMeasure这个方法是用来取指定片段(不熟悉这个类用法的请自行学习),我们播放动画的思路就是不停的绘制曲线,每次增加一个单位,这样看起来就像在往前冲一样,而我们的动画是这样写的:

    private void initListener() {
            mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mAnimatorValue = (float) animation.getAnimatedValue();
                    invalidate();
                }
            };
        }
        private void initAnimator() {
            valueAnimator = ValueAnimator.ofFloat(1, 0).setDuration(defaultDuration);
            valueAnimator.addUpdateListener(mUpdateListener);
            valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
    
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    isOver=true;
                    invalidate();
                }
    
                //代码省略...
        }

    看到第11行,值的变化是1–>0,当在取线段的时候就是从最后取,因为我们构造path是倒序,所以最先绘制的就是第一个坐标点,这样随着动画插值器逐渐减小,绘制的曲线则越来越长,造成了动态绘制的效果~

    最后来看下触摸事件,每个坐标点应该都是可以点击的:

    @Override
        public boolean onTouch(View v, MotionEvent event) {
            if(datas!=null&&datas.size()>0){
                if(isInArea(event.getX(),event.getY())){
                    Toast.makeText(getContext(),selectedValue.percent+"%", Toast.LENGTH_SHORT).show();
                }
            }
            return false;
        }
    
        private boolean isInArea(float x,float y){
            float radius= TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics());
            for (int i = 0; i < points.length; i++) {
                if((x<=points[i][0]+radius)&&x>=(points[i][0]-radius)&&(y<=points[i][1]+radius)&&y>=(points[i][1]-radius)){
                    selectedValue=datas.get(i);
                    return true;
                }
            }
            return false;
        }

    思路也很简单,设置touch监听事件就可以了,当手指触摸点在图表坐标10dp圆形范围内均认为触发了坐标点的点击事件。

    最后我在图表中加入了一些可配置信息,如:是否采用动画,是否绘制顶点等等,大家可以自己尝试效果,最终调用的时候只需要setDatas就可以显示出来了,非常简单!

    今天的讲解就到此结束了,如果有不明白的小伙伴可以在下方留言,看到后会第一时间回复大家~

    源码下载

    欢迎star,欢迎fork,欢迎watch~

    展开全文
  • 一款天气app的温度曲线图的实现

    千次阅读 2016-01-19 20:09:25
    最近在开发一款天气app,有一个功能是显示当天24小时每三个小时的气温状况,这个功能无疑要用图表来实现最好了。所以在github上找到一个国人开发的图表库,XCL-Charts。 先上效果: 首先创建一个SplineChartView...
    最近在开发一款天气app,有一个功能是显示当天24小时每三个小时的气温状况,这个功能无疑要用图表来实现最好了。所以在github上找到一个国人开发的图表库,XCL-Charts。
    先上效果图:
    

    这里写图片描述
    首先创建一个SplineChartView继承自GraphicalView,再主要实现三个方法
    第一个是关于图表的渲染
    private void chartRender()
    {
    try {

            //设置绘图区默认缩进px值,留置空间显示Axis,Axistitle....     
            int [] ltrb = getBarLnDefaultSpadding();
            chart.setPadding(ltrb[0] + DensityUtil.dip2px(this.getContext(), 20), ltrb[1],
                        ltrb[2]+DensityUtil.dip2px(this.getContext(), 30), ltrb[3]);    
    
    
    
    
            //显示边框
            chart.showRoundBorder();
    
            //数据源   
            chart.setCategories(labels);
            chart.setDataSource(chartData);
        //  chart.setCustomLines(mCustomLineDataset);
    
            //坐标系
            //数据轴最大值
            chart.getDataAxis().setAxisMax(40);
            chart.getDataAxis().setAxisMin(-40);
            //数据轴刻度间隔
            chart.getDataAxis().setAxisSteps(2);
    
            //标签轴最大值
            chart.setCategoryAxisMax(5);    
            //标签轴最小值
            chart.setCategoryAxisMin(0);    
    
    
            //背景网格
            PlotGrid plot = chart.getPlotGrid();        
            plot.hideHorizontalLines();
            plot.hideVerticalLines();       
    
    
            chart.getPlotArea().setBackgroundColor(true, Color.GRAY);
    
    
            chart.getCategoryAxis().getAxisPaint().setColor(Color.WHITE);
            chart.getCategoryAxis().getAxisPaint().setTextSize(6);
            chart.getCategoryAxis().hideTickMarks();                    
            chart.getCategoryAxis().getTickLabelPaint().setColor(Color.WHITE);  
            chart.getCategoryAxis().getTickLabelPaint().setFakeBoldText(true);
            chart.getCategoryAxis().setTickLabelMargin(25);
            chart.getCategoryAxis().getTickLabelPaint().setTextSize(25);        
    
            //不使用精确计算,忽略Java计算误差,提高性能
            chart.disableHighPrecision();
    
            chart.disablePanMode();
            chart.hideBorder();
            chart.getPlotLegend().hide();
            chart.getDataAxis().hide();
    
    
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.e("tag", e.toString());
        }
    }
    

    其中chart.getPlotArea().setBackgroundColor(true, Color.GRAY);是设置图表绘制区的颜色,chart.getDataAxis().setAxisMax(40);在我的app中表示能显示的最高温度是40摄氏度,chart.getDataAxis().setAxisMin(-40);表示能显示的最低温度是-40摄氏度。

    第二个和第三个都是绑定数据的。
    

    public void setChartDataSet(List temps)
    {
    //线1的数据集
    List linePoint1 = new ArrayList();
    linePoint1.add(new PointD(0d, Double.parseDouble(temps.get(0))));
    linePoint1.add(new PointD(1d, Double.parseDouble(temps.get(1))));
    linePoint1.add(new PointD(2d, Double.parseDouble(temps.get(2))));
    linePoint1.add(new PointD(3d, Double.parseDouble(temps.get(3))));
    linePoint1.add(new PointD(4d, Double.parseDouble(temps.get(4))));
    linePoint1.add(new PointD(5d, Double.parseDouble(temps.get(5))));

        SplineData dataSeries1 = new SplineData("Go",linePoint1,
                Color.WHITE ); 
        //把线弄细点
        dataSeries1.getLinePaint().setStrokeWidth(3);
        dataSeries1.setLineStyle(XEnum.LineStyle.DASH); 
        dataSeries1.setLabelVisible(false);                 
        dataSeries1.setDotStyle(XEnum.DotStyle.RING);
        dataSeries1.getDotPaint().setColor(getResources().getColor(R.color.white));             
        dataSeries1.getPlotLine().getPlotDot().setRingInnerColor(getResources().getColor(R.color.grey));
    
        chartData.add(dataSeries1); 
        this.invalidate();
    }
    
    public void setChartLabels(List<String> weather){
        String[] times={"20:00\n","23:00\n","2:00\n","5:00\n","8:00\n","11:00\n"};
        for(int i=0;i<weather.size();i++){
            labels.add(times[i]+weather.get(i));
        }
        this.invalidate();
    }
    由于需要动态添加数据,也就是温度,这里我设置了6个时段的温度,每个时段三个小时。在setChartDataSet方法中添加了参数,dataSeries1.getLinePaint().setStrokeWidth(3);设置了绘制曲线的线宽度,dataSeries1.setLineStyle(XEnum.LineStyle.DASH)设置了曲线的类型。setChartLabels(List<String> weather)设置了横轴坐标表示什么意思,在这里表示时段和天气状态。
    

    第四个是图批注

    public void setChartAnchor(List<String> temps){
        //激活点击监听
                chart.ActiveListenItemClick();
                //为了让触发更灵敏,可以扩大5px的点击监听范围
                chart.extPointClickRange(5);        
                chart.showClikedFocus();        
    
                //批注
                List<AnchorDataPoint> mAnchorSet = new ArrayList<AnchorDataPoint>();
    
    
                AnchorDataPoint an2 = new AnchorDataPoint(0,0,XEnum.AnchorStyle.TOBOTTOM);
                an2.setBgColor(Color.WHITE);
                an2.setLineWidth(15);
                an2.setLineStyle(XEnum.LineStyle.DASH);
    
                an2.setTextColor(Color.WHITE);
                an2.setTextSize(55);
                an2.setAnchor(temps.get(0));
    
    
                AnchorDataPoint an3 = new AnchorDataPoint(0,1,XEnum.AnchorStyle.TOBOTTOM);
                an3.setBgColor(Color.WHITE);
                an3.setLineStyle(XEnum.LineStyle.DASH);
                an3.setTextColor(Color.WHITE);
                an3.setTextSize(55);
                an3.setAnchor(temps.get(1));
    
                //从点到底的标识线
                //从点到底的标识线
                AnchorDataPoint an4 = new AnchorDataPoint(0,2,XEnum.AnchorStyle.TOBOTTOM);
                an4.setBgColor(Color.WHITE);
                an4.setLineWidth(15);
                an4.setLineStyle(XEnum.LineStyle.DASH);
                an4.setTextColor(Color.WHITE);
                an4.setTextSize(55);
                an4.setAnchor(temps.get(2));
    
                AnchorDataPoint an5 = new AnchorDataPoint(0,3,XEnum.AnchorStyle.TOBOTTOM);
                an5.setBgColor(Color.WHITE);
                an5.setLineWidth(15);
                an5.setLineStyle(XEnum.LineStyle.DASH);
                an5.setTextColor(Color.WHITE);
                an5.setTextSize(55);
                an5.setAnchor(temps.get(3));
    
                AnchorDataPoint an6 = new AnchorDataPoint(0,4,XEnum.AnchorStyle.TOBOTTOM);
                an6.setBgColor(Color.WHITE);
                an6.setLineWidth(15);
                an6.setLineStyle(XEnum.LineStyle.DASH);
                an6.setTextColor(Color.WHITE);
                an6.setTextSize(55);
                an6.setAnchor(temps.get(4));
    
                AnchorDataPoint an7 = new AnchorDataPoint(0,5,XEnum.AnchorStyle.TOBOTTOM);
                an7.setBgColor(Color.WHITE);
                an7.setLineWidth(15);
                an7.setLineStyle(XEnum.LineStyle.DASH);
                an7.setTextColor(Color.WHITE);
                an7.setTextSize(55);
                an7.setAnchor(temps.get(5));
    
                mAnchorSet.add(an2);
                mAnchorSet.add(an3);
                mAnchorSet.add(an4);
                mAnchorSet.add(an5);
                mAnchorSet.add(an6);
                mAnchorSet.add(an7);
                chart.setAnchorDataPoint(mAnchorSet);       
    
                this.invalidate();
    }
    

    an2.setBgColor(Color.WHITE);
    an2.setLineWidth(15);
    an2.setLineStyle(XEnum.LineStyle.DASH);
    an2.setTextColor(Color.WHITE);
    an2.setTextSize(55);
    an2.setAnchor(temps.get(0));
    上面第一行依然是设置背景色为白色,第二行是批注线的宽度,第三行是设置批注线为虚线,第四、五行设置了批注文字的颜色和大小,第六行则是将批注文字绑定到an2上。

    附上完整代码
    package com.example.springweather.customview;
    import java.util.ArrayList;
    import java.util.LinkedList;
    import java.util.List;
    import org.xclcharts.chart.PointD;
    import org.xclcharts.chart.SplineChart;
    import org.xclcharts.chart.SplineData;
    import org.xclcharts.common.DensityUtil;
    import org.xclcharts.renderer.XEnum;
    import org.xclcharts.renderer.info.AnchorDataPoint;
    import org.xclcharts.renderer.plot.PlotGrid;
    import org.xclcharts.view.ChartView;
    import org.xclcharts.view.GraphicalView;
    import com.example.springweather.R;
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.util.AttributeSet;
    import android.util.Log;
    public class SplineChartView extends GraphicalView {
    private SplineChart chart = new SplineChart();
    //分类轴标签集合
    private LinkedList labels = new LinkedList();
    private LinkedList chartData = new LinkedList();
    Paint pToolTip = new Paint(Paint.ANTI_ALIAS_FLAG);

    public SplineChartView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        initView();
    }
    
    public SplineChartView(Context context, AttributeSet attrs){   
        super(context, attrs);   
        initView();
     }
    
     public SplineChartView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            initView();
     }
    
    @Override
    public void refreshChart() {
        super.refreshChart();
        labels.clear();
        chartData.clear();
    }
    
    
     private void initView()
     {
            List<String> weather=new ArrayList<String>();
            for(int i=0;i<6;i++){
                weather.add("晴");
            }
            List<String> temps=new ArrayList<String>();
            for(int i=0;i<6;i++){
                temps.add("1");
            }
            setChartLabels(weather);
            setChartDataSet(temps);
            setChartAnchor(temps);
    
            chartRender();
     }
    
    
    @Override  
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
        super.onSizeChanged(w, h, oldw, oldh);  
       //图所占范围大小
        chart.setChartRange(w,h);
    }               
    
    protected int[] getBarLnDefaultSpadding()
    {
        int [] ltrb = new int[4];
        ltrb[0] = DensityUtil.dip2px(getContext(), 0); //left   
        ltrb[1] = DensityUtil.dip2px(getContext(), 0); //top    
        ltrb[2] = DensityUtil.dip2px(getContext(), 0); //right  
        ltrb[3] = DensityUtil.dip2px(getContext(), 30); //bottom                        
        return ltrb;
    }
    private void chartRender()
    {
        try {
    
            //设置绘图区默认缩进px值,留置空间显示Axis,Axistitle....     
            int [] ltrb = getBarLnDefaultSpadding();
            chart.setPadding(ltrb[0] + DensityUtil.dip2px(this.getContext(), 20), ltrb[1],
                        ltrb[2]+DensityUtil.dip2px(this.getContext(), 30), ltrb[3]);    
    
    
    
    
            //显示边框
            chart.showRoundBorder();
    
            //数据源   
            chart.setCategories(labels);
            chart.setDataSource(chartData);
        //  chart.setCustomLines(mCustomLineDataset);
    
            //坐标系
            //数据轴最大值
            chart.getDataAxis().setAxisMax(40);
            chart.getDataAxis().setAxisMin(-40);
            //数据轴刻度间隔
            chart.getDataAxis().setAxisSteps(2);
    
            //标签轴最大值
            chart.setCategoryAxisMax(5);    
            //标签轴最小值
            chart.setCategoryAxisMin(0);    
    
    
            //背景网格
            PlotGrid plot = chart.getPlotGrid();        
            plot.hideHorizontalLines();
            plot.hideVerticalLines();       
    
    
            chart.getPlotArea().setBackgroundColor(true, Color.GRAY);
    
    
            chart.getCategoryAxis().getAxisPaint().setColor(Color.WHITE);
            chart.getCategoryAxis().getAxisPaint().setTextSize(6);
            chart.getCategoryAxis().hideTickMarks();                    
            chart.getCategoryAxis().getTickLabelPaint().setColor(Color.WHITE);  
            chart.getCategoryAxis().getTickLabelPaint().setFakeBoldText(true);
            chart.getCategoryAxis().setTickLabelMargin(25);
            chart.getCategoryAxis().getTickLabelPaint().setTextSize(25);        
    
            //不使用精确计算,忽略Java计算误差,提高性能
            chart.disableHighPrecision();
    
            chart.disablePanMode();
            chart.hideBorder();
            chart.getPlotLegend().hide();
            chart.getDataAxis().hide();
    
    
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            Log.e("tag", e.toString());
        }
    }
    
    public void setChartDataSet(List<String> temps)
    {
        //线1的数据集
        List<PointD> linePoint1 = new ArrayList<PointD>();              
        linePoint1.add(new PointD(0d, Double.parseDouble(temps.get(0))));   
        linePoint1.add(new PointD(1d, Double.parseDouble(temps.get(1))));                   
        linePoint1.add(new PointD(2d, Double.parseDouble(temps.get(2))));               
        linePoint1.add(new PointD(3d, Double.parseDouble(temps.get(3))));               
        linePoint1.add(new PointD(4d, Double.parseDouble(temps.get(4))));
        linePoint1.add(new PointD(5d, Double.parseDouble(temps.get(5))));
    
        SplineData dataSeries1 = new SplineData("Go",linePoint1,
                Color.WHITE ); 
        //把线弄细点
        dataSeries1.getLinePaint().setStrokeWidth(3);
        dataSeries1.setLineStyle(XEnum.LineStyle.DASH); 
        dataSeries1.setLabelVisible(false);                 
        dataSeries1.setDotStyle(XEnum.DotStyle.RING);
        dataSeries1.getDotPaint().setColor(getResources().getColor(R.color.white));             
        dataSeries1.getPlotLine().getPlotDot().setRingInnerColor(getResources().getColor(R.color.grey));
    
        chartData.add(dataSeries1); 
        this.invalidate();
    }
    
    public void setChartLabels(List<String> weather){
        String[] times={"20:00\n","23:00\n","2:00\n","5:00\n","8:00\n","11:00\n"};
        for(int i=0;i<weather.size();i++){
            labels.add(times[i]+weather.get(i));
        }
        this.invalidate();
    }
    
    
    public void setChartAnchor(List<String> temps){
        //激活点击监听
                chart.ActiveListenItemClick();
                //为了让触发更灵敏,可以扩大5px的点击监听范围
                chart.extPointClickRange(5);        
                chart.showClikedFocus();        
    
                //批注
                List<AnchorDataPoint> mAnchorSet = new ArrayList<AnchorDataPoint>();
    
    
                AnchorDataPoint an2 = new AnchorDataPoint(0,0,XEnum.AnchorStyle.TOBOTTOM);
                an2.setBgColor(Color.WHITE);
                an2.setLineWidth(15);
                an2.setLineStyle(XEnum.LineStyle.DASH);
    
                an2.setTextColor(Color.WHITE);
                an2.setTextSize(55);
                an2.setAnchor(temps.get(0));
    
    
                AnchorDataPoint an3 = new AnchorDataPoint(0,1,XEnum.AnchorStyle.TOBOTTOM);
                an3.setBgColor(Color.WHITE);
                an3.setLineStyle(XEnum.LineStyle.DASH);
                an3.setTextColor(Color.WHITE);
                an3.setTextSize(55);
                an3.setAnchor(temps.get(1));
    
                //从点到底的标识线
                //从点到底的标识线
                AnchorDataPoint an4 = new AnchorDataPoint(0,2,XEnum.AnchorStyle.TOBOTTOM);
                an4.setBgColor(Color.WHITE);
                an4.setLineWidth(15);
                an4.setLineStyle(XEnum.LineStyle.DASH);
                an4.setTextColor(Color.WHITE);
                an4.setTextSize(55);
                an4.setAnchor(temps.get(2));
    
                AnchorDataPoint an5 = new AnchorDataPoint(0,3,XEnum.AnchorStyle.TOBOTTOM);
                an5.setBgColor(Color.WHITE);
                an5.setLineWidth(15);
                an5.setLineStyle(XEnum.LineStyle.DASH);
                an5.setTextColor(Color.WHITE);
                an5.setTextSize(55);
                an5.setAnchor(temps.get(3));
    
                AnchorDataPoint an6 = new AnchorDataPoint(0,4,XEnum.AnchorStyle.TOBOTTOM);
                an6.setBgColor(Color.WHITE);
                an6.setLineWidth(15);
                an6.setLineStyle(XEnum.LineStyle.DASH);
                an6.setTextColor(Color.WHITE);
                an6.setTextSize(55);
                an6.setAnchor(temps.get(4));
    
                AnchorDataPoint an7 = new AnchorDataPoint(0,5,XEnum.AnchorStyle.TOBOTTOM);
                an7.setBgColor(Color.WHITE);
                an7.setLineWidth(15);
                an7.setLineStyle(XEnum.LineStyle.DASH);
                an7.setTextColor(Color.WHITE);
                an7.setTextSize(55);
                an7.setAnchor(temps.get(5));
    
                mAnchorSet.add(an2);
                mAnchorSet.add(an3);
                mAnchorSet.add(an4);
                mAnchorSet.add(an5);
                mAnchorSet.add(an6);
                mAnchorSet.add(an7);
                chart.setAnchorDataPoint(mAnchorSet);       
    
                this.invalidate();
    }
    
    @Override
    public void render(Canvas canvas) {
        try{
            canvas.drawColor(Color.GRAY);
            chart.render(canvas);
        } catch (Exception e){
            Log.e("tag", e.toString());
        }
    }
    

    }

    展开全文
  • HTML 绘制曲线图

    万次阅读 2019-01-18 09:23:59
    怎么样画一个漂亮的HTML曲线图

    先上链接资源

    非常漂亮的HTML5数据曲线走势图表样式代码
    10款绚丽实用的HTML5图表动画应用
    优秀的图表JS插件

    复制 粘贴 删库 跑路


    一点题外话

     过去钟繇评价荀攸:我每有所行,反复思惟,自谓无以易;以咨公达,辄复过人意。
     身边总有人在某些方面比自己强,本当にうれしい


    开发总结

    1. Echart开发总结:
       Echart所绘制的区域及其父类,包括html、body都必须指定style=“height: xxx%”
       如果不指定会报告Echart Can’t get dom width or height错误。网上有很多帖子都不解决问题,坑人的,就这么一个简单的前段框架,baidu还不至于蠢到兼容性很差
      上我移植好的代码,注意从html中的 style=“height: 100%”
    <!DOCTYPE html>
    <html lang="en" style="height: 100%">
      <head>
        <meta charset="utf-8">
        <title>用户参数配置</title>
        <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="">
        <meta name="author" content="">
    
        <link rel="stylesheet" type="text/css" href="../lib/bootstrap/css/bootstrap.css">
        
        <link rel="stylesheet" type="text/css" href="../stylesheets/theme.css">
        <link rel="stylesheet" href="../lib/font-awesome/css/font-awesome.css">
    
        <script src="../lib/jquery-1.7.2.min.js" type="text/javascript"></script>
    	<!-- Demo page code -->
    	
        <style type="text/css">
            #line-chart {
                height:300px;
                width:800px;
                margin: 0px auto;
                margin-top: 1em;
            }
            .brand { font-family: georgia, serif; }
            .brand .first {
                color: #ccc;
                font-style: italic;
            }
            .brand .second {
                color: #fff;
                font-weight: bold;
            }
        </style>
    
        <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
        <!--[if lt IE 9]>
          <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    
        <!-- Le fav and touch icons -->
        <link rel="shortcut icon" href="../assets/ico/favicon.ico">
        <link rel="apple-touch-icon-precomposed" sizes="144x144" href="../../assets/ico/apple-touch-icon-144-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="114x114" href="../../assets/ico/apple-touch-icon-114-precomposed.png">
        <link rel="apple-touch-icon-precomposed" sizes="72x72" href="../../assets/ico/apple-touch-icon-72-precomposed.png">
        <link rel="apple-touch-icon-precomposed" href="../../assets/ico/apple-touch-icon-57-precomposed.png">
      </head>	
    
    <body style="height: 100%; margin: 0">
    
        <div class="navbar">
            <div class="navbar-inner">
                    <ul class="nav pull-right">
                        
                        <li><a href="#" class="hidden-phone visible-tablet visible-desktop" role="button">Settings</a></li>
                        <li id="fat-menu" class="dropdown">
                            <a href="#" role="button" class="dropdown-toggle" data-toggle="dropdown">
                                <i class="icon-user"></i> 用户
                                <i class="icon-caret-down"></i>
                            </a>
    
                            <ul class="dropdown-menu">
                                <li><a tabindex="-1" href="">我的账号</a></li>
                                <li class="divider"></li>
                                <li><a tabindex="-1" class="visible-phone" href="">Settings</a></li>
                                <li class="divider visible-phone"></li>
                                <li><a tabindex="-1" href="../index.html">退出</a></li>
                            </ul>
                        </li>
                        
                    </ul>
            </div>
        </div>
    	
    	
        <div class="sidebar-nav">
            <a href="#legal-menu" class="nav-header" data-toggle="collapse"><i class="icon-legal"></i>记录信息</a>
            <ul id="legal-menu" class="nav nav-list collapse">
                <li ><a href="hisRecord.html">历史记录</a></li>
    			<li ><a href="alamRecord.html">告警记录</a></li>		
            </ul>
        </div>
    
    
        <div class="content" style="height: 100%">
            
            <div class="header">
    
                <h1 class="page-title">用户参数</h1>
            </div>
            
                    <ul class="breadcrumb">
                <li><a href="">策略配置</a> <span class="divider">/</span></li>
                <li class="active">用户参数</li>
            </ul>
    	
    
           <div id="container" style="height: 80%"></div>
    	   <script type="text/javascript" src="../js/echarts.js"></script>
           <script type="text/javascript">
    			var dom = document.getElementById("container");
    			var myChart = echarts.init(dom);
    			var app = {};
    			option = null;
    			option = {
    				xAxis: {
    					type: 'category',
    					boundaryGap: false,
    					data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    				},
    				yAxis: {
    					type: 'value'
    				},
    				series: [{
    					data: [820, 932, 901, 934, 1290, 1330, 1320],
    					type: 'line',
    					areaStyle: {}
    				}]
    			};
    			;
    			if (option && typeof option === "object") {
    				myChart.setOption(option, true);
    			}
           </script>
    	</div>   
       </body>  
    </html>  
    

    Demo

    嵌入式linux基于boa cigic js Echart 的动态表格生成


    展开全文
  • 收益曲线图

    千次阅读 2018-01-16 20:13:32
    收益曲线图 布局: xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"

    收益曲线图


    布局:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.lantianbaiyunyk.asus.rikao_1_9.MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
    
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textColor="#888888"
                android:textSize="18sp"
                android:text="每年年化收益率(%)"
                />
    
            <com.lantianbaiyunyk.asus.rikao_1_9.AnnualyieIdView
                android:id="@+id/line"
                android:layout_width="match_parent"
                android:layout_height="200dip"
                android:layout_marginTop="10dip"
                android:layout_marginBottom="10dip" />
        </LinearLayout>
    
    </RelativeLayout>

    MainActivity:

    public class MainActivity extends Activity {
        private AnnualyieIdView annualyieldView;
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            annualyieldView=(AnnualyieIdView) findViewById(R.id.line);
            initdata();
        }
    
        private void initdata() {
            List<Float> yline=new ArrayList<Float>();
            yline.add(2.4f);
            yline.add(2.44f);
            yline.add(2.45f);
            yline.add(2.45f);
            yline.add(2.44f);
            yline.add(2.44f);
            yline.add(2.43f);
            annualyieldView.setDataY(yline);
        }
    }
    Math:
    public class Math {
        public static float initData(float a){
    
            if (2.40f<=a&&a<2.41f) {
                a=540f-540f/(a/0.01f);
            }else if(2.41f<=a&&a<2.42f){
                a=480f-480f/(a/0.01f);
            }else if (2.42f<=a&&a<2.43f) {
                a=360f-360f/(a/0.01f);
            }else if (2.43f<=a&&a<2.44f) {
                a=270f-270f/(a/0.01f);
            }else if (2.44f<=a&&a<2.45f) {
                a=180f-180f/(a/0.01f);
            }else if (2.45f<=a&&a<2.46f) {
                a=90f-90f/(a/0.01f);
            }
    
            return a;
    
        }
    }

    AnnualyieIdView:
    public class AnnualyieIdView extends View{
        private Paint mTextPaint, mLinePaint,mPathPaint,mPointPaint;
        //柱状图的宽度
        private float mPaintRectWidth;
        //路径
        private Path mPath;
        //高跟宽
        private float mWidth, mHeight;
        //柱状图的数量
        private final float mCount = 6;
        //偏移量
        private final float offsets=1;
    
        private float mRectHeight;
        //x轴的坐标
        private List<Float> xline=new ArrayList<Float>();
        //Y轴的坐标
        private List<Float> yline=new ArrayList<Float>();
    
        //左边文字
        private float []x={2.46f,2.45f,2.44f,2.43f,2.42f,2.41f,2.40f};
        //底部文字
        private String [] day={"07-01","07-02","07-03","07-04","07-05","07-06","07-07"};
    
        public AnnualyieIdView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            initView();
    
        }
    
        public AnnualyieIdView(Context context, AttributeSet attrs) {
            super(context, attrs);
    
            initView();
        }
    
        public AnnualyieIdView(Context context) {
            super(context);
    
            initView();
        }
    
        private void initView() {
            //绘制线和文字的颜色
            mTextPaint = new Paint();
            mTextPaint.setAntiAlias(true);
            mTextPaint.setColor(Color.parseColor("#cccccc"));
            mTextPaint.setTextSize(25);
            mTextPaint.setStrokeWidth(1);
    
            //绘制折线图的点
            mPointPaint= new Paint();
            mPointPaint.setAntiAlias(true);
            mPointPaint.setColor(Color.parseColor("#000000"));
            mPointPaint.setTextSize(25);
            mPointPaint.setStrokeWidth(5);
    
            //绘制柱状图的画笔
            mLinePaint = new Paint();
            mLinePaint.setAntiAlias(true);
    
            //绘制折线图的画笔
            mPathPaint= new Paint();
            mPathPaint.setAntiAlias(true);
            mPathPaint.setColor(Color.parseColor("#ff0000"));
            mPathPaint.setStyle(Paint.Style.STROKE);
    
            //折线图的路径
            mPath=new Path();
    
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth=(float)(getWidth()-getWidth()*0.1);
            mHeight=(float)(getHeight()-getHeight()*0.1);
            mRectHeight=(float)(getHeight()-getHeight()*0.1);
            mPaintRectWidth=(float) (mWidth*0.8/mCount);
            mLinePaint.setStrokeWidth(mPaintRectWidth);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            onDrawRect(canvas);
            onDrawLine(canvas);
            canvasPath(canvas);
        }
        //绘制6个矩形
        private void onDrawRect(Canvas canvas) {
            for (int i = 0; i < 7; i++) {
                if (i%2==0) {
                    mLinePaint.setColor(Color.parseColor("#eeeeee"));
                }else {
                    mLinePaint.setColor(Color.parseColor("#ece1f3"));
                }
                float left  =(float) (mWidth * 0.4 / 2 + mPaintRectWidth * i + offsets);
                float right=(float) (mWidth * 0.4 / 2 + mPaintRectWidth* (i + 1));
    
                canvas.drawRect(left,(float)(mRectHeight*0.01),right, mHeight, mLinePaint);
            }
    
        }
        //绘制网格线
        private void onDrawLine(Canvas canvas){
            //第一条线
            canvas.drawLine(mPaintRectWidth-mPaintRectWidth/2, (float)(mRectHeight*0.01), getWidth(),  (float)(mRectHeight*0.01), mTextPaint);
            //定义这里高度
            float height;
            //横七条
            for (float i = 0; i < 7; i++) {
                //从上到下
                if (i==0) {
                    height=i;
                }else {
                    height=mRectHeight*(i/6);
                    float size=mTextPaint.measureText(x[(int)i]+"");
                    //绘制线
                    canvas.drawLine(mPaintRectWidth+mPaintRectWidth/2, height, getWidth(),  height, mTextPaint);
                    //绘制左边Y轴的文字
                    canvas.drawText(x[(int)i]+"", (float)(mPaintRectWidth-mPaintRectWidth*0.35), height+size/5, mTextPaint);
                }
    
            }
            //竖七条
            canvas.drawLine((float) (mPaintRectWidth-mPaintRectWidth/2),0, (float) (mPaintRectWidth-mPaintRectWidth/2),  mHeight, mTextPaint);
            for (float i = 0; i < 7; i++) {
                //从左到右
                canvas.drawLine((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),0, (float) (mWidth * 0.4 / 2 + mPaintRectWidth * i),  mHeight, mTextPaint);
                //绘制底边的日期文字
                canvas.drawText(day[(int) i], (float) (mWidth * 0.34 / 2 + mPaintRectWidth * i), (float)(mHeight+mHeight*0.1), mTextPaint);
                //准备好下面折线图的X轴坐标
                xline.add((float) (mWidth * 0.4 / 2 + mPaintRectWidth * i));
            }
            //折线图的第一个点
            xline.add((float) (mPaintRectWidth-mPaintRectWidth/2));
    
    
    
        }
        //绘制折线路径
        public void canvasPath(Canvas canvas){
    
    
            for (int j = 0; j < yline.size(); j++) {
    
                float x=xline.get(j);
                float y =yline.get(j);
                float aftery=Math.initData(y);
                if (j==0) {
                    mPath.moveTo(x,aftery );
                }else{
    
                    mPath.lineTo(x,aftery );
                }
                canvas.drawPoint(x, aftery, mPointPaint);
                float size=mPointPaint.measureText(y+"");
                canvas.drawText(y+"", (float)(x-size/2), (float)(aftery+size*0.25), mPointPaint);
            }
            canvas.drawPath(mPath, mPathPaint);
        }
        //用于设置Y轴的坐标值
        public void setDataY( List<Float> yline) {
            this.yline.clear();
            this.yline=yline;
        }
        //一个更新UI的方法
        public void invalidata(){
            invalidate();
        }
    }



    展开全文
  • Android 自定义View之绘制折线图、曲线图。上一篇文章根据之前大学同学的一个需求画了一个矩形渐变对比效果图,这篇文章给大家分享一个绘制折线图和曲线图的案列。效果如下:
  • MPChartLib绘制曲线图

    千次阅读 2015-09-28 17:26:36
    关于android实现绘制曲线图或者折线图功能,有很多第三方架包,也可以自己画 ,不过不建议自己画,第一时间浪费掉了 ,第二性能还不一定好,既然有第三方的,为什么不直接使用第三方的呢? 刚开始我使用的是...
  • 图形报表很常用,因为展示数据比较直观,常见的形式有很多,如:折线、柱形、饼图、雷达、股票、还有一些3D效果的图表等。 Android中也有不少第三方图表库,但是很难兼容各种各样的需求。 如果第三方库不...
  • android 曲线图(自定义)

    千次阅读 2015-10-22 22:56:47
    想看下曲线的使用方法,先上网搜索了一下,按照步骤完成然后在本地无法运行起来,经过修改可以运行了。 先上效果:   接着上代码, 请往下看. 1.MainActivity.java package com.chart.activity; import ...
  • Flourish之动态曲线图

    2020-07-31 17:14:49
    我们总是会在网上看到一些动态曲线图,其实用Flourish工具制作它们十分简单。 首先打开网址: https://app.flourish.studio/@flourish/horserace 此网站是国外网站,访问速度有点慢,但不需要翻墙。 点击创建...
  • 前言 本文介绍基于安卓开源图表MPandroidChart实现后台自动绘制二维曲线图 MPandroidChart效果图 其他开源图表项目 – –
  • 发现最新的MPAndroidChart和以前版本的使用有一些差距,就写下了现在新版的使用方法 相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0...Android图表控件MPAndroidChart——曲线图LineCh
  • android曲线图

    千次阅读 2011-05-19 00:21:00
    import android.app.Activity; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint;
  • ↑关注 + 星标~有趣的不像个技术号每晚九点,我们准时相约大家好,我是朱小五昨天的次条给大家发了一个新华社的视频45秒看清多国疫情变化!(点击下即可观看)之前大家遇到的最多的...
  • 使用AChartEngine画动态曲线图

    千次阅读 2015-05-19 17:18:43
    转自:... AChartEngine是一个开源的Android图表库,可以用来画折线、平滑折线、饼图、直方等等。使用简单,功能强大。 AChartEngine官网:http://www.achartengine.org/ AChartEngine库文件
  • 统计图表之MPAndroidChart曲线图解说

    万次阅读 2014-12-17 15:10:40
    统计图表之MPAndroidChart曲线图解说
  • Android利用Achartengine实现实时曲线图

    千次阅读 2017-01-09 20:32:09
    也正是因为公司项目需要实时展现从BLE设备获取到的心电图数据,所以有机会对实时曲线图的实现过程进行了较深入的探究。本文会讲述两种实现方式,其中每种实现方式里都会包含两种展现方式(曲线图平移方向:左、右)...
  • 2.曲线展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3.曲线完善 3.1 图表背景、边框、网格线修改 3.2 X Y轴值的自定义 3.3 线条的渐变背景、值、点的修改 3.4 MarkerView的实现 3.5 X轴的...
  • 在Android中绘制曲线图

    千次阅读 2011-12-09 14:24:26
    应用程序的开发过程中,经常会遇到和曲线图打交道的情况,相比自己写代码绘制,无疑的,使用一些美观高效的开源库是一个更好的选择。目前开源的曲线图绘制工作有很多,本文以achartengine为例,介绍在Android系统下...
  • android自定义View之曲线图

    千次阅读 2015-05-28 14:49:32
    最近项目里要一个简单的曲线图来标识数据,开始以为很简单,android已经有那么多的开源图表库了,什么achartenginee,hellochart,mpandroidchart等等,下载Demo一找,都强大到有点不适合我这个小小的展示功能了,...
  • jfreechart曲线图

    千次阅读 2006-08-18 08:22:00
     //曲线图X轴提示  private String domain = "月份走势";  //曲线图Y轴提示  private String range = "应收余额";  //曲线图自标题  private String subtitleStr = "2005财年分析";  //创建时间数据源  //每...
  • QT简单曲线图绘制(基于QChart)

    千次阅读 2020-08-12 22:02:49
    本例指定一系列离散点,可绘制曲线图,并可将图表嵌入widget中(本例嵌入了mainwi) 效果如下: 本例曲线图绘制使用QT的QChart模块实现(QT5.7及其以上版本才有此功能),自行封装了Chart类, 调用如下: .pro工程...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 24,904
精华内容 9,961
关键字:

做曲线图的app