250x250
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 풀스택
- 프론트엔드
- react
- HTML
- 비전공 개발자
- image
- IOS
- javascript
- css3
- keyframes
- iOS 개발자
- ipad
- MAC
- effect
- button
- Animation
- xcode
- 백엔드
- 개발자
- 비전공자
- 자바스크립트
- iPhone
- hover
- php
- html5
- front-end
- 애니메이션
- SWIFT
- CSS
- jQuery
Archives
- Today
- Total
비전공자 개발일기
Image Editor 본문
728x90
SMALL
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IMAGE EDITOR</title>
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://unpkg.com/boxicons@2.1.2/css/boxicons.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" />
<script defer src="main.js"></script>
</head>
<body>
<div style="display:block">
<div class="container disable">
<h2>Easy Image Editor</h2>
<div class="wrapper">
<div class="editor-panel">
<div class="filter">
<label class="title">Filters</label>
<div class="options">
<button id="brightness" class="active">Brightness</button>
<button id="saturation">Saturation</button>
<button id="inversion">Inversion</button>
<button id="grayscale">Grayscale</button>
</div>
<div class="slider">
<div class="filter-info">
<p class="name">Brighteness</p>
<p class="value">100%</p>
</div>
<input type="range" value="100" min="0" max="200">
</div>
</div>
<div class="rotate">
<label class="title">Rotate & Flip</label>
<div class="options">
<button id="left"><i class="fa-solid fa-rotate-left"></i></button>
<button id="right"><i class="fa-solid fa-rotate-right"></i></button>
<button id="horizontal"><i class='bx bx-reflect-vertical'></i></button>
<button id="vertical"><i class='bx bx-reflect-horizontal'></i></button>
</div>
</div>
</div>
<div class="preview-img">
<img src="https://cdn.shopify.com/s/files/1/0533/2089/files/placeholder-images-image_large.png?format=jpg&quality=90&v=1530129081"
alt="preview-img">
</div>
</div>
<div class="controls">
<button class="reset-filter">Reset Filters</button>
<div class="row">
<input type="file" class="file-input" accept="image/*" hidden>
<button class="choose-img">Choose Image</button>
<button class="save-img">Save Image</button>
</div>
</div>
</div>
</div>
</body>
</html>
/* Import Google font - Poppins */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
body {
display: flex;
padding: 10px;
min-height: 100vh;
align-items: center;
justify-content: center;
background: #e3f2fd;
}
.container {
width: 850px;
padding: 30px 35px 35px;
background: #fff;
border-radius: 10px;
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.container.disable .editor-panel,
.container.disable .controls .reset-filter,
.container.disable .controls .save-img {
opacity: 0.5;
pointer-events: none;
}
.container h2 {
margin-top: -8px;
font-size: 22px;
font-weight: 500;
}
.container .wrapper {
display: flex;
margin: 20px 0;
min-height: 335px;
}
.wrapper .editor-panel {
padding: 15px 20px;
width: 280px;
border-radius: 5px;
border: 1px solid #ccc;
}
.editor-panel .title {
display: block;
font-size: 16px;
margin-bottom: 12px;
}
.editor-panel .options,
.controls {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.editor-panel button {
outline: none;
height: 40px;
font-size: 14px;
color: #6c757d;
background: #fff;
border-radius: 3px;
margin-bottom: 8px;
border: 1px solid #aaa;
}
.editor-panel .filter button {
width: calc(100% / 2 - 4px);
}
.editor-panel button:hover {
background: #f5f5f5;
}
.filter button.active {
color: #fff;
border-color: #5372f0;
background: #5372f0;
}
.filter .slider {
margin-top: 12px;
}
.filter .slider .filter-info {
display: flex;
color: #464646;
font-size: 14px;
justify-content: space-between;
}
.filter .slider input {
width: 100%;
height: 5px;
accent-color: #5372f0;
}
.editor-panel .rotate {
margin-top: 17px;
}
.editor-panel .rotate button {
display: flex;
align-items: center;
justify-content: center;
width: calc(100% / 4 - 3px);
}
.rotate .options button:nth-child(3),
.rotate .options button:nth-child(4) {
font-size: 18px;
}
.rotate .options button:active {
color: #fff;
background: #5372f0;
border-color: #5372f0;
}
.wrapper .preview-img {
flex-grow: 1;
display: flex;
overflow: hidden;
margin-left: 20px;
border-radius: 5px;
align-items: center;
justify-content: center;
}
.preview-img img {
max-width: 490px;
max-height: 335px;
width: 100%;
height: 100%;
object-fit: contain;
}
.controls button {
padding: 11px 20px;
font-size: 14px;
border-radius: 3px;
outline: none;
color: #fff;
cursor: pointer;
background: none;
transition: all 0.3s ease;
text-transform: uppercase;
}
.controls .reset-filter {
color: #6c757d;
border: 1px solid #6c757d;
}
.controls .reset-filter:hover {
color: #fff;
background: #6c757d;
}
.controls .choose-img {
background: #6c757d;
border: 1px solid #6c757d;
}
.controls .save-img {
margin-left: 5px;
background: #5372f0;
border: 1px solid #5372f0;
}
@media screen and (max-width: 760px) {
.container {
padding: 25px;
}
.container .wrapper {
flex-wrap: wrap-reverse;
}
.wrapper .editor-panel {
width: 100%;
}
.wrapper .preview-img {
width: 100%;
margin: 0 0 15px;
}
}
@media screen and (max-width: 500px) {
.controls button {
width: 100%;
margin-bottom: 10px;
}
.controls .row {
width: 100%;
}
.controls .row .save-img {
margin-left: 0px;
}
}
const fileInput = document.querySelector(".file-input"),
filterOptions = document.querySelectorAll(".filter button"),
filterName = document.querySelector(".filter-info .name"),
filterValue = document.querySelector(".filter-info .value"),
filterSlider = document.querySelector(".slider input"),
rotateOptions = document.querySelectorAll(".rotate button"),
previewImg = document.querySelector(".preview-img img"),
resetFilterBtn = document.querySelector(".reset-filter"),
chooseImgBtn = document.querySelector(".choose-img"),
saveImgBtn = document.querySelector(".save-img");
let brightness = "100",
saturation = "100",
inversion = "0",
grayscale = "0";
let rotate = 0,
flipHorizontal = 1,
flipVertical = 1;
const loadImage = () => {
let file = fileInput.files[0];
if (!file) return;
previewImg.src = URL.createObjectURL(file);
previewImg.addEventListener("load", () => {
resetFilterBtn.click();
document.querySelector(".container").classList.remove("disable");
});
};
const applyFilter = () => {
previewImg.style.transform = `rotate(${rotate}deg) scale(${flipHorizontal}, ${flipVertical})`;
previewImg.style.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`;
};
filterOptions.forEach((option) => {
option.addEventListener("click", () => {
document.querySelector(".active").classList.remove("active");
option.classList.add("active");
filterName.innerText = option.innerText;
if (option.id === "brightness") {
filterSlider.max = "200";
filterSlider.value = brightness;
filterValue.innerText = `${brightness}%`;
} else if (option.id === "saturation") {
filterSlider.max = "200";
filterSlider.value = saturation;
filterValue.innerText = `${saturation}%`;
} else if (option.id === "inversion") {
filterSlider.max = "100";
filterSlider.value = inversion;
filterValue.innerText = `${inversion}%`;
} else {
filterSlider.max = "100";
filterSlider.value = grayscale;
filterValue.innerText = `${grayscale}%`;
}
});
});
const updateFilter = () => {
filterValue.innerText = `${filterSlider.value}%`;
const selectedFilter = document.querySelector(".filter .active");
if (selectedFilter.id === "brightness") {
brightness = filterSlider.value;
} else if (selectedFilter.id === "saturation") {
saturation = filterSlider.value;
} else if (selectedFilter.id === "inversion") {
inversion = filterSlider.value;
} else {
grayscale = filterSlider.value;
}
applyFilter();
};
rotateOptions.forEach((option) => {
option.addEventListener("click", () => {
if (option.id === "left") {
rotate -= 90;
} else if (option.id === "right") {
rotate += 90;
} else if (option.id === "horizontal") {
flipHorizontal = flipHorizontal === 1 ? -1 : 1;
} else {
flipVertical = flipVertical === 1 ? -1 : 1;
}
applyFilter();
});
});
const resetFilter = () => {
brightness = "100";
saturation = "100";
inversion = "0";
grayscale = "0";
rotate = 0;
flipHorizontal = 1;
flipVertical = 1;
filterOptions[0].click();
applyFilter();
};
const saveImage = () => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = previewImg.naturalWidth;
canvas.height = previewImg.naturalHeight;
ctx.filter = `brightness(${brightness}%) saturate(${saturation}%) invert(${inversion}%) grayscale(${grayscale}%)`;
ctx.translate(canvas.width / 2, canvas.height / 2);
if (rotate !== 0) {
ctx.rotate((rotate * Math.PI) / 180);
}
ctx.scale(flipHorizontal, flipVertical);
ctx.drawImage(
previewImg,
-canvas.width / 2,
-canvas.height / 2,
canvas.width,
canvas.height
);
const link = document.createElement("a");
link.download = "image.jpg";
link.href = canvas.toDataURL();
link.click();
};
filterSlider.addEventListener("input", updateFilter);
resetFilterBtn.addEventListener("click", resetFilter);
saveImgBtn.addEventListener("click", saveImage);
fileInput.addEventListener("change", loadImage);
chooseImgBtn.addEventListener("click", () => fileInput.click());
728x90
LIST
'Javascript' 카테고리의 다른 글
Spin Wheel (0) | 2022.11.09 |
---|---|
Drag & Drop File Upload (0) | 2022.11.08 |
Captcha validation (0) | 2022.10.31 |
Parallax Tilt Effect Cards (0) | 2022.10.29 |
TIP CAlculator (0) | 2022.10.23 |