anycoder-35c780fc / index.html
HI7RAI's picture
Upload folder using huggingface_hub
0a14f88 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flux | Creative Transition Playground</title>
<!-- Fonts & Icons -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=Space+Grotesk:wght@700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg-dark: #0f0f13;
--panel-bg: #1a1a24;
--accent: #6c5ce7;
--accent-hover: #a29bfe;
--text-main: #ffffff;
--text-muted: #a0a0a0;
--border: #2d2d3b;
--glass: rgba(26, 26, 36, 0.8);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-dark);
color: var(--text-main);
height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* Header */
header {
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid var(--border);
background: var(--panel-bg);
z-index: 10;
}
.brand {
font-family: 'Space Grotesk', sans-serif;
font-size: 1.5rem;
background: linear-gradient(45deg, var(--accent), #00d2d3);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -1px;
}
.anycoder-link {
font-size: 0.9rem;
color: var(--text-muted);
text-decoration: none;
transition: color 0.3s;
display: flex;
align-items: center;
gap: 8px;
}
.anycoder-link:hover {
color: var(--accent-hover);
}
/* Main Layout */
main {
flex: 1;
display: grid;
grid-template-columns: 350px 1fr;
height: calc(100vh - 70px);
}
/* Sidebar Controls */
.controls {
background: var(--panel-bg);
border-right: 1px solid var(--border);
padding: 2rem;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 2rem;
}
.control-group {
display: flex;
flex-direction: column;
gap: 0.8rem;
}
.control-group label {
font-size: 0.85rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
color: var(--text-muted);
}
/* Inputs & Selects */
input[type="file"] {
display: none;
}
.file-btn {
background: var(--bg-dark);
border: 1px dashed var(--border);
padding: 1rem;
border-radius: 8px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
color: var(--text-muted);
font-size: 0.9rem;
}
.file-btn:hover {
border-color: var(--accent);
color: var(--text-main);
}
select {
width: 100%;
padding: 0.8rem;
background: var(--bg-dark);
border: 1px solid var(--border);
color: white;
border-radius: 6px;
outline: none;
}
/* Sliders */
.slider-container {
display: flex;
flex-direction: column;
gap: 5px;
}
.slider-header {
display: flex;
justify-content: space-between;
font-size: 0.8rem;
}
input[type="range"] {
-webkit-appearance: none;
width: 100%;
height: 4px;
background: var(--border);
border-radius: 2px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: var(--accent);
border-radius: 50%;
cursor: pointer;
transition: transform 0.2s;
}
input[type="range"]::-webkit-slider-thumb:hover {
transform: scale(1.2);
}
/* Play Button */
.play-btn {
background: var(--accent);
color: white;
border: none;
padding: 1rem;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: background 0.3s, transform 0.1s;
font-size: 1rem;
margin-top: auto;
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
.play-btn:hover {
background: var(--accent-hover);
}
.play-btn:active {
transform: scale(0.98);
}
/* Stage / Canvas */
.stage {
position: relative;
background: #000;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
/* Grid pattern background */
background-image:
linear-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
background-size: 40px 40px;
}
.canvas-wrapper {
position: relative;
width: 600px;
height: 400px;
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
overflow: hidden;
border-radius: 4px;
transform-style: preserve-3d; /* For 3D effects */
perspective: 1000px;
}
.canvas-wrapper img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
user-select: none;
}
/* Layer A (Base) */
#layer-a {
z-index: 1;
}
/* Layer B (Transition) */
#layer-b {
z-index: 2;
opacity: 0;
pointer-events: none;
}
/* --- TRANSITIONS --- */
/* 1. Fade */
.transition-fade #layer-b {
opacity: 0;
transition: opacity var(--duration) var(--ease);
}
.transition-fade.active #layer-b {
opacity: var(--opacity-end);
}
/* 2. Slide Left */
.transition-slide-left #layer-b {
transform: translateX(100%);
opacity: 1;
transition: transform var(--duration) var(--ease);
}
.transition-slide-left.active #layer-b {
transform: translateX(0);
}
/* 3. Zoom In */
.transition-zoom #layer-b {
transform: scale(var(--scale-start));
opacity: 1;
transition: transform var(--duration) var(--ease);
}
.transition-zoom.active #layer-b {
transform: scale(var(--scale-end));
}
/* 4. Rotate 3D Cube */
.transition-cube #canvas-wrapper {
transform-style: preserve-3d;
}
.transition-cube #layer-a {
transform: rotateY(0deg);
backface-visibility: hidden;
}
.transition-cube #layer-b {
transform: rotateY(90deg);
opacity: 1;
backface-visibility: hidden;
}
.transition-cube.active #layer-b {
animation: cubeRotate var(--duration) forwards var(--ease);
}
@keyframes cubeRotate {
0% { transform: rotateY(90deg); }
100% { transform: rotateY(0deg); }
}
/* Fix for cube reverse logic requires more complex DOM, simplifying for CSS only */
.transition-cube.active #layer-a {
animation: cubeRotateBack var(--duration) forwards var(--ease);
}
@keyframes cubeRotateBack {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(-90deg); }
}
/* 5. Vertical Blinds (Clip Path) */
.transition-blinds #layer-b {
clip-path: polygon(0 0, 0 0, 0 100%, 0 100%);
opacity: 1;
transition: clip-path var(--duration) var(--ease);
}
.transition-blinds.active #layer-b {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}
/* 6. Glitch (Cyberpunk) */
.transition-glitch #layer-b {
opacity: 1;
clip-path: polygon(0 0, 100% 0, 100% 0, 0 0);
transition: none;
}
.transition-glitch.active #layer-b {
animation: glitch-anim var(--duration) steps(10) forwards;
}
@keyframes glitch-anim {
0% { clip-path: polygon(0 0, 100% 0, 100% 0, 0 0); opacity: 1;}
20% { clip-path: polygon(0 20%, 100% 20%, 100% 20%, 0 20%); transform: translate(-5px, 0); }
40% { clip-path: polygon(0 60%, 100% 60%, 100% 60%, 0 60%); transform: translate(5px, 0); }
60% { clip-path: polygon(0 80%, 100% 80%, 100% 80%, 0 80%); transform: translate(-5px, 0); }
80% { clip-path: polygon(0 40%, 100% 40%, 100% 40%, 0 40%); transform: translate(5px, 0); }
100% { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); transform: translate(0, 0); opacity: 1;}
}
/* Responsive */
@media (max-width: 900px) {
main {
grid-template-columns: 1fr;
grid-template-rows: 1fr 300px;
overflow-y: auto;
height: auto;
}
.stage {
min-height: 50vh;
}
.canvas-wrapper {
width: 90%;
height: 300px;
}
.controls {
border-right: none;
border-top: 1px solid var(--border);
}
}
</style>
</head>
<body>
<header>
<div class="brand"><i class="fa-solid fa-layer-group"></i> FLUX</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">
Built with anycoder <i class="fa-solid fa-arrow-up-right-from-square"></i>
</a>
</header>
<main>
<aside class="controls">
<!-- Image Inputs -->
<div class="control-group">
<label>Source Images</label>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
<label class="file-btn">
<input type="file" id="input-a" accept="image/*">
<i class="fa-regular fa-image"></i> Image A
</label>
<label class="file-btn">
<input type="file" id="input-b" accept="image/*">
<i class="fa-solid fa-image"></i> Image B
</label>
</div>
</div>
<!-- Transition Selector -->
<div class="control-group">
<label>Transition Style</label>
<select id="effect-select">
<option value="fade">Smooth Fade</option>
<option value="slide-left">Slide Left</option>
<option value="zoom">Zoom In/Out</option>
<option value="cube">3D Cube Rotate</option>
<option value="blinds">Vertical Blinds</option>
<option value="glitch">Cyber Glitch</option>
</select>
</div>
<!-- Parameter Editors -->
<div class="control-group">
<label>Parameters</label>
<div class="slider-container">
<div class="slider-header">
<span>Duration</span>
<span id="val-duration">1000ms</span>
</div>
<input type="range" id="duration" min="100" max="3000" step="100" value="1000">
</div>
<div class="slider-container">
<div class="slider-header">
<span>Scale Multiplier</span>
<span id="val-scale">1.5</span>
</div>
<input type="range" id="scale" min="0.5" max="3.0" step="0.1" value="1.5">
</div>
<div class="slider-container">
<div class="slider-header">
<span>End Opacity</span>
<span id="val-opacity">1.0</span>
</div>
<input type="range" id="opacity" min="0" max="1" step="0.1" value="1">
</div>
</div>
<button class="play-btn" id="play-btn">
<i class="fa-solid fa-play"></i> Play Transition
</button>
</aside>
<section class="stage">
<div class="canvas-wrapper" id="canvas-wrapper">
<!-- Default placeholders -->
<img id="layer-a" src="https://picsum.photos/id/10/800/600" alt="Image A">
<img id="layer-b" src="https://picsum.photos/id/20/800/600" alt="Image B">
</div>
</section>
</main>
<script>
// Elements
const playBtn = document.getElementById('play-btn');
const canvasWrapper = document.getElementById('canvas-wrapper');
const layerA = document.getElementById('layer-a');
const layerB = document.getElementById('layer-b');
const effectSelect = document.getElementById('effect-select');
const inputA = document.getElementById('input-a');
const inputB = document.getElementById('input-b');
// Sliders
const durationSlider = document.getElementById('duration');
const scaleSlider = document.getElementById('scale');
const opacitySlider = document.getElementById('opacity');
// Display Values
const valDuration = document.getElementById('val-duration');
const valScale = document.getElementById('val-scale');
const valOpacity = document.getElementById('val-opacity');
// State
let isTransitioning = false;
let currentEffect = 'fade';
// 1. Handle File Uploads
const handleImageUpload = (input, imgElement) => {
input.addEventListener('change', function(e) {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
imgElement.src = e.target.result;
}
reader.readAsDataURL(file);
}
});
};
handleImageUpload(inputA, layerA);
handleImageUpload(inputB, layerB);
// 2. Update CSS Variables based on sliders
function updateParams() {
const duration = durationSlider.value;
const scale = scaleSlider.value;
const opacity = opacitySlider.value;
// Update text
valDuration.textContent = duration + 'ms';
valScale.textContent = scale;
valOpacity.textContent = opacity;
// Update CSS variables on the canvas wrapper
canvasWrapper.style.setProperty('--duration', `${duration}ms`);
canvasWrapper.style.setProperty('--scale-start', '0.5');
canvasWrapper.style.setProperty('--scale-end', scale);
canvasWrapper.style.setProperty('--opacity-end', opacity);
}
durationSlider.addEventListener('input', updateParams);
scaleSlider.addEventListener('input', updateParams);
opacitySlider.addEventListener('input', updateParams);
// 3. Handle Effect Change
effectSelect.addEventListener('change', (e) => {
// Reset classes
canvasWrapper.classList.remove(`transition-${currentEffect}`);
currentEffect = e.target.value;
canvasWrapper.classList.add(`transition-${currentEffect}`);
// Reset state
canvasWrapper.classList.remove('active');
isTransitioning = false;
playBtn.innerHTML = '<i class="fa-solid fa-play"></i> Play Transition';
// Adjust sliders for default feel based on effect
if(currentEffect === 'zoom') {
scaleSlider.value = 2.0;
} else {
scaleSlider.value = 1.5;
}
updateParams();
});
// Initialize first effect
canvasWrapper.classList.add(`transition-${currentEffect}`);
updateParams();
// 4. Play Animation Logic
playBtn.addEventListener('click', () => {
if (isTransitioning) {
// If we are mid-way, reset and play again
canvasWrapper.classList.remove('active');
setTimeout(runAnimation, 50);
} else {
runAnimation();
}
});
function runAnimation() {
isTransitioning = true;
playBtn.innerHTML = '<i class="fa-solid fa-rotate-right"></i> Replay';
// Force reflow to restart CSS transition
void canvasWrapper.offsetWidth;
canvasWrapper.classList.add('active');
// Optional: Reset automatically after duration + buffer
// For a playground, we usually let the user toggle back,
// but for "Play" feel, let's let it stay on image B.
}
</script>
</body>
</html>