H5扇形
使用H5 canvas绘制的可交互扇形
requestAnimationFrame()
现有动画实现方式的不足
setTimeout和setInterval都不十分精确。为它们传入的第二个参数,实际上只是指定了把动画代码添加到浏览器UI线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。
css3动画有局限性,比如不是所有属性都能参与动画、动画缓动效果太少、无法完全控制动画过程等。
requestAnimationFrame()的优势
它告诉浏览器某些JavaScript代码将要执行动画,浏览器可以再运行某些代码后进行适当的优化,十分精确,没有css3的局限问题,可对所有属性操作,动画缓动效果可以依据缓动公式,十分丰富。
requestAnimationFrame()就是为了绘制canvas而生,再合适不过了。
代码实现
var requestAnimationFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame;
function updateProgress() {
var div = document.getElementById("status");
div.style.width = (parseInt(div.style.width, 10) + 5) + "%";
if(div.style.left != "100%") {
requestAnimationFrame(uploadProgress);
}
}
requestAnimationFrame(uploadProgress);
这里展示高级浏览器版本,兼容版请自行google。

easing缓冲动画
当初学习的时候的文章找不到了,大致的理解是:时间间隔一直,每个间隔运行的距离不同。
//iteration当前执行次数
//startValue执行开始的位置
//changeValue需要执行到的最终位置
//totalIterations需要执行的总次数
easing.easeOutBounce(iteration, startValue, changeValue, totalIterations);
看上面的参数能了解到,easing产生的是与直线的偏移,iteration表示的是偏移的延续,totalIterations表示的动画进行速度,startValue表示的是偏移的起始,changeValue表示的是偏移的量。
canvas方法
用到的一些canvas方法:
fillRect():在画布上绘制的矩形会填充指定颜色,由fillStyle属性指定
strokeRect():在画布上绘制的矩形会使用指定的颜色描边,由strokeStyle属性指定
clearRect():清除画布上的矩形区域
arc(x, y, radius, startAngle, endAngle, counterclockwise):以(x, y)为圆心绘制一条弧线,弧线半径为radius,起始和结束角度(用弧度表示)分别为startAngle和endAngle。最后一个参数表示是否按逆时针方向计算,值为false表示顺时针方向计算
lineTo(x, y):从上一点开始绘制一条直线,到(x, y)为止
drawImage(image, x, y, width, height):绘制图像到画布上,参数有3种,不一一介绍
save()与restore():保存上下文环境,操作...,恢复上次保存的上下文环境
这里只用到了这些,其他方法以后再介绍
css3 3D Transform
为了能更酷炫点,再加上css3的3D翻转效果
transform-style:指定嵌套元素如何在3D空间中呈现。它主要有两个属性值:flat和preserve-3d,它本身需要设置在父元素中,如果设置了transform-style值为preserve-3d,就不能设置overflow值为hidden
perspective:设置查看者的位置,并将可视内容映射到一个视锥上,继而投到一个2D视平面上,就是视距
perspective-origin:决定perspective属性的源点角度
transition:过渡效果
translateZ():使一个元素在三维空间移动
rotateY():指定一个元素围绕Y轴旋转,旋转的量被定义为指定的角度;如果值为正值,元素围绕Y轴顺时针旋转;反之,如果值为负值,元素围绕Y轴逆时针旋转
这里只用到了这些,不做详细介绍,太多了...
准备工作先进行到这里,接下来进行本例的讲解。
具体实现
参数数组
value:所占比重,百分之几
color:选中时颜色
highlight:选中时鼠标悬停时颜色
grey:未选中时颜色
greylight:未选中时鼠标悬停时颜色
我自己设置传入的参数:
var pieData = [
{
value: 0.32,
color:"#E8264b",
highlight: "#FF0049",
grey: "#5B5B5B",
greylight: "#333"
},
{
value: 0.13,
color: "#E64261",
highlight: "#FF5A5E",
grey: "#666",
greylight: "#333"
},
{
value: 0.13,
color: "#E05070",
highlight: "#FF5A5E",
grey: "#727272",
greylight: "#444"
},
{
value: 0.1,
color: "#E05D7D",
highlight: "#FF5A5E",
grey: "#7F7F7F",
greylight: "#444"
},
{
value: 0.09,
color: "#DB7691",
highlight: "#FF5A5E",
grey: "#8E8E8E",
greylight: "#666"
},
{
value: 0.09,
color: "#D6829C",
highlight: "#FF5A5E",
grey: "#999",
greylight: "#666"
},
{
value: 0.07,
color: "#D497AA",
highlight: "#FF5A5E",
grey: "#A5A5A5",
greylight: "#666"
},
{
value: 0.07,
color: "#D497AA",
highlight: "#FF5A5E",
grey: "#A5A5A5",
greylight: "#666"
}
];
绘制圆盘
function drawing (ctx, i) {//传入canvas的context
startValue = endValue;//每个扇形开始绘制的位置
endValue = startValue + Math.PI * pieData[i].value * 2;//每个扇形结束绘制的位置
ctx.beginPath();//开始绘制
ctx.arc(225, 225, radiusBig, startValue, endValue, false);//绘制扇形的弧线
ctx.lineTo(225,225);//绘制扇形链接圆心的两条直线
ctx.lineWidth = 2;//设置线的宽度
ctx.closePath();//结束绘制
ctx.fillStyle = pieData[i].grey;//设置扇形颜色
ctx.strokeStyle = "#fff";//设置线的颜色
ctx.fill();//填充
ctx.stroke();//描边
}
绘制文字及其位置
putIcon()用来计算绘制位置,r为半径,θ为角度,x = r + r sinθ, y = r - r cosθ,left和top的值为x和y。
(先写在这,本人不会画图,等学会再来画)
function drawThing(ctx) {
var i = 0;
var icon = undefined;
for( ; i < pieLen ; i++ ) {
drawing(ctx, i);
}
for(i = 0 ; i < pieLen ; i++ ) {
if( !effects[i].clicked ) {
icon = putIcon(i, 225, 140);
ctx.font = "bold 30px Arial";
ctx.textAlign = "center";
ctx.fillStyle = "#fff";
ctx.fillText(i + 1, icon.x, icon.y);
}
}
}
function putIcon(count, radiusW, radiusN) {
var values =
angle =
i = 0;
for( ; i < count; i++) {
values += pieData[i].value;
}
angle = Math.PI * 2 * (values + pieData[count].value / 2);
return {
x: Math.floor(radiusW + Math.sin(angle) * radiusN),
y: Math.floor(radiusW - Math.cos(angle) * radiusN)
}
}
确定交互区域
确定交互区域本人的思路是获取鼠标在视口上的(x ,y),再将这个点是否是可交互区域,能耗可能会比较大,没想到更好的做法,不过看到css3的clip-path属性可以实现类似效果,之后会研究下。
首先确定点击区域为外层大圆与内层小圆之间,公式:(x - r) (x - r) + (y - r) (y - r) = r * r;
直线方程:(x - x1)/(x2 - x1) = (y - y1)/(y2 - y1);
两点即可判断一条直线,先确定圆心点(r, r),再根据角度确定直线与圆交点(r + r sinθ, y = r - r cosθ)
得到的直线方程为:y = (x - r) (-r cosθ) / (r * sinθ) + r;
相邻两条直线建立二元一次不等式组,即可确定中间区域;

动画缓动
将easing与requestAnimationFrame()的结合使用,这是实现掉落效果的动画
function clickThing (ctx, i) {
var iteration = 0;
var totalIterations = 30;
var backX, backY;
var icon = putIcon(i, 225, 140, true);
var ty = icon.y - 25;
//立即执行的递归方法
(function miniIcon () {
ctx.clearRect(0, 0, 500, 500);
backY = easing.easeOutBounce(iteration, ty, 25, totalIterations);
ctx.font = "bold 30px Arial";
ctx.textAlign = "center";
ctx.fillStyle = "#fff";
ctx.fillText(i + 1, icon.x, backY);
if(iteration < totalIterations) {
iteration++;
requestAnimationFrame(function () {
miniIcon();
});
}
})();
}
使用css3实现3D翻转效果
最外层设置视距perspective: 2000px;perspective-origin:right top;
父级设置transition: all 0.7s ease-out;transform-style: preserve-3d;子级设置left和top为自身高宽的一半,使圆心位置为翻转中心点,back-c为背面,front-c为正面,改变rotatey(0deg)为rotatey(-180deg)表示从正面翻转180度到背面,反之亦然,translateZ()在这里用来表示层叠关系,一层盖在另一层上面。
.wrap {
perspective: 2000px;
perspective-origin:right top;
position: relative;
width: 450px;
height: 450px;
}
.wrap .wrap-box {
transition: all 0.7s ease-out;
transform-style: preserve-3d;
position: absolute;
top: 50%;
left: 50%;
}
#back-c {
position: absolute;
top: -225px;
left: -225px;
transform: translateZ(1px) rotatey(0deg);
}
#white-c {
position: absolute;
top: -225px;
left: -225px;
transform: translateZ(-2px) rotatey(0deg);
}
#front-c {
position: absolute;
top: -225px;
left: -225px;
transform: translateZ(-1px) rotatey(-180deg);
}
html内容
写了很多canvas,white-c是翻转之后盖在上面的白色小圆,每次绘制都要画一次,所以拿出来减少能耗,text-c也是出于这个原因,text-c用来绘制小动画,line-c是拿出来当触发器用的,没必要单拎出来,只是想区分用途才拿出来的。
<div class="content">
<div class="wrap">
<div class="wrap-box">
<canvas id="back-c" height="450" width="450"></canvas>
<canvas id="front-c" height="450" width="450"></canvas>
<canvas id="white-c" height="450" width="450"></canvas>
</div>
</div>
<canvas id="text-c" height="450" width="450"></canvas>
<canvas id="line-c" height="450" width="450"></canvas>
</div>
总结
花了点时间看了下自己的代码,找寻下迷失的自己,继续启程。
感兴趣的看官点击这里:coding:circle
本文转载自笔者的个人博客:Gaoxuefeng's Blog
H5扇形的更多相关文章
- 旺财速啃H5框架之Bootstrap(五)
在上一篇<<旺财速啃H5框架之Bootstrap(四)>>做了基本的框架,<<旺财速啃H5框架之Bootstrap(二)>>篇里也大体认识了bootst ...
- 旺财速啃H5框架之Bootstrap(四)
上一篇<<旺财速啃H5框架之Bootstrap(三)>>已经把导航做了,接下来搭建内容框架.... 对于不规整的网页,要做成自适应就有点玩大了.... 例如下面这种版式的页面. ...
- H5单页面手势滑屏切换原理
H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...
- 快速构建H5单页面切换骨架
在Web App和Hybrid App横行的时代,为了拥有更好的用户体验,单页面应用顺势而生,单页面应用简称`SPA`,即Single Page Application,就是只有一个HTML页面的应用 ...
- 07. Web大前端时代之:HTML5+CSS3入门系列~H5 地理位置
Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 源码:https://github.com/duniti ...
- 旺财速啃H5框架之Bootstrap(三)
好多天没有写了,继续走起 在上一篇<<旺财速啃H5框架之Bootstrap(二)>>中已经把CSS引入到页面中,接下来开始写页面. 首先有些问题要先处理了,问什么你要学boot ...
- H5程序员如何利用cordova开发跨平台应用
什么是Cordova? Cordova以前也叫PhoneGap,它提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头.麦克风等.Cordova还 ...
- H5项目开发分享——用Canvas合成文字
以前曾用Canvas合成.裁剪.图片等<用H5中的Canvas等技术制作海报>.这次用Canvas来画文字. 下图中"老王考到驾照后"这几个字是画在Canvas上的,与 ...
- MMORPG大型游戏设计与开发(攻击区域 扇形)
距离上次发布已经有了很长一段时间,期间由于各种原因没有更新这方面的技术分享,在这里深表遗憾.在MMO或其他的游戏中,会有针对各种形状的计算,通常在攻击区域里不会很复杂,常见的为矩形.圆形.扇形.今天分 ...
随机推荐
- Qt:QFile、QIODevice
QFile 0.说明 QFile是读写文件的类,这里的文件包括文本文件.二进制文件.资源文件. 通常情况下,文件读写使用QFile.QTextStream.QDataStream就够了. file n ...
- strtok:This function or variable may be unsafe.
https://jingyan.baidu.com/article/49711c616b8a1ffa441b7cdc.html
- ibv_close_device()函数
int ibv_close_device(struct ibv_context *context); 描述 函数用来关闭一个RDMA设备context: 注意: 函数不能用来释放与该Context关联 ...
- 简单认识java enum枚举
什么是枚举 枚举是java5中新增的特性,他是一个特殊的数据类型,他的特殊性在于他既是一种类类型,又比类类型多了安全性,简洁性,便捷性.java枚举类型是功能十分强大齐全的类,功能比其他语言中的对等物 ...
- java后端工程师学习路线
根据自己的经历和见识梳理了一份java后端工程师的学习路线(不含安卓方向),难免有局限性和疏漏,请在评论区反馈意见和建议! 很明显的是我的学习路线过于庞大了[尴尬],你可以认为这些只是我的一家之言,具 ...
- laravel 公共类json库封装
封装常用的接口响应: 创建 response.php 在app下创建如下文件下(目录及文件名可以自己设置) app/common/response.php,在内部补充如下代码: <?php /* ...
- jq 页面添加布局
要求: 1)实现如上图页面布局(10分) 2)实现选择城市所添加的内容追加到你喜欢哪个城市下(10分) 3)实现选择游戏所添加的内容追加到你喜欢哪款游戏下(10分) 4)新增的数据字体颜色设置为粉色( ...
- XSS攻击防范
前端安全系列之XSS攻击防范 1.使用textContent 2.使用HTML转义 把JS中的标签转成字符 3.对于链接跳转 禁止含有'javascript:'开头的字符 4.标签属性中含有恶意执行代 ...
- LGP2522题解
双倍经验题. 柯以看成是P3455的扩展. 首先这个范围内是数我们柯以用类似二维前缀和的思想,看成: \(ans(a,b,c,d)=ans(1,b,1,d)+ans(1,a-1,1,c-1)-ans( ...
- oneAPI DPC++学习资料和实验平台
DPC++ 一种新的异构平台,弥补了OPENCL 编写复杂的难题.基于SYCL 抽象层.基于SYCL 有多种实现,其中DPC++是相对成熟的方案. 书籍 由Intel工程师撰写的免费电子图书 Data ...