android自定义控件——画一个海底世界

本文介绍如何在Android自定义视图中绘制一个海底世界,包括使用Shader创建渐变背景、绘制动态游动的鲸鱼、设置路径让鲸鱼沿路径游泳,以及添加太阳和气泡元素。通过实例代码展示了Android图形绘制的技巧。
摘要由CSDN通过智能技术生成

欢迎关注我的公众号 “安安安安卓”,学习更多知识

读一本好书。 ——我说的

前面几篇文章我们分别讲了自定义控件中常用到的 Canvas、Paint、Path。本篇我们在前面几篇的基础上更进一步,绘制一篇海底世界的效果。

项目github地址

git入口

绘制过程

绘制背景

首先大海应该是蓝色的吧,而且应该是一个渐变色,那么根据 paint 篇的内容,我们便可以使用 paint.setShader 来实现,实现思路就是使用 Canvas.drawRect 方法绘制整个画布,画笔 Paint 设置一个 Shader,代码如下:

paintBack.shader = LinearGradient(
            measuredWidth / 3f,
            0f,
            measuredWidth * 2 / 3f,
            measuredHeight.toFloat(),
            Color.WHITE,
            Color.parseColor("#000055"),
            Shader.TileMode.CLAMP
        )
canvas.drawRect(background, paintBack)

效果大概这个样子

绘制鲸鱼

咳咳,鲸鱼这个东西我在百度上面找了一张图片

而后使用 ps 抠出了其中最漂亮的大蓝鲸,并且使用 ps 液化工具对蓝鲸的尾巴进行了处理,目的就是让蓝鲸在运动的过程中尾巴不停的摆动从而实现游泳的效果




代码:
 private val bitmaps = listOf<Bitmap>(
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish1),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish2),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish3),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish4),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish3),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish2),
        BitmapFactory.decodeResource(context.resources, R.drawable.bluefish1),
    )
 canvas.run {
            drawBitmap(bitmaps[bitmapIndex % bitmaps.size], 100f, 100f, paint)
            bitmapIndex++
            drawFishWithPath()
        }
实现效果:

虎鲸光能摆动尾巴还是不够的,我们还应有让他能做游泳的动作,最好能按照我们指定的路径来运动是最好的了

定义路径的核心代码
 fishPath.moveTo(100f, 100f)
        for (i in 0..20) {
            fishPath.apply {
                cubicTo(randowX(), randowY(), randowX(), randowY(), randowX(), randowY())
            }
        }
        fishPath.close()
画出路径效果

这里是有问题的,因为路径转向的时候有很多锐角,可想而知这样是不行的,虎鲸宝宝也不会这么游泳的对吧,这个后续再优化,目前重要的是实现效果

让鱼沿着路径动起来

这里要借助PathMeasure工具了

dstPath.reset()
        var stop = start+100f
        pathMeasure.getSegment(start, stop, dstPath, true)
        val matrix =  Matrix()
        pathMeasure.getMatrix(stop, matrix, (PathMeasure.POSITION_MATRIX_FLAG.or(PathMeasure.TANGENT_MATRIX_FLAG)))
        val bitmap = bitmaps[bitmapIndex % bitmaps.size]
        matrix.preTranslate(-bitmap.width / 2f, -bitmap.height / 2f)
        canvas.drawBitmap(bitmap, matrix, paint)

代码是通过pathMeasure.getSegment方法可以截取path,从而在path的某个位置绘制鲸鱼图片,因为能拿到path某个点的正切值,所以我们的鲸鱼可以始终做到沿着切线游泳

游泳效果:

悲剧的是,中间一时忘记录制屏幕,只能把最终效果图放上来了

画太阳和气泡

既然最终效果已经出来了,那么后面直接放画太阳和气泡的代码吧

画太阳

画太阳主要的点在于画周围的阳光。画阳光的时候我们将太阳弧度20等分,然后从两个等分点之间向外画三角就能实现我们的阳光效果了。

path.moveTo(radius + sunX, sunY)
        val degree = 3.14f * 2 / leafNum
        for (i in 1..leafNum) {
            val x1 = radius * cos(i * degree) + sunX
            val y1 = radius * sin(i * degree) + sunY

            val halfDegree = (i - 0.5) * degree
            val shineRadius = radius + Random.nextInt(50)
            val controllX = shineRadius * cos(halfDegree).toFloat() + sunX
            val controllY =  shineRadius * sin(halfDegree).toFloat() + sunY
            path.lineTo(controllX, controllY)
            path.lineTo(x1, y1)
        }
        path.close()
画气泡

我们使用RadiaGradient镜像渐变的方式实现气泡效果,要注意的点是镜像渐变的颜色中间点不要选在圆心,否则会很难看

paint.shader=RadialGradient(cycleX+40,cycleY-40,radius+300, Color.WHITE,Color.GREEN,Shader.TileMode.CLAMP)
        canvas.drawCircle(cycleX, cycleY, radius, paint)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值