Canvas 仿百度贴吧客户端 loading 小球

前言

几天前在简书上看到在一篇文章《Android仿百度贴吧客户端Loading小球》,看了一下作者,他写了两个好玩的 demo,效果图如下:

今天趁着周末有空,用 H5 的 Canvas 仿了一下。这篇文章只实现第一个效果图。
这是我实现的效果:

实现原理

实现原理是参考简书的那篇文章,这里不再复述。现在我们来一步一步实现这样的效果。

第零步:画一个圆

源码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>百度贴吧客户端Loading小球</title>
    <style>
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script>
    var canvas = document.getElementById(‘canvas‘)
    var ctx = canvas.getContext(‘2d‘)
    canvas.width = 500
    canvas.height = 500

    var grid = canvas.width / 4
    var cx = canvas.width / 2 // 圆中心点 x 坐标
    var cy = canvas.height / 2 // 圆中心点 y 坐标

    function circle() {
        ctx.beginPath()
        ctx.arc(cx, cy, grid / 2, 0, 2 * Math.PI)
    }

    circle()
    ctx.stroke()
</script>
</body>
</html>

运行效果如下:

这个 demo 只涉及 Canvas 最简单的用法。

第一步:绘制蓝色的“贴”字

使用 ctx.fillText,在圆的中心绘制一个蓝色的“帖”字。文字粗体、水平居中。

代码如下:

function text(fillStyle) {
    var fontSize = size / 250 * 120
    ctx.font = ‘bold ‘ + fontSize + ‘px Arial‘
    ctx.textAlign = ‘center‘
    ctx.fillStyle = fillStyle
    ctx.fillText(‘贴‘, cx, cy + fontSize * 0.3)
}

text(‘#29a3fe‘)

效果如下:

第二步:绘制蓝色的波浪

var waveSize = size / 6 // 波浪大小
var x = 0 // 波浪位置偏移大小

function curve() {
    ctx.beginPath()
    ctx.moveTo(cx - size + x + size / 2, cy)
    ctx.quadraticCurveTo(cx - size + size / 4 + x + size / 2, cy - waveSize, cx - size + size / 2 + x + size / 2, cy)
    ctx.quadraticCurveTo(cx - size + size * 3 / 4 + x + size / 2, cy + waveSize, cx - size + size + x + size / 2, cy)

    ctx.quadraticCurveTo(cx + size / 4 + x + size / 2, cy - waveSize, cx + size / 2 + x + size / 2, cy)
    ctx.quadraticCurveTo(cx + size * 3 / 4 + x + size / 2, cy + waveSize, cx + size + x + size / 2, cy)
    ctx.lineTo(cx + size + x + size / 2, canvas.height)
    ctx.lineTo(cx - size + x + size / 2, canvas.height)
    ctx.lineTo(cx - size + x + size / 2, cy)
    ctx.closePath()
}

ctx.fillStyle = ‘#29a3fe‘
curve()
ctx.fill()

效果如下:

第三步:绘制白色的“贴”字

curve()
ctx.clip()
text(‘#f00‘)

第一句代码 curve() 创建了一个波浪形状的路径,和第三步不同的是,这里并没有使用 ctx.fill() 填充路径,而是使用了 ctx.clip() 裁剪路径,这样的话,后面绘制的路径(包括文字)只有在剪裁区域内才能显示。

为了和背景色区分开来,我把“贴”字改成红色。

效果如下:

第四步:绘制运动的波浪

function loop(){
    ctx.clearRect(0, 0, canvas.width, canvas.height)

    x -= 1.5
    x = x % size

    ctx.save()

    circle()
    ctx.stroke()

    ctx.fillStyle = ‘#29a3fe‘
    curve()
    ctx.fill()

    ctx.restore()

    requestAnimationFrame(loop)
}
loop()

效果如下:

第五步:整合前面的内容

效果如下:

第六步:剪裁圆形

把第零步的:

circle()
ctx.stroke()

改成:

circle()
ctx.clip()

这样就能把圆形外面的形状剪裁掉,然后就大功告成了。

最后,附上完整源码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        html,
        body {
            height: 100%;
        }
        canvas {
            border: 1px solid #ccc;
        }
    </style>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script>
    var canvas = document.getElementById(‘canvas‘)
    var ctx = canvas.getContext(‘2d‘)
    canvas.width = 500
    canvas.height = 500

    var size = canvas.width / 4 // 圆的大小
    var cx = canvas.width / 2 // 圆中心点 x 坐标
    var cy = canvas.height / 2 // 圆中心点 y 坐标
    var waveSize = size / 6 // 波浪大小
    var x = 0 // 波浪位置偏移大小

    function circle() {
        ctx.beginPath()
        ctx.arc(cx, cy, size / 2, 0, 2 * Math.PI)
    }

    function curve() {
        ctx.beginPath()
        ctx.moveTo(cx - size + x + size / 2, cy)
        ctx.quadraticCurveTo(cx - size + size / 4 + x + size / 2, cy - waveSize, cx - size + size / 2 + x + size / 2, cy)
        ctx.quadraticCurveTo(cx - size + size * 3 / 4 + x + size / 2, cy + waveSize, cx - size + size + x + size / 2, cy)

        ctx.quadraticCurveTo(cx + size / 4 + x + size / 2, cy - waveSize, cx + size / 2 + x + size / 2, cy)
        ctx.quadraticCurveTo(cx + size * 3 / 4 + x + size / 2, cy + waveSize, cx + size + x + size / 2, cy)
        ctx.lineTo(cx + size + x + size / 2, canvas.height)
        ctx.lineTo(cx - size + x + size / 2, canvas.height)
        ctx.lineTo(cx - size + x + size / 2, cy)
        ctx.closePath()
    }

    function text(fillStyle) {
        var fontSize = size / 250 * 120
        ctx.font = ‘bold ‘ + fontSize + ‘px Arial‘
        ctx.textAlign = ‘center‘
        ctx.fillStyle = fillStyle
        ctx.fillText(‘贴‘, cx, cy + fontSize * 0.3)
    }

    function loop(){
        ctx.clearRect(0, 0, canvas.width, canvas.height)

        x -= 1.5
        x = x % size

        ctx.save()

        circle()
        ctx.clip()

        text(‘#29a3fe‘)

        ctx.fillStyle = ‘#29a3fe‘
        curve()
        ctx.fill()

        curve()
        ctx.clip()

        text(‘#fff‘)

        ctx.restore()

        requestAnimationFrame(loop)
    }
    loop()
</script>
</body>
</html>
时间: 2024-11-07 17:14:14

Canvas 仿百度贴吧客户端 loading 小球的相关文章

在Android上仿百度贴吧客户端Loading图标小球

封面预览 前言 使用百度贴吧客户端的时候发发现加载的小动画挺有意思的,于是自己动手写写看.想学习自定义View以及自定义动画的小伙伴一定不要错过哦. 读者朋友需要有最基本的canvas绘图功底,比如画笔Paint的简单使用.Path如何画直线等简单的操作,不熟悉也没关系,下文带大家撸代码的时候会简单的讲一下. 此篇文章用到如下知识点: 1).自定义View的测量 2).自定义View属性的自定义及使用 3).Path绘制贝塞尔曲线 4).Canvas的裁剪 5).用ValueAnimator控制

【Android自定义View实战】之仿百度加载动画,一种优雅的Loading方式

转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53470872 本文出自[DylanAndroid的博客] Android自定义View实战之仿百度加载动画一种优雅的Loading方式 第一个仿百度加载动画用ObjectAnimator属性动画操作ImageView的属性方法实现 第二个仿百度加载动画第二种实现方式用ValueAnimator原生的ondraw方法实现 第三个扔球动画-水平旋转动画 第四个扔球动画-垂直旋转动

仿百度壁纸客户端(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化

仿百度壁纸客户端(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度壁纸客户端(二)--主页自定义ViewPager广告定时轮播图 仿百度壁纸客户端(三)--首页单向,双向事件冲突处理,壁纸列表的实现 仿百度壁纸客户端(四)--自定义上拉加载实现精选壁纸墙 仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 仿百度壁纸客

仿百度壁纸客户端(五)——实现搜索动画GestureDetector手势识别,动态更新搜索关键字

仿百度壁纸客户端(五)--实现搜索动画GestureDetector手势识别,动态更新搜索关键字 我们重新来看看这个效果 想实现这个逻辑,其实就是监听两个View的显示隐藏加上一点小动画,所以我们在布局上是这样的 search_fragment.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.c

仿百度壁纸客户端(三)——首页单向,双向事件冲突处理,壁纸列表的实现

仿百度壁纸客户端(三)--首页单向,双向事件冲突处理,壁纸列表的实现 上回把广告轮播图给实现了,今天就来把主页的大部分功能给实现了 一.ScrollView和ViewPager滑动事件冲突的解决办法 我们仔细想想,我们的主页架构,首先他是上下滑动的,所以这样要一个ScrollView,然后就是轮播图和其他内容了,这样的话,上下滑动有事件,轮播图也有事件,我们先看下xml的实现原理 home_fragment_xml <?xml version="1.0" encoding=&qu

高仿网易云音乐客户端的Home页面切换Tabhost-IT蓝豹

1.高仿网易云音乐客户端的Home页面切换Tabhost 高仿网易云音乐客户端的Home页面切换Tabhost,并且三角形是透明的,实现方式,自定义AnimTabsView继承 RelativeLayout 里面对当前选中的item 处理 三角形变成透明效果,即在onDraw 里面对三角形图片经行透明度处理,AnimTabsView提供 setOnAnimTabsItemViewChangeListener方法的onChange()用来监听点击切换tabhost. 下面主要是AnimTabsVi

仿优酷Android客户端图片左右滑动(自动滑动)

最终效果: 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent

浅谈asp.net通过本机cookie仿百度(google)实现搜索input框自动弹出搜索提示

对于通过用户输入关键词实现自动弹出相关搜索结果,这里本人给两种解决方案,用于两种不同的情形. 常见方法是在数据库里建一个用户搜索关系表,然后通过用户搜索框输入的关键字异步调用数据表中的相关数据,显示在一个隐藏div中. 第二种方式也就是我现在着重讨论的方式,适用于单个用户,基于此用户以往的搜索数据来实现搜索提示功能.技术关键是记录下用户的以往搜索数据,写入cookie,然后页面从用户本机cookie调用数据. ok,下面进入正题.本文主要讲实现步骤,代码可根据自己实际需要更改. 一,如何写入co

仿百度文库、豆丁文档在线文档带全套工具

这个是非常棒的一套在线文档分享系统源码,仿百度文库.豆丁文档网站源码,在这里完全免费提供给大家学习.在这里无需任何币就可以下载到非常多的精品源码,如果觉得好站长资源做的不错,请帮忙推荐给更多的站长朋友,并且里面还有一个设置说明图.    此套源码非常干净的,不像现在很多所谓VIP源码论坛放大量的垃圾广告文件在里面,更没有在里面加入垃圾加密广告代码.    安装以下软件前,先要在本机装好OFFICE2007   net2.0以上    windows2003 系统   退掉杀毒软件切忌! 1:安装