Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>360° Page Enhancer</title> | |
<script src="https://cdn.tailwindcss.com"></script> | |
<style> | |
/* Custom CSS for the magnifier effect */ | |
.magnifier-glass { | |
position: absolute; | |
width: 150px; | |
height: 150px; | |
border-radius: 50%; | |
border: 3px solid rgba(255, 255, 255, 0.8); | |
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3); | |
background-repeat: no-repeat; | |
background-color: white; | |
cursor: none; | |
z-index: 9999; | |
pointer-events: none; | |
display: none; | |
transform: translate(-50%, -50%); | |
mix-blend-mode: multiply; | |
} | |
.rotate-controls { | |
position: fixed; | |
bottom: 20px; | |
left: 50%; | |
transform: translateX(-50%); | |
background: rgba(0, 0, 0, 0.7); | |
padding: 10px; | |
border-radius: 20px; | |
display: flex; | |
gap: 10px; | |
z-index: 10000; | |
opacity: 0; | |
transition: opacity 0.3s; | |
} | |
.rotate-controls.visible { | |
opacity: 1; | |
} | |
.rotate-btn { | |
width: 40px; | |
height: 40px; | |
border-radius: 50%; | |
background: white; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
cursor: pointer; | |
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); | |
transition: transform 0.2s; | |
} | |
.rotate-btn:hover { | |
transform: scale(1.1); | |
} | |
.zoom-level { | |
position: fixed; | |
top: 20px; | |
right: 20px; | |
background: rgba(0, 0, 0, 0.7); | |
color: white; | |
padding: 5px 10px; | |
border-radius: 10px; | |
font-family: sans-serif; | |
font-size: 14px; | |
z-index: 10000; | |
display: none; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100"> | |
<div class="container mx-auto p-4"> | |
<!-- Extension UI --> | |
<div class="bg-white rounded-lg shadow-lg p-6 mb-6"> | |
<h1 class="text-2xl font-bold text-gray-800 mb-4">360° Page Enhancer</h1> | |
<p class="text-gray-600 mb-4">This extension adds a 360° zoom and rotation feature to web pages. Click on any element to activate the magnifier.</p> | |
<div class="flex flex-wrap gap-4 mb-6"> | |
<div class="flex-1 min-w-[200px]"> | |
<label class="block text-sm font-medium text-gray-700 mb-1">Zoom Level</label> | |
<input type="range" id="zoomRange" min="1" max="5" step="0.5" value="2" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
<div class="flex justify-between text-xs text-gray-500 mt-1"> | |
<span>1x</span> | |
<span>2x</span> | |
<span>3x</span> | |
<span>4x</span> | |
<span>5x</span> | |
</div> | |
</div> | |
<div class="flex-1 min-w-[200px]"> | |
<label class="block text-sm font-medium text-gray-700 mb-1">Magnifier Size</label> | |
<input type="range" id="sizeRange" min="100" max="300" step="50" value="150" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"> | |
<div class="flex justify-between text-xs text-gray-500 mt-1"> | |
<span>100px</span> | |
<span>200px</span> | |
<span>300px</span> | |
</div> | |
</div> | |
</div> | |
<div class="flex flex-wrap gap-4"> | |
<div class="flex items-center"> | |
<input type="checkbox" id="enableRotation" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"> | |
<label for="enableRotation" class="ml-2 block text-sm text-gray-700">Enable 360° Rotation</label> | |
</div> | |
<div class="flex items-center"> | |
<input type="checkbox" id="showControls" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked> | |
<label for="showControls" class="ml-2 block text-sm text-gray-700">Show Rotation Controls</label> | |
</div> | |
<div class="flex items-center"> | |
<input type="checkbox" id="smoothZoom" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded" checked> | |
<label for="smoothZoom" class="ml-2 block text-sm text-gray-700">Smooth Zoom Transition</label> | |
</div> | |
</div> | |
<button id="toggleExtension" class="mt-6 bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200"> | |
Activate Extension | |
</button> | |
</div> | |
<!-- Demo content to test the extension --> | |
<div class="bg-white rounded-lg shadow-lg p-6"> | |
<h2 class="text-xl font-semibold text-gray-800 mb-4">Try it on this demo content</h2> | |
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<h3 class="font-medium text-gray-700 mb-2">Sample Image</h3> | |
<img src="https://images.unsplash.com/photo-1682686580391-615b4f715f5e?w=500&auto=format&fit=crop" alt="Sample" class="w-full h-auto rounded cursor-pointer demo-target"> | |
</div> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<h3 class="font-medium text-gray-700 mb-2">Sample Text</h3> | |
<p class="text-gray-600 cursor-pointer demo-target"> | |
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in dui mauris. Vivamus hendrerit arcu sed erat molestie vehicula. Sed auctor neque eu tellus rhoncus ut eleifend nibh porttitor. | |
</p> | |
</div> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<h3 class="font-medium text-gray-700 mb-2">Sample UI Elements</h3> | |
<div class="flex flex-wrap gap-2 cursor-pointer demo-target"> | |
<button class="bg-blue-500 text-white px-3 py-1 rounded">Button</button> | |
<button class="bg-green-500 text-white px-3 py-1 rounded">Another</button> | |
<button class="bg-red-500 text-white px-3 py-1 rounded">Click Me</button> | |
</div> | |
</div> | |
<div class="bg-gray-50 p-4 rounded-lg"> | |
<h3 class="font-medium text-gray-700 mb-2">Sample Complex Content</h3> | |
<div class="cursor-pointer demo-target"> | |
<div class="flex items-center mb-2"> | |
<div class="w-8 h-8 bg-purple-500 rounded-full mr-2"></div> | |
<span class="text-gray-700">User Avatar</span> | |
</div> | |
<div class="border-t pt-2"> | |
<p class="text-sm text-gray-600">This is a more complex UI element that you can zoom into.</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Magnifier elements that will be added to the page --> | |
<div id="magnifier" class="magnifier-glass"></div> | |
<div id="zoomLevel" class="zoom-level">2x</div> | |
<div id="rotateControls" class="rotate-controls"> | |
<div id="rotateLeft" class="rotate-btn" title="Rotate Left">←</div> | |
<div id="resetRotation" class="rotate-btn" title="Reset Rotation">↻</div> | |
<div id="rotateRight" class="rotate-btn" title="Rotate Right">→</div> | |
</div> | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
// Extension state | |
const state = { | |
active: false, | |
zoomLevel: 2, | |
magnifierSize: 150, | |
enableRotation: false, | |
showControls: true, | |
smoothZoom: true, | |
currentRotation: 0, | |
currentTarget: null | |
}; | |
// DOM elements | |
const magnifier = document.getElementById('magnifier'); | |
const zoomLevelDisplay = document.getElementById('zoomLevel'); | |
const rotateControls = document.getElementById('rotateControls'); | |
const toggleExtensionBtn = document.getElementById('toggleExtension'); | |
const zoomRange = document.getElementById('zoomRange'); | |
const sizeRange = document.getElementById('sizeRange'); | |
const enableRotation = document.getElementById('enableRotation'); | |
const showControls = document.getElementById('showControls'); | |
const smoothZoom = document.getElementById('smoothZoom'); | |
const rotateLeftBtn = document.getElementById('rotateLeft'); | |
const rotateRightBtn = document.getElementById('rotateRight'); | |
const resetRotationBtn = document.getElementById('resetRotation'); | |
// Demo targets | |
const demoTargets = document.querySelectorAll('.demo-target'); | |
// Initialize UI | |
function updateUI() { | |
toggleExtensionBtn.textContent = state.active ? 'Deactivate Extension' : 'Activate Extension'; | |
toggleExtensionBtn.className = state.active ? | |
'mt-6 bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200' : | |
'mt-6 bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded-lg transition duration-200'; | |
if (state.active) { | |
document.body.style.cursor = 'crosshair'; | |
demoTargets.forEach(el => el.style.cursor = 'crosshair'); | |
} else { | |
document.body.style.cursor = ''; | |
demoTargets.forEach(el => el.style.cursor = ''); | |
hideMagnifier(); | |
} | |
} | |
// Show magnifier | |
function showMagnifier(e, target) { | |
if (!state.active) return; | |
state.currentTarget = target; | |
magnifier.style.display = 'block'; | |
zoomLevelDisplay.style.display = 'block'; | |
if (state.enableRotation && state.showControls) { | |
rotateControls.classList.add('visible'); | |
} | |
updateMagnifier(e); | |
} | |
// Hide magnifier | |
function hideMagnifier() { | |
magnifier.style.display = 'none'; | |
zoomLevelDisplay.style.display = 'none'; | |
rotateControls.classList.remove('visible'); | |
state.currentTarget = null; | |
state.currentRotation = 0; | |
} | |
// Update magnifier position and content | |
function updateMagnifier(e) { | |
if (!state.active || !state.currentTarget) return; | |
const targetRect = state.currentTarget.getBoundingClientRect(); | |
const x = e.clientX; | |
const y = e.clientY; | |
// Position the magnifier | |
magnifier.style.left = `${x}px`; | |
magnifier.style.top = `${y}px`; | |
magnifier.style.width = `${state.magnifierSize}px`; | |
magnifier.style.height = `${state.magnifierSize}px`; | |
// Calculate the background position for the magnifier | |
const bgX = ((x - targetRect.left) / targetRect.width) * 100; | |
const bgY = ((y - targetRect.top) / targetRect.height) * 100; | |
// Create a screenshot of the target | |
const screenshot = createScreenshot(state.currentTarget); | |
// Apply transformations | |
magnifier.style.backgroundImage = `url(${screenshot})`; | |
magnifier.style.backgroundSize = `${targetRect.width * state.zoomLevel}px ${targetRect.height * state.zoomLevel}px`; | |
magnifier.style.backgroundPosition = `${bgX}% ${bgY}%`; | |
if (state.enableRotation) { | |
magnifier.style.transform = `translate(-50%, -50%) rotate(${state.currentRotation}deg)`; | |
} | |
// Update zoom level display | |
zoomLevelDisplay.textContent = `${state.zoomLevel}x`; | |
zoomLevelDisplay.style.top = '20px'; | |
zoomLevelDisplay.style.right = '20px'; | |
} | |
// Create a screenshot of an element | |
function createScreenshot(element) { | |
// In a real extension, we would use more sophisticated methods | |
// For this demo, we'll just create a basic representation | |
const canvas = document.createElement('canvas'); | |
const rect = element.getBoundingClientRect(); | |
// Set canvas dimensions | |
canvas.width = rect.width; | |
canvas.height = rect.height; | |
const ctx = canvas.getContext('2d'); | |
// Draw a representation of the element | |
if (element.tagName === 'IMG') { | |
// For images, we can actually draw them | |
ctx.drawImage(element, 0, 0, rect.width, rect.height); | |
} else { | |
// For other elements, create a simplified representation | |
ctx.fillStyle = window.getComputedStyle(element).backgroundColor || 'white'; | |
ctx.fillRect(0, 0, rect.width, rect.height); | |
// Add text if the element contains text | |
if (element.textContent.trim()) { | |
ctx.fillStyle = window.getComputedStyle(element).color || 'black'; | |
ctx.font = '14px Arial'; | |
ctx.fillText(element.textContent.trim(), 10, 20); | |
} | |
} | |
return canvas.toDataURL(); | |
} | |
// Event listeners | |
toggleExtensionBtn.addEventListener('click', function() { | |
state.active = !state.active; | |
updateUI(); | |
}); | |
zoomRange.addEventListener('input', function() { | |
state.zoomLevel = parseFloat(this.value); | |
zoomLevelDisplay.textContent = `${state.zoomLevel}x`; | |
}); | |
sizeRange.addEventListener('input', function() { | |
state.magnifierSize = parseInt(this.value); | |
magnifier.style.width = `${state.magnifierSize}px`; | |
magnifier.style.height = `${state.magnifierSize}px`; | |
}); | |
enableRotation.addEventListener('change', function() { | |
state.enableRotation = this.checked; | |
if (!state.enableRotation) { | |
state.currentRotation = 0; | |
magnifier.style.transform = 'translate(-50%, -50%)'; | |
} | |
}); | |
showControls.addEventListener('change', function() { | |
state.showControls = this.checked; | |
if (state.showControls && state.active && state.currentTarget && state.enableRotation) { | |
rotateControls.classList.add('visible'); | |
} else { | |
rotateControls.classList.remove('visible'); | |
} | |
}); | |
smoothZoom.addEventListener('change', function() { | |
state.smoothZoom = this.checked; | |
if (state.smoothZoom) { | |
magnifier.style.transition = 'transform 0.2s ease, width 0.2s ease, height 0.2s ease'; | |
} else { | |
magnifier.style.transition = 'none'; | |
} | |
}); | |
// Rotation controls | |
rotateLeftBtn.addEventListener('click', function() { | |
if (!state.active || !state.enableRotation || !state.currentTarget) return; | |
state.currentRotation -= 15; | |
updateMagnifier({ clientX: parseFloat(magnifier.style.left), clientY: parseFloat(magnifier.style.top) }); | |
}); | |
rotateRightBtn.addEventListener('click', function() { | |
if (!state.active || !state.enableRotation || !state.currentTarget) return; | |
state.currentRotation += 15; | |
updateMagnifier({ clientX: parseFloat(magnifier.style.left), clientY: parseFloat(magnifier.style.top) }); | |
}); | |
resetRotationBtn.addEventListener('click', function() { | |
if (!state.active || !state.enableRotation || !state.currentTarget) return; | |
state.currentRotation = 0; | |
updateMagnifier({ clientX: parseFloat(magnifier.style.left), clientY: parseFloat(magnifier.style.top) }); | |
}); | |
// Document event listeners | |
document.addEventListener('mousemove', function(e) { | |
if (!state.active || !state.currentTarget) return; | |
updateMagnifier(e); | |
}); | |
document.addEventListener('click', function(e) { | |
if (!state.active) return; | |
// Find the target element | |
let target = e.target; | |
// Ignore clicks on the magnifier itself or its controls | |
if (target === magnifier || target.closest('#rotateControls')) { | |
return; | |
} | |
// If we're already showing a magnifier and click outside, hide it | |
if (state.currentTarget && !target.closest('.demo-target')) { | |
hideMagnifier(); | |
return; | |
} | |
// If clicking on a demo target, show magnifier | |
if (target.closest('.demo-target')) { | |
target = target.closest('.demo-target'); | |
showMagnifier(e, target); | |
} | |
}); | |
// Initialize | |
updateUI(); | |
}); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Mackin7/browser-enhancer2" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |