Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
hub
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Package registry
Operate
Terraform modules
Analyze
Contributor analytics
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
thomasDOTwtf
hub
Commits
4f2dd94e
Commit
4f2dd94e
authored
Dec 25, 2021
by
Dj
Browse files
Options
Downloads
Patches
Plain Diff
Add support for multiple layer of particles.
parent
d63762cb
Branches
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/parallax-css-testpage/particles.js
+120
-160
120 additions, 160 deletions
src/parallax-css-testpage/particles.js
src/parallax-css-testpage/template.html
+42
-28
42 additions, 28 deletions
src/parallax-css-testpage/template.html
with
162 additions
and
188 deletions
src/parallax-css-testpage/particles.js
+
120
−
160
View file @
4f2dd94e
/*
/*
* Particles.js
* Particles.js
*
* Particle emitter and renderer.
*/
*/
const
Debug
=
false
const
Debug
=
false
const
Static
=
true
const
Static
=
true
// Needed for fps calculation.
let
Then
=
Date
.
now
()
// Argh.. Global, mutable, variable..!
//
//
// Helper
// Helper
//
//
// Random Value without zero
function
randomValue
(
min
,
max
)
{
function
randomValue
(
min
,
max
)
{
const
value
=
(
Math
.
random
()
*
(
+
max
-
+
min
)
+
+
min
)
const
value
=
(
Math
.
random
()
*
(
+
max
-
+
min
)
+
+
min
)
return
(
value
===
0
)
?
randomValue
(
min
,
max
)
:
value
// Prevent values that can be possible boring
return
(
value
===
0
||
value
===
1
)
?
randomValue
(
min
,
max
)
:
value
}
}
function
getNodeYOffset
(
node
)
{
function
getNodeYOffset
(
node
)
{
...
@@ -30,38 +31,6 @@ function getNodeHeight(node) {
...
@@ -30,38 +31,6 @@ function getNodeHeight(node) {
return
(
dimensions
)
?
dimensions
.
height
:
window
.
innerHeight
return
(
dimensions
)
?
dimensions
.
height
:
window
.
innerHeight
}
}
function
getScene
(
canvasId
,
height
)
{
const
width
=
window
.
innerWidth
const
fov
=
0.8
const
perspective
=
width
*
fov
const
yOffset
=
0
const
canvas
=
document
.
getElementById
(
canvasId
)
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
ctx
.
canvas
.
width
=
width
ctx
.
canvas
.
height
=
window
.
innerHeight
return
{
width
,
height
,
yOffset
,
perspective
,
ctx
}
}
// function to2dParticle(scene, particle) {
// const perspective = scene.perspective
// const scale = perspective / (perspective + particle.position.z)
// const yOffset = scene.yOffset * scale
// const offset = particle.size.value * 0.5
// const x = particle.position.x - offset
// const y = (yOffset + (particle.position.y - offset))
// const size = particle.size.value
// // const y = (yOffset + (particle.position.y - offset)) * scale
// // const size = particle.size.value * scale
// return { x, y, size }
// }
function
calcScrolledYPos
(
ctx
,
yPos
,
yOffset
)
{
const
y
=
(
yPos
+
yOffset
)
return
(
y
<=
0
)
?
ctx
.
canvas
.
height
-
y
:
y
}
//
//
// Data
// Data
...
@@ -72,10 +41,6 @@ function Point2D(x, y) {
...
@@ -72,10 +41,6 @@ function Point2D(x, y) {
return
{
x
,
y
}
return
{
x
,
y
}
}
}
function
Point3D
(
x
,
y
,
z
)
{
return
{
x
,
y
,
z
}
}
function
MinMax
(
min
,
max
)
{
function
MinMax
(
min
,
max
)
{
return
{
min
,
max
}
return
{
min
,
max
}
}
}
...
@@ -90,16 +55,6 @@ function RandomPoint2D(minMaxX, minMaxY) {
...
@@ -90,16 +55,6 @@ function RandomPoint2D(minMaxX, minMaxY) {
return
Point2D
(
x
,
y
)
return
Point2D
(
x
,
y
)
}
}
function
RandomPoint3D
(
minMaxX
,
minMaxY
,
minMaxZ
)
{
const
x
=
randomValue
(
minMaxX
.
min
,
minMaxX
.
max
)
const
y
=
randomValue
(
minMaxY
.
min
,
minMaxY
.
max
)
const
z
=
(
typeof
minMaxZ
===
'
number
'
)
?
minMaxZ
:
randomValue
(
minMaxZ
.
min
,
minMaxZ
.
max
)
return
Point3D
(
x
,
y
,
z
)
}
function
Particle
({
position
,
direction
,
size
,
color
})
{
function
Particle
({
position
,
direction
,
size
,
color
})
{
return
{
position
,
direction
,
size
,
color
}
return
{
position
,
direction
,
size
,
color
}
}
}
...
@@ -132,8 +87,8 @@ function Update(scene, particle) {
...
@@ -132,8 +87,8 @@ function Update(scene, particle) {
Object
.
assign
({},
updateSizeStep
,
{
Object
.
assign
({},
updateSizeStep
,
{
size
:
Object
.
assign
({},
updateSizeStep
.
size
,
{
size
:
Object
.
assign
({},
updateSizeStep
.
size
,
{
value
:
value
:
// Todo: Animate puls effect with the help of Math.sin()
updateSizeStep
.
size
.
value
+
updateSizeStep
.
size
.
step
*
updateSizeStep
.
size
.
direction
,
updateSizeStep
.
size
.
value
+
updateSizeStep
.
size
.
step
*
updateSizeStep
.
size
.
direction
,
// updateSizeStep.size.value
})
})
})
})
...
@@ -142,8 +97,8 @@ function Update(scene, particle) {
...
@@ -142,8 +97,8 @@ function Update(scene, particle) {
const
sizeOffset
=
particle
.
size
.
value
*
0.5
const
sizeOffset
=
particle
.
size
.
value
*
0.5
const
y
=
particle
.
position
.
y
const
y
=
particle
.
position
.
y
const
top
=
y
-
sizeOffset
const
top
=
y
+
sizeOffset
const
bottom
=
y
+
sizeOffset
const
bottom
=
y
-
sizeOffset
const
left
=
particle
.
position
.
x
-
sizeOffset
const
left
=
particle
.
position
.
x
-
sizeOffset
const
right
=
particle
.
position
.
x
+
sizeOffset
const
right
=
particle
.
position
.
x
+
sizeOffset
...
@@ -156,10 +111,11 @@ function Update(scene, particle) {
...
@@ -156,10 +111,11 @@ function Update(scene, particle) {
Object
.
assign
({},
updateSize
,
{
Object
.
assign
({},
updateSize
,
{
direction
:
direction
:
Point2D
(
Point2D
(
// Bounce of the right and left edges of the sc
re
en
.
// Bounce of the right and left edges of the scen
e
(
isRightEdge
||
isLeftEdge
)
(
isRightEdge
||
isLeftEdge
)
?
updateSize
.
direction
.
x
*
-
1
?
updateSize
.
direction
.
x
*
-
1
:
updateSize
.
direction
.
x
,
:
updateSize
.
direction
.
x
,
// Bounce from the top and bottom edges of the scene
(
isTopEdge
||
isBottomEdge
)
(
isTopEdge
||
isBottomEdge
)
?
particle
.
direction
.
y
*
-
1
?
particle
.
direction
.
y
*
-
1
:
particle
.
direction
.
y
,
:
particle
.
direction
.
y
,
...
@@ -168,7 +124,7 @@ function Update(scene, particle) {
...
@@ -168,7 +124,7 @@ function Update(scene, particle) {
const
updatePosition
=
const
updatePosition
=
Object
.
assign
({},
updateDirection
,
{
Object
.
assign
({},
updateDirection
,
{
position
:
position
:
Point
3
D
(
Point
2
D
(
updateDirection
.
position
.
x
+
updateDirection
.
direction
.
x
,
updateDirection
.
position
.
x
+
updateDirection
.
direction
.
x
,
updateDirection
.
position
.
y
+
updateDirection
.
direction
.
y
,
updateDirection
.
position
.
y
+
updateDirection
.
direction
.
y
,
// (isTopEdge)
// (isTopEdge)
...
@@ -176,7 +132,6 @@ function Update(scene, particle) {
...
@@ -176,7 +132,6 @@ function Update(scene, particle) {
// : (isBottomEdge)
// : (isBottomEdge)
// ? -sizeOffset
// ? -sizeOffset
// : (updateDirection.position.y + updateDirection.direction.y),
// : (updateDirection.position.y + updateDirection.direction.y),
updateDirection
.
position
.
z
)
)
})
})
...
@@ -187,18 +142,19 @@ function Update(scene, particle) {
...
@@ -187,18 +142,19 @@ function Update(scene, particle) {
function
Draw
(
scene
,
particle
)
{
function
Draw
(
scene
,
particle
)
{
// Cache object access
// Cache object access
const
size
=
particle
.
size
.
value
const
size
=
particle
.
size
.
value
const
position
=
particle
.
position
const
perspective
=
scene
.
perspective
// Draw calculations
const
scale
=
perspective
/
(
perspective
+
particle
.
position
.
z
)
const
yOffset
=
scene
.
yOffset
*
scene
.
depthScale
const
yOffset
=
scene
.
yOffset
*
scale
const
drawOffset
=
size
*
0.5
const
drawOffset
=
size
*
0.5
const
y
=
yOffset
+
(
particle
.
position
.
y
-
drawOffset
)
const
y
=
yOffset
+
(
position
.
y
-
drawOffset
)
const
ctx
=
scene
.
ctx
const
ctx
=
scene
.
ctx
const
isVisible
=
(
size
>
0
)
&&
(
y
<
window
.
innerHeight
)
&&
(
y
>
0
)
const
isVisible
=
(
size
>
0
)
&&
(
y
<
window
.
innerHeight
)
&&
(
y
>
0
)
// Draw
if
(
isVisible
)
{
if
(
isVisible
)
{
ctx
.
fillStyle
=
particle
.
color
ctx
.
fillStyle
=
particle
.
color
ctx
.
fillRect
(
particle
.
position
.
x
-
drawOffset
,
y
,
size
,
size
)
ctx
.
fillRect
(
position
.
x
-
drawOffset
,
y
,
size
,
size
)
}
}
}
}
...
@@ -209,100 +165,79 @@ function Clear(scene) {
...
@@ -209,100 +165,79 @@ function Clear(scene) {
function
Render
(
scene
,
particles
)
{
function
Render
(
scene
,
particles
)
{
Clear
(
scene
)
Clear
(
scene
)
particles
.
forEach
(
particles
.
forEach
(
function
(
particle
)
{
function
doDraw
(
particle
)
{
Draw
(
scene
,
particle
)
Draw
(
scene
,
particle
)
}
}
)
)
}
}
function
Animate
({
scene
,
fpsInterval
,
particles
,
anchorNode
})
{
function
Animate
(
scene
,
particles
)
{
scene
.
yOffset
=
getNodeYOffset
(
anchorNode
)
var
fpsInterval
=
scene
.
fpsInterval
var
now
=
Date
.
now
()
var
then
=
scene
.
then
var
elapsed
=
now
-
then
// Update particle positions and register for the next frame
// Just render when we're reaching the configured fps
// to render.
if
(
elapsed
>
scene
.
fpsInterval
)
{
requestAnimationFrame
(()
=>
{
scene
.
yOffset
=
getNodeYOffset
(
scene
.
anchorNode
)
const
updatedParticles
=
scene
.
then
=
now
-
(
elapsed
%
fpsInterval
)
particles
.
map
(
function
(
p
)
{
Render
(
scene
,
particles
)
}
// Update particle positions for the next render call
const
updatedParticles
=
particles
.
map
(
function
doUpdate
(
p
)
{
return
Update
(
scene
,
p
)
return
Update
(
scene
,
p
)
})
})
Animate
({
scene
,
fpsInterval
,
particles
:
updatedParticles
,
anchorNode
})
})
// Render particles to canvas and do some fps calculations
// Function to animate the next frame
const
now
=
Date
.
now
()
return
function
()
{
const
elapsed
=
now
-
Then
return
Animate
(
scene
,
updatedParticles
)
if
(
elapsed
>
fpsInterval
)
{
Then
=
now
-
(
elapsed
%
fpsInterval
)
Render
(
scene
,
particles
)
}
}
}
}
function
CreateScene
({
canvasId
,
contentId
,
depth
,
fps
})
{
const
contentNode
=
document
.
getElementById
(
contentId
)
const
height
=
getNodeHeight
(
contentNode
)
//
const
fpsInterval
=
1000
/
fps
// Api
const
width
=
window
.
innerWidth
//
const
yOffset
=
0
const
canvas
=
document
.
getElementById
(
canvasId
)
const
ctx
=
canvas
.
getContext
(
'
2d
'
)
const
depthScaledHeight
=
height
*
(
depth
+
1
)
ctx
.
canvas
.
width
=
width
ctx
.
canvas
.
height
=
window
.
innerHeight
function
Particles
({
return
{
canvasId
,
width
,
contentId
,
height
:
depthScaledHeight
,
yOffset
,
depthScale
:
depth
,
ctx
,
fps
,
fps
,
fpsInterval
,
then
:
Date
.
now
(),
anchorNode
:
contentNode
}
}
function
CreateParticles
(
scene
,
{
amount
,
amount
,
color
,
color
,
size
,
size
,
speed
,
speed
,
depth
,
lifespan
,
lifespan
,
})
{
})
{
const
contentNode
=
document
.
getElementById
(
contentId
)
return
Array
.
from
(
const
height
=
getNodeHeight
(
contentNode
)
// Init the canvas for rendering.
//
const
scene
=
getScene
(
canvasId
,
height
)
if
(
!
scene
.
ctx
)
{
console
.
error
(
"
Particles: Can't find Canvas
"
,
canvasId
)
return
}
// Generate some particles
//
const
z
=
depth
*
-
1000
const
particles
=
(
Debug
)
?
(
Static
)
?
[
Particle
({
position
:
Point3D
(
100
,
500
,
z
),
direction
:
Point2D
(
0
,
0
),
size
:
{
value
:
15
,
bound
:
MinMax
(
100
,
100
),
step
:
0
,
direction
:
1
},
color
:
'
white
'
})
]
:
[
Particle
({
position
:
Point3D
(
100
,
100
,
z
),
direction
:
Point2D
(
0
,
+
1
),
size
:
{
value
:
100
,
bound
:
MinMax
(
100
,
100
),
step
:
0
,
direction
:
1
},
color
:
'
white
'
})
]
:
Array
.
from
(
{
length
:
amount
},
{
length
:
amount
},
()
=>
Particle
({
function
createParticle
()
{
return
Particle
({
position
:
position
:
RandomPoint
3
D
(
RandomPoint
2
D
(
MinMax
(
0
,
(
scene
.
width
-
(
size
*
2
))),
MinMax
(
0
,
(
scene
.
width
-
(
size
*
2
))),
MinMax
(
0
,
(
scene
.
height
-
(
size
*
2
))),
MinMax
(
0
,
(
scene
.
height
-
(
size
*
2
))),
z
),
),
direction
:
direction
:
RandomPoint2D
(
RandomPoint2D
(
...
@@ -312,19 +247,44 @@ function Particles({
...
@@ -312,19 +247,44 @@ function Particles({
size
:
{
size
:
{
value
:
randomValue
(
-
size
,
size
),
value
:
randomValue
(
-
size
,
size
),
bound
:
MinMax
(
-
size
,
size
),
bound
:
MinMax
(
-
size
,
size
),
step
:
size
/
((
lifespan
)
/
fps
),
step
:
size
/
((
lifespan
)
/
scene
.
fps
),
direction
:
direction
:
// 50% Chance for the particle floating in one
// direction or the other.
(
randomValue
(
0
,
100
)
<
50
)
(
randomValue
(
0
,
100
)
<
50
)
?
-
1
?
-
1
:
+
1
,
:
+
1
,
},
},
color
color
})
})
}
)
)
}
// Prepare Animation and animate
const
fpsInterval
=
1000
/
fps
//
Then
=
Date
.
now
()
// Api
Animate
({
scene
,
fpsInterval
,
particles
,
anchorNode
:
contentNode
})
//
return
function
Particles
(
configs
)
{
function
doRenderParticles
(
rendererList
)
{
requestAnimationFrame
(
function
()
{
doRenderParticles
(
rendererList
.
map
(
function
doRender
(
render
)
{
return
render
()
})
)
})
}
return
function
()
{
doRenderParticles
(
configs
.
map
(
function
(
particleConfig
)
{
var
scene
=
CreateScene
(
particleConfig
.
scene
)
var
particles
=
CreateParticles
(
scene
,
particleConfig
.
particles
)
return
Animate
(
scene
,
particles
)
})
)
}
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
src/parallax-css-testpage/template.html
+
42
−
28
View file @
4f2dd94e
...
@@ -82,36 +82,50 @@
...
@@ -82,36 +82,50 @@
<script>
<script>
var
bgParticles
=
{
var
fgParticleConfig
=
{
scene
:
{
// Id of the canvas to render to
canvasId
:
'
fg-particles
'
,
// Id of the content container, we're using it to get the
// rendering height and it's the anchor to get the y offset
// to simulate scrolling.
contentId
:
'
content
'
,
fps
:
30
,
depth
:
2
,
},
particles
:
{
amount
:
100
,
color
:
'
white
'
,
size
:
30
,
speed
:
0.5
,
lifespan
:
3000
// in milliseconds
}
}
var
bgParticleConfig
=
{
scene
:
{
// Id of the canvas to render to
// Id of the canvas to render to
canvasId
:
'
bg-particles
'
,
canvasId
:
'
bg-particles
'
,
// Id of the content container, we're using it to get the
// Id of the content container, we're using it to get the
// rendering height and it's the anchor to get the y offset
// rendering height and it's the anchor to get the y offset
// to simulate scrolling.
// to simulate scrolling.
contentId
:
'
content
'
,
contentId
:
'
content
'
,
fps
:
16
,
fps
:
16
,
amount
:
120
,
depth
:
0.08
,
},
particles
:
{
amount
:
200
,
color
:
'
white
'
,
color
:
'
white
'
,
size
:
10
,
size
:
10
,
speed
:
0.2
,
speed
:
0.2
,
depth
:
-
8
,
lifespan
:
4000
// in milliseconds
lifespan
:
4000
// in milliseconds
}
}
Particles
(
bgParticles
)
var
fgParticles
=
{
canvasId
:
'
fg-particles
'
,
contentId
:
'
content
'
,
fps
:
24
,
amount
:
20
,
color
:
'
white
'
,
size
:
30
,
speed
:
0.5
,
depth
:
2
,
lifespan
:
4000
// in milliseconds
}
}
// Particles(fgParticles)
var
animate
=
Particles
([
fgParticleConfig
,
bgParticleConfig
,
])
animate
()
</script>
</script>
</body>
</body>
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment