一、學習目標
今天的目標是讓網頁具備「圖片壓縮」與「資訊顯示」的功能。由於在實際應用中,使用者可能會上傳過大的圖片,因此需要一個方法在前端先壓縮圖片,避免造成網頁加載緩慢,並提升整體體驗。
二、學習內容
圖片上傳
<input type="file">
讓使用者選擇圖片。FileReader
讀取檔案內容,並將其轉換為 Base64 格式,方便後續操作。圖片壓縮
<canvas>
畫布,將圖片繪製在上面。canvas.toDataURL("image/jpeg", 0.8)
產生壓縮後的圖片,並設定品質為 0.8
。圖片預覽
<img id="preview">
。資訊顯示
在 <p id="info">
顯示圖片資訊,包括:
三、學習內容
以下是完整的Day7成果:
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>Day7 - 圖片壓縮與重新選擇</title>
<style>
body {
font-family: "Microsoft JhengHei", Arial, sans-serif;
background-color: #f3f8fc;
margin: 20px;
}
h1 {
text-align: center;
color: #2b7cbf;
}
.container {
display: flex; /*設定成彈性排版*/
justify-content: center;
align-items: flex-start;
gap: 20px;
max-width: 900px;
margin: 0 auto;
}
.upload-box, .preview-box {
flex: 1;
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
.upload-box input[type="file"] {
display: none;
}
.custom-button {
display: inline-block;
padding: 12px 25px;
background: #4aa3df;
color: white;
font-size: 16px;
font-weight: bold;
border-radius: 8px;
cursor: pointer;
transition: 0.3s;
}
.custom-button:hover {
background: #2b7cbf;
}
.preview-box img {
max-width: 100%;
max-height: 400px;
margin-top: 15px;
border-radius: 10px;
border: 2px solid #ddd;
display: none;
}
.note {
margin-top: 10px;
font-size: 14px;
color: gray;
}
</style>
</head>
<body>
<h1>🌟 我的第七天網頁 🌟</h1>
<div class="container">
<!--上傳區-->
<div class="upload-box">
<h2>圖片上傳</h2>
<p>請點擊下方按鈕,選擇一張圖片:</p>
<label for="upload" class="custom-button">選擇圖片</label>
<input type="file" id="upload" accept="image/*">
<p class="note">建議選擇 2MB 以下的圖片,系統會自動壓縮。</p>
</div>
<!--預覽區-->
<div class="preview-box">
<h2>圖片預覽</h2>
<img id="preview" src="" alt="預覽圖片">
<p class="note" id="info"></p>
</div>
</div>
<script>
const upload = document.getElementById("upload");
const preview = document.getElementById("preview");
const info = document.getElementById("info");
upload.addEventListener("change", function() {
const file = this.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.onload = function() {
//設定最大寬高
const maxWidth = 800;
const maxHeight = 800;
let width = img.width;
let height = img.height;
//按比例縮小
if (width > maxWidth || height > maxHeight) {
if (width > height) {
height = Math.round((maxWidth / width)*height);
width = maxWidth;
} else {
width = Math.round((maxHeight / height)*width);
height = maxHeight;
}
}
//建立canvas壓縮圖片
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
//轉成壓縮後的DataURL
const compressedDataUrl = canvas.toDataURL("image/jpeg", 0.8);
//顯示壓縮後的圖片
preview.src = compressedDataUrl;
preview.style.display = "block";
//顯示圖片資訊
info.textContent = `原始大小:${(file.size/1024).toFixed(1)} KB → 壓縮後寬高: ${width}x${height}`;
};
img.src = e.target.result;
};
reader.readAsDataURL(file);
}
});
</script>
</body>
</html>
讀取圖片
const reader = new FileReader();
reader.onload = function(e) {
const img = new Image();
img.src = e.target.result;
};
reader.readAsDataURL(file);
→ 將使用者選擇的圖片讀取並轉換成 Data URL。
圖片等比縮小
if (width > maxWidth || height > maxHeight) {
if (width > height) {
height = Math.round((maxWidth / width) * height);
width = maxWidth;
} else {
width = Math.round((maxHeight / height) * width);
height = maxHeight;
}
}
→ 計算縮小後的寬高,確保圖片保持比例。
使用 Canvas 壓縮
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
const compressedDataUrl = canvas.toDataURL("image/jpeg", 0.8);
→ 把圖片畫在畫布上,再轉換為壓縮後的 Base64 格式。
顯示結果
preview.src = compressedDataUrl;
preview.style.display = "block";
info.textContent = `原始大小:${(file.size/1024).toFixed(1)} KB → 壓縮後寬高: ${width}x${height}`;
→ 在網頁中預覽壓縮後的圖片,並顯示資訊。
四、學習心得
透過今天的練習,我的網頁不僅能讓使用者上傳圖片,還能自動壓縮過大的圖片,並即時顯示壓縮後的效果與資訊。這是一個更接近實際應用的功能,對於未來要結合 AR 項目會非常有幫助,因為圖片壓縮能有效提升效能與使用體驗。今天的挑戰讓我更熟悉了 FileReader
、Image
、Canvas
的用法。這些知識不僅能應用在壓縮圖片上,也能延伸到圖片編輯、即時濾鏡等更進階的應用。我感受到程式設計的靈活性,也更期待後續的 AR 整合。