Compare commits
18 Commits
3f99b8b62f
...
b3038644ad
Author | SHA1 | Date |
---|---|---|
Asif Bacchus | b3038644ad | |
Asif Bacchus | fb5a4675f8 | |
Asif Bacchus | fe51090807 | |
Asif Bacchus | 24af3c33ac | |
Asif Bacchus | 8d08d145c4 | |
Asif Bacchus | bf5321eec5 | |
Asif Bacchus | 6b165f24da | |
Asif Bacchus | c0e4424257 | |
Asif Bacchus | 89263b1495 | |
Asif Bacchus | e937b17e17 | |
Asif Bacchus | 63971cb860 | |
Asif Bacchus | 5b0d2d108a | |
Asif Bacchus | d9b18cdb9e | |
Asif Bacchus | 1a519a1d55 | |
Asif Bacchus | e52855f954 | |
Asif Bacchus | 507c5f6e38 | |
Asif Bacchus | b410e55915 | |
Asif Bacchus | bcfe64f427 |
|
@ -0,0 +1,81 @@
|
|||
# Common settings that generally should always be used with your language specific settings
|
||||
|
||||
# Auto detect text files and perform LF normalization
|
||||
# https://www.davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
|
||||
* text=auto
|
||||
|
||||
#
|
||||
# The above will handle all files NOT found below
|
||||
#
|
||||
|
||||
# Documents
|
||||
*.bibtex text diff=bibtex
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
*.md text
|
||||
*.tex text diff=tex
|
||||
*.adoc text
|
||||
*.textile text
|
||||
*.mustache text
|
||||
*.csv text
|
||||
*.tab text
|
||||
*.tsv text
|
||||
*.txt text
|
||||
*.sql text
|
||||
|
||||
# Graphics
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.tif binary
|
||||
*.tiff binary
|
||||
*.ico binary
|
||||
# SVG treated as an asset (binary) by default.
|
||||
*.svg text
|
||||
# If you want to treat it as binary,
|
||||
# use the following line instead.
|
||||
# *.svg binary
|
||||
*.eps binary
|
||||
|
||||
# Scripts
|
||||
*.bash text eol=lf
|
||||
*.fish text eol=lf
|
||||
*.sh text eol=lf
|
||||
# These are explicitly windows files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
|
||||
# Serialisation
|
||||
*.json text
|
||||
*.toml text
|
||||
*.xml text
|
||||
*.yaml text
|
||||
*.yml text
|
||||
|
||||
# Archives
|
||||
*.7z binary
|
||||
*.gz binary
|
||||
*.tar binary
|
||||
*.tgz binary
|
||||
*.zip binary
|
||||
|
||||
# Text files where line endings should be preserved
|
||||
*.patch -text
|
||||
|
||||
#
|
||||
# Exclude files from exporting
|
||||
#
|
||||
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.vscode export-ignore
|
|
@ -0,0 +1,14 @@
|
|||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/numbered-bookmarks.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# compiled CSS
|
||||
css-review
|
||||
css
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>animated particles</title>
|
||||
<link rel="stylesheet"
|
||||
href="css/index.min.css"
|
||||
crossorigin="anonymous"/>
|
||||
</head>
|
||||
<body onload='particles(avoidMouse=false)'>
|
||||
<canvas id="particles"></canvas>
|
||||
<!-- javascript -->
|
||||
<script
|
||||
src="js/particles.js"
|
||||
crossorigin="anonymous"
|
||||
async>
|
||||
</script>
|
||||
<!-- end javascript -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,194 @@
|
|||
function particles(){
|
||||
/* create particles animation
|
||||
based on the amazing tutorial by 'Franks Labratory'
|
||||
https://youtu.be/d620nV6bp0A
|
||||
*/
|
||||
|
||||
// handle parameters
|
||||
particles = (
|
||||
typeof particles !== 'undefined'
|
||||
&& Number.isFinite(particles)
|
||||
) ? particles : 1;
|
||||
sizeMultiplier = (
|
||||
typeof sizeMultiplier !== 'undefined'
|
||||
&& Number.isFinite(sizeMultiplier)
|
||||
) ? sizeMultiplier : 3;
|
||||
speed = (
|
||||
typeof speed !== 'undefined'
|
||||
&& Number.isFinite(speed)
|
||||
&& (1 <= speed && speed <= 1000)
|
||||
) ? (speed / 100) : 0.5;
|
||||
avoidMouse = (
|
||||
typeof avoidMouse !== 'undefined'
|
||||
&& typeof avoidMouse === 'boolean'
|
||||
) ? avoidMouse : true;
|
||||
hover = (
|
||||
typeof hover !== 'undefined'
|
||||
&& typeof hover === 'boolean'
|
||||
) ? hover : true;
|
||||
|
||||
// read css colour variables from root element
|
||||
const particleColour = getComputedStyle(document.documentElement).getPropertyValue('--col-particle');
|
||||
const strokeColour = getComputedStyle(document.documentElement).getPropertyValue('--col-particle-stroke');
|
||||
const strokeHoverColour = getComputedStyle(document.documentElement).getPropertyValue('--col-particle-stroke-hover');
|
||||
|
||||
// get canvas element, set context and size
|
||||
const canvas = document.getElementById('particles');
|
||||
const canvasContext = canvas.getContext('2d');
|
||||
canvas.width = window.innerWidth;
|
||||
canvas.height = window.innerHeight;
|
||||
|
||||
let particlesArray;
|
||||
|
||||
// get mouse position
|
||||
let mousePosition ={
|
||||
x: undefined,
|
||||
y: undefined,
|
||||
radius: (canvas.height / 80) * (canvas.width / 80)
|
||||
};
|
||||
|
||||
// add mouse position event listener
|
||||
window.addEventListener('mousemove', function(event){
|
||||
mousePosition.x = event.x;
|
||||
mousePosition.y = event.y;
|
||||
});
|
||||
|
||||
// create particle class
|
||||
class Particle{
|
||||
constructor(x, y, directionX, directionY, size, colour) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.directionX = directionX;
|
||||
this.directionY = directionY;
|
||||
this.size = size;
|
||||
this.colour = colour;
|
||||
}
|
||||
// method to draw individual particles
|
||||
draw(){
|
||||
canvasContext.beginPath();
|
||||
canvasContext.arc(this.x, this.y, this.size, 0, Math.PI * 2, false);
|
||||
canvasContext.fillStyle = particleColour;
|
||||
canvasContext.fill();
|
||||
}
|
||||
// check particle position, mouse position, move particle and draw it
|
||||
update(){
|
||||
// check if particle is still within canvas
|
||||
if (this.x > canvas.width || this.x < 0){
|
||||
this.directionX = -this.directionX;
|
||||
}
|
||||
if (this.y > canvas.height || this.y < 0){
|
||||
this.directionY = -this.directionY;
|
||||
}
|
||||
|
||||
// avoid the mouse if avoidMouse = true (default)
|
||||
if (avoidMouse){
|
||||
let dx = mousePosition.x - this.x;
|
||||
let dy = mousePosition.y - this.y;
|
||||
let distance = Math.sqrt((dx * dx) + (dy * dy));
|
||||
if (distance < mousePosition.radius + this.size){
|
||||
if (mousePosition.x < this.x && this.x < canvas.width - this.size * 10){
|
||||
this.x += 10;
|
||||
}
|
||||
if (mousePosition.x > this.x && this.x > this.size * 10){
|
||||
this.x -= 10;
|
||||
}
|
||||
if (mousePosition.y < this.y && this.y < canvas.height - this.size * 10){
|
||||
this.y += 10;
|
||||
}
|
||||
if (mousePosition.y > this.y && this.y > this.size * 10){
|
||||
this.y -= 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// move particle
|
||||
this.x += this.directionX * speed;
|
||||
this.y += this.directionY * speed;
|
||||
|
||||
// draw particle
|
||||
this.draw();
|
||||
}
|
||||
}
|
||||
|
||||
// create particle array
|
||||
function init(){
|
||||
particlesArray = [];
|
||||
let numberOfParticles = (canvas.height * canvas.width) / 9000;
|
||||
for (let i = 0; i < numberOfParticles * particles; i++){
|
||||
let size = (Math.random() * sizeMultiplier) + 1;
|
||||
let x = (Math.random() * ((innerWidth - size * 2) - (size * 2)) + size * 2);
|
||||
let y = (Math.random() * ((innerHeight - size * 2) - (size * 2)) + size * 2);
|
||||
let directionX = (Math.random() * 5) - 2.5;
|
||||
let directionY = (Math.random() * 5) - 2.5;
|
||||
let colour = '#8c5523';
|
||||
|
||||
particlesArray.push(new Particle(x, y, directionX, directionY, size, colour));
|
||||
}
|
||||
}
|
||||
|
||||
// check if particles are close enough to connect to eachother
|
||||
function connect(){
|
||||
let opacityValue = 1;
|
||||
for (let a = 0; a < particlesArray.length; a++){
|
||||
for (let b = a; b < particlesArray.length; b++){
|
||||
let distance = ((particlesArray[a].x - particlesArray[b].x) * (particlesArray[a].x - particlesArray[b].x)) + ((particlesArray[a].y - particlesArray[b].y) * (particlesArray[a].y - particlesArray[b].y));
|
||||
if (distance < (canvas.width / 10) * (canvas.height / 10)){
|
||||
opacityValue = 1 - (distance / 20000);
|
||||
// change colour on 'hover' if hover = true (default)
|
||||
if(hover){
|
||||
let dx = mousePosition.x - particlesArray[a].x;
|
||||
let dy = mousePosition.y - particlesArray[a].y;
|
||||
let mouseDistance = Math.sqrt((dx * dx) + (dy * dy));
|
||||
if (mouseDistance < 200) {
|
||||
// change colour if mouse is close
|
||||
canvasContext.globalAlpha = opacityValue;
|
||||
canvasContext.strokeStyle = strokeHoverColour;
|
||||
}
|
||||
else {
|
||||
// use regular stroke colour
|
||||
canvasContext.globalAlpha = opacityValue;
|
||||
canvasContext.strokeStyle = strokeColour;
|
||||
}
|
||||
}
|
||||
else {
|
||||
canvasContext.globalAlpha = opacityValue;
|
||||
canvasContext.strokeStyle = strokeColour;
|
||||
}
|
||||
canvasContext.lineWidth = 1;
|
||||
canvasContext.beginPath();
|
||||
canvasContext.moveTo(particlesArray[a].x, particlesArray[a].y);
|
||||
canvasContext.lineTo(particlesArray[b].x, particlesArray[b].y);
|
||||
canvasContext.stroke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// animation loop
|
||||
function animate(){
|
||||
requestAnimationFrame(animate);
|
||||
canvasContext.clearRect(0, 0, innerWidth, innerHeight);
|
||||
|
||||
for (let i = 0; i < particlesArray.length; i++){
|
||||
particlesArray[i].update();
|
||||
}
|
||||
connect();
|
||||
}
|
||||
|
||||
// resize event
|
||||
window.addEventListener('resize', function(){
|
||||
canvas.width = innerWidth;
|
||||
canvas.height = innerHeight;
|
||||
mousePosition.radius = ((canvas.height / 80) * (canvas.width / 80));
|
||||
init();
|
||||
});
|
||||
|
||||
// mouse-out event (mouse leaving the window)
|
||||
window.addEventListener('mouseout', function(){
|
||||
mousePosition.x = undefined;
|
||||
mousePosition.y = undefined;
|
||||
});
|
||||
|
||||
init();
|
||||
animate();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// colours used thoughout site
|
||||
:root {
|
||||
--col-bg-canvas: #2c2830;
|
||||
--col-particle: #ebe7c5;
|
||||
--col-particle-stroke: #692e50;
|
||||
--col-particle-stroke-hover: #9aa68b;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* based on Eric Meyer's CSS Reset 2.0 (http://meyerweb/eric/tools/css/reset/)
|
||||
modified for easier implementation of REM font-sizing with default set to
|
||||
62.5% or 10px on most browsers by default. Media-queries adjusts this base conversion.
|
||||
*/
|
||||
|
||||
@media only screen and (max-width: 640px) {
|
||||
:root {
|
||||
font-size: 42.5%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 641px) and (max-width: 1024px) {
|
||||
:root {
|
||||
font-size: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1025px) {
|
||||
:root {
|
||||
font-size: 62.5%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
:root {
|
||||
height: 100%;
|
||||
scroll-behavior: smooth;
|
||||
width: 100%;
|
||||
body {
|
||||
font-size: 2.2rem;
|
||||
height: 100%;
|
||||
line-height: 2.2rem * 1.25;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, sub, sup, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
border: 0;
|
||||
box-sizing: border-box;
|
||||
font-size: inherit;
|
||||
font: inherit;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
/* HTML5 display-role reset for older browsers */
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/* styles of index */
|
||||
|
||||
/*
|
||||
import partials
|
||||
*/
|
||||
@import 'reset';
|
||||
@import 'palette';
|
||||
|
||||
#particles {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--col-bg-canvas);
|
||||
}
|
Loading…
Reference in New Issue