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(),求余弦值,切记,切记;

还有手机屏幕坐标系与数学坐标系是不同的哦:

   0--------------------------->X轴|  1  2   3   4|1||    坐标一区|2||3|VY轴

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 ); 
对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:以改变绘制的角度来实现旋转绘制
  }

两种方式的区别:

    用rotate,相当于采用了相同的绘制模板,所以绘制出来的文字等样式是相同的(其他条件不变的话,如角度、坐标),而采用角度叠加方式,所有的文字等都属于新样式绘制的(角度改变了绘制的坐标),所以绘制的文字效果可能是不同的;
直接这么说也许不太好懂,下面结合具体情况和代码再来看试试:
下边是自定义View中onDraw代码:
    @Overrideprotected 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替换}}

drawText代码:

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);}

drawIcon代码:

 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上的项目地址:点 我!


canvas应用之各种游戏转盘相关推荐

  1. php 设计五子棋游戏,基于js+canvas实现五子棋小游戏

    本文实例为大家分享了js+canvas实现五子棋小游戏的具体代码,供大家参考,具体内容如下 效果展示: 源码展示: 五子棋 * { margin: 0; padding: 0; } body { ma ...

  2. 使用jquery—Canvas实现html5小游戏——《坦克大战》

    目录 1.项目背景 2.项目展示 3.设计思路 3.1.坦克移动 3.2.坦克开火 3.3.击中坦克 4.实现代码 5.总结 1.项目背景 2021年春节期间在家无聊,正好又学过一些前端的知识,因此就 ...

  3. canvas刮刮卡游戏开发

    canvas刮刮卡游戏开发 先看效果: 一.基础知识-画布元素的使用 1 绘制线条 思路 在页面中添加画布元素 获取画布元素的上下文环境对象 使用上下文环境对象绘制图形,保存在内存中 绘制一个线条 / ...

  4. 用canvas整个打飞机游戏

    之前在当耐特的DEMO里看到个打飞机的游戏,然后就把他的图片和音频扒了了下来....自己凭着玩的心情重新写了一个.仅供娱乐哈......我没有用框架,所有js都是自己写的......所以就可以来当个简 ...

  5. JavaScript+ Canvas开发趣味小游戏《贪吃蛇》

    一.效果展示 二.<贪吃蛇>基本实现思路 蛇头部分+蛇身体部分:采用对象形式来存储坐标,并将每个坐标对象放到一个snake数组中,方便使用.设置每个方格宽度30px,高度30px,画布高度 ...

  6. canvas 绘制贪吃蛇游戏

    效果如下 代码 <!DOCTYPE html> <html lang="zh_CN"> <head><meta charset=" ...

  7. HTML5 Canvas 射击类小游戏 平滑的移动 思路

    这篇博客主要讲了如何处理HTML5 Canvas 游戏中的角色移动问题. 笔者这几天做了一个 HTML5 Canvas 的射击类小游戏,嗯,名字叫做<DroppingBalls>,大概就是 ...

  8. html打飞机游戏代码,利用HTML5 Canvas实现打飞机游戏

    这篇文章主要介绍了利用HTML5 Canvas制作一个简单的打飞机游戏,作者也给出了相关的Javascript代码,需要的朋友可以参考下 之前在当耐特的DEMO里看到个打飞机的游戏,然后就把他的图片和 ...

  9. canvas + JavaScript实现幸运大转盘

    HTML代码: <!doctype html> <html> <head> <meta charset="utf-8"> <t ...

  10. html中canvas动画游戏显示,【Fes】基于canvas的前端动画/游戏入门(一)

    前言 本系列虽说是基础教程,但这是相对动画/游戏领域来说,在前端领域算是中级教程了,不适合前端小白或萌新.阅读前请确保自己对前端三大件(JavaScript+CSS+HTML)的基础已经十分熟悉,而且 ...

最新文章

  1. 面试官:精通 Mybatis?请回答下这几个问题
  2. 嵌入式成长轨迹11 【嵌入式环境及基础】【Linux shell深入】【深入讨论】
  3. 八十六、从拓扑排序探究有向图
  4. javajs ---- 判断字符串中是否包含子串
  5. oracle滚动统计,sql – 按月滚动或运行Oracle总计
  6. vs2015安装vax助手
  7. Swarm创始人:强调BZZ主网上线不需要质押
  8. 你应该懂得的关于电脑配置冷知识
  9. 爬虫 and 数据分析 | 一万条b站评论看工作细胞
  10. Chromium内核和Webkit的关系到底是什么?
  11. 华为光纤猫HG8240破解,开启路由功能表
  12. C# 后台GC 的前因后果
  13. 数据分析:当回音哥唱music时,他在唱些什么~~~
  14. InnoDB Persistent Statistics问题
  15. 搭建网站用虚拟主机好还是云服务器好?
  16. tiny4412 裸机程序 八、重定位到DRAM及LCD实验
  17. 日语在线翻译网站大全
  18. Swiper轮播图插件之如何修改前进后退按钮swiper-button-prev和swiper-button-next的默认样式
  19. 4月10日服务器例行维护公告,4月10日服务器例行维护公告
  20. 2017年8月23日 星期三 --出埃及记 Exodus 29:2

热门文章

  1. DXperience12.2入门设置以及应用教程
  2. 源码多多- Discuz x2.5 版块的常用设置方法和技巧
  3. 操作系统实验及代码(全)
  4. 计算机毕业设计之答辩
  5. 固态硬盘在线测试软件,SSD检测工具(SSDlife Pro)
  6. CMM3 正式评估全过程
  7. c语言设计一个自动阅卷功能,程序阅卷论文,关于编程题自动阅卷系统的设计实现相关参考文献资料-免费论文范文...
  8. 二、Json对象、Json数组和Json字符串
  9. 孩子学Java编程_7个最适合儿童学习编程的应用程序(上)
  10. Eclipse安装SVN插件的方法