canvas数据直线流动
最近做平台优化的时候,有两个涉及到了canvas的需求,初有成效,在此分享下。先看需求效果(如下图 ps:用手机视频做的动图请忽略粗糙的观感)大概的意思是背景图中的城市空中有很多的数据衔接,之前就是单纯的一张效果背景图,现在产品让优化下,添加些动态效果,于是乎就想到了用canvas
首先声明以下所需要的变量
const numberLine = 56;//光线数量
const tail = 400; //光线长度
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
// 创建img对象 引如背景图
var img = new Image();
img.src = "./img/zhiNengSouSuo_back.png";
//设置画布长宽
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas绘制线条的时候是靠moveTo和lineTo属性,所以现在随机生成一组线条坐标
//n为传如的生成线条的个数
const createLine = n => {
const line = [];
for (let i = 0; i < n; ++i) {
line.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
s: Math.random() * 2 + 1
});
}
return line;
};
有了坐标点,然后开始绘制
const render = line => {
var bg = ctx.createPattern(img, "no-repeat");//createPattern() 方法在指定的方向内重复指定的元素。
ctx.fillStyle = bg;//fillStyle 属性设置或返回用于填充绘画的颜色、渐变或模式。
ctx.fillRect(0, 0, canvas.width, canvas.height);//定义了矩形当前的填充方式。
for (let l of line) {
renderLine(l);
}
};
const renderLine = l => {
//设置线条渐变
const grad = ctx.createLinearGradient(l.x, l.y, l.x, l.y + tail);
//添加颜色时直接时候能够色值的时候效果很生硬,所以用hsla色值
//简单介绍一下
//H(色调:Hue):衍生于色盘,其中0和360是红色,接近120的是绿色,240是蓝色;
//S(饱和度:Saturation):值为一个百分比数,0%代表灰度,100%代表最高饱和度;
//L(亮度:Lightness):值也为一个百分比数,其中0%代表最暗,50%为均值,100%表示最亮。
//A(透明度:Alpha):值为0~1之间的一个数,其中0代表不透明,1代表完全透明
const a = 1 - (canvas.height - l.y) / canvas.height * 0.8;
grad.addColorStop(0, `hsla(202,100%,100%,${a})`);
grad.addColorStop(1, "hsla(202,100%,50%,0)");
ctx.strokeStyle = grad;
ctx.beginPath();
ctx.lineWidth=2.5;
ctx.moveTo(l.x, l.y);
ctx.lineTo(l.x, l.y + tail);
ctx.stroke();
};
render(createLine(numberLine));
此时,可以看到的效果如下
接下来就需要让这些线段动起来,window有一个requestAnimationFrame方法,可以执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。
那么我们把他加进来
const render = line => {
var bg = ctx.createPattern(img, "no-repeat");//createPattern() 方法在指定的方向内重复指定的元素。
ctx.fillStyle = bg;//fillStyle 属性设置或返回用于填充绘画的颜色、渐变或模式。
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (let l of line) {
renderLine(l);
}
requestAnimationFrame(() => render(line));
};
然而刷新之后,线条并没有按预想的动起来,是因为我们么有去更新线条的moveTo和lineTo,那就再把这个加进来
const updateLine = l => {
//改变之前生成线条的坐标值
l.y -= l.s;
if (l.y < -tail) {
l.y = canvas.height;
}
};
将之放在render 中,每次renderLine之后就更新。如此数据线条就动起来了。完整代码可以到码云查看link