-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathlightningGenerator.js
114 lines (79 loc) · 2.71 KB
/
lightningGenerator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
onmessage = (event) => {
const msg = event.data;
// console.log(msg);
let imgElement = generateLightningBolt(msg.width, msg.height);
postMessage(imgElement);
};
function generateLightningBolt(width, height)
{
const lightningCanvas = new OffscreenCanvas(width, height);
const ctx = lightningCanvas.getContext('2d');
ctx.clearRect(0, 0, width, height);
function genLightningColor(lineWidth)
{
const colR = 12;
const colG = 12;
const colB = 12;
brightness = Math.pow(lineWidth, 2.0);
return `rgb(${colR * brightness}, ${colG * brightness}, ${colB * brightness})`;
}
ctx.beginPath();
let startX = width / 2.0;
let startY = 0;
let angle = Math.PI / 6.;
let lineWidth = 9.0;
const targetAngle = 0.0;
ctx.moveTo(startX, startY);
ctx.lineWidth = lineWidth;
while (startY < height) {
const nextX = startX + Math.sin(angle);
const nextY = startY + Math.cos(angle);
angle += (Math.random() - 0.5) * 1.4; // 0.7
angle -= (angle - targetAngle) * 0.08; // keep it going in a general direction
ctx.lineTo(nextX, nextY);
startX = nextX;
startY = nextY;
if (Math.random() < 0.015 * (1. - nextY / height)) { // branch
ctx.strokeStyle = genLightningColor(lineWidth);
ctx.stroke();
drawBranch(nextX, nextY, targetAngle + (Math.random() - 0.5) * 2.5, lineWidth * 0.5 * Math.random());
ctx.beginPath();
ctx.moveTo(nextX, nextY); // move back to last position after drawing branch
ctx.lineWidth = lineWidth;
}
}
ctx.strokeStyle = genLightningColor(lineWidth);
ctx.stroke();
return ctx.getImageData(0, 0, width, height);
function drawBranch(startX, startY, targetAngle, line_width)
{
let angle = targetAngle;
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineWidth = line_width;
while (startY < height) {
const nextX = startX + Math.sin(angle);
const nextY = startY + Math.cos(angle);
angle += (Math.random() - 0.5) * 0.7;
angle -= (angle - targetAngle) * 0.08; // keep it going in a general direction
ctx.lineTo(nextX, nextY);
startX = nextX;
startY = nextY;
if (Math.random() < 0.018) { // reduce width
ctx.strokeStyle = genLightningColor(line_width);
ctx.stroke();
line_width -= 0.2;
if (line_width < 0.1)
return;
if (Math.random() < 0.1) { // branch 0.005
drawBranch(nextX, nextY, targetAngle + (Math.random() - 0.5) * 1.5, line_width);
}
ctx.beginPath();
ctx.moveTo(nextX, nextY); // move back to last position after drawing branch
ctx.lineWidth = line_width;
}
}
ctx.strokeStyle = genLightningColor(line_width);
ctx.stroke();
}
}