Для малювання лінії у canvas використовується метод lineTo().
Найпростіший спосіб намалювати блискавку це лінія яка у випадковому порядку має зміщення вліво або право. Тобто малюємо ламану криву лінії, і від цієї лінії також малюємо інші криві лінії.
Функція Lightning приймає параметри: елемент canvas, координати полотна x і y з яких почнеться малюватися блискавка. Дочірна функція random генерує ціле випадкове число за допомогою Math.random(). Дочірна функція createLightning створює масив з координатами лінії блискавки.
<canvas id="canva1" width="400" height="400"></canvas>
function Lightning(canvas,x,y){
//функція випадкового числа від min до max
function random(min,max){return parseInt(Math.random()*(max-min)+min);}
//функція створення блискавки
function createLightning(x,y){
var res=[];
for(var i=0, sx=x, sy=y, l=random(5,30);i<l;i++){
res.push({x:sx, y:sy});
sx+=Math.random()>0.5?random(5,10):0-random(5,10);
sy+=random(5,15);
}
return res;
}
var ctx=canvas.getContext('2d');
var path=[];
//створюємо першу лінії блискавки
path[0]=createLightning(x,y);
//створюємо інші лінії блискавки від 1 до 3
for(var i=0, j, z, l=random(1,3);i<l;i++){
j=random(0, path.length-1);
z=random(0, path[j].length-1);
path[path.length]=createLightning(path[j][z].x, path[j][z].y);
}
//очищаємо полотно canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//малюємо блискавки на полотні
for(var i=0; i<path.length;i++){
//ширина лінії блискавки
ctx.lineWidth=path.length-i;
//колір блискавки
ctx.strokeStyle='#C6D4DC';
ctx.beginPath();
ctx.moveTo(path[i][0].x, path[i][0].y);
for(var j=1;j<path[i].length;j++){
ctx.lineTo(path[i][j].x, path[i][j].y);
}
ctx.stroke();
}
}
//виклик функції
Lightning(document.getElementById('canva1'), 150, 0);
<canvas id="canva2" width="400" height="400"></canvas>
function Lightning(canvas, x1, y1, x2, y2, color){
var ctx=canvas.getContext('2d');
//очищаємо полотно canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//довжина блискавки (лінії)
var len=Math.max(y1,y2)-Math.min(y1,y2);
//крок поділу лінії блискавки
var step=2;
//кількість кроків
var stepCount=len/step;
//максимальне зміщення px від прямої лінії блискавки
var maxOffset=8;
var cx=x1,cy=y1;
ctx.strokeStyle=color;
ctx.lineWidth=2;
ctx.beginPath();
//встановлюємо початкову точку лінії
ctx.moveTo(cx, cy);
for(var i=stepCount;i>1;i--){
cx+=(x2-cx)/i+Math.random()*maxOffset-(maxOffset/2);
cy+=(y2-cy)/i+Math.random()*maxOffset-(maxOffset/2);
ctx.lineTo(cx, cy);
}
ctx.stroke();
}
Lightning(document.getElementById('canva2'), 50, 0, 60, 350, 'blue');
Зробимо кінець лінії блискавки тоншим, а початок широким.
<canvas id="canva3" width="400" height="400"></canvas>
function Lightning(canvas, x1, y1, x2, y2, color, lineWidth){
var ctx=canvas.getContext('2d');
//очищаємо полотно canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//довжина блискавки (лінії)
var len=Math.max(y1,y2)-Math.min(y1,y2);
//крок поділу лінії блискавки
var step=2;
//кількість кроків
var stepCount=len/step;
//крок ширини лінії
var steplineWidth=lineWidth/stepCount;
//максимальне зміщення px від прямої лінії блискавки
var maxOffset=8;
var cx=x1,cy=y1;
//колір блискавки
ctx.strokeStyle=color;
//ctx.shadowColor=color;
//ctx.shadowBlur=2;
ctx.lineWidth=lineWidth;
for(var i=stepCount;i>1;i--){
ctx.moveTo(cx, cy);
cx+=(x2-cx)/i+Math.random()*maxOffset-(maxOffset/2);
cy+=(y2-cy)/i+Math.random()*maxOffset-(maxOffset/2);
ctx.lineWidth-=steplineWidth;
ctx.lineTo(cx, cy);
ctx.stroke();
}
}
Lightning(document.getElementById('canva3'),100, 0, 25, 250, 'red', 4);
<canvas id="canvaL" width="400" height="450"></canvas>
function Lightning(canvas, options){
//функція випадкового числа від min до max
function random(min,max){return parseInt(Math.random()*(max-min)+min);}
//параметри по замовчуванню
var DEF_OPTIONS={x1: canvas.width/2, y1:0, color:'hsl(180, 80%, 80%)', lineWidth:random(1,3)};
DEF_OPTIONS.x2=random(DEF_OPTIONS.x1+50,canvas.height);
DEF_OPTIONS.y2=random(DEF_OPTIONS.y1+50,canvas.height);
//якщо параметр не вказано то присвоюємо параметр по замовчуванню
for(var a in DEF_OPTIONS)options[a]=(a in options?options[a]:DEF_OPTIONS[a]);
var ctx = canvas.getContext("2d");
//створюємо лінію блискавки
var size=Math.max(options.y1, options.y2)-Math.min(options.y1, options.y2);
var roughness=2; //1.8 ... 2.2
var maxDifference=size/5;
var count=size;
var lightning=[];
//початкові координати блискавки
lightning.push({x: options.x1, y: options.y1});
//кінцеві координати блискавки
lightning.push({x: options.x2, y: options.y2});
var currDiff=maxDifference;
while(count>1){
var newSegments=[];
for(var i=0; i<lightning.length-1; i++){
var start=lightning[i];
var end=lightning[i+1];
var midX=(start.x+end.x)/2;
var newX = midX + ((Math.random() * 2 - 1) * currDiff);
newSegments.push(start, {x: newX, y: (start.y + end.y) / 2});
}
newSegments.push(lightning.pop());
lightning=newSegments;
currDiff=currDiff/roughness;
count=count/2;
}
//очищаємо полотно canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//малюємо лінію блискавки
//колір лінії
ctx.strokeStyle=options.color;
//розмір лінії
ctx.lineWidth=options.lineWidth;
//колір тіні
ctx.shadowColor=options.color;
//розмір тіні
ctx.shadowBlur=15;
ctx.beginPath();
for(var i=0; i<lightning.length; i++){
ctx.lineTo(lightning[i].x, lightning[i].y);
}
ctx.stroke();
}
//виклик функції
Lightning(document.getElementById("canvaL"), {x1:150, y1:0, x2:155, y2:400});
function Lightning(canvas, options){
//функція випадкового числа від min до max
function random(min,max){return parseInt(Math.random()*(max-min)+min);}
//параметри по замовчуванню
var DEF_OPTIONS={x1: canvas.width/2, y1:0, color:'hsl(180, 80%, 80%)', lineWidth:random(1,3)};
DEF_OPTIONS.x2=random(DEF_OPTIONS.x1+50,canvas.height);
DEF_OPTIONS.y2=random(DEF_OPTIONS.y1+50,canvas.height);
//якщо параметр не вказано то присвоюємо параметр по замовчуванню
for(var a in DEF_OPTIONS)options[a]=(a in options?options[a]:DEF_OPTIONS[a]);
var ctx = canvas.getContext("2d");
//функція створення лінії блискавки
function createLightning(x1, y1, x2, y2){
var size=Math.max(y1, y2)-Math.min(y1, y2);
var roughness=2; //1.8 ... 2.2
var maxDifference=size/5;
var count=size;
var lightning=[];
//початкові координати блискавки
lightning.push({x: x1, y: y1});
//кінцеві координати блискавки
lightning.push({x: x2, y: y2});
var currDiff=maxDifference;
while(count>1){
var newSegments=[];
for(var i=0; i<lightning.length-1; i++){
var start=lightning[i];
var end=lightning[i+1];
var midX=(start.x+end.x)/2;
var newX = midX + ((Math.random()*2-1)*currDiff);
newSegments.push(start, {x: newX, y: (start.y + end.y) / 2});
}
newSegments.push(lightning.pop());
lightning=newSegments;
currDiff=currDiff/roughness;
count=count/2;
}
return lightning;
}
var lightning=[];
lightning[0]=createLightning(options.x1, options.y1, options.x2, options.y2);
for(var i=1, j, l=random(1,5);i<l;i++){
j=random(0, lightning[0].length-1);
lightning[i]=createLightning(lightning[0][j].x, lightning[0][j].y, random(lightning[0][j].x-50, lightning[0][j].x+50), random(lightning[0][j].y+50, lightning[0][j].y+150));
}
//очищаємо полотно canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//малюємо лінію блискавки
//колір лінії
ctx.strokeStyle=options.color;
//колір тіні
ctx.shadowColor=options.color;
//розмір тіні
ctx.shadowBlur=15;
for(var i=0; i<lightning.length; i++){
ctx.lineWidth=lightning.length-i;
ctx.beginPath();
for(var j=0; j<lightning[i].length;j++){
ctx.lineTo(lightning[i][j].x, lightning[i][j].y);
}
ctx.stroke();
}
}
//виклик функції
Lightning(document.getElementById("canvaL2"), {x1:50, y1:15, x2:155, y2:250});