Compare commits
10 Commits
25a330b1a4
...
4d1eb2a944
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d1eb2a944 | ||
|
|
a01f5a31fd | ||
|
|
6913851839 | ||
|
|
76888b1660 | ||
|
|
5df89aad65 | ||
|
|
3d6e616d1a | ||
|
|
8a3348ae59 | ||
|
|
1115a37340 | ||
|
|
3e66fca0be | ||
|
|
13ec138c1f |
@@ -10,8 +10,8 @@ steps:
|
||||
from_secret: reg_user
|
||||
password:
|
||||
from_secret: reg_password
|
||||
registry: dockerreg.gltronic.ovh
|
||||
repo: dockerreg.gltronic.ovh/nexusv7
|
||||
registry: registry.glt.sx
|
||||
repo: registry.glt.sx/nexusv7
|
||||
|
||||
- name: deploy
|
||||
image: appleboy/drone-ssh
|
||||
|
||||
1
convertToWebp.sh
Normal file
@@ -0,0 +1 @@
|
||||
find . -name "*.png" -exec sh -c 'cwebp $1 -q 90 -o ${1%.*}.webp' sh {} \;
|
||||
@@ -6,14 +6,12 @@ yearonly: true
|
||||
url: 2020.html
|
||||
---
|
||||
|
||||
Ordre de création décroissant
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
@@ -6,8 +6,9 @@ yearonly: true
|
||||
url: 2021.html
|
||||
---
|
||||
|
||||
Ordre de création décroissant
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
11
raws/artworks/2022.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: Blender 2022
|
||||
tags: 2022 blender artworks
|
||||
date: 2022-01-01
|
||||
yearonly: true
|
||||
url: 2022.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Les sites web perso
|
||||
tags: blog sites perso
|
||||
date: 2020-01-04
|
||||
yearonly: false
|
||||
url: les-sites-web-perso.html
|
||||
---
|
||||
|
||||
Le web est construit sur le principe de la décentralisation. L’extinction d’une machine ne réduit pas à néant le réseau. Pourtant, la navigation de la plupart des gens repose sur quelques sites majeurs. Je pourrais en dire autant. YouTube, Twitter, reddit et par extension imgur composent l’entièreté de ma consommation de média régulier. Et il est le problème. Si un de ces sites s’arrête, des millions de personnes se retrouvent démunies de leur expérience d’Internet.
|
||||
|
||||
Pourtant j’apprécie tout particulièrement les sites web personnels. Ils ont une personnalité, parfois un petit air naïf. On est loin de ces sites sans vie optimisée pour la consommation de contenu et de pub. Toujours pensé pour le mobile, adaptable à tous et pour tous. Mais ils sont bien pratiques ces sites. Ils centralisent à eux seul la grande majorité du contenu. On cherche une vidéo ? YouTube a sans doute quelque chose. PeerTube est une réponse au problème de YouTube. Mais il y a quelques problèmes sur la forme pour que cela décolle vraiment. La gestion des comptes est confuse et l’utilisation tout autant. Pour Twitter, Mastodon existe. Et il marche excellemment bien. Mais il y a à peu près le même problème que PeerTube. Enfin Reddit est manquant à l’appel de la décentralisation.
|
||||
|
||||
Mais le cas de Reddit est particulier. Jusqu’à récemment, Reddit n’hébergeaient que du texte. Il était donc facile de déplacer une petite communauté. En soi Reddit n’est qu’un imageboard avec un système de vote. Mais le site est pratique. Sur une même plateforme, on rassemble toutes sortes de communautés. Il y en a pour tous les goûts, elles sont chacune autogérés par leurs propres modérateurs.
|
||||
|
||||
Les sites personnels ont toujours été présents et le seront toujours. Avec plus ou moins de visibilités. Le problème c’est la découvrabilité. On peut difficilement tomber sur un site personnel par un total hasard. Le site Medium tente, d’une certaine manière, de répondre a ce problème. Aujourd’hui beaucoup de sites de presse utilisent des rédacteurs indépendants pour remplir leur site d’un contenu divers et constant. Mais il y a une sélection. Donc exit les sites étranges et les sous-cultures.
|
||||
|
||||
Viens ensuite l’accès à la création. Tout le monde n’a pas la capacité de créer de toutes pièces son site et de l’héberger. Dans mon monde idéal tout le monde a un petit serveur simple chez soi pour ses données personnelles. Il y a certain temp, les Skyblogs étaient un outil simple, gratuit, utilisable par tout le monde. Il y avait de tout. Des blogs étranges de partout. Tumblr fait ça aujourd’hui. Facebook mais sans la personnalité. Mais le souci, c’est encore la centralisation. Tout dépend du bon vouloir et des envies de l’entreprise derrière. Lorsque Tumblr fut racheté par Verizon, une violente politique de censure fut mise en place pour rendre le site le plus compatible avec les annonceurs.
|
||||
|
||||
Alors pour lutter contre tout ça et perpétué l’esprit décentralisé d’Internet, ce site existe. Il n’est qu’une goutte d’eau dans un océan, et l’expression n’est presque pas assez, mais c’est déjà quelque chose.
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: La grande virtualization
|
||||
tags: docker virtualization
|
||||
date: 2020-01-12
|
||||
yearonly: false
|
||||
url: la-grande-virtualization.html
|
||||
---
|
||||
|
||||
J’ai deux serveurs chez moi. Un très vieux (dual core, 1Go ram !) que j’ai récupéré d’une destruction certaine. Et un autre, plus récent, d’occasion aussi, aussi récupéré. C’est sur ce dernier que tournent la plupart de mes services. Il y a ce site, un git, plex, urbackup et le truc du moment que je teste.
|
||||
|
||||
Sur ces deux machines, la recette est la même : Fedora Server et tout est installé depuis les sources. C’est souvent difficile à maintenir à jour et facile de casser quelque chose. Alors bien souvent, il y a eu des week-ends de frustration. Une fois que ça tenait vaguement je n’y touchais plus pendant quelques mois et puis je me dis que je vais refaire mais en mieux. Et tout recommence. Avec le temps, j’ai appris mais ça restait long et fastidieux.
|
||||
|
||||
Un peu partout, tout le monde parlait de la nouvelle technique a la mode pour les serveurs : tout virtualisé. Tout mettre dans des conteneurs. Je me suis longtemps dit que c’était un peu exagéré pour mon cas. Et puis j’ai fini par installer Docker, Docker-compose et Portainer.
|
||||
|
||||
Le week-end dernier j’ai déplacé tous mes services dans des conteneurs Docker. Les images de LinuxServer.io sont une bénédiction. Avec un minimum de connaissances sur Docker, j’ai pu tout mettre en place en une petite après-midi. Mettre en jours n’importe lequel de ces conteneurs n’est qu’une histoire d’exécuter le docker-compose.yml lui correspondant. En installer un nouveau prends quelques minutes. C’est très « plug & play » une fois qu’on a compris la logique pour les gérer. Le site est dans son propre conteneur maison. Dockeriser un programme Node.js est très simple.
|
||||
|
||||
Couplé avec urbackup pour sauvegarder les configurations des conteneurs sur un disque annexe, je peux aisément changer de distribution, avoir du matériel en panne ou même le changer.
|
||||
@@ -1,51 +0,0 @@
|
||||
---
|
||||
title: Migration gitea vers docker
|
||||
tags: gitea docker
|
||||
date: 2020-03-03
|
||||
yearonly: false
|
||||
url: migration-gitea-docker.html
|
||||
---
|
||||
|
||||
# Introduction
|
||||
Lors de la grande migration vers Docker, une étape majeure était l’instance gitea. J’avais déja une installation faite du 'binary' gitea et d’un service Linux.
|
||||
|
||||
Gitea fourni une explication 'Backup and Restore' dans la documentation officielle.
|
||||
|
||||
# La marche à suivre
|
||||
## Première étape : Exporter l’installation actuelle.
|
||||
> su git
|
||||
|
||||
> ./gitea dump -c /etc/gitea/app.ini
|
||||
|
||||
Il faut prendre soin de fournir une copie du binary 'gitea' a l’utilisateur git. En le copiant dans son dossier home avec un chown par exemple.
|
||||
Quitter l’utilisateur avec 'exit', récupérer l’archive obtenue et l’extraire.
|
||||
|
||||
## Seconde étape : Docker
|
||||
Créé et lancer son conteneur gitea. Je le fais à partir d’un docker-compose.yml que l’on trouve dans la documentation officielle, dans la section 'installation With Docker'.
|
||||
|
||||
Ne pas oublier d’arrêter le service existant de gitea pour éviter les conflits de ports.
|
||||
|
||||
Une fois le conteneur lancé, il faut configurer l’instance et terminer l’installation pour obtenir la configuration nécessaire. En particulier la base de données et les repositories.
|
||||
|
||||
## Troisième étape : Migration
|
||||
Depuis le dossier de l’archive extraite, copier les repositories.
|
||||
|
||||
> mv gitea-repositories/* /data/gitea_data/git/repositories/
|
||||
|
||||
La destination '/data/gitea_data/' dépend de la configuration des volumes du conteneur.
|
||||
|
||||
Ne pas oublier d’attribuer les bons droits aux dossiers copiés.
|
||||
|
||||
> chown -R user:user repositories/
|
||||
|
||||
'user' étant l’utilisateur attribuer a Docker.
|
||||
|
||||
Ensuite faire la migration de la base de données :
|
||||
|
||||
> sqlite3 /data/gitea_data/gitea/gitea.db < gitea-db.sql
|
||||
|
||||
La commande dépend de la base de données utilisée.
|
||||
|
||||
|
||||
|
||||
Et c’est tout. Si tout s’est bien passé, on peut se connecter a son instance gitea comme d’habitude et retrouver tous ses repo abandonnés.
|
||||
@@ -1,100 +0,0 @@
|
||||
---
|
||||
title: Faire une PWA avec VueJS
|
||||
tags: docker vuejs buefy
|
||||
date: 2020-03-07
|
||||
yearonly: false
|
||||
url: pwavuejs.html
|
||||
---
|
||||
|
||||
Récemment, j’ai voulu reprendre des applications mobiles que j’avais créés avec Flutter il y a quelques mois.
|
||||
À ma grande surprise, aucune ne marchait. Google était passé par là et avait changé l’API d’Android une fois de plus.
|
||||
Le plus simple pour récupérer mon code c’était de recréer des nouveaux projets, malheureusement la plupart des plugins aussi étaient devenus obsolète.
|
||||
|
||||
Alors plutôt que de tout refaire, je me suis penché sur une alternative pour créer des applications cross-platform : les applications web progressives. Alias PWA.
|
||||
|
||||
Une PWA, basiquement c’est un site web capable de plus ou moins fonctionner sans serveur. Tout le rendu est sur le client, on embarque un maximum dans le client. Cependant il y a des règles à respecter, par exemple : https obligatoire.
|
||||
|
||||
Alors comment on fait ? En soit, on peut écrire l’application en HTML/CSS/Javascript natif. Mais le code devient vite brouillon, difficile à maintenir. Si les pages sont un minimum dynamiques, on retrouve avec du HTML dans les scripts. C’est pourquoi il existe des frameworks Javascript.
|
||||
|
||||
# VueJS
|
||||
|
||||
Il existe plusieurs frameworks, notamment Angular, React et VueJS. VueJS est, pour moi, le plus abordable. La structure de ses fichiers ‘.vue’ est simple, on comprend vite l’intérêt de faire des composants. Alors allons-y.
|
||||
|
||||
## Installation
|
||||
Premièrement, on a besoin de ‘npm’. On commence par installer VueJS :
|
||||
|
||||
npm install -g @vue/cli
|
||||
|
||||
Puis on crée le projet. Le preset 'SimplePWA' ferra l'affaire :
|
||||
|
||||
vue create todo_app
|
||||
|
||||
Optionnel mais Buefy est une bibliothèque qui facilite grandement la création d'interfaces responsives.
|
||||
|
||||
cd todo_app
|
||||
npm install buefy
|
||||
|
||||
## La to-do list
|
||||
On va écrire une application rapide : une to-do liste.
|
||||
|
||||
Dans 'src/main.js' :
|
||||
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import './registerServiceWorker'
|
||||
import Buefy from 'buefy'
|
||||
|
||||
import 'buefy/dist/buefy.css'
|
||||
|
||||
vue.config.productionTip = false
|
||||
Vue.use(Buefy)
|
||||
|
||||
new Vue({
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
|
||||
Dans 'src/App.vue', on a trois grandes parties: Le template qui décrivent les éléments de la page, le script qui contient la logique applicative de la page et le css.
|
||||
|
||||
Dans 'src/App.vue' :
|
||||
|
||||
Missing code here
|
||||
|
||||
|
||||
## Configuration vers PWA
|
||||
Pour configurer la partie PWA, il y a deux principaux fichiers : vue.config.js et registerServiceWorker.js.
|
||||
Le premier n'existe pas pour le moment, c'est a nous de le créé.
|
||||
|
||||
vue.config.js, placé a la racine du projet:
|
||||
|
||||
module.exports = {
|
||||
pwa: {
|
||||
name: 'Todo',
|
||||
themeColor: '#2c3e50',
|
||||
msTileColor: '#2c3e50',
|
||||
appleMobileWebAppCapable: 'yes',
|
||||
appleMobileWebAppStatusBarStyle: 'black',
|
||||
|
||||
workboxOptions: {
|
||||
skipWaiting: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerServiceWorker.js contient plusieurs callback permetant d'adapter le comportement de l'application a son environnement.
|
||||
Une immédiate est 'updated()', pour mettre a jour l'application locale lorsque la source change.
|
||||
|
||||
updated () {
|
||||
console.log('New content is available; please refresh.')
|
||||
window.location.reload(true)
|
||||
},
|
||||
|
||||
Enfin pour avoir une PWA valide, il faut des généré une séries d'icone pour notre application. Il existe bon nombre de sites et petits logiciels qui permettent
|
||||
de générer tout ça automatiquement. De mon coté, je fais un mix de [RealFavIconGenerator](https://realfavicongenerator.net/) et d'ajustements a la main.
|
||||
|
||||
|
||||
## Outils
|
||||
|
||||
Un bon outil pour vérifié la validité de l'application en tant que PWA, c'est Google Lighthouse. Sous forme d'une extension Chromium, il fournit pas mal d'informations utile
|
||||
pour notre PWA mais aussi pour n'importe quel autre site.
|
||||
|
||||
Aussi il existe une extension très utile au développement de Vue: Vue.js devtools sous forme d'extension Firefox ou Chromium.
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
title: Sculpter avec Blender
|
||||
tags: sculpt blender 3D
|
||||
date: 2020-04-19
|
||||
yearonly: false
|
||||
url: sculptblender.html
|
||||
---
|
||||
|
||||
Depuis quelque temps déjà, je voulais apprendre à utiliser Blender correctement. Je l’avais déjà utilisé au travers d’un cours mais l’objectif était de programmer des outils avec Blender. Pas tellement de l’utiliser pour créer quelque chose.
|
||||
|
||||
J’ai souvent voulu créer des personnages, auparavant c’était sur papier avec un crayon. Mais je ne suis pas très doué et malgré plusieurs tentatives, j’ai beaucoup de mal travailler ma pratique du dessin.
|
||||
|
||||
Alors j’ai regardé la sculpture sous Blender. Dans un sens j’étais déjà familier avec de genre d’outils. J’ai pas mal fouillé, regarder beaucoup de tutoriels. La chaîne de YanSculpts en produit énormément, mais pour un débutant, je trouvais pas ça très clair. C’est plus une suite de conseil quand on connaît déjà la base.
|
||||
Puis j’ai trouvé la chaîne de Grant Abbitt, ses vidéo sont plus posés et très bien guidée. À partir de la, j’ai fait mes premiers pas.
|
||||
|
||||
## Un premier jet
|
||||
|
||||

|
||||
|
||||
C’est un début, j’ai aussi exploré l’application de texture avec le UV mapping. La bouche restait un défi particulier. Évidement pour un premier jet, il y a plein de défaut.
|
||||
|
||||
|
||||
## Un second essai
|
||||
|
||||
Ensuite j’ai fait un second essai, c’était surtout pour retravailler les bases sans suivre d’instructions.
|
||||
|
||||

|
||||
|
||||
Je l’ai abandonné, puis j’ai en est commencé un autre.
|
||||
|
||||
## L'expérience
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Celui-ci, c’est mon plus avancé. J’ai travaillé divers détails et finitions ainsi que les cheveux. Je suis pas fan des émetteurs pour les cheveux, donc je les ai faits en bloc. Mais ça donne un effet plastique et le détail est pas évident. Là ou il y a eu un problème, c’est que bien trop tard dans le processus, j’ai voulu retravailler la forme du visage. À ce moment-là, le niveau de détail était trop élevé et la forme global de la tête est devenu pour le moins étrange. Aussi même si la bouche n’a pas été un franc succès, j’ai compris la forme et la technique pour la faire.
|
||||
|
||||
En somme, j’ai beaucoup appris en une semaine. Évidement, il va falloir du temps et plus d’essais avant d’arriver a quelque chose qui ne fasse pas immédiatement peur.
|
||||
Mais c’est sur toutes ces erreurs que l’on apprend et la progression est satisfaisante.
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: Les frameworks Javascript
|
||||
tags: javascript framework
|
||||
date: 2020-04-23
|
||||
yearonly: false
|
||||
url: vanillajs.html
|
||||
---
|
||||
|
||||
Le mois dernier je vantais les mérites de Vue sur tous les toits. Aujourd’hui j'ai nouveau point de vue.
|
||||
|
||||
## L’état des lieux
|
||||
C’était peut-être dû a l’effet de nouveauté pour moi. Moi qui venais du monde du C et du Java EE, les applications web semblaient si déstructurées.
|
||||
L’ajout d’un framework a permis d’ajouter un contexte & des règles sur le style du code ainsi que son architecture. C’était bien.
|
||||
Mais il faut remonter a pourquoi ces outils. Certains diraient que c’est pour créer une fausse complexité de la part des développeurs web, d’autre que c’est seulement par mode. Mais le web reste très jeune, chaque mois il y a une nouvelle manière de faire, pas forcément mieux mais différente de l’ancienne. Et puis le web évolue plus vite que ses normes. Ça devient vite compliqué de faire du web proprement.
|
||||
|
||||
Les frameworks comme Vue apporte une stabilité dans tout ça. Mais ça inclue aussi de la complexité. En regardant plusieurs conférences sur le Javascript, j’ai compris que les frameworks ne sont pas nécessaire. Ils ne sont pas l’outil absolu dont on est obligé pour faire quoi que ce soit. Moi-même je suis tombé dans un cas ou le framework me limitait dans ce que je voulais faire. C’était plus simple d’écrire l’application sans framework.
|
||||
|
||||
## Au bûcher
|
||||
|
||||
En réalité, c’est au cas par cas. Il faut savoir quand un framework est vraiment utile. Souvent, du Javascript ou Typescript, c’est selon les préférences, accompagné de quelques bibliothèques simple dont on a vraiment besoin est plus stable, simple à utiliser et maintenir qu’un framework comportant plus de 1000 dépendances.
|
||||
|
||||
Il y a ce sentiment d’usine à gaz qui apparaît souvent dans ce genre de cas. Alors qu’est-ce qu’on fait ? On met tout ça a la poubelle ? On brûle npm avec tous ses défauts, convertit tous les sites des plus grands au Javascript pur ? Bien sûr que non. Comme dit plus haut, le web avec tous ses sites dynamiques et ses applications comparables au Desktop est très jeune. On est dans une période d’expérimentation. Personne n’a trouvé la formule magique, elle change tous les mois après tout.
|
||||
@@ -1,37 +0,0 @@
|
||||
---
|
||||
title: Sculpter avec Blender 2
|
||||
tags: sculpt blender 3D
|
||||
date: 2020-06-06
|
||||
yearonly: false
|
||||
url: sculptblender2.html
|
||||
---
|
||||
|
||||
Je reviens après presque deux mois de progrès. J’ai été beaucoup occupé ce dernier mois, je n’ai pas pu autant avancer que ce que j'imaginais.
|
||||
Au début, j’ai essayé de faire une sculpture tous les jours. Chaque jour, a 18 h après le travail, une session d’une voir deux heures.
|
||||
Ça a tenu vaguement deux semaines. Puis la motivation a oscillé, je ne savais plus dans quelle direction aller. Youtube est outil précieux pour
|
||||
Blender. J’ai continué à suivre les tutoriels de Grant Abbitt et ces derniers jours, Yan Sculpt aussi. J’avais du mal avec ce dernier au début. Mais
|
||||
il a des conseils et techniques très utiles quand on sait déja à peu près ce qu’on fait.
|
||||
|
||||
Alors voilà tout ce que j’ai sculpté depuis :
|
||||
|
||||
Tout est fait a la souris, je m’aide de plusieurs références, tous les personnages sont imaginés “sur le coup”.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||

|
||||
C’est sur celle ce que j’ai passé le plus de temps. Mais pas forcément pour sculpter le visage.
|
||||
|
||||
|
||||
## Le rendu
|
||||
Sur ma dernière sculpture j’ai compris que la présentation finale était importante. Un modèle a beau être très bien, s’il est mal éclairé avec un rendu bidon, il serra perçu comme tout pourri.
|
||||
|
||||
Alors je me suis mis à faire les matériaux de la peau et des yeux. La peau c’est quelque chose de subtile, il y a plein de manières et de style. J’ai essayé de rajouter du détail en peignant des rougeurs sur le visage (nez, joues, bouche) mais je fais tout a la souris pour le moment. Difficile d’éviter les gros points alors ça reste très discret. À grand ranfort de tuto Youtube, j’ai obtenu ça pour la peau :
|
||||

|
||||
|
||||
Et le rendu final après m’être battu avec les lumières et les réglages de rendu. Je ne les ai pas encore tous compris et je suis pas encore parfaitement satisfait. L’image fait un effet “flou” et les couleurs manque de contraste.
|
||||

|
||||
@@ -1,167 +0,0 @@
|
||||
---
|
||||
title: Setup Gitea / Drone / Docker
|
||||
tags: gitea drone cicd docker
|
||||
date: 2021-01-15
|
||||
yearonly: false
|
||||
url: giteadronedocker.html
|
||||
---
|
||||
|
||||
Je suis un grand fan du selfhosted. J'essais d'avoir un maximum de services directement dans mon chez moi. Le but n'est pas de s'isoler d'internet mais de
|
||||
reprendre le contrôle sur ce qui peut l'être.
|
||||
|
||||
# Gitea, Drone, Docker & You
|
||||
|
||||
Le plan est simple: avoir tout le pipeline d'intégration en local. Exit les coûts du ci/cd et de l'hébergement.
|
||||
|
||||
## Docker
|
||||
|
||||
Tout repose sur Docker pour simplifier un maximum la gestion / installation de l'ensemble de nos composants.
|
||||
Les commandes sont pour un système basé sur Debian, tout se base sur la [documentation officielle de Docker](https://docs.docker.com/engine/install/debian/).
|
||||
|
||||
On commence par ajouter le repo de Docker avec ses dépendances:
|
||||
|
||||
apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
|
||||
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian $(lsb_release -cs) stable"
|
||||
|
||||
On install Docker lui même:
|
||||
|
||||
apt-get update
|
||||
apt-get install docker-ce docker-ce-cli containerd.io
|
||||
systemctl enable docker
|
||||
|
||||
Puis Docker-compose:
|
||||
|
||||
curl -L "https://github.com/docker/compose/releases/download/1.27.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
|
||||
Enfin, on créé un registre docker local qui nous servira de cible pour drone.
|
||||
|
||||
Dans un fichier docker-compose.yml:
|
||||
|
||||
---
|
||||
version: "2"
|
||||
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
|
||||
services:
|
||||
registry:
|
||||
image: registry:2
|
||||
container_name: registry
|
||||
environment:
|
||||
- REGISTRY_HTTP_RELATIVEURLS=true
|
||||
volumes:
|
||||
- /docker_data/registry:/var/lib/registry
|
||||
ports:
|
||||
- 5000:5000
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
|
||||
## Gitea
|
||||
|
||||
C'est ici que le fun commence. On ajoute dans notre docker-compose sous services:
|
||||
|
||||
services:
|
||||
...
|
||||
gitea:
|
||||
image: gitea/gitea:latest
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER_UID=1000
|
||||
- USER_GID=1000
|
||||
restart: always
|
||||
networks:
|
||||
- gitea
|
||||
volumes:
|
||||
- /docker_data/gitea:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- 3000:3000
|
||||
- 222:22
|
||||
restart: unless-stopped
|
||||
|
||||
Sous volumes, /docker_data/gitea, est une préférence personnel pour ranger les fichiers de config des conteneurs Docker.
|
||||
|
||||
On lance le tout avec 'docker-compose up -d', et on va sur 'serveurIP:3000' pour configurer Gitea.
|
||||
|
||||
|
||||
## Drone
|
||||
|
||||
Même combat qu'avec Gitea, on ajoute Drone et un runner de base a notre docker-compose:
|
||||
|
||||
services:
|
||||
...
|
||||
drone:
|
||||
image: drone/drone
|
||||
container_name: drone
|
||||
depends_on:
|
||||
- gitea
|
||||
volumes:
|
||||
- /docker_data/drone:/var/lib/drone/
|
||||
environment:
|
||||
- DRONE_GITEA_SERVER=git.monsite
|
||||
- DRONE_GITEA_CLIENT_ID=...
|
||||
- DRONE_GITEA_CLIENT_SECRET=...
|
||||
- DRONE_RPC_SECRET=...
|
||||
- DRONE_SERVER_HOST=...
|
||||
- DRONE_SERVER_PROTO=http
|
||||
ports:
|
||||
- 8383:80
|
||||
- 8484:443
|
||||
restart: unless-stopped
|
||||
|
||||
drone-runner-docker:
|
||||
image: drone/drone-runner-docker
|
||||
container_name: drone-runner-docker
|
||||
depends_on:
|
||||
- drone
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
environment:
|
||||
- DRONE_RPC_PROTO=http
|
||||
- DRONE_RPC_HOST=...
|
||||
- DRONE_RPC_SECRET=...
|
||||
- DRONE_RUNNER_CAPACITY=2
|
||||
- DRONE_RUNNER_NAME=DefaultDockerRunner
|
||||
ports:
|
||||
- 8585:3000
|
||||
restart: unless-stopped
|
||||
|
||||
La on a plus de choses a configurer avant de lancer. Depuis Gitea, ajoutez une application et récupéré toutes les clé nécessaire a Drone. Avoir la [documentation de Drone](https://docs.drone.io/server/provider/gitea/#install-runners) avec soit ne fait pas de mal.
|
||||
|
||||
|
||||
## Utilisation du tout
|
||||
|
||||
Sur votre projet git favorit, par exemple superProjet, ajoutez un '.drone.yml':
|
||||
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
steps:
|
||||
- name: build
|
||||
image: plugins/docker
|
||||
settings:
|
||||
registry: dockerreg.monsite
|
||||
repo: dockerreg.monsite/superProjet
|
||||
- name: deploy
|
||||
image: appleboy/drone-ssh
|
||||
settings:
|
||||
host:
|
||||
from_secret: deploy_host
|
||||
username:
|
||||
from_secret: deploy_user
|
||||
password:
|
||||
from_secret: deploy_password
|
||||
port: 22
|
||||
script:
|
||||
- docker-compose pull superProjet
|
||||
- docker-compose up -d superProjet
|
||||
|
||||
Depuis l'interface de Drone, on active le repo de superProjet et on ajoute les secrets nécessaire.
|
||||
|
||||
Et maintenant on profite et abuse de notre super pipeline qui nous fait gagner du temps.
|
||||
@@ -6,7 +6,7 @@ yearonly: true
|
||||
url: initial2D.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [github.com/GLTron3000/Initial2D](https://github.com/GLTron3000/Initial2D.git)
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@ yearonly: true
|
||||
url: oozik.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/OozikApp](https://git.gltronic.ovh/gltron/OozikApp)
|
||||
git: [git.glt.sx/gltron/OozikApp](https://git.glt.sx/gltron/OozikApp)
|
||||
|
||||
Oozik est un lecteur de musique collaboratif conçu avec Flutter.
|
||||
Il se décline en une version avec serveur et une version en peer-to-peer.
|
||||
@@ -6,9 +6,9 @@ yearonly: true
|
||||
url: nexusv6.html
|
||||
---
|
||||
|
||||
git: [git.gltronic.ovh/gltron/NexusV6](https://git.gltronic.ovh/gltron/NexusV6)
|
||||
git: [git.glt.sx/gltron/NexusV6](https://git.glt.sx/gltron/NexusV6)
|
||||
|
||||
app: [gltronic.ovh](https://gltronic.ovh)
|
||||
app: [glt.sx](https://glt.sx)
|
||||
|
||||
NexusV6 est un générateur de site statique écrit Typescript tournant sous Node.
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ yearonly: true
|
||||
url: etienneremote.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/EtienneRemote](https://git.gltronic.ovh/gltron/EtienneRemote)
|
||||
git: [git.glt.sx/gltron/EtienneRemote](https://git.glt.sx/gltron/EtienneRemote)
|
||||
|
||||
app: [etienneremote.gltronic.ovh](https://etienneremote.gltronic.ovh)
|
||||
app: [etienneremote.glt.sx](https://etienneremote.glt.sx)
|
||||
|
||||
Etienne's Remote est une application web (PWA) créé avec Vue. Son but est de commander un bot Discord s'apparantant a une soundboard au travers d'une API Rest.
|
||||
@@ -6,10 +6,10 @@ yearonly: true
|
||||
url: cloud32.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/Cloud32](https://git.gltronic.ovh/gltron/Cloud32)
|
||||
git: [git.glt.sx/gltron/Cloud32](https://git.glt.sx/gltron/Cloud32)
|
||||
|
||||
app: [cloud.gltronic.ovh](https://cloud.gltronic.ovh)
|
||||
app: [cloud.glt.sx](https://cloud.glt.sx)
|
||||
|
||||
Cloud32 est un cloud personnel simple. Sert de 'to do list project' pour essayer des tech stack.
|
||||
@@ -6,10 +6,10 @@ yearonly: true
|
||||
url: lilstreamy.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/LilStreamy](https://git.gltronic.ovh/gltron/LilStreamy)
|
||||
git: [git.glt.sx/gltron/LilStreamy](https://git.glt.sx/gltron/LilStreamy)
|
||||
|
||||
app: [lilstreamy.gltronic.ovh](https://lilstreamy.gltronic.ovh)
|
||||
app: [lilstreamy.glt.sx](https://lilstreamy.glt.sx)
|
||||
|
||||
LilStreamy est une application web permettant de regarder une vidéo a plusieurs en peer-to-peer.
|
||||
@@ -6,10 +6,10 @@ yearonly: true
|
||||
url: mozen.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/Mozen](https://git.gltronic.ovh/gltron/Mozen)
|
||||
git: [git.glt.sx/gltron/Mozen](https://git.glt.sx/gltron/Mozen)
|
||||
|
||||
app: [mozen.gltronic.ovh](https://mozen.gltronic.ovh)
|
||||
app: [mozen.glt.sx](https://mozen.glt.sx)
|
||||
|
||||
Mozen est une plateforme de partage de modèle de machine learning.
|
||||
@@ -6,11 +6,11 @@ yearonly: true
|
||||
url: voozik.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/oozik](https://git.gltronic.ovh/gltron/oozik)
|
||||
git: [git.glt.sx/gltron/oozik](https://git.glt.sx/gltron/oozik)
|
||||
|
||||
app: [voozik.gltronic.ovh](https://voozik.gltronic.ovh)
|
||||
app: [voozik.glt.sx](https://voozik.glt.sx)
|
||||
|
||||
Voozik est une évolution de la version p2p de oozik.
|
||||
C'est une application web (PWA) permettant de partager une playlist youtube (musique/vidéo)
|
||||
|
||||
@@ -6,10 +6,10 @@ yearonly: true
|
||||
url: tronio.html
|
||||
---
|
||||
|
||||

|
||||

|
||||
|
||||
git: [git.gltronic.ovh/gltron/Tron.io](https://git.gltronic.ovh/gltron/Tron.io)
|
||||
git: [git.glt.sx/gltron/Tron.io](https://git.glt.sx/gltron/Tron.io)
|
||||
|
||||
app: [tronio.gltronic.ovh](https://tronio.gltronic.ovh)
|
||||
app: [tronio.glt.sx](https://tronio.glt.sx)
|
||||
|
||||
Tron.io est un jeu web multijoueurs
|
||||
|
||||
@@ -6,9 +6,9 @@ yearonly: true
|
||||
url: nexusv7.html
|
||||
---
|
||||
|
||||
git: [git.gltronic.ovh/gltron/NexusV7](https://git.gltronic.ovh/gltron/NexusV7)
|
||||
git: [git.glt.sx/gltron/NexusV7](https://git.glt.sx/gltron/NexusV7)
|
||||
|
||||
app: [gltronic.ovh](https://gltronic.ovh)
|
||||
app: [glt.sx](https://glt.sx)
|
||||
|
||||
NexusV7 est un générateur de site statique écrit en Rust.
|
||||
|
||||
|
||||
15
raws/projets/2022-01-01_quiz.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Out Of Quiz
|
||||
tags: rust vanillaJS jeu
|
||||
date: 2022-01-01
|
||||
yearonly: true
|
||||
url: quiz.html
|
||||
---
|
||||
|
||||

|
||||
|
||||
git: [git.glt.sx/gltron/OutOfQuiz](https://git.glt.sx/gltron/OutOfQuiz)
|
||||
|
||||
app: [quiz.glt.sx](https://quiz.glt.sx/)
|
||||
|
||||
Out Of Quiz est un jeu multijoueur de type quiz de vitesse, basé sur le Out Of Context d'un serveur Discord
|
||||
15
raws/projets/2022-02-01_impact.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Deep Impact
|
||||
tags: vanillaJS jeu
|
||||
date: 2022-02-01
|
||||
yearonly: true
|
||||
url: impact.html
|
||||
---
|
||||
|
||||

|
||||
|
||||
git: [git.glt.sx/gltron/DeepImpact](https://git.glt.sx/gltron/DeepImpact)
|
||||
|
||||
app: [impact.glt.sx](https://impact.glt.sx/)
|
||||
|
||||
Deep Impact est un missile command musical
|
||||
@@ -3,12 +3,11 @@ html, body {
|
||||
font-size: 17px;
|
||||
font-family: sans-serif;
|
||||
color:#444;
|
||||
background-color: #EEEEEE;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-image: url(/img/background.jpg);
|
||||
background-color: #465e5e;
|
||||
}
|
||||
|
||||
/** custom landing **/
|
||||
@@ -40,6 +39,14 @@ html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/** website **/
|
||||
|
||||
.avatar {
|
||||
@@ -66,6 +73,7 @@ html, body {
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
footer {
|
||||
@@ -90,8 +98,11 @@ footer {
|
||||
flex-grow: 1;
|
||||
width: 120px;
|
||||
max-width: 120px;
|
||||
height: 100%;
|
||||
margin: 15px;
|
||||
margin-right: 0px;
|
||||
border-radius: 10px;
|
||||
background-color: rgb(34, 34, 34);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.menuContainer ul {
|
||||
@@ -126,9 +137,14 @@ footer {
|
||||
flex-grow: 1;
|
||||
width: 400px;
|
||||
max-width: 400px;
|
||||
height: 100%;
|
||||
margin: 30px;
|
||||
margin-left: 0px;
|
||||
border-radius: 10px;
|
||||
border-top-left-radius: 0px;
|
||||
border-bottom-left-radius: 0px;
|
||||
overflow-y: scroll;
|
||||
background-color: rgb(219, 219, 219);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.submenuContainer h1 {
|
||||
@@ -184,17 +200,22 @@ footer {
|
||||
overflow-y: scroll;
|
||||
transition: 0.5s;
|
||||
text-align: justify;
|
||||
background-color: rgba(57, 57, 57, 0.649);
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.contentContainer article{
|
||||
.contentContainer article {
|
||||
overflow-y: auto;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
box-sizing: border-box;
|
||||
max-width: 900px;
|
||||
min-height: calc(100% - 20px);
|
||||
padding: 20px;
|
||||
background-color: rgb(219, 219, 219);
|
||||
border-radius: 10px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.contentContainer article h5 {
|
||||
@@ -240,8 +261,8 @@ footer {
|
||||
|
||||
@media only screen and (max-width: 1000px) {
|
||||
.menuContainer { width:100%; height: auto; max-width: 100%; }
|
||||
.submenuContainer { width:100%; height: auto; max-width: 100%; max-height: 500px; }
|
||||
.contentContainer { width:100%; height: auto; max-width: 100%; max-height: auto; overflow-y: visible; }
|
||||
.contentContainer article { width:100%; height: auto; max-width: 100%; overflow-y: visible; }
|
||||
.submenuContainer { width:100%; height: auto; max-width: 100%; max-height: 500px; border-radius: 10px; margin: 5px; }
|
||||
.contentContainer { width:100%; height: auto; max-width: 100%; max-height: auto; overflow-y: visible; border-radius: 10px; margin: 5px; }
|
||||
.contentContainer article { width:100%; height: auto; max-width: 100%; overflow-y: visible; border-radius: 10px; margin: 5px; }
|
||||
.sidebarnav a { font-size: 30px; }
|
||||
}
|
||||
BIN
resources/img/artworks/.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/img/artworks/2020/crown.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
resources/img/artworks/2020/face10.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
resources/img/artworks/2020/face11.webp
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
resources/img/artworks/2020/face12.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
resources/img/artworks/2020/face13.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
resources/img/artworks/2020/face14.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
resources/img/artworks/2020/face14full.webp
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
resources/img/artworks/2020/full1.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
resources/img/artworks/2020/full2.webp
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
resources/img/artworks/2021/LP_barrels.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/img/artworks/2021/LP_island.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
resources/img/artworks/2021/LP_planet.webp
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
resources/img/artworks/2021/roomBlackChair.webp
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
resources/img/artworks/2021/roomOrangeChair2.webp
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
resources/img/artworks/2021/roomWhiteChair.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
resources/img/artworks/2022/LP_airship.webp
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
resources/img/artworks/2022/the_end_r2b.webp
Normal file
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 560 KiB |
BIN
resources/img/avatar.webp
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 794 KiB |
BIN
resources/img/avatar2.webp
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 518 KiB |
BIN
resources/img/background.webp
Normal file
|
After Width: | Height: | Size: 131 KiB |
|
Before Width: | Height: | Size: 120 KiB |
BIN
resources/img/icon.webp
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 132 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 56 KiB |
BIN
resources/img/projets/c32_logo.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 26 KiB |
BIN
resources/img/projets/c32_node_logo.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 21 KiB |
BIN
resources/img/projets/c32b_logo.webp
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
|
Before Width: | Height: | Size: 105 KiB |
BIN
resources/img/projets/etienne_logo.webp
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
resources/img/projets/impact_logo.webp
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 139 KiB |
BIN
resources/img/projets/initial2D_logo.webp
Normal file
|
After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 14 KiB |
BIN
resources/img/projets/lilstreamy_logo.webp
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 26 KiB |
BIN
resources/img/projets/mozen_logo.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 74 KiB |
BIN
resources/img/projets/oozik_logo.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
resources/img/projets/quiz_logo.webp
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 24 KiB |
BIN
resources/img/projets/tronio_logo.webp
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB |
BIN
resources/img/projets/voozik_logo.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
85
resources/js/matrix.js
Normal file
@@ -0,0 +1,85 @@
|
||||
// Canvas Matrix
|
||||
|
||||
const hex = "0123456789ABCDEF".split("");
|
||||
const jap = "阪熊奈岡鹿梨阜埼茨栃媛".split("");
|
||||
|
||||
const matrix = document.getElementById("matrix");
|
||||
matrix.height = window.innerHeight;
|
||||
matrix.width = window.innerWidth;
|
||||
const ctx = matrix.getContext("2d", { alpha: false });
|
||||
|
||||
const font_size = 15;
|
||||
let columns = 0;
|
||||
let drops = [];
|
||||
const color = '#FFFFFF';
|
||||
let lastFrame = performance.now();
|
||||
|
||||
const gradient = ctx.createLinearGradient(0, 0, matrix.width, 0);
|
||||
gradient.addColorStop(0, '#ff0000');
|
||||
gradient.addColorStop(1 / 7, '#ff8000');
|
||||
gradient.addColorStop(2 / 7, '#ffff00');
|
||||
gradient.addColorStop(3 / 7, '#00ff00');
|
||||
gradient.addColorStop(4 / 7, '#00ffff');
|
||||
gradient.addColorStop(5 / 7, '#0000ff');
|
||||
gradient.addColorStop(6 / 7, '#ff00ff');
|
||||
gradient.addColorStop(1, '#ff0040');
|
||||
|
||||
|
||||
|
||||
function initDrop(pos) {
|
||||
return { pos, speed: Math.random() * 3 + 0.2, text: jap[Math.floor(Math.random()*jap.length)], red: Math.random() > 0.99 };
|
||||
}
|
||||
|
||||
function init() {
|
||||
columns = matrix.width / font_size;
|
||||
drops = [];
|
||||
for(let x=0; x < columns; x++) drops[x] = initDrop(matrix.height);
|
||||
}
|
||||
|
||||
function render() {
|
||||
// ctx.clearRect(0, 0, matrix.width, matrix.height);
|
||||
ctx.fillStyle = "#465e5e";
|
||||
ctx.globalAlpha = 0.1;
|
||||
ctx.fillRect(0, 0, matrix.width, matrix.height);
|
||||
ctx.globalAlpha = 1.0;
|
||||
|
||||
ctx.font = font_size + "px arial";
|
||||
|
||||
for(let i=0; i < drops.length; i++){
|
||||
const drop = drops[i];
|
||||
|
||||
if (drop.red) {
|
||||
ctx.fillStyle = "red";
|
||||
} else {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
|
||||
ctx.fillText(jap[Math.floor(Math.random()*jap.length)], i*font_size, drop.pos*(font_size/2));
|
||||
|
||||
if(drop.pos*(font_size/2) > matrix.height && Math.random() > 0.98) {
|
||||
drops[i] = initDrop(0);
|
||||
} else {
|
||||
drop.pos += drop.speed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function renderLoop() {
|
||||
const now = performance.now();
|
||||
|
||||
if ((now - lastFrame) > (1000 / 60)) {
|
||||
render();
|
||||
lastFrame = now;
|
||||
}
|
||||
|
||||
requestAnimationFrame(renderLoop);
|
||||
}
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
init();
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
init();
|
||||
requestAnimationFrame(renderLoop);
|
||||
});
|
||||
133
resources/js/planet.js
Normal file
@@ -0,0 +1,133 @@
|
||||
import * as THREE from 'https://cdn.skypack.dev/three@0.135.0';
|
||||
import { GLTFLoader } from 'https://cdn.skypack.dev/three@0.135.0/examples/jsm/loaders/GLTFLoader.js';
|
||||
|
||||
// Global vars
|
||||
const container = document.getElementById("background");
|
||||
let scene;
|
||||
let camera;
|
||||
let renderer;
|
||||
|
||||
let modelMoon;
|
||||
let modelPlanet;
|
||||
|
||||
// Animations global vars
|
||||
let incrementer = 0.01;
|
||||
let reverse = false;
|
||||
const rotationSpeed = 0.001;
|
||||
const orbitRadius = 1;
|
||||
let lastRender = 0
|
||||
|
||||
// Helper
|
||||
function setupContainer (container) {
|
||||
const width = container.offsetWidth;
|
||||
const height = container.offsetHeight;
|
||||
const aspect = width / height;
|
||||
camera.aspect = aspect;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(width, height);
|
||||
};
|
||||
|
||||
async function loadModel(path) {
|
||||
return new Promise((resolve) => new GLTFLoader().load(path, resolve));
|
||||
}
|
||||
|
||||
// Init
|
||||
function initScene() {
|
||||
// Scene
|
||||
renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.shadowMap.enabled = true;
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0xdfc465);
|
||||
scene.fog = new THREE.Fog(0x56bac9, 5, 25);
|
||||
|
||||
// Camera
|
||||
camera = new THREE.PerspectiveCamera(40, 1, 1, 100);
|
||||
camera.position.set(1, 1, 11);
|
||||
|
||||
// Listeners
|
||||
setupContainer(container);
|
||||
window.addEventListener("resize", () => setupContainer(container), false);
|
||||
}
|
||||
|
||||
function initLights() {
|
||||
// Global Light
|
||||
const hemiLight = new THREE.HemisphereLight(0xeab044, 0x444444);
|
||||
hemiLight.position.set(4, 0, 2);
|
||||
scene.add(hemiLight);
|
||||
|
||||
const dirLight = new THREE.DirectionalLight(0xffffff);
|
||||
dirLight.position.set(3, 10, 10);
|
||||
dirLight.castShadow = true;
|
||||
dirLight.shadow.camera.top = 2;
|
||||
dirLight.shadow.camera.bottom = -2;
|
||||
dirLight.shadow.camera.left = -2;
|
||||
dirLight.shadow.camera.right = 2;
|
||||
dirLight.shadow.camera.near = 0.1;
|
||||
dirLight.shadow.camera.far = 40;
|
||||
scene.add(dirLight);
|
||||
}
|
||||
|
||||
async function initModels() {
|
||||
// Load Models
|
||||
|
||||
modelPlanet = (await loadModel('models/LP_planet_only.glb')).scene;
|
||||
modelMoon = (await loadModel('models/LP_planet_moon.glb')).scene;
|
||||
|
||||
|
||||
modelPlanet.position.set(1, 1, 0);
|
||||
modelPlanet.castShadow = true;
|
||||
modelPlanet.receiveShadow = true;
|
||||
scene.add(modelPlanet);
|
||||
|
||||
modelMoon.position.set(1, 1, 0);
|
||||
modelMoon.castShadow = true;
|
||||
modelMoon.receiveShadow = true;
|
||||
scene.add(modelMoon);
|
||||
}
|
||||
|
||||
// Animation
|
||||
function easeInOut() {
|
||||
if (reverse) {
|
||||
incrementer -= 0.005;
|
||||
} else {
|
||||
incrementer += 0.005;
|
||||
}
|
||||
|
||||
if (incrementer >= 1 || incrementer <= 0) {
|
||||
reverse = !reverse;
|
||||
}
|
||||
|
||||
return incrementer < 0.5
|
||||
? 2 * incrementer * incrementer
|
||||
: 1 - Math.pow(-2 * incrementer + 2, 2) / 2;
|
||||
};
|
||||
|
||||
function animateScene() {
|
||||
|
||||
if ((performance.now() - lastRender) > (1000 / 60)) {
|
||||
modelPlanet.position.set(1, easeInOut() / 4 + 0.5, 0);
|
||||
modelPlanet.rotation.y += rotationSpeed;
|
||||
|
||||
// const x = Math.cos(incrementer) * orbitRadius;
|
||||
// const z = Math.sin(incrementer) * orbitRadius;
|
||||
modelMoon.position.set(0, 1 - easeInOut() - 2, 0);
|
||||
modelMoon.rotation.y -= rotationSpeed + 0.01;
|
||||
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
|
||||
requestAnimationFrame(animateScene);
|
||||
}
|
||||
|
||||
// Main
|
||||
export async function init() {
|
||||
initScene();
|
||||
initLights();
|
||||
await initModels();
|
||||
animateScene();
|
||||
}
|
||||
|
||||
init();
|
||||