android 动态水球,Canvas 制作动态进度加载水球详解及实例代码
Canvas 动态进度加载水球
前言
之前看到一些球型的动态加载的效果,一直想自己动手做一个,正好这段时间重温了一个Canvas,所以就尝试了一下。
实现思路
关于水波的实现,使用了sin()函数,通过每一帧不断的移动sin()函数曲线,实现水波动态效果。然后,通过绘制圆形路径,进行clip(),实现球型效果。
sin()函数相关
这里说一下sin()函数的相关基础,对于绘制水波的影响。
看一下图,回顾一下中学sin()函数的基础。
从图中可以看出,当函数为sin(x)时,值域为[-1, 1],周期为2π。
当sin(x)乘以一个数,可以改变值域,也就是峰值,如下图:
系数大于1时曲线更陡峭,小于1大于0时曲线更缓。
当sin(x ± 某个数)时,实现曲线的左右移动,减时右移,加时左移。
当sin(x * 某个数)时,曲线的周期会变化,某个数大于1时,周期变短;某个数小于1大于0时,周期变长。
在一点,sin()是一个周期函数,所以只要不断的给它值,它就会周期变化。
好了,sin()的数学基础差不多了,接下来开始步入正题。
绘制 sin() 曲线
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
//画布属性
var mW = canvas.width = 700;
var mH = canvas.height = 300;
var lineWidth = 1;
//Sin 曲线属性
var sX = 0;
var sY = mH / 2;
var axisLength = mW; //轴长
var waveWidth = 0.011 ; //波浪宽度,数越小越宽
var waveHeight = 70; //波浪高度,数越大越高
ctx.lineWidth = lineWidth;
//画sin 曲线函数
var drawSin = function(xOffset){
ctx.save();
var points=[]; //用于存放绘制Sin曲线的点
ctx.beginPath();
//在整个轴长上取点
for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
//此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
var y = -Math.sin((sX + x) * waveWidth);
points.push([x, sY + y * waveHeight]);
ctx.lineTo(x, sY + y * waveHeight);
}
//封闭路径
ctx.lineTo(axisLength, mH);
ctx.lineTo(sX, mH);
ctx.lineTo(points[0][0],points[0][1]);
ctx.stroke()
ctx.restore();
};
drawSin()
此处通过waveWidth和waveHeight调节曲线的陡峭度和周期。
加入动态效果
var speed = 0.04; //波浪速度,数越大速度越快
var xOffset = 0; //波浪x偏移量
速度变量和x偏移变量
var y = -Math.sin((sX + x) * waveWidth + xOffset);
修改y点的函数。
var render = function(){
ctx.clearRect(0, 0, mW, mH);
drawSin(xOffset);
xOffset += speed; //形成动态效果
requestAnimationFrame(render);
}
render()
加入渲染。
百分比控制
因为要加入百分比不同的涨幅效果,所以要对y的坐标时行百分比控制修改。
var dY = mH * (1 - nowRange / 100 );
球型显示
这里需要用到clip()进行球型裁切显示。
ctx.beginPath();
ctx.arc(r, r, cR, 0, 2 * Math.PI);
ctx.clip();
其他
可以通过修改如下变量来修改曲线的形状以及速度:
var waveWidth = 0.015 ; //波浪宽度,数越小越宽
var waveHeight = 6; //波浪高度,数越大越高
var speed = 0.09; //波浪速度,数越大速度越快
完整代码
Document
#c{
margin: 0 auto;
display: block;
}
#r{
display: block;
margin: 0 auto;
}
#r::before{
color: black;
content: attr(min);
padding-right: 10px;
}
#r::after{
color: black;
content: attr(max);
padding-left: 10px;
}
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var range = document.getElementById('r');
//range控件信息
var rangeValue = range.value;
var nowRange = 0; //用于做一个临时的range
//画布属性
var mW = canvas.width = 250;
var mH = canvas.height = 250;
var lineWidth = 2;
//圆属性
var r = mH / 2; //圆心
var cR = r - 16 * lineWidth; //圆半径
//Sin 曲线属性
var sX = 0;
var sY = mH / 2;
var axisLength = mW; //轴长
var waveWidth = 0.015 ; //波浪宽度,数越小越宽
var waveHeight = 6; //波浪高度,数越大越高
var speed = 0.09; //波浪速度,数越大速度越快
var xOffset = 0; //波浪x偏移量
ctx.lineWidth = lineWidth;
//画圈函数
var IsdrawCircled = false;
var drawCircle = function(){
ctx.beginPath();
ctx.strokeStyle = '#1080d0';
ctx.arc(r, r, cR+5, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.arc(r, r, cR, 0, 2 * Math.PI);
ctx.clip();
}
//画sin 曲线函数
var drawSin = function(xOffset){
ctx.save();
var points=[]; //用于存放绘制Sin曲线的点
ctx.beginPath();
//在整个轴长上取点
for(var x = sX; x < sX + axisLength; x += 20 / axisLength){
//此处坐标(x,y)的取点,依靠公式 “振幅高*sin(x*振幅宽 + 振幅偏移量)”
var y = -Math.sin((sX + x) * waveWidth + xOffset);
var dY = mH * (1 - nowRange / 100 );
points.push([x, dY + y * waveHeight]);
ctx.lineTo(x, dY + y * waveHeight);
}
//封闭路径
ctx.lineTo(axisLength, mH);
ctx.lineTo(sX, mH);
ctx.lineTo(points[0][0],points[0][1]);
ctx.fillStyle = '#1c86d1';
ctx.fill();
ctx.restore();
};
//写百分比文本函数
var drawText = function(){
ctx.save();
var size = 0.4*cR;
ctx.font = size + 'px Microsoft Yahei';
ctx.textAlign = 'center';
ctx.fillStyle = "rgba(06, 85, 128, 0.8)";
ctx.fillText(~~nowRange + '%', r, r + size / 2);
ctx.restore();
};
var render = function(){
ctx.clearRect(0, 0, mW, mH);
rangeValue = range.value;
if(IsdrawCircled == false){
drawCircle();
}
if(nowRange <= rangeValue){
var tmp = 1;
nowRange += tmp;
}
if(nowRange > rangeValue){
var tmp = 1;
nowRange -= tmp;
}
drawSin(xOffset);
drawText();
xOffset += speed;
requestAnimationFrame(render);
}
render();
效果
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
android 动态水球,Canvas 制作动态进度加载水球详解及实例代码相关推荐
- android 图片横竖判断_Android横竖屏切换及其对应布局加载问题详解
本文为大家分享了Android横竖屏切换及其对应布局加载问题,供大家参考,具体内容如下 第一,横竖屏切换连带横竖屏布局问题: 如果要让软件在横竖屏之间切换,由于横竖屏的高宽会发生转换,有可能会要求不同 ...
- 新手必看:访问url到加载全过程详解(看完不会我吃shi)
新手必看:访问url到加载全过程详解(看完不会我吃shi) 1.放在前面:新手必须知道的那些概念 1.1 什么是IP.域名.主机名.url.服务器 1.2 http & https 1.3 O ...
- JVM--类加载器详解
42. JVM--类加载器详解 ● 类加载器子系统作用: 1. 类加载器子系统负责从文件系统或者网络中加载Class文件,class文件在文件开头有特定的文件标识. 2. ClassLoader只负责 ...
- JVM-类加载器 详解(手画多图)面试常问 绝对值得阅读!!!
受多种情况的影响,又开始看JVM 方面的知识. 1.Java 实在过于内卷,没法不往深了学. 2.面试题问的多,被迫学习. 3.纯粹的好奇. 很喜欢一句话:"八小时内谋生活,八小时外谋发展. ...
- php自动加载类与路由,PHP实现路由与类自动加载步骤详解
这次给大家带来PHP实现路由与类自动加载步骤详解,PHP实现路由与类自动加载步骤详解的注意事项有哪些,下面就是实战案例,一起来看一下. 项目目录如下 入口文件index.php<?php def ...
- Java类的加载过程详解 面试高频!!!值得收藏!!!
受多种情况的影响,又开始看JVM 方面的知识. 1.Java 实在过于内卷,没法不往深了学. 2.面试题问的多,被迫学习. 3.纯粹的好奇. 很喜欢一句话: 八小时内谋生活,八小时外谋发展. 望别日与 ...
- 中yeti不能加载_第二十章_类的加载过程详解
类的加载过程详解 概述 在 Java 中数据类型分为基本数据类型和引用数据类型.基本数据类型由虚拟机预先定义,引用数据类型则需要进行类的加载 按照 Java 虚拟机规范,从 Class 文件到加载到内 ...
- tableview插入刷新_iOS开发之UITableView与UISearchController实现搜索及上拉加载,下拉刷新实例代码...
废话不多说了,直接给大家贴代码了. 具体代码如下所示: #import "ViewController.h" #import "TuanGouModel.h" ...
- C 编译器、链接器、加载器详解
原文请见 C 编译器.链接器.加载器详解 0. 预编译 在编译 C++ 程序的预处理阶段,源程序中的所有常量表达式都需要首先计算并替换为对应的具体数值. C语言编译器在对源代码编译之前,还需要进一步的 ...
最新文章
- C++编程进阶2(编译器在类内默认生成的函数讨论以及纯虚析构函数)
- tomcat 显示访问的ip白名单
- ansible roles角色(模块化)详解
- Android当中layer-list使用来实现多个图层堆叠到一块儿
- python中range函数是什么意思_python里range是什么
- 如何关掉Microsoft Office Click-to-Run服务
- 50+企业数字化转型、管理的方法论,这本书到底有什么干货?
- Servlet学习笔记(四)之请求转发与重定向(RequestDispatcher与sendRedirect)
- 2008-03-17 淋湿的心情
- [Hadoop] - SSH免密码登录
- php 生成小程序码
- 新手传奇gm架设要学会的几个修改技巧
- C++多线程卡死问题--访问冲突未必崩溃
- 浙江大学计算机科学与技术学院导师,浙江大学计算机科学与技术学院导师介绍:杨莹春...
- 学生成绩管理系统完整版
- 二进制安装Kubernetes(k8s) v1.25.0 IPv4/IPv6双栈
- USB设备的VID与PID
- Python开发实习心得~
- 1至9填入九个方框内_把19这九个数字填在方框里
- 计算机科学与技术核心期刊和相关网站
热门文章
- org.springframework.util.xml.SimpleSaxErrorHandler warning org.xml.sax.SAXParseException; systemId:
- 计算机的流水线-----流水线的原理
- centos6 实现网站搭建
- 瑞萨开发记录04:按键控制数码管(R5F104FEA芯片)
- Java入门学习-使用Math,实现lg、平方、开方、round、floor、ceil的算法。
- Java的开方和次方Math.sqrt()方法和Math.pow()方法以及求解有多少种连续正整数之和为N的算法详解
- viso 画背景框_如何在visio中画虚线框以及将visio图形复制到word文档
- CSDN 博客板块升级规则
- Asp.net mvc partialView
- Web前端第四季(jQuery):四:301-jQuery基本过滤器(奇数和偶数)+302-实现隔行换色+401-祖先选择器和子代选择器