canvas应用之各种游戏转盘
来源:互联网 发布:java程序设计基础pdf 编辑:程序博客网 时间:2024/05/16 15:12
canvas应用之各种游戏转盘
转盘的画法网上有很多,好多都是H5或CSS方式实现的,我这里是Android中实现方式,也算是多种转盘形式集合吧,对canvas的绘制能力的提高会有一定的帮助。先来看下有关绘制过程中重要参数等的个人理解:
radian :弧度
angle :角度
所以由角度变成弧度,再变成余弦值:
double radians = Math.toRadians(30 + startAngle);
float cos = (float) (Math.cos(radians) * r + r);
也就是:double cos = (Math.cos(Math.toRadians(startAngle);
注意:只有变为弧度后才能使用Math.cos(),求余弦值,切记,切记;
还有手机屏幕坐标系与数学坐标系是不同的哦:
RectF rectF = new RectF(float left, float top, float right, float bottom);
rectF中的参数理解:左:左边线的X坐标值;上:上边线的Y坐标值;右:右边线的X坐标值;下:下边线的Y坐标值;
扇形圆弧的绘制:
canvas.drawArc(RectF rectF, float startAngle, float sweepAngle, boolean useCenter,Paint paint);
其会根据rectF中给的四个坐标,自动确定圆心点坐标,然后再根据 startAngle设置弧线的起始线位置, startAngle=0起点是x轴正方向,sweepAngle是绘制弧线的角度,若sweepAngle为正则逆时针绘制弧线,sweepAngle为负数则顺时针绘制弧线(注意使用数学极坐标方式),useCenter表示是否使用中心;
angle :角度
所以由角度变成弧度,再变成余弦值:
double radians = Math.toRadians(30 + startAngle);
float cos = (float) (Math.cos(radians) * r + r);
也就是:double cos = (Math.cos(Math.toRadians(startAngle);
注意:只有变为弧度后才能使用Math.cos(),求余弦值,切记,切记;
还有手机屏幕坐标系与数学坐标系是不同的哦:
0--------------------------->X轴| 1234|1|| 坐标一区|2||3|V Y轴
RectF rectF = new RectF(float left, float top, float right, float bottom);
rectF中的参数理解:左:左边线的X坐标值;上:上边线的Y坐标值;右:右边线的X坐标值;下:下边线的Y坐标值;
扇形圆弧的绘制:
canvas.drawArc(RectF rectF, float startAngle, float sweepAngle, boolean useCenter,Paint paint);
其会根据rectF中给的四个坐标,自动确定圆心点坐标,然后再根据 startAngle设置弧线的起始线位置, startAngle=0起点是x轴正方向,sweepAngle是绘制弧线的角度,若sweepAngle为正则逆时针绘制弧线,sweepAngle为负数则顺时针绘制弧线(注意使用数学极坐标方式),useCenter表示是否使用中心;
Paint字体属性的设置方法:
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
p.setTypeface( font );
p.setTypeface( font );
对paint等的理解:
mCanvas.drawText(char[] text, int index, int count, float x, float y,Paint paint)中,paint绘制的文字都是冲上的(文字竖直),无论你无论你是上下或是斜着写,所绘制的单个文字都是冲上的;
而mCanvas.drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,float vOffset, @NonNull Paint paint);文字会根据路径path的绘制方向,而随之改变文字的显示方向;hOffset表示"path的前端"处空出来的空间大小(值为正则增大间隙空间,负值则反向减小空间),vOffset表示"path垂直"方向偏移的大小(正值向内偏移,负值向外偏移);
对于旋转绘制问题,有两种方式:
方式一:
mCanvas.drawText(@NonNull String text, float x, float y, @NonNull Paint paint);
mCanvas.rotate(everyAngle ,r,r); //替换方式1:旋转的是带有文字的“纸——mCanvas”,此时笔(View的坐 标)是不动的
方式二:
for (int i = 0; i < size; i++) {
drawText(InitAngle + 3*halfAngle, strs[i],radius, textPaint, canvas, rectF);
InitAngle += everyAngle; //替换方式2:以改变绘制的角度来实现旋转绘制
}
两种方式的区别:
而mCanvas.drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,float vOffset, @NonNull Paint paint);文字会根据路径path的绘制方向,而随之改变文字的显示方向;hOffset表示"path的前端"处空出来的空间大小(值为正则增大间隙空间,负值则反向减小空间),vOffset表示"path垂直"方向偏移的大小(正值向内偏移,负值向外偏移);
对于旋转绘制问题,有两种方式:
方式一:
mCanvas.drawText(@NonNull String text, float x, float y, @NonNull Paint paint);
mCanvas.rotate(everyAngle ,r,r); //替换方式1:旋转的是带有文字的“纸——mCanvas”,此时笔(View的坐 标)是不动的
方式二:
for (int i = 0; i < size; i++) {
drawText(InitAngle + 3*halfAngle, strs[i],radius, textPaint, canvas, rectF);
InitAngle += everyAngle; //替换方式2:以改变绘制的角度来实现旋转绘制
}
两种方式的区别:
用rotate,相当于采用了相同的绘制模板,所以绘制出来的文字等样式是相同的(其他条件不变的话,如角度、坐标),而采用角度叠加方式,所有的文字等都属于新样式绘制的(角度改变了绘制的坐标),所以绘制的文字效果可能是不同的;
直接这么说也许不太好懂,下面结合具体情况和代码再来看试试:
下边是自定义View中onDraw代码:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); final int paddingLeft = getPaddingLeft(); final int paddingRight = getPaddingRight(); final int paddingTop = getPaddingTop(); final int paddingBottom = getPaddingBottom(); int width = getWidth() - paddingLeft - paddingRight; int height = getHeight() - paddingTop - paddingBottom; int MinValue = Math.min(width, height); radius = MinValue / 2; RectF rectF = new RectF(getPaddingLeft(), getPaddingTop(), width, height); float angle = InitAngle; //这里的扇形背景与文字或图片需要相差30度,因为文字和图片要在30度角处(背景中间处)显示 //扇形背景绘制 for (int i = 0; i < size; i++) { if (i % 2 == 0) { canvas.drawArc(rectF, angle, everyAngle, true, dPaint); } else { canvas.drawArc(rectF, angle, everyAngle, true, sPaint); } angle += everyAngle; } //图片和文字绘制 for (int i = 0; i < size; i++) { //在此处加3*halfAngle只是为了显示正确,这和直接给InitAngle赋值决定pos是不一样的// drawIcon(width / 2, height / 2, radius, InitAngle + 3*halfAngle, i, canvas); drawText(InitAngle + everyAngle, strs[i], radius, textPaint, canvas, rectF); InitAngle += everyAngle; //方式1:以改变绘制的角度来实现旋转绘制,可用方式1替换 } }
private void drawText(float startAngle, String string, int r, Paint mTextPaint, Canvas mCanvas, RectF mRange) {/************************************* 1 文字圆弧状显示 *********************************///设计思路:沿着弧线方向对字符串进行绘制,注意textPaint.setTextAlign(Paint.Align.CENTER);设定的绘制的起始位置值,这里字间距没办法修改 Path path = new Path(); path.addArc(mRange, startAngle, everyAngle); //startAngle就决定了初始位置// mTextPaint.setTextAlign(Paint.Align.LEFT);// float textWidth = mTextPaint.measureText(string);// //文字水平偏移量,偏移到扇形中间位置(作用与textPaint.setTextAlign(Paint.Align.CENTER)等同)// float hOffset = (float) (r * Math.PI / size - textWidth / 2); float vOffset = r / 4; mTextPaint.setTypeface(Typeface.create(Typeface.MONOSPACE, Typeface.NORMAL)); //字体设置 mCanvas.drawTextOnPath(string, path, 0, vOffset, mTextPaint); }
private void drawIcon(int xx, int yy, int mRadius, float startAngle, int i, Canvas mCanvas) { int imgWidth = mRadius / 4; float angle = (float) Math.toRadians(startAngle); float x = (float) (xx + mRadius / 2 * Math.cos(angle)); float y = (float) (yy + mRadius / 2 * Math.sin(angle)); // 确定绘制图片的位置 RectF rect = new RectF(x - imgWidth * 3 / 4, y - imgWidth * 3 / 4, x + imgWidth * 3 / 4, y + imgWidth * 3 / 4); Bitmap bitmap = bitmaps.get(i); mCanvas.drawBitmap(bitmap, null, rect, null); }
代码实现只需要替换drawText方法中代码即可:
/********************************* 2 文字横扫同向模式 ********************************///设计思路:采用直线型路径path由中心向外绘制每个字符串,字符串首字符与圆心距离用转盘内部小同心圆的半径作为限定, path的两个点坐标可由两圆半径算得 //使文字竖着摆放显示,(但文字方向有点问题) mTextPaint.setTextAlign(Paint.Align.CENTER); Rect bounds = new Rect(); mTextPaint.getTextBounds(string,0,1,bounds); int wordHeight = bounds.height(); Path path1 = new Path(); //分别计算x,y初始的坐标 double radians = Math.toRadians(startAngle + halfAngle); //startAngle的正负决定旋转方向,负为顺时针旋转 halfAngle为调整位置显示值 float bigX = (float) (Math.cos(radians) * r + r);//大圆坐标,此固定值在开发时不需要放到循环中 float bigY = r + (float) Math.sin(radians) * r; double cos = Math.cos(radians); double sin = Math.sin(radians); float smallR = r/3; //内圆半径,也是字符串与圆心的距离 //内部小圆x,y坐标 float smallX = (float)(cos * smallR + r); //小圆坐标 float smallY = (float) (sin * smallR + r);//采用从圆心向外发射画法// path1.moveTo(bigX,bigY); //采用直线路径法绘制文字,这里的hOffset1代表也可称为文字竖直偏移量// path1.lineTo(smallX,smallY); path1.moveTo(smallX,smallY); //设置文字显示方向倒转 path1.lineTo(bigX,bigY); mCanvas.drawTextOnPath(string, path1, 0, wordHeight/2, mTextPaint);
多状态显示型(字体还可能都是对齐摆放的) 横扫多变型(字体对齐和倾斜摆放都有)
drawText方法中代码如下:
/********************************** 3 文字横扫多变模式或多状态显示 ******************************///设计思路:通过给转盘添加同心小圆的方式,确定一条字符串的首个字符位置(以具体坐标定位),其他字符则根据手字符进行适当偏移生成 //该方式文字竖直显示1,但英文显示会有问题 Rect bounds = new Rect(); mTextPaint.getTextBounds(string.substring(0, 1), 0, 1, bounds); int wordHeight = bounds.height() + 20; //增大字间距 mTextPaint.setTextAlign(Paint.Align.CENTER); if (isClicked) { du = halfAngle; //du决定整体文字朝向,就是以该角度处的文字样式为模板,然后偏移到别的地方,就像是在固定一个地方写字,人不动而纸动 } double radians = Math.toRadians(startAngle + du); //startAngle的正负决定旋转方向,负为顺时针旋转 double cos = Math.cos(radians); double sin = Math.sin(radians); float smallR = r/3; //内部小圆x,y坐标 float x = (float)(cos * smallR + r); float y = (float) (sin * smallR + r);//采用从圆心向外发射画法 for (int j = string.length()-1;j >=0 ;j--) { //从后往前取文字,文字汇聚式阅读 mCanvas.drawText(string.substring(j, j + 1), (float) (x + wordHeight * cos * (string.length() - j)), (float) (y + wordHeight * sin * (string.length() - j)), textPaint); }//方式2:旋转的是带有文字的“纸——mCanvas”,此时笔(View的坐标)是不动的,可替换换方式1处代码// mCanvas.rotate(everyAngle ,r,r);
drawText方法中代码如下:
/************************************************* 4 文字发射状显示 ************************************************************///设计思路:采用每个字符串使用一个圆弧,并且每个圆弧都只放一个文字,该字符串的其他文字则根据该文字进行相对位置平移生成 Path path = new Path(); path.addArc(mRange, startAngle, everyAngle); //startAngle决定了绘制的初始位置,该位置的值可调整以适应扇形背景区域 Rect bounds = new Rect(); //此固定值在开发时不需要放到循环中 mTextPaint.getTextBounds(string.substring(0, 1), 0, 1, bounds); //14是增加的字间距,因为中英文的文字高度不同,会导致显示效果不均一,这里可以用定值替代 int wordHeight = bounds.height() + 14; //因绘制文字采用的是由中心向四周发射方式,此处指定vOffset相对path垂直向内偏移量(包括字间距) int i = 6; //为了使每串字符串都与圆心保持相同距离,此处采用倒序绘制文字 for (int j = string.length() - 1; j >= 0; j--) { //若hOffset和vOffset都为0时,该方法会让文字沿着Path路径绘制文本,hOffset参数指定相对path水平偏移,hOffset值为正数则向path正方向偏移,vOffset指定相对path垂直偏移,若vOffset值为正则向下向内偏移; mCanvas.drawTextOnPath(string.substring(j, j + 1), path,0, wordHeight * i--, textPaint); }// mCanvas.rotate(everyAngle ,r,r); //用于替代InitAngle += everyAngle;的第二种实现方式 }
关键要看需求中文字的显示方向和方式都是什么样的,当然大家要是有好的实现和例子可以告诉我哦!
最后附上git上的项目地址:点 我!
1 0
- canvas应用之各种游戏转盘
- canvas-转盘
- HTML5之CANVAS学习,实现抽奖转盘
- Android之仿腾讯游戏转盘抽奖
- HTML5(九)canvas操作文字实例之转盘
- html5<canvas操作文字实例之转盘>
- canvas游戏开发学习之四:应用图像
- canvas绘制旋转转盘
- 游戏制作之canvas
- html5 canvas 绘制大转盘类似的游戏,并填充文
- 转盘抽奖游戏
- 微信大转盘游戏
- 大转盘游戏
- 游戏转盘html5
- 大转盘游戏
- 大转盘游戏
- canvas标签应用 简单"贪吃蛇"游戏
- Android游戏开发教程之四:Canvas与Paint的应用实例
- 图的概念
- 释疑の生产订单作业价格重估-CON2
- Android RecyclerView的使用
- (PHP面试)数猴子(原型:约瑟夫环)
- M-Openstack入门指导
- canvas应用之各种游戏转盘
- pip报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xb1 in position 7: ordinal not in range(12
- web的数据传递(jsp,servlet和数据库)
- 西安落户政策2017.3.1
- C#通用类库--农历类(很全面)
- hello world
- 3.3女儿节
- HPUOJ---2017寒假训练--专题2/N-畅通工程再续(最小生成树)
- CCF201609-4 交通规划(100分)