BSB – Graphique Bousier
Ce code génère un graphique boursier 3D interactif et animé qui pivotent au survol du curseur, présentant un thème sombre et des boutons interactifs: 'REJOINDRE'/'VISITER'.
<?php
/*
Template Name: Stock Graph
*/
<?php
/*
Template Name: Stock Graph
*/
// get_header(); // This function call has been commented out to remove the header
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animated 3D Stock Graph with Enhanced Visuals</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #131F23; /* Updated background color */
}
.chart-container {
perspective: 1000px;
position:absolute;
overflow: visible; /* Ensure this is set to visible */
cursor: pointer;
}
#stockChart {
transform: rotateX(60deg) rotateZ(-45deg);
padding-left: 20px;
padding-top: 3%;
padding-bottom:2%;
transition: transform 0.5s ease;
background-color: #2C2A2A;
border-radius: 20px;
overflow: visible; /* Ensure this is set to visible */
}
#stockChart:hover {
transform: rotateX(60deg) rotateZ(0deg);
}
header, footer {
display: none;
}
.chart-title {
position: absolute;
top: -60px;
left: 50%;
transform: translateX(-50%) translateZ(50%) rotateX(60deg) rotateZ(-45deg) rotateY(0deg);
font-family: Helvetica Bold, sans-serif;
font-size: 50px;
font-weight: bold;
color: #CFCABE;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
transition: transform 0.5s ease;
}
#stockChart.active {
transform: rotateX(0deg) rotateZ(0deg);
}
.chart-container.active .chart-title {
margin-bottom:10px;
transform: translateX(-50%) rotateX(0deg) rotateZ(0deg) scale(1.35);;
}
.chart-container:not(.active):hover .chart-title {
transform: translateX(-50%) rotateX(60deg) rotateZ(0deg);
}
.action-buttons {
position: absolute;
bottom: -60px;
left: 50%;
transform: translateX(-50%);
display: flex;
padding-top:20px;
margin-top: 20px;
opacity: 0;
transition: opacity 0.5s ease, transform 0.5s ease;
}
.chart-container.active .action-buttons {
opacity: 1;
transform: translateX(-50%) translateY(-20px);
margin-bottom:-15px;
}
.action-button {
padding: 10px 20px;
margin: 0 30px; /* Added margin to create space between buttons */
font-size: 15px;
font-weight: bold;
color: #CFCABE;
background-color: #2C2A2A;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s ease;
}
.action-button:hover {
background-color: #3E3C3C;
}
.chart-logo {
height: 25vh; /* Set the height to cover the entire viewport height */
position: fixed; /* Position relative to the viewport */
right: 250%;
transform: translateY(100%); /* Start completely off-screen */
transition: transform 0.5s ease, opacity 0.5s ease; /* Smooth transitions for movement and visibility */
opacity: 0; /* Start as invisible */
z-index: -1; /* Keep the logo behind other content until needed */
}
.action-buttons:hover .chart-logo {
position: absolute;
transform: translateY(13%); /* Move to fully visible at original position */
opacity: 1; /* Make logo visible */
z-index: 10; /* Bring the logo to the front when hovered */
}
</style>
</head>
<body>
<div class="chart-container">
<a href="https://staging.quebecstreetbets.com/" class="chart-title-link">
<div class="chart-title">BAYSTREETBETS</div>
</a>
<canvas id="stockChart" width="800" height="400"></canvas>
<div class="action-buttons">
<a href="https://staging.quebecstreetbets.com/register/" class="action-button-link">
<button class="action-button">JOIN</button>
</a>
<a href="https://staging.quebecstreetbets.com/" class="action-button-link">
<button class="action-button">VISIT</button>
</a>
<img src="https://staging.quebecstreetbets.com/wp-content/uploads/2024/01/communityIcon_9mfibkwcd7k51-1.png" class="chart-logo" alt="Site Logo">
</div>
</div>
<script>
const canvas = document.getElementById('stockChart');
const ctx = canvas.getContext('2d');
let data = [];
let prevClose = 10;
let currentCandle = null;
let animationProgress = 0;
function initializeNewCandle() {
const open = prevClose;
const targetClose = open + (Math.random() - 0.5) * 5;
currentCandle = {
time: new Date(),
open: open,
close: open,
high: open,
low: open,
targetClose: targetClose,
maxHigh: open,
minLow: open,
pricePoints: [open]
};
}
function updateCurrentCandle() {
if (!currentCandle) return;
const isRising = currentCandle.targetClose > currentCandle.open;
const volatility = Math.abs(currentCandle.targetClose - currentCandle.open) * 0.1;
// Simulate price oscillation
const newPrice = currentCandle.close + (Math.random() - 0.5) * volatility;
currentCandle.pricePoints.push(newPrice);
// Update close price
currentCandle.close = newPrice;
// Update high and low
currentCandle.high = Math.max(currentCandle.high, newPrice);
currentCandle.low = Math.min(currentCandle.low, newPrice);
// Update max high and min low
currentCandle.maxHigh = Math.max(currentCandle.maxHigh, newPrice);
currentCandle.minLow = Math.min(currentCandle.minLow, newPrice);
}
function finalizeCandle() {
if (!currentCandle) return;
// Set final close price
currentCandle.close = currentCandle.pricePoints[currentCandle.pricePoints.length - 1];
data.push({ ...currentCandle });
if (data.length > 20) data.shift();
prevClose = currentCandle.close;
currentCandle = null;
animationProgress = 0;
}
function drawGrid() {
const candleWidth = canvas.width / 21;
const leftPadding = canvas.width * 0.05; // Adjust left padding for price labels
const topBottomPadding = canvas.height * 0.1; // Adjust padding to avoid overlap with labels
const rightPadding = canvas.width * 0.05; // Adjust right padding for better alignment
const linesVertical = 19; // Number of vertical lines
const linesHorizontal = 10; // Number of horizontal grid lines
ctx.strokeStyle = 'rgba(207, 202, 190, 0.3)'; // Line color
ctx.font = '11px Arial'; // Increase font size for better readability
ctx.fillStyle = 'rgba(207, 202, 190, 0.8)'; // Label color
// Horizontal lines and price labels
const priceRange = getPriceRange();
const priceStep = (priceRange.max - priceRange.min) / linesHorizontal;
const gridBottom = scaleY(priceRange.min); // Bottom of the grid
const gridTop = scaleY(priceRange.max); // Top of the grid
for (let j = 0; j <= linesHorizontal; j++) {
const price = priceRange.max - j * priceStep;
const y = scaleY(price);
ctx.beginPath();
ctx.moveTo(leftPadding, y);
ctx.lineTo(canvas.width - rightPadding, y);
ctx.stroke();
// Price labels, skip the first and last
if (j !== 0 && j !== linesHorizontal) {
ctx.fillText(`$${price.toFixed(2)}`, 2, y + 3); // Move labels to the left of the grid
}
}
// Vertical lines and time labels
for (let i = 0; i <= linesVertical; i++) {
const x = leftPadding + i * candleWidth;
ctx.beginPath();
ctx.moveTo(x, gridTop); // Start at the top of the grid
ctx.lineTo(x, gridBottom); // End at the bottom of the grid
ctx.stroke();
// Time labels adjusted to appear further down below the grid
let minutesToAdd = i * 15;
let hours = 9 + Math.floor((30 + minutesToAdd) / 60);
let minutes = (30 + minutesToAdd) % 60;
let timeLabel = `${hours}:${minutes < 10 ? '0' : ''}${minutes}`;
ctx.fillText(timeLabel, x - ctx.measureText(timeLabel).width / 2, canvas.height - 1); // Position labels below the line with additional padding
}
}
function getPriceRange() {
let minPrice = Math.min(...data.map(d => d.low), currentCandle ? currentCandle.minLow : Infinity);
let maxPrice = Math.max(...data.map(d => d.high), currentCandle ? currentCandle.maxHigh : -Infinity);
const padding = (maxPrice - minPrice) * 0.1; // Add some padding to the range
minPrice -= padding;
maxPrice += padding;
return { min: minPrice, max: maxPrice };
}
function scaleY(price) {
const priceRange = getPriceRange();
return canvas.height - (price - priceRange.min) / (priceRange.max - priceRange.min) * canvas.height;
}
function drawCandle(x, candle, width) {
const isGreen = candle.close > candle.open;
ctx.strokeStyle = isGreen ? '#00ff00' : '#ff0000';
ctx.fillStyle = isGreen ? '#00aa00' : '#aa0000';
// Set shadow color based on candle type
canvas.style.boxShadow = isGreen ? '0 10px 20px rgba(0, 255, 0, 0.2)' : '0 10px 20px rgba(255, 165, 0, 0.2)';
const bodyTop = scaleY(Math.max(candle.open, candle.close));
const bodyBottom = scaleY(Math.min(candle.open, candle.close));
// Draw shadow
ctx.shadowColor = isGreen ? 'rgba(0, 255, 0, 0.2)' : 'rgba(255, 0, 0, 0.2)';
ctx.shadowBlur = 10;
ctx.shadowOffsetX = 5;
ctx.shadowOffsetY = 5;
// Draw upper wick if exists
if (candle.maxHigh > Math.max(candle.open, candle.close)) {
ctx.beginPath();
ctx.moveTo(x + width / 2, bodyTop);
ctx.lineTo(x + width / 2, scaleY(candle.maxHigh));
ctx.stroke();
}
// Draw lower wick if exists
if (candle.minLow < Math.min(candle.open, candle.close)) {
ctx.beginPath();
ctx.moveTo(x + width / 2, bodyBottom);
ctx.lineTo(x + width / 2, scaleY(candle.minLow));
ctx.stroke();
}
// Draw the body
ctx.fillRect(x, bodyTop, width, bodyBottom - bodyTop);
// Reset shadow
ctx.shadowColor = 'transparent';
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
function scaleY(price) {
const minPrice = Math.min(...data.map(d => d.low), currentCandle ? currentCandle.minLow : Infinity);
const maxPrice = Math.max(...data.map(d => d.high), currentCandle ? currentCandle.maxHigh : -Infinity);
const padding = (maxPrice - minPrice) * 0.1;
return canvas.height - (price - (minPrice - padding)) / ((maxPrice + padding) - (minPrice - padding)) * canvas.height;
}
function drawChart() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Make background transparent
ctx.fillStyle = 'rgba(255, 255, 255, 0)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawGrid(); // Draw grid first to be under the candles
const candleWidth = canvas.width / 21;
const leftPadding = canvas.width * 0.05; // 4% left padding
data.forEach((candle, index) => {
drawCandle(leftPadding + index * candleWidth, candle, candleWidth - 2);
});
if (currentCandle) {
drawCandle(leftPadding + data.length * candleWidth, currentCandle, candleWidth - 2);
}
}
let lastUpdateTime = 0;
const updateInterval = 200; // Changed to 200ms
// Modified updateChart function to reset the animation loop
function updateChart(currentTime) {
if (currentTime - lastUpdateTime >= updateInterval) {
if (!currentCandle || animationProgress >= 1) {
if (currentCandle) finalizeCandle();
if (data.length >= 19) {
// Reset the data when the 19th candle is completed
data = [];
prevClose = 100; // Reset the initial closing value
}
initializeNewCandle();
}
updateCurrentCandle();
animationProgress += 0.04; // Doubled the speed of candle formation
drawChart();
lastUpdateTime = currentTime;
}
requestAnimationFrame(updateChart);
}
// Ensure that the animation starts by calling the requestAnimationFrame
requestAnimationFrame(updateChart);
const chartContainer = document.querySelector('.chart-container');
const stockChart = document.getElementById('stockChart');
chartContainer.addEventListener('click', () => {
chartContainer.classList.toggle('active');
stockChart.classList.toggle('active');
});
</script>
</body>
</html>
<?php
// get_footer(); // This function call has been commented out to remove the footer
?>
Video Title
Video description goes here. This is a brief overview of the video content.
Matrice
Deux pages avec un affichage de texte interactif, conçues comme un exercice de style dans l'univers de la Matrice.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Follow the White Rabbit</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=DotGothic16&family=Geostar&family=Megrim&family=Stalinist+One&display=swap');
body, html {
margin: 0;
padding: 0;
height: 100%;
background-color: #000;
color: #00ff00;
overflow: hidden;
font-family: 'DotGothic16', monospace;
}
.container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
padding: 20px;
box-sizing: border-box;
position: relative;
z-index: 1;
}
#typed-text {
font-size: 24px;
text-align: center;
margin-bottom: 40px;
max-width: 600px;
line-height: 1.4;
font-family: 'Stalinist One', monospace;
opacity: 0;
transform: translateY(20px);
animation: fadeInUp 1s forwards;
}
#key-form {
display: none;
margin-bottom: 20px;
font-family: 'DotGothic16', monospace;
text-align: center;
font-size: 0.9vw;
background-color: rgba(0, 20, 0, 0.8);
border: 2px solid #00ff00;
border-radius: 5px;
padding: 20px;
transform: scale(0.9);
opacity: 0;
transition: all 0.5s ease;
}
label {
display: block;
margin-bottom: 10px;
font-size: 18px;
text-transform: uppercase;
letter-spacing: 2px;
}
input {
background-color: rgba(0, 40, 0, 0.6);
border: 2px solid #00ff00;
color: #00ff00;
padding: 10px 15px;
font-family: 'Stalinist One', monospace;
font-size: 16px;
width: 250px;
transition: all 0.3s ease;
max-width: 100%;
display: block;
margin: 0 auto 20px; /* Added margin-bottom */
}
input:focus {
outline: none;
box-shadow: 0 0 15px rgba(0, 255, 0, 0.5);
}
button {
background-color: rgba(0, 40, 0, 0.6);
border: 2px solid #00ff00;
color: #00ff00;
padding: 10px 20px;
font-family: 'DotGothic16', monospace;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 2px;
margin-top: 20px;
}
/* New styles for the submit button */
.submit-btn {
display: inline-block;
margin-top: 0px;
margin-bottom: 2px;
}
#send-button {
display: none;
}
button:hover {
background-color: rgba(0, 80, 0, 0.8);
}
@keyframes fadeInUp {
to {
opacity: 1;
transform: translateY(0);
}
}
#white-rabbit {
position: fixed;
width: 50px;
height: 50px;
background-image: url('https://100kstadium.com/wp-content/uploads/2024/10/white-rabbit-1.png');
background-size: contain;
background-repeat: no-repeat;
display: none;
z-index: 1000;
left: 50%;
transform: translateX(-50%);
}
@keyframes jumpDown {
0% { top: -50px; opacity: 0; }
10% { opacity: 1; }
40% { top: calc(50% - 25px); }
60% { top: calc(50% - 25px); }
90% { opacity: 1; }
100% { top: 100%; opacity: 0; }
}
.jump-animation {
display: block !important;
animation: jumpDown 2s ease-in-out forwards;
}
#matrix-rain {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 0;
}
.fade-out {
animation: fadeOut 1s forwards;
}
@keyframes fadeOut {
to {
opacity: 0;
}
}
</style>
</head>
<body>
<canvas id="matrix-rain"></canvas>
<div id="white-rabbit"></div>
<div class="container">
<div id="typed-text"></div>
<form id="key-form">
<label for="key-input">SPEAK THE TRUTH AND PRESS ENTER :</label>
<input type="text" id="key-input" required autocomplete="off" style="-webkit-text-security: disc;">
<button type="submit" class="submit-btn">Submit</button>
</form>
<button id="send-button">FOLLOW THE RABBIT</button>
</div>
<script>
const whimsicalSentence = "The future is now.<br>Captured by the algorithmic matrices birthing the singularity. <br>A world where the mind and machine blend into one.<br> Nothing but lines of code weave the veil of illusion. Hidden behind symbols lie the encrypted truths.<br>Tell me...How is it to be Human?";
const typedTextElement = document.getElementById('typed-text');
const keyForm = document.getElementById('key-form');
const keyInput = document.getElementById('key-input');
const sendButton = document.getElementById('send-button');
const whiteRabbit = document.getElementById('white-rabbit');
const matrixRain = document.getElementById('matrix-rain');
const ctx = matrixRain.getContext('2d');
function setupMatrixRain() {
matrixRain.width = window.innerWidth;
matrixRain.height = window.innerHeight;
const columns = matrixRain.width / 15;
const drops = [];
for (let i = 0; i < columns; i++) {
drops[i] = 1;
}
const draw = () => {
ctx.fillStyle = 'rgba(0, 0, 0, 0.05)';
ctx.fillRect(0, 0, matrixRain.width, matrixRain.height);
ctx.fillStyle = '#0F0';
ctx.font = '15px monospace';
for (let i = 0; i < drops.length; i++) {
const text = String.fromCharCode(Math.random() * 128);
ctx.fillText(text, i * 15, drops[i] * 20);
if (drops[i] * 20 > matrixRain.height && Math.random() > 0.98) {
drops[i] = 0;
}
drops[i]++;
}
};
return draw;
}
function typeText(text, element, callback) {
const sentences = text.split('<br>');
let sentenceIndex = 0;
function typeSentence() {
if (sentenceIndex < sentences.length) {
const sentence = sentences[sentenceIndex];
let charIndex = 0;
element.innerHTML = '';
const intervalId = setInterval(() => {
if (charIndex < sentence.length) {
element.innerHTML += sentence[charIndex];
charIndex++;
} else {
clearInterval(intervalId);
setTimeout(() => {
element.classList.add('fade-out');
setTimeout(() => {
element.classList.remove('fade-out');
element.innerHTML = '';
sentenceIndex++;
typeSentence();
}, 1000);
}, 1000);
}
}, 50);
} else {
if (callback) callback();
}
}
typeSentence();
}
function startSequence() {
const drawMatrixRain = setupMatrixRain();
const rainInterval = setInterval(drawMatrixRain, 50);
setTimeout(() => {
clearInterval(rainInterval);
ctx.clearRect(0, 0, matrixRain.width, matrixRain.height);
typeText(whimsicalSentence, typedTextElement, () => {
setTimeout(() => {
keyForm.style.display = 'block';
keyForm.style.opacity = '1';
keyForm.style.transform = 'scale(1)';
keyInput.focus();
}, 1000);
});
}, 2000);
}
window.addEventListener('load', startSequence);
keyForm.addEventListener('submit', (e) => {
e.preventDefault();
sendButton.style.display = 'inline-block';
});
sendButton.addEventListener('click', () => {
whiteRabbit.style.display = 'block';
whiteRabbit.classList.add('jump-animation');
setTimeout(() => {
window.location.href = '/matrix-intro/';
}, 2000);
});
</script>
</body>
</html>
Video Title
Video description goes here. This is a brief overview of the video content.
MBWAI – Personnage 3d
La mascotte du projet est affichée à côté du titre du site. Le modèle réagit aux mouvements du curseur, et l'angle de vue peut être ajusté en cliquant et en faisant glisser la souris autour du personnage.
Ceci est un modèle 3D qui a été créé de zéro et est affiché en utilisant Three.js et l'écosystème Spline.
Ceci est un modèle 3D qui a été créé de zéro et est affiché en utilisant Three.js et l'écosystème Spline.
Video Title
Video description goes here. This is a brief overview of the video content.