目录
【前端动手玩创意】等待的转圈圈效果 (1)
【前端动手玩创意】google五星评分的星星(2)
【前端动手玩创意】CSS-3D卡片翻转效果(3) (今天难度颇高,想挑战再进来!)
【前端动手玩创意】一句CSS做出好看的hero section!(4)
【前端动手玩创意】创造一个Skill bar(5)
【前端动手玩创意】遮蔽广告(D卡未登入)脚本、自定义新增名单(6)
【前端动手玩创意】前端canvas截图的招式!竟然有三招,可存成SVG或PNG (7)
【前端动手玩创意】让你的PDF档案更难被抓取(8)
【前端动手玩创意】哇操!你敢信?花式写todo-list,body里面一行都没有也能搞?(9)
【前端动手玩创意】卡片製作,才不是!是卡片製作器!(10)
前情提要
常常看到好看的卡片效果,今天我们就来写一个hero section吧!
但是……等一下什么!你说你已经看到标题!
没错!已经来到前端动手玩创意系列的第十篇,我们累积了那么多,特别的第十篇才不要带你写「卡片製作」,
我们要来搞一个card maker,呼应了大前端时代模组化的风格(๑ • ‿ • ๑ )。
到底什么是製作你的製作呢?我们来看看效果:
效果预览
没错就是这样子,可以输入图片网址、让人看不懂的日文(我也不懂那啥意思XD)
就可以跳出一张很有感觉的hero section!
甚至还写了调整图片的移动轴:
还可以下载!?这真的是太讚了,完全就是实现动手玩创意的绝佳精神呀~~
程式码内容
<!DOCTYPE html><html> <head> <title>Card Maker</title> <style> body { display: flex; flex-direction: row; } .input-container { display: flex; flex-direction: column; margin-right: 20px; } .input-container label { margin-bottom: 10px; } .card-container { position: relative; width: 600px; height: 600px; margin-right: 20px; } .card-container canvas { position: absolute; top: 0; left: 0; } .download-button { margin-top: 10px; } .ui-panel { display: flex; flex-direction: column; } .ui-panel label { margin-bottom: 10px; } .ui-panel input[type="range"] { margin-bottom: 20px; } .hero-image { position: relative; width: 100%; height: 100%; background-size: cover; background-position: center; } .hero-text { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; color: white; } </style> </head> <body> <div class="input-container"> <label for="image-input">Image URL:</label> <input type="text" id="image-input" /> <label for="text-input">Text:</label> <input type="text" id="text-input0" /> <input type="text" id="text-input" /> <button id="confirm-button">Confirm</button> </div> <div class="card-container"> <div class="hero-image"> <div class="hero-text"> <h1 id="card-title"></h1> <p id="card-text"></p> </div> </div> <div class="ui-panel"> <label for="brightness-slider">亮度</label> <input type="range" id="brightness-slider" min="-1" max="1" value="0" step="0.1" /> <label for="saturation-slider">饱和度</label> <input type="range" id="saturation-slider" min="-1" max="1" value="0" step="0.1" /> <label for="size-slider">大小</label> <input type="range" id="size-slider" min="0.5" max="2" value="1" step="0.1" /> </div> <button class="download-button" id="download-button">Download</button> <canvas id="card-canvas"></canvas> </div> <script> const imageInput = document.getElementById("image-input"); const textInput = document.getElementById("text-input"); const textInput0 = document.getElementById("text-input0"); const confirmButton = document.getElementById("confirm-button"); const cardTitle = document.getElementById("card-title"); const cardText = document.getElementById("card-text"); const downloadButton = document.getElementById("download-button"); const cardCanvas = document.getElementById("card-canvas"); confirmButton.addEventListener("click", () => { // Update the card title and text cardTitle.innerText = textInput0.value; cardText.innerText = textInput.value; // Update the hero image background const imageUrl = imageInput.value; const heroImage = document.querySelector(".hero-image"); heroImage.style.backgroundImage = `linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("${imageUrl}")`; // Generate the card image const cardImage = new Image(); cardImage.onload = () => { // Get the canvas context and set its dimensionsconst ctx = cardCanvas.getContext('2d'); const canvasWidth = (cardCanvas.width = heroImage.clientWidth * parseFloat(sizeSlider.value)); const canvasHeight = (cardCanvas.height = heroImage.clientHeight * parseFloat(sizeSlider.value)); // Draw the hero image onto the canvasctx.drawImage(heroImage, 0, 0, cardCanvas.width, cardCanvas.height); // Apply brightness and saturation filters to the canvas applyFilters( context, parseFloat(brightnessSlider.value), parseFloat(saturationSlider.value) ); // Update the download button href attribute with the canvas data URL downloadButton.href = cardCanvas.toDataURL("image/png"); }; }); function applyFilters(context, brightness, saturation) { // Convert brightness and saturation values to filter functions const brightnessFilter = createBrightnessFilter(brightness); const saturationFilter = createSaturationFilter(saturation); // Apply the filters to the canvas context.filter = `${brightnessFilter} ${saturationFilter}`; context.drawImage(cardCanvas, 0, 0); context.filter = "none"; } function createBrightnessFilter(value) { // Use a matrix filter to adjust brightness const brightnessMatrix = [ 1, 0, 0, 0, value, 0, 1, 0, 0, value, 0, 0, 1, 0, value, 0, 0, 0, 1, 0, ]; return `brightness(${value})`; } function createSaturationFilter(value) { // Use a matrix filter to adjust saturation const saturationMatrix = [ 0.3086 * (1 - value) + value, 0.6094 * (1 - value), 0.082 * (1 - value), 0, 0, 0.3086 * (1 - value), 0.6094 * (1 - value) + value, 0.082 * (1 - value), 0, 0, 0.3086 * (1 - value), 0.6094 * (1 - value), 0.082 * (1 - value) + value, 0, 0, 0, 0, 0, 1, 0, ]; return `saturate(${value})`; } const brightnessSlider = document.getElementById("brightness-slider"); const saturationSlider = document.getElementById("saturation-slider"); const sizeSlider = document.getElementById("size-slider"); brightnessSlider.addEventListener("input", () => { applyFilters( cardCanvas.getContext("2d"), parseFloat(brightnessSlider.value), parseFloat(saturationSlider.value) ); }); saturationSlider.addEventListener("input", () => { applyFilters( cardCanvas.getContext("2d"), parseFloat(brightnessSlider.value), parseFloat(saturationSlider.value) ); }); sizeSlider.addEventListener("input", () => { cardCanvas.width = heroImage.clientWidth * parseFloat(sizeSlider.value); cardCanvas.height = heroImage.clientHeight * parseFloat(sizeSlider.value); applyFilters( cardCanvas.getContext("2d"), parseFloat(brightnessSlider.value), parseFloat(saturationSlider.value) ); }); const image = document.querySelector('.hero-image');brightnessSlider.addEventListener('change', () => { image.style.filter = `brightness(${brightnessSlider.value}) saturate(${saturationSlider.value})`;});saturationSlider.addEventListener('change', () => { image.style.filter = `brightness(${brightnessSlider.value}) saturate(${saturationSlider.value})`;});sizeSlider.addEventListener('change', () => { image.style.transform = `scale(${sizeSlider.value})`;});const canvas = document.getElementById('card-canvas'); downloadButton.addEventListener('click', () => { const link = document.createElement('a'); link.download = 'image.png'; link.href = canvas.toDataURL(); link.click();}); </script> </body></html>
观念笔记
目前代码的部分canvas还没转好,晚点应该会修正为用html2canvas套件来抓。
不过可以先玩玩看卡片製作的部分唷!
心得
很有趣的小项目,其实学前端什么专业知识、构造函数、模组那些都太无聊了,
讲真的如果只是自己做开心的,
那用什么技术与概念又何妨呢是吧?人生就是轻鬆玩乐不需要一直给自己找碴,生活还不够苦吗XD
前端最有趣的就是你怎么写,画面就怎么回馈给你,
比这个人生online还要好操控多惹d(`・∀・)b
就当作游戏来跟着这个系列探索世界吧!!
请继续关注,
跟着我们这个系列继续动手玩创意!!未来还有更多更新鲜的花招呢(。◕∀◕。)