随机图形

前言 

最近写了2个自定义图形,随机矩形和漂浮的圆环,代码参考https://github.com/isqing/BubbleChart

随机矩形
漂浮的圆环

随机矩形

随机矩形最关键的是算随机的坐标,我计算的矩形左上角的x,y坐标,根据x,y坐标和矩形的宽高度绘制一个一个的小矩形

其实我计算的时候是有规律可循的,是一行一行的计算的,根据屏幕的宽度计算最大列数,根据个数计算最大行数,每行最少随机生成一个点的坐标,如果到最大行数还没到总个数,再次循环随机点,下面是计算的方法

public staticList getPoints(intw,inth,intmRectX,intmRectY,intmSpaceH,intamount){

List pointList=newArrayList<>();

intmaxRows =(int)Math.ceil(h/(mRectY+mSpaceH));//最大行数

intmaxCol =Math.min(5,w/mRectX);//最大列数

intmSum=0;//累计每次生成的个数

Map numberMap=newHashMap<>();

while(mSum

for(inti =0; i < maxRows; i++) {

intmPreRandom=0;//上次循环生成的值

if(numberMap.containsKey(i)){

mPreRandom=numberMap.get(i);

}

intmRandom =0;//随机生成一个的个数

if(maxCol>mPreRandom){

mRandom =newRandom().nextInt(maxCol-mPreRandom +1-1)+1;//生成1到maxCol,随机生成的每行的个数

}else{

mRandom=0;//当前行的个数超过最大个是

}

//当生成的随机数和之前的和大于图形总个数时

if(mSum + mRandom >= amount) {

mRandom = amount - mSum;

mSum = amount;

numberMap.put(i,mRandom+mPreRandom);

break;

}else{

mSum += mRandom;

numberMap.put(i,mRandom+mPreRandom);

}

}

}

for(inti=0;i

intcol=numberMap.get(i);//第i行的个数

intoverW=w;//计算剩余的宽度

floataverageW = w / col;//第一次取平均值

floatstartX=0;

floatendX=0;

floatmRandomX=0;

if(j==0){

startX=0;

endX=averageW- mRectX;

}else{

averageW=overW/(col-j);//计算剩余的平均宽度

startX = mRandomX+mRectX;

endX = mRandomX+mRectX + averageW - mRectX-10;//10为间隔

//                    Log.i("startX",startX+"==="+endX);

}

//计算y的范围

floatstartY=i*(mRectY+mSpaceH);

floatendY=(i+1)*(mRectY+mSpaceH)-mRectY;

mRandomX=startX + ((endX - startX) *newRandom().nextFloat());//x坐标

floatmRandomY =startY + ((endY - startY) *newRandom().nextFloat());//Y坐标

//                Log.i("mRandomX",mRandomX+"==="+mRectX+"==="+overW);

overW=(int)(w-(mRandomX+mRectX));

//                Log.i("overW",""+overW);

Point point=newPoint(mRandomX,mRandomY);

pointList.add(point);

}

}

returnpointList;

}

绘制随机图形

在onMeasure里面

intwidthP = DensityUtil.getScreenWidth(getContext());

intheightP = DensityUtil.getScreenHeight(getContext());

intheightZ1=((int)Math.ceil(hashOvalList.size()/4))*(mRectY+mSpaceH);

intheightZ2= (int)Math.ceil(hashOvalList.size()/(widthP/mRectX))*(mRectY+mSpaceH);

heightZ= Math.max(heightZ1,heightZ2)+mSpaceH;

if(heightZ<=0||heightZ

heightZ=heightP;

//            isHalfScreen=true;

}

setMeasuredDimension(widthP,heightZ);

chartPait=newPaint();

textPaint=newPaint();

//透明度动画

initAnimatorRed();

initAnimatorGreen();


drawRect主要是根据生成的坐标绘制矩形

for(inti =0; i

HashOval hashOval=hashOvalList.get(i);

Point point =pointList.get(i);

//画圆角矩形

floatleft =  point.getX();

floatrigth = point.getX() +mRectX;

floattop = point.getY();

floatbottom = point.getY() +mRectY;

if(isHalfScreen) {

top = point.getY()+marginTop;

bottom = point.getY() +mRectY+marginTop;

}

mRect=newRectF(left+pading, top+pading, rigth-pading, bottom-pading);

chartPait.setStyle(Paint.Style.FILL);//充满

chartPait.setColor(hashOval.getChartColor());

chartPait.setAntiAlias(true);// 设置画笔的锯齿效果

intred = (hashOval.getChartColor() &0xff0000) >>16;

intgreen = (hashOval.getChartColor() &0x00ff00) >>8;

intblue = (hashOval.getChartColor() &0x0000ff);

if(hashOval.getIsAlpha()==0) {

chartPait.setARGB(animatedAplaGreen, red, green, blue);

}else{

chartPait.setARGB(animatedAplaRed, red, green, blue);

}

canvas.drawRoundRect(mRect,20,20,chartPait);//第二个参数是x半径,第三个参数是y半径

//写字

Rect bounds =newRect();

textPaint.setStyle(Paint.Style.FILL);//充满

textPaint.setColor(hashOval.getTextColor());

textPaint.setTextSize(DensityUtil.dip2px(getContext(),hashOval.getTextSize()));

textPaint.setAntiAlias(true);// 设置画笔的锯齿效果

textPaint.getTextBounds(hashOval.getText(),0, hashOval.getText().length(), bounds);

inttextW = bounds.width();

inttextH = bounds.height();

//            Log.i("textw",textW+","+mRectX);

//            Log.i("textH",textH+","+mRectY);

floattLeft=left+(mRectX-textW)/2;

floattTop=top+(mRectY-textH);

String text=hashOval.getText();

if(text.length()>4){

text=text.substring(0,4);

textPaint.getTextBounds(text,0, text.length(), bounds);

textW = bounds.width();

textH = bounds.height();

tLeft=left+(mRectX-textW)/2;

tTop=top+(mRectY-textH);

}

inttextRed = (Color.WHITE&0xff0000) >>16;

inttextGreen = (Color.WHITE&0x00ff00) >>8;

inttextBlue = (Color.WHITE&0x0000ff);

if(hashOval.getIsAlpha()==0) {

textPaint.setARGB(animatedAplaGreen, textRed, textGreen, textBlue);

}else{

textPaint.setARGB(animatedAplaRed, textRed, textGreen, textBlue);

}

canvas.drawText(text,tLeft,tTop,textPaint);

}


点击事件

重写onTouchEvent事件中的MotionEvent.ACTION_DOWN调用setClick(event.getX(),event.getY());根据点击的坐标,判断点击的在哪个小矩形里

private voidsetClick(floatx,floaty){

for(inti =0; i

HashOval hashOval =hashOvalList.get(i);

Point point =pointList.get(i);

//矩形

floatleft =  point.getX();

floatrigth = point.getX() +mRectX;

floattop = point.getY();

floatbottom = point.getY() +mRectY;

if(isHalfScreen){

top = point.getY()+marginTop;

bottom = point.getY() +mRectY+marginTop;

}

if(x>left&xtop&y

//                Toast.makeText(getContext(),hashOval.getText(),Toast.LENGTH_SHORT).show();

onClickChartItem.setOnClickChartItem(hashOval);

}

}

}


漂浮的圆环

这里有参考其他人的方法,在屏幕上随机生成圆环,然后向角度的方向移动,偏移圆心,根据圆心画圆环,计算圆环是否碰到边界,可配置圆环的分配,加了一些绘制动画

定义一个类Ball

classBall {

intradius;// 半径

floatcx;// 圆心

floatcy;// 圆心

floatvx;// X轴速度

floatvy;// Y轴速度

Paintpaint;

// 移动

voidmove() {

//向角度的方向移动,偏移圆心

cx+=vx;

cy+=vy;

}

intleft() {

return(int) (cx-radius);

}

intright() {

return(int) (cx+radius);

}

intbottom() {

return(int) (cy+radius);

}

inttop() {

return(int) (cy-radius);

}

onMeasure初始化一些数据

mWidth=resolveSize(mWidth, widthMeasureSpec);

mHeight=resolveSize(mHeight, heightMeasureSpec);

setMeasuredDimension(mWidth,mHeight);

maxRadius=mWidth/12;

minRadius=maxRadius/2;

// 初始化圆的半径和圆心

for(inti=0; i

mBalls[i].radius=mRandom.nextInt(maxRadius+1-minRadius) +minRadius;

//            mBalls[i].mass = (int) (Math.PI * mBalls[i].radius * mBalls[i].radius);

// 初始化圆心的位置, x最小为 radius, 最大为mwidth- radius

mBalls[i].cx=mRandom.nextInt(mWidth-mBalls[i].radius) +mBalls[i].radius;

mBalls[i].cy=mRandom.nextInt(mHeight-mBalls[i].radius) +mBalls[i].radius;

}

cyclePaint=newPaint();

center= getWidth() /2;

mRadius= (int) (center-mStrokeWidth/2);

oval=newRectF(center-mRadius,center-mRadius,center+mRadius,center+mRadius);

centerTextPaint=newPaint();

centerTextRect=newRect();

centerTextPaint.getTextBounds(centerText,0,centerText.length(),centerTextRect);

dataPaint=newPaint();

initRingAnimator();

initCenterAnimator();

initDataAnimator();


drawRing画环,根据数据所占比例计算绘制的角度

floatstartPercent =0;

floatsweepPercent =0;

for(inti =0; i

floatbfb =dataList.get(i).getRingData() / sumData(dataList);

//            Log.i(TAG, dataList.get(i) + ", " + sumData(dataList) + "," + dataList.get(i).getRingData() / sumData(dataList));

sweepPercent = bfb *360;

//            Log.i(TAG, "sweepPercent: " + sweepPercent);

//第一段

cyclePaint.setAntiAlias(true);

cyclePaint.setStyle(Paint.Style.STROKE);

cyclePaint.setStrokeWidth(mStrokeWidth);

cyclePaint.setColor(dataList.get(i).getRingColor());

if(Math.min(sweepPercent -1,animatedRingValue- startPercent) >=0) {

canvas.drawArc(oval, startPercent, Math.min(sweepPercent -1,animatedRingValue- startPercent),false,cyclePaint);

//                drawText(canvas,sweepPercent/2+startPercent,dataList.get(i)+"",sweepPercent);

}

startPercent += sweepPercent;

}

drawDataText绘制环上的字,根据不同象限计算

dataPaint.setAntiAlias(true);

dataPaint.setStyle(Paint.Style.FILL);

dataPaint.setTextSize(dataTextSize);

dataPaint.setStrokeWidth(1);

//        dataPaint.setAlpha(animatedDataValue);

//        dataPaint.setColor(dataTextColor);

intred = (getDataTextColor() &0xff0000) >>16;

intgreen = (getDataTextColor() &0x00ff00) >>8;

intblue = (getDataTextColor() &0x0000ff);

dataPaint.setARGB(animatedDataValue, red, green, blue);

floatdataPre =0;

floatdataCurr =0;

for(inti =0; i

if(i ==0) {

dataPre =0;

}else{

dataPre += (dataList.get(i -1).getRingData() / sumData(dataList)) *360;

}

//            Log.i(TAG, "dataPre: " + dataPre);

dataCurr = (dataList.get(i).getRingData() / sumData(dataList)) *360+ dataPre;

//            Log.i(TAG, "dataCurr: " + dataCurr);

//一四象限

if(((dataPre + (dataCurr - dataPre) /2)>=0&&(dataPre + (dataCurr - dataPre) /2)<90)||((dataPre + (dataCurr - dataPre) /2)>=270&&(dataPre + (dataCurr - dataPre) /2)<360)){

PointF point2 = MathHelper.getInstance().calcArcEndPointXY(

ball.cx, ball.cy, ball.radius, dataPre + (dataCurr - dataPre) /2);

//标识2

DrawHelper.getInstance().drawRotateText(String.valueOf(dataList.get(i).getRingText()), point2.x, point2.y,0,

canvas,dataPaint);

}else{

//二三象限

PointF point2 = MathHelper.getInstance().calcArcEndPointXY(

ball.cx, ball.cy, ball.radius, dataPre + (dataCurr - dataPre) /2);

//标识2

DrawHelper.getInstance().drawRotateText(String.valueOf(dataList.get(i).getRingText()), point2.x, point2.y,0,

canvas,dataPaint);

}

}


在onDraw里面利用for循环绘制,判断环边界

// 先画出所有圆

for(inti =0; i

Ball ball =mBalls[i];

//            canvas.drawCircle(ball.cx, ball.cy, ball.radius, ball.paint);

center=(int) ball.cx;

oval=newRectF(ball.cx- ball.radius,ball.cy- ball.radius, ball.cx+ ball.radius, ball.cy+ ball.radius);

drawRing(canvas);

drawCenterText(canvas,ball);

drawDataText(canvas,ball);

}

// 球碰撞边界

for(inti =0; i

Ball ball =mBalls[i];

collisionDetectingAndChangeSpeed(ball);// 碰撞边界的计算

ball.move();// 移动

}

longstopTime = System.currentTimeMillis();

longrunTime = stopTime - startTime;

// 16毫秒执行一次

postInvalidateDelayed(Math.abs(runTime -16));

判断小球边界

public voidcollisionDetectingAndChangeSpeed(Ball ball) {

intleft = getLeft();

inttop = getTop();

intright = getRight();

intbottom = getBottom();

floatspeedX = ball.vx;

floatspeedY = ball.vy;

// 碰撞左右,X的速度取反。 speed的判断是防止重复检测碰撞,然后黏在墙上了=。=

if(ball.left() <= left && speedX <0) {

ball.vx= -ball.vx;

}else if(ball.top() <= top && speedY <0) {

ball.vy= -ball.vy;

}else if(ball.right() >= right && speedX >0) {

ball.vx= -ball.vx;

}else if(ball.bottom() >= bottom && speedY >0) {

ball.vy= -ball.vy;

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • The Inner Game of Tennis W Timothy Gallwey Jonathan Cape ...
    网事_79a3阅读 14,258评论 3 20
  • 文/简小白sky 曾经有一首叫《挑妈妈》的诗走红网络,令无数人潸然泪下。 你问我出生前在做什么/我答,我在天上挑妈...
    简小白sky阅读 3,273评论 4 12
  • 感恩天地滋养万物 感恩祖先慈悲智慧 感恩国家培养护佑 感恩父母养育之恩 感恩老师辛勤教导 感恩同仁关心帮助 感恩农...
    快乐小屋刘丽华阅读 1,781评论 0 0
  • C++的代码的组织,依赖的管理规定几乎为零。学习golang的时候,一上来就是看语法,看代码,在代码组织和依赖管理...
    linjinhe阅读 3,564评论 0 0