Follow Us On Telegram Telegram link
This free source code allows you to create a simple and interactive animated avatar on your website.
The avatar is designed using HTML and CSS, and the animation is powered by JavaScript.
The avatar moves horizontally across the screen in a smooth and continuous loop.
You can customize the avatar's appearance by adjusting the background color, size, and animation properties in the CSS code.
Feel free to use this code snippet to enhance the visual appeal of your website and engage your users.
To access the complete source code and implementation details, please visit codeatnow.com.
Download Code
HTML
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title>CodeAtNow - Avatar Input</title> <link rel="stylesheet" href="./style.css"> </head> <body> <!-- partial:index.partial.html --> <div class="avatar-input"> <label class="avatar-input__label" for="file-input"> <input type="file" id="file-input" class="avatar-input__input" /> <div class="avatar-input__icon"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 460.8 460.8" fill="currentColor" > <path d="M230.432,239.282c65.829,0,119.641-53.812,119.641-119.641C350.073,53.812,296.261,0,230.432,0 S110.792,53.812,110.792,119.641S164.604,239.282,230.432,239.282z" /> <path d="M435.755,334.89c-3.135-7.837-7.314-15.151-12.016-21.943c-24.033-35.527-61.126-59.037-102.922-64.784 c-5.224-0.522-10.971,0.522-15.151,3.657c-21.943,16.196-48.065,24.555-75.233,24.555s-53.29-8.359-75.233-24.555 c-4.18-3.135-9.927-4.702-15.151-3.657c-41.796,5.747-79.412,29.257-102.922,64.784c-4.702,6.792-8.882,14.629-12.016,21.943 c-1.567,3.135-1.045,6.792,0.522,9.927c4.18,7.314,9.404,14.629,14.106,20.898c7.314,9.927,15.151,18.808,24.033,27.167 c7.314,7.314,15.673,14.106,24.033,20.898c41.273,30.825,90.906,47.02,142.106,47.02s100.833-16.196,142.106-47.02 c8.359-6.269,16.718-13.584,24.033-20.898c8.359-8.359,16.718-17.241,24.033-27.167c5.224-6.792,9.927-13.584,14.106-20.898 C436.8,341.682,437.322,338.024,435.755,334.89z" /> </svg> </div> </label> </div> <!-- partial --> <script src="./script.js"></script> </body> </html>
CSS
* { box-sizing: border-box; } :root { --background-color: #11131e; --shadow-color: #030305; --input-bg-color: hsl(208.7, 20%, 80%); --input-icon-color: hsl(208.7, 20%, 50%); --outline-color: hsl(208.7, 100%, 50%); --check-color: hsl(202, 100%, 53%); background-color: var(--background-color); } body { margin: 0; display: flex; place-items: center; min-width: 320px; min-height: 100vh; display: flex; align-items: center; justify-content: center; } .avatar-input { display: flex; align-items: center; justify-content: center; transition: 0.2s ease all; width: 150px; height: 150px; padding: 4px; position: relative; } .avatar-input__label { box-shadow: 0 20px 25px -5px var(--shadow-color), 0 8px 10px -6px var(--shadow-color); display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; border-radius: 50%; position: relative; transition: 0.4s ease all; overflow: hidden; cursor: pointer; z-index: 1; } .avatar-input--dragover, .avatar-input--uploading, .avatar-input--success, .avatar-input:active { transform: scale(0.9); } .avatar-input:active .avatar-input__label { box-shadow: none; } .avatar-input--dragover .avatar-input__label, .avatar-input--uploading .avatar-input__label, .avatar-input--success .avatar-input__label { box-shadow: none; filter: brightness(0.5); } .avatar-input__input { display: none; } .avatar-input__icon { width: 100%; height: 100%; display: flex; align-items: flex-end; justify-content: center; overflow: hidden; color: var(--input-icon-color); background: var(--input-bg-color); transition: 0.2s ease all; } .avatar-input__icon svg { width: 80%; position: relative; bottom: -6%; } .avatar-input__preview { position: absolute; z-index: 2; top: 0; left: 0; object-fit: cover; width: 100%; height: 100%; transition: 0.2s ease all; transform: scale(1.05); } .avatar-input__outline { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); stroke-opacity: 0; z-index: 2; width: 100%; height: 100%; color: var(--outline-color); stroke-dasharray: var(--outline-total-stroke) var(--outline-stroke-offset); stroke-dashoffset: var(--outline-total-stroke); transition: 0.05s linear all; pointer-events: none; } .avatar-input--uploading .avatar-input__outline, .avatar-input--success .avatar-input__outline { stroke-opacity: 1; } .avatar-input--uploading .avatar-input__percentage { opacity: 1; } .avatar-input__percentage { position: absolute; opacity: 0; z-index: 2; top: 50%; left: 50%; transform: translate(-50%, -50%); font-family: Arial, Helvetica, sans-serif; color: white; font-weight: bold; transition: 0.25s ease opacity; pointer-events: none; } .avatar-input__success { position: absolute; z-index: 2; top: 50%; left: 50%; transform: translate(-50%, -50%); font-family: Arial, Helvetica, sans-serif; color: white; transition: 0.25s ease opacity; width: 40%; pointer-events: none; } .avatar-input__success-icon { stroke-dasharray: var(--check-total-stroke) var(--check-total-stroke); stroke-dashoffset: var(--check-stroke-offset); opacity: 0; transition: 0.4s ease all; transition-delay: 100ms; color: var(--check-color); } .avatar-input--success .avatar-input__success-icon { opacity: 1; }
JS
class AvatarInput { percentage = 0 constructor(el) { this.root = el this.label = el.querySelector('.avatar-input__label') this.input = el.querySelector('.avatar-input__input') this.addOutline() this.addPercentageText() this.addPreviewImage() this.addSuccessMessage() this.root.addEventListener('dragover', this.onDragOver.bind(this)) this.root.addEventListener('dragleave', this.onDragLeave.bind(this)) this.root.addEventListener('drop', this.onDrop.bind(this)) this.reader = new FileReader() this.reader.addEventListener('load', this.onFileRead.bind(this)) this.input.addEventListener('input', this.onFileSelect.bind(this)) } onDragOver(e) { e.preventDefault() this.root.classList.add('avatar-input--dragover') } onDragLeave() { this.removeDragoverState() } removeDragoverState() { this.root.classList.remove('avatar-input--dragover') } addPercentageText() { this.percentageText = document.createElement('div') this.percentageText.classList.add('avatar-input__percentage') this.percentageText.textContent = '0%' this.percentageText.style.fontSize = `${this.root.clientWidth * 0.2}px` this.root.appendChild(this.percentageText) } startUploading() { setTimeout(() => { this.uploadTick() }, 600) } addSuccessMessage() { this.success = document.createElement('div') this.success.classList.add('avatar-input__success') this.successSvg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ) this.successSvg.setAttribute('viewBox', '0 0 24 24') this.successSvg.classList.add('avatar-input__success-icon') const svgIcon = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ) svgIcon.setAttribute( 'd', 'M3.36902 12.4213L9.0003 18.0527C9.20134 18.2537 9.52933 18.2469 9.72183 18.0376L20.8689 5.92126' ) svgIcon.setAttribute('stroke', 'currentColor') svgIcon.setAttribute('stroke-width', '2') svgIcon.setAttribute('stroke-linecap', 'round') svgIcon.setAttribute('fill', 'none') this.successSvg.appendChild(svgIcon) this.success.appendChild(this.successSvg) this.root.appendChild(this.success) this.totalCheckStrokeLength = Math.ceil(svgIcon.getTotalLength()) + 2 this.successSvg.style.setProperty( '--check-stroke-offset', this.totalCheckStrokeLength ) this.successSvg.style.setProperty( '--check-total-stroke', this.totalCheckStrokeLength ) } onDone() { this.root.classList.remove('avatar-input--uploading') this.successSvg.style.setProperty('--check-stroke-offset', 0) this.root.classList.add('avatar-input--success') setTimeout(() => { this.percentage = 0 this.updateText() }, 200) setTimeout(() => { this.successSvg.style.setProperty( '--check-stroke-offset', this.totalCheckStrokeLength ) }, 800) setTimeout(() => { this.root.classList.remove('avatar-input--success') this.updateOutline() }, 1200) } uploadTick() { if (this.percentage === 100) { setTimeout(() => { this.onDone() }, 400) return } this.percentage++ this.updateOutline() this.updateText() requestAnimationFrame(this.uploadTick.bind(this)) } updateText() { this.percentageText.textContent = this.percentage + '%' } updateOutline() { this.outline.style.setProperty( '--outline-stroke-offset', this.totalOutlineStrokeLength - this.totalOutlineStrokeLength * this.percentage * 0.01 ) } addOutline() { const rootWidth = this.root.clientWidth const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg') svg.setAttribute('viewBox', `0 0 ${rootWidth} ${rootWidth}`) svg.classList.add('avatar-input__outline') const svgCircle = document.createElementNS( 'http://www.w3.org/2000/svg', 'circle' ) svgCircle.setAttribute('cx', '50%') svgCircle.setAttribute('cy', '50%') svgCircle.setAttribute('r', rootWidth / 2 - 3) svgCircle.setAttribute('fill', 'none') svgCircle.setAttribute('stroke', 'currentColor') svgCircle.setAttribute('stroke-width', '3px') svg.appendChild(svgCircle) this.outline = svg this.root.appendChild(svg) this.totalOutlineStrokeLength = Math.ceil(svgCircle.getTotalLength()) + 2 svg.style.setProperty( '--outline-stroke-offset', this.totalOutlineStrokeLength ) svg.style.setProperty( '--outline-total-stroke', this.totalOutlineStrokeLength ) } onDrop(e) { e.preventDefault() const items = [...e.dataTransfer.items] if (!items || items?.[0].kind !== 'file') return const file = items[0].getAsFile() this.reader.readAsDataURL(file) setTimeout(() => { this.removeDragoverState() this.root.classList.add('avatar-input--uploading') }, 300) } onFileSelect() { const file = this.input.files[0] if (file) { this.root.classList.add('avatar-input--uploading') this.reader.readAsDataURL(file) } } setPreviewImage(src) { this.previewImage.src = src } addPreviewImage() { this.previewImage = document.createElement('img') this.previewImage.classList.add('avatar-input__preview') this.label.appendChild(this.previewImage) } onFileRead() { const image = this.reader.result this.setPreviewImage(image) this.startUploading() } } Array.from(document.querySelectorAll('.avatar-input')).forEach( (el) => new AvatarInput(el) )
0 Comments