NAVERボタンの作成
57229 ワード
NAVERボタンの作成
バージョンの移動
モバイル版でユーザー体験を増やすため、NAVERは下に丸いボタンを作り、その中に機能を加えた.△個人的には苦手な機能です.
NAVERは、音楽、カメラ、翻訳、画像、音声検索、位置、qrなどの他の機能を検索するのではなく、人々が「検索」する行為に使用されます.
もちろんこの機能をうまく利用している人もいますが、どれだけのユーザーがいるのか疑問です.
この機能をうまく利用できない私のような人のために作られたインタラクティブなボタンなのかもしれません.
インプリメンテーション
要するに、本題に移行すると、以下の画像に示すボタンが表示されます.
次のツイッターのニュースやショッピングなどのサイドメニューは作らず、ツイッターの曲線レイアウトのみを実現します.
まず,結論から言えば,実力がまだ足りないため,アイコンへのグラデーション応用やタッチで移動できる回転円盤は実現できない.
代替として、白い円板をクリックして回転させる制限的な反応として現れ、多くの問題が以下に説明される.
コード#コード#
HTML
<!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">
<link rel="stylesheet" href="style.css">
<script src="./main.js" defer></script>
<title>naver_mobile_handle</title>
</head>
<body>
<!-- 버튼 메뉴 전체를 감싸는 div를 만들었다. -->
<div class="menu">
<!-- 버튼의 중간 원을 만들기 위해(그라데이션 적용부분) div를 만들고-->
<div class="gradation">
<!-- 실제로 이 부분만 애니메이션을 적용하여 그라데이션을 돌렸다. -->
<div></div>
</div>
<!-- 작은 원을 만들기 위해 따로 만듦-->
<div class="circle"></div>
<!-- 흰색 원과 그 중심으로 아이콘들을 배치함 -->
<div class="menu_background">
<!-- 검색 아이콘, style var(--i :0으로 설정) -->
<li style="--i:0">
<a href="#"><ion-icon class="icon" name="search-circle-outline"></ion-icon></a>
</li>
<!-- 번역 아이콘 -->
<li style="--i:1">
<a href="#"><ion-icon class="ion1 icon" name="globe-outline"></ion-icon></a>
</li>
<!-- 카메라 아이콘 -->
<li style="--i:2">
<a href="#"><ion-icon class="ion2 icon" name="camera-outline"></ion-icon></a>
</li>
<!-- qr 아이콘 -->
<li style="--i:3">
<a href="#"><ion-icon class="ion3 icon" name="qr-code-outline"></ion-icon></a>
</li>
<!-- 사진 아이콘 -->
<li style="--i:4">
<a href="#"><ion-icon class="ion4 icon" name="image-outline"></ion-icon></a>
</li>
<!-- 음악 아이콘 -->
<li style="--i:5">
<a href="#"><ion-icon class="ion5 icon" name="musical-notes-outline"></ion-icon></a>
</li>
<!-- 음성 메모 아이콘 -->
<li style="--i:6">
<a href="#"><ion-icon class="ion6 icon" name="mic-outline"></ion-icon></a>
</li>
<!-- 위치 아이콘 -->
<li style="--i:7">
<a href="#"><ion-icon class="ion7 icon" name="location-outline"></ion-icon></a>
</li>
</div>
</div>
<!-- 아이콘을 불러오기 위한 CDN링크 -->
<script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>
</body>
</html>
CSS
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 전체를 flex로 배치하고 버튼을 중간으로 가져옴 */
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #00000066;
}
/* 그라데이션이 들어가는 중간 부분의 원형 */
.menu .gradation {
position: absolute;
width: 150px;
height: 150px;
border-radius: 50%;
box-shadow: 0px -3px 2px rgb(80, 80, 80);
z-index: 9;
transition: 0.5s;
}
/* 실제로 그라데이션 적용되는 원형 */
.menu .gradation div {
width: 150px;
height: 150px;
background: radial-gradient(
circle at 50% 0,
rgba(0, 255, 170, 0.9) 20%,
rgba(0, 240, 199, 1) 35%,
rgba(0, 240, 200, 1) 50%,
rgba(0, 212, 255, 1) 100%
);
border-radius: 50%;
animation: rotate 8s linear infinite;
}
/* 애니메이션을 적용하여 그라데이션을 움직임 */
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
/* 작은 원형 설정 */
.menu .circle {
position: relative;
width: 80px;
height: 80px;
z-index: 100;
top: 35px;
left: 35px;
border: 3px solid #fff;
border-top: 0;
box-shadow: 0 2px 5px #a6bab4;
background: #85ffda;
border-radius: 50%;
cursor: pointer;
transition: 0.5s;
}
/* 흰색 큰원을 설정 */
.menu_background {
position: relative;
top: -155px;
left: -75px;
width: 300px;
height: 300px;
border-radius: 50%;
border: 75px solid #fff;
/* 45도씩 움직여야 정렬됨 */
transform: rotate(0);
transition: all 0.5s;
}
/* 아이콘의 li를 설정 */
.menu li {
position: absolute;
list-style: none;
top: 62px;
left: -55px;
transform-origin: 130px;
z-index: 8;
}
/* 8개의 아이콘들을 순서대로 일정한 간격으로 배치함 */
.menu_background li {
transform: rotate(calc(360deg / 8 * var(--i)));
}
.menu_background li a {
display: flex;
font-size: 1.5em;
justify-content: center;
align-items: center;
color: rgba(0, 240, 200, 1);
transform: rotate(calc(360deg / -8 * var(--i)));
z-index: 15;
}
/* 흰원판이 돌아갈때 아이콘을 반대로 같은 각도로 움직여 기준을 이룸 */
/* 45도씩 움직여야 정렬됨 */
/* 흰색 원이 돌아갈때 transition으로 부드럽게 위치를 잡음 */
.icon {
transform: rotate(0);
transition: all 0.5s;
}
/* 작은원이 클릭되었을때 작게 만든다.*/
.circle.active {
transform: scale(0.2);
background-color: #fff;
animation: circle_scale 2s linear infinite;
animation-direction: alternate-reverse;
}
@keyframes circle_scale {
0% {
transform: scale(0.3);
}
50% {
transform: scale(0.4);
}
100% {
transform: scale(0.6);
}
}
/* active가 붙을때 작게 만든다. */
.gradation.active {
transform: scale(0.55);
transition: 0.23s;
}
/* active가 붙을때 작게 만든다. */
.menu_background.active {
transform: scale(0.32) !important;
transition: all 0.23s;
}
/* 아이콘 위에 마우스를 올리면 색상을 변경함. */
.menu_background li a:hover .icon {
color: #ffa1ac;
}
JS
// 동그란 버튼을 누르면 스케일을 업시키기 위한 선택자를 classlist에 넣어줌
let circle = document.querySelector('.circle');
let menubgd= document.querySelector('.menu_background')
let grd = document.querySelector('.gradation')
//클릭 시 다음 함수를 실행한다.
circle.onclick = function(){
// 아래 3개의 클래스에 active 클래스를 붙임
circle.classList.toggle('active')
menubgd.classList.toggle('active')
grd.classList.toggle('active')
}
//클릭하면 움직이는 걸로 대체하자.....
//icon을 가져옴
let icon = document.getElementsByClassName('icon');
let rotate_deg = 0;
//menubgd을 가져와 이벤트를 적용하고 클릭 시 rotate_1 함수를 실행
menubgd.addEventListener('click', (e) => rotate_1(e.offsetX, e.offsetY));
const rotate_1 = function(x,y){
//x와 y 좌표들을 중심 기준으로 음수와 양수로 만들었다.
let cord_x = (75+x)-150;
let cord_y =150-(y+75);
//console.log((75+x)-150)
//console.log(150-(y+75))
// console.log(x,y)
if(cord_x>0 && cord_y>0){
console.log('here1')
rotate_plus()
}else if(cord_x>0 && cord_y<0){
console.log('here2')
rotate_plus()
}else if(cord_x<0 && cord_y>0){
console.log('here3')
rotate_minus()
}else if(cord_x<0 && cord_y<0){
console.log('here4')
rotate_minus()
}
console.log(rotate_deg)
//함수가 실행되면 아래의 스타일을 적용시킨다.
menubgd.style.transform = `rotate(${rotate_deg}deg)`
//icon은 배열로 여러클래스를 가져왔기 때문에 아래와 같이 적용시킴
for(let i = 0; i<8; i++){
icon[i].style.transform = `rotate(${-rotate_deg}deg)`
}
//console.log(icon[1])
}
//아이콘들의 정렬을 위해 45도씩 적용되는 함수
const rotate_plus = function(){
rotate_deg += 45;
}
const rotate_minus = function(){
rotate_deg -= 45;
}
//흰색 원판 회전 시키기(하다가 실패함..)
// let icon = document.querySelector('.icon');
// let rotate_start_x = 0;
// let rotate_gab = 0;
// let is_rotate = false;
// // 화면을 처음 클릭했을때 x좌표
// const rotate_start = function(e){
// rotate_start_x = e;
// is_rotate = true;
// }
// const rotate_move = function(e){
// if(is_rotate){
// rotate_gab = (e - rotate_start_x)
// }
// menubgd.style.transform = `rotate(${rotate_gab}deg)`
// console.log(e)
// console.log(rotate_gab)
// }
// const rotate_end = function(){
// is_rotate = false;
// }
// menubgd.addEventListener('mousedown', (e) => rotate_start(e.offsetX))
// menubgd.addEventListener('mousemove', (e)=> rotate_move(e.offsetX))
// menubgd.addEventListener('mouseup', ()=> rotate_end())
// menubgd.addEventListener('mouseout', ()=> rotate_end())
今後の課題。
1.円形回転の場合、スリップが可能です。
2.一方向に回し続けても、間違いなく運転を続けます。
Reference
この問題について(NAVERボタンの作成), 我々は、より多くの情報をここで見つけました
https://velog.io/@km2535/네이버-버튼-만들기
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
<!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">
<link rel="stylesheet" href="style.css">
<script src="./main.js" defer></script>
<title>naver_mobile_handle</title>
</head>
<body>
<!-- 버튼 메뉴 전체를 감싸는 div를 만들었다. -->
<div class="menu">
<!-- 버튼의 중간 원을 만들기 위해(그라데이션 적용부분) div를 만들고-->
<div class="gradation">
<!-- 실제로 이 부분만 애니메이션을 적용하여 그라데이션을 돌렸다. -->
<div></div>
</div>
<!-- 작은 원을 만들기 위해 따로 만듦-->
<div class="circle"></div>
<!-- 흰색 원과 그 중심으로 아이콘들을 배치함 -->
<div class="menu_background">
<!-- 검색 아이콘, style var(--i :0으로 설정) -->
<li style="--i:0">
<a href="#"><ion-icon class="icon" name="search-circle-outline"></ion-icon></a>
</li>
<!-- 번역 아이콘 -->
<li style="--i:1">
<a href="#"><ion-icon class="ion1 icon" name="globe-outline"></ion-icon></a>
</li>
<!-- 카메라 아이콘 -->
<li style="--i:2">
<a href="#"><ion-icon class="ion2 icon" name="camera-outline"></ion-icon></a>
</li>
<!-- qr 아이콘 -->
<li style="--i:3">
<a href="#"><ion-icon class="ion3 icon" name="qr-code-outline"></ion-icon></a>
</li>
<!-- 사진 아이콘 -->
<li style="--i:4">
<a href="#"><ion-icon class="ion4 icon" name="image-outline"></ion-icon></a>
</li>
<!-- 음악 아이콘 -->
<li style="--i:5">
<a href="#"><ion-icon class="ion5 icon" name="musical-notes-outline"></ion-icon></a>
</li>
<!-- 음성 메모 아이콘 -->
<li style="--i:6">
<a href="#"><ion-icon class="ion6 icon" name="mic-outline"></ion-icon></a>
</li>
<!-- 위치 아이콘 -->
<li style="--i:7">
<a href="#"><ion-icon class="ion7 icon" name="location-outline"></ion-icon></a>
</li>
</div>
</div>
<!-- 아이콘을 불러오기 위한 CDN링크 -->
<script type="module" src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.esm.js"></script>
<script nomodule src="https://unpkg.com/[email protected]/dist/ionicons/ionicons.js"></script>
</body>
</html>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 전체를 flex로 배치하고 버튼을 중간으로 가져옴 */
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #00000066;
}
/* 그라데이션이 들어가는 중간 부분의 원형 */
.menu .gradation {
position: absolute;
width: 150px;
height: 150px;
border-radius: 50%;
box-shadow: 0px -3px 2px rgb(80, 80, 80);
z-index: 9;
transition: 0.5s;
}
/* 실제로 그라데이션 적용되는 원형 */
.menu .gradation div {
width: 150px;
height: 150px;
background: radial-gradient(
circle at 50% 0,
rgba(0, 255, 170, 0.9) 20%,
rgba(0, 240, 199, 1) 35%,
rgba(0, 240, 200, 1) 50%,
rgba(0, 212, 255, 1) 100%
);
border-radius: 50%;
animation: rotate 8s linear infinite;
}
/* 애니메이션을 적용하여 그라데이션을 움직임 */
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(-360deg);
}
}
/* 작은 원형 설정 */
.menu .circle {
position: relative;
width: 80px;
height: 80px;
z-index: 100;
top: 35px;
left: 35px;
border: 3px solid #fff;
border-top: 0;
box-shadow: 0 2px 5px #a6bab4;
background: #85ffda;
border-radius: 50%;
cursor: pointer;
transition: 0.5s;
}
/* 흰색 큰원을 설정 */
.menu_background {
position: relative;
top: -155px;
left: -75px;
width: 300px;
height: 300px;
border-radius: 50%;
border: 75px solid #fff;
/* 45도씩 움직여야 정렬됨 */
transform: rotate(0);
transition: all 0.5s;
}
/* 아이콘의 li를 설정 */
.menu li {
position: absolute;
list-style: none;
top: 62px;
left: -55px;
transform-origin: 130px;
z-index: 8;
}
/* 8개의 아이콘들을 순서대로 일정한 간격으로 배치함 */
.menu_background li {
transform: rotate(calc(360deg / 8 * var(--i)));
}
.menu_background li a {
display: flex;
font-size: 1.5em;
justify-content: center;
align-items: center;
color: rgba(0, 240, 200, 1);
transform: rotate(calc(360deg / -8 * var(--i)));
z-index: 15;
}
/* 흰원판이 돌아갈때 아이콘을 반대로 같은 각도로 움직여 기준을 이룸 */
/* 45도씩 움직여야 정렬됨 */
/* 흰색 원이 돌아갈때 transition으로 부드럽게 위치를 잡음 */
.icon {
transform: rotate(0);
transition: all 0.5s;
}
/* 작은원이 클릭되었을때 작게 만든다.*/
.circle.active {
transform: scale(0.2);
background-color: #fff;
animation: circle_scale 2s linear infinite;
animation-direction: alternate-reverse;
}
@keyframes circle_scale {
0% {
transform: scale(0.3);
}
50% {
transform: scale(0.4);
}
100% {
transform: scale(0.6);
}
}
/* active가 붙을때 작게 만든다. */
.gradation.active {
transform: scale(0.55);
transition: 0.23s;
}
/* active가 붙을때 작게 만든다. */
.menu_background.active {
transform: scale(0.32) !important;
transition: all 0.23s;
}
/* 아이콘 위에 마우스를 올리면 색상을 변경함. */
.menu_background li a:hover .icon {
color: #ffa1ac;
}
// 동그란 버튼을 누르면 스케일을 업시키기 위한 선택자를 classlist에 넣어줌
let circle = document.querySelector('.circle');
let menubgd= document.querySelector('.menu_background')
let grd = document.querySelector('.gradation')
//클릭 시 다음 함수를 실행한다.
circle.onclick = function(){
// 아래 3개의 클래스에 active 클래스를 붙임
circle.classList.toggle('active')
menubgd.classList.toggle('active')
grd.classList.toggle('active')
}
//클릭하면 움직이는 걸로 대체하자.....
//icon을 가져옴
let icon = document.getElementsByClassName('icon');
let rotate_deg = 0;
//menubgd을 가져와 이벤트를 적용하고 클릭 시 rotate_1 함수를 실행
menubgd.addEventListener('click', (e) => rotate_1(e.offsetX, e.offsetY));
const rotate_1 = function(x,y){
//x와 y 좌표들을 중심 기준으로 음수와 양수로 만들었다.
let cord_x = (75+x)-150;
let cord_y =150-(y+75);
//console.log((75+x)-150)
//console.log(150-(y+75))
// console.log(x,y)
if(cord_x>0 && cord_y>0){
console.log('here1')
rotate_plus()
}else if(cord_x>0 && cord_y<0){
console.log('here2')
rotate_plus()
}else if(cord_x<0 && cord_y>0){
console.log('here3')
rotate_minus()
}else if(cord_x<0 && cord_y<0){
console.log('here4')
rotate_minus()
}
console.log(rotate_deg)
//함수가 실행되면 아래의 스타일을 적용시킨다.
menubgd.style.transform = `rotate(${rotate_deg}deg)`
//icon은 배열로 여러클래스를 가져왔기 때문에 아래와 같이 적용시킴
for(let i = 0; i<8; i++){
icon[i].style.transform = `rotate(${-rotate_deg}deg)`
}
//console.log(icon[1])
}
//아이콘들의 정렬을 위해 45도씩 적용되는 함수
const rotate_plus = function(){
rotate_deg += 45;
}
const rotate_minus = function(){
rotate_deg -= 45;
}
//흰색 원판 회전 시키기(하다가 실패함..)
// let icon = document.querySelector('.icon');
// let rotate_start_x = 0;
// let rotate_gab = 0;
// let is_rotate = false;
// // 화면을 처음 클릭했을때 x좌표
// const rotate_start = function(e){
// rotate_start_x = e;
// is_rotate = true;
// }
// const rotate_move = function(e){
// if(is_rotate){
// rotate_gab = (e - rotate_start_x)
// }
// menubgd.style.transform = `rotate(${rotate_gab}deg)`
// console.log(e)
// console.log(rotate_gab)
// }
// const rotate_end = function(){
// is_rotate = false;
// }
// menubgd.addEventListener('mousedown', (e) => rotate_start(e.offsetX))
// menubgd.addEventListener('mousemove', (e)=> rotate_move(e.offsetX))
// menubgd.addEventListener('mouseup', ()=> rotate_end())
// menubgd.addEventListener('mouseout', ()=> rotate_end())
1.円形回転の場合、スリップが可能です。
2.一方向に回し続けても、間違いなく運転を続けます。
Reference
この問題について(NAVERボタンの作成), 我々は、より多くの情報をここで見つけました https://velog.io/@km2535/네이버-버튼-만들기テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol