html中动画取⾊效果,Canvas中颜⾊过渡动画效果的实现在CSS3中,我们要想实现从A颜⾊到B颜⾊的过渡效果,是相当容易的,只要指定起⽌颜⾊,配合transition过渡或者animation动画都可以时间我们想要的效果。
但是,在中却没有这么简单,因为本质上是⼀个静态画布,要想实现颜⾊变化,需要JS去不断绘制,实现起来要⽐CSS实现⿇烦很多。再加上颜⾊值本⾝就不⼀定是纯粹的数值,更增加了我们实现的难度。
本⽂就将通过多个案例,逐步深⼊,介绍⼀些在Canvas中的颜⾊处理技巧,有些技巧说不定会让你⼤开眼界。
Canvas颜⾊动画硬实现
所谓“硬实现”,就是不通过“奇巧淫技”,按照正常逻辑,⼀条路⾛到底的实现⽅式。
例如,我们要在中实现⼀个蓝⾊到红⾊的动画效果,思路如下:
1. 获取蓝⾊和红⾊的RGB⾊值;
2. 使⽤定时器,配合运动算法,R,G,B数值同时变化产⽣变⾊。
具体如何实现,可以参见这个案例。您可以狠狠地点击这⾥:颜⾊数值变化下的颜⾊动画demo
实现的效果如下GIF截图(上⾯是Canvas实现,下⾯是CSS3实现,⽅便效果对⽐):
完整JS代码如下:var canvas = ElementById('canvas');
var context = Context('2d');
var width = canvas.width, height = canvas.height;
// 动画执⾏的帧数
var start = 0, frames = 200;
// 过渡颜⾊ 蓝⾊ 到 红⾊
var from = [0, 0, 255];
var to = [255, 0, 0];
// 动画算法,这⾥使⽤Cubic.easeOut算法
var cubicEaseOut = function(t, b, c, d) {
return c * ((t = t/d - 1) * t * t + 1) + b;
};
// 绘制⽅法
var draw = function () {
context.clearRect(0, 0, width, height);
// 计算此时r, g, b数值
var r = cubicEaseOut(start, from[0], to[0] - from[0], frames);
var g = cubicEaseOut(start, from[1], to[1] - from[1], frames);
var b = cubicEaseOut(start, from[2], to[2] - from[2], frames);
// 可以确定⾊值
context.fillStyle = 'rgb('+ [r, g, b].join() +')';
context.arc(width / 2, height / 2, height / 2, 0, 2 * Math.PI);
context.fill();
// 持续变化
start++;
if (start <= frames) {
requestAnimationFrame(draw);
}
};
draw();
“硬实现”的局限所在
“硬实现”虽然基本效果有了,但是也存在⼀些局限,主要就是我们前后变化的⾊值不⼀定正好就是RGB颜⾊,可能是#RRGGBB这种⼗六进制⾊值,或者hsl颜⾊,这个还好,我们可以⾊值转换下(转换⽅法参见“HEX⼗六进制与RGB, HSL颜⾊的相互转换”这篇⽂章);
还有可能颜⾊是半透明的RGBA或者HSLA颜⾊,这么也还⾏,咬咬⽛,也可以实现,不就是多⼀个透明度变化的数值参数嘛;然⽽,最怕的就是⾊值是147个颜⾊关键字之⼀,例如请实现blue到red的效果。是不是只能望码兴叹了。
⾊值转换⿇烦,关键字变化⽆能为⼒,有没有什么技巧可以⼀次性搞定呢?有!
任意颜⾊转RGB⾊值技巧
所有web浏览器有这么⼀个特性,当我们使⽤getComputedStyle原⽣接⼝去获取DOM元素的⾊值的时候,返回的全部都是RGB⾊值或者RGBA⾊值。
举个例⼦,如下JavaScript代码:var div = ateElement('div');
lor = 'red';
document.body.appendChild(div);
console.ComputedStyle(div).color);
结果是:rgb(255, 0, 0)
并不是'red'。
于是,借助浏览器特性,⽆论什么颜⾊值,想要在canvas中有动画效果,都不成问题了。我们可以封装⼀个任意⾊值转RGBA颜⾊的⽅法,如下:/**
* 任意颜⾊转RGBA⽅法
*/
var toRGBA = function (color) {
// 创建div元素并设置颜⾊
var div = ateElement('div');
lor = color;
document.body.appendChild(div);
/
/ 返回计算后的颜⾊值
var cssColor = ComputedStyle(div).color;
// div元素移除
veChild(div);
// 如果是RGB颜⾊,则转换成RGBA表⽰
var arrRGBA = cssColor.match(/\d+/g);
if (arrRGBA.length == 3) {
arrRGBA.push(1);
}
// 每⼀项转换成数值类型
return arrRGBA.map(function (value) {
return value * 1;
});
};
于是乎,关键字⾊值的转换效果实现也不在话下了,您可以狠狠地点击这⾥:canvas任意⾊值下的过渡动画demo
实现的是深天空蓝'deepskyblue'到佩奇粉'deeppink'颜⾊动画效果,如下GIF⽰意:
JavaScript代码如下:var canvas = ElementById('canvas'); var context = Context('2d');
var width = canvas.width, height = canvas.height;
// 动画执⾏的帧数
var start = 0, frames = 200;
// 过渡颜⾊ 天空蓝 到 佩奇粉
var from = toRGBA('deepskyblue');
var to = toRGBA('deeppink');
// 动画算法,这⾥使⽤Cubic.easeOut算法
var cubicEaseOut = function(t, b, c, d) {
return c * ((t = t/d - 1) * t * t + 1) + b;
};
// 绘制⽅法
var draw = function () {
context.clearRect(0, 0, width, height);
// 计算此时r, g, b, a数值
var r = cubicEaseOut(start, from[0], to[0] - from[0], frames);
var g = cubicEaseOut(start, from[1], to[1] - from[1], frames);
var b = cubicEaseOut(start, from[2], to[2] - from[2], frames);
var a = cubicEaseOut(start, from[3], to[3] - from[3], frames);
// 可以确定⾊值
context.fillStyle = 'rgba('+ [r, g, b, a].join() +')';
context.arc(width / 2, height / 2, height / 2, 0, 2 * Math.PI);
context.fill();
// 持续变化
start++;
if (start <= frames) {
requestAnimationFrame(draw);
}
};
draw();
依然存在的局限
⽬前Canvas中从A⾊到B⾊的过渡动画效果已经可以实现了,但是,如果我们的颜⾊变化是丰富的有层次的,则我们的实现⼜变得⿇烦了。
例如,要实现红橙黄绿青蓝紫7⾊渐变,且每种过渡所占时间都不⼀样,该怎么办?
如果是CSS3实现,则很简单,定义⼀个animation动画就可以,类似这样:@keyframes color {
0% { background-color: red; }
7% { background-color: orange; }
17% { background-color: yellow; }
22% { background-color: green; }
js控制css3动画触发42% { background-color: cyan; }
82% { background-color: blue; }
90% { background-color: purple; }
}
如果要在Canvas中实现,我去,不敢想象,代码估计会很啰嗦。有没有什么简单取巧的⽅法实现复杂颜⾊动画效果呢?有!
借助CSS3实现复杂canvas动画
⽆论是CSS3 transition过渡或者animation动画,我们都可以使⽤JS实时返回当前动画中的颜⾊值等CSS属性值,于是,我们根本就不需要在Canvas中“硬实现”动画效果,直接把DOM中的变化量实时赋值就好了。
效果如下GIF:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论