Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
Chandler hugging album
Upload image
Download
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } @import url("https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap"); *, *::after, *::before { margin: 0; padding: 0; box-sizing: border-box; } html, body { min-height: 100vh; } body { display: grid; justify-content: center; align-content: start; font-family: "Inter", sans-serif; text-align: center; color: #222; } .wrapper { padding: 4rem 2rem; display: grid; justify-items: center; max-width: 50rem; } h1 { margin-bottom: 1.25em; max-width: 25ch; font-size: clamp(1.2rem, 0.5rem + 5vw, 4rem); font-family: "Bebas Neue", "Inter", sans-serif; font-weight: 400; font-style: normal; } .visually-hidden { clip: rect(0 0 0 0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } .container { position: relative; display: grid; overflow: hidden; background-color: #222; } .upload-container { text-align: center; font-size: clamp(0.5rem, 0.1rem + 3vw, 2rem); display: grid; justify-content: center; position: absolute; top: 57.5%; left: 24.7%; width: 43.5%; min-height: 42%; transform: rotate(0deg) perspective(51px) rotateX(1deg) rotateY(0.5deg) skew(-17deg, 0deg); background-color: #222; color: #fff; cursor: pointer; height: 0; overflow: hidden; } .upload-container > * { grid-column: 1; grid-row: 1; cursor: pointer; } .upload-label { display: flex; justify-content: center; align-items: center; } .upload-label span { max-width: 6.5ch; } input { opacity: 0; align-self: center; } input:focus + .upload-label span { outline: 2px dashed currentColor; } img { z-index: 99; } .canvases, .canvases > *, img { grid-column: 1; grid-row: 1; pointer-events: none; } img, canvas { max-width: 100%; display: block; } .canvases { display: grid; pointer-events: none; } #canvas-album { display: none; } #canvas-chandler { position: relative; z-index: 99; } a[download] { margin-top: 2rem; color: inherit; text-decoration: none; background: #222; color: #fff; font-weight: 700; padding: 1rem 2rem; border-radius: 17px; } a:focus-visible { outline: 2px dashed #222; outline-offset: 2px; } footer { color: #555555; font-size: 0.9em; }
console.log("Event Fired") const canvasesContainer = document.querySelector(".canvases"); const canvasChandler = canvasesContainer.querySelector("#canvas-chandler"); const canvasAlbum = canvasesContainer.querySelector("#canvas-album"); const input = document.querySelector("#input-pic"); const inputLabel = document.querySelector("#input-label"); const downloadButton = document.querySelector("a[download]"); const liveRegion = document.querySelector("#feedback"); function applyTransformations(ctx, canvas) { ctx.translate(canvas.width / 2, canvas.height / 2); ctx.rotate((2 * Math.PI) / 180); const perspective = 390; const scale = 1 / (1 + perspective / canvas.width); ctx.scale(scale, scale); ctx.transform(1, 0, Math.tan((-18 * Math.PI) / 180), 1, 0, 0); ctx.scale(1.93, 1.23); ctx.translate(-canvas.width / 2, -canvas.height / 2); } function drawImage(albumCover) { return new Promise((resolve) => { const ctx = canvasChandler.getContext("2d"); const { width, height } = canvasChandler; const pictureChandler = new Image(); pictureChandler.crossOrigin = "anonymous"; pictureChandler.src = "https://ik.imagekit.io/rsgqxitab/for-codepens/chandler-hugging-album.png?updatedAt=1723031615623"; pictureChandler.onload = () => { ctx.fillStyle = "#fff"; ctx.fillRect(0, 0, width, height); ctx.save(); applyTransformations(ctx, canvasAlbum); ctx.drawImage( albumCover, (37 * width) / 100, (70.7 * height) / 100, canvasAlbum.width, canvasAlbum.height ); ctx.restore(); ctx.drawImage(pictureChandler, 0, 0); resolve(canvasChandler.toDataURL("image/jpeg", 0.8)); }; }); } function showDownloadButton(base64) { const image = new Image(); image.src = base64; image.onload = () => { downloadButton.href = base64; downloadButton.hidden = false; downloadButton.focus(); }; } function updateLiveRegion() { liveRegion.textContent = "Your meme has been generated and is ready to be downloaded."; } function handleUpload(e) { const file = e.target.files[0]; const image = new Image(); image.src = URL.createObjectURL(file); image.onload = async (e) => { const result = await drawImage(e.currentTarget); updateLiveRegion(); showDownloadButton(result); }; } input.addEventListener("change", handleUpload);