常常看到好看的卡片效果,今天我們就來寫一個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 dimensions
const 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 canvas
ctx.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
就當作遊戲來跟著這個系列探索世界吧!!
請繼續關注,
跟著我們這個系列繼續動手玩創意!!未來還有更多更新鮮的花招呢(。◕∀◕。)