★ 요즘 평점 혹은 별점 리뷰를 등록하는 UI가 많이 보인다
이를 드래그 기능을 포함하여 구현해보자 ✨
📃 vue.js
<template v-for="idx in 5">
<!-- id는 label의 for값과 연결 됨 -->
<!-- v-model과 value값이 연결 됨 -->
<!-- radio 타입으로 클릭하면 v-model에 값이 반영됨 -->
<input
:id="`star${idx}`"
:key="idx"
v-model="selectedStarNum"
type="radio"
:value="idx"
:disabled="isRegistered"
/>
<label :key="idx" :for="`star${idx}`" @touchmove="$_onTouchMove">
</label>
</template>
<script>
export default {
data() {
return {
selectedStarNum: 0, // 별점,
starLeftOffsetXs: [], // 드래그를 위한 위치 좌표값
isRegistered: false, // 등록이 완료 되었는지 여부
};
},
mounted() {
this.$_initStarOffsets();
},
methods: {
$_setStarNum(num) {
this.selectedStarNum = num;
},
// 드래그 기능을 위한 이벤트 감지
$_onTouchMove(e) {
if (this.isRegistered) {
return;
}
const touchEndPosX = e.changedTouches[0].pageX;
const starNum = this.$_getTouchEndStar(touchEndPosX);
this.$_setStarNum(starNum);
},
// 각 별들의 위치를 저장
$_initStarOffsets() {
[1, 2, 3, 4, 5].forEach((idx) => {
const leftOffset = document.getElementById(`star${idx}`).offsetLeft;
this.starLeftOffsetXs.push(leftOffset);
});
},
// param - 사용자의 마지막 터치지점
$_getTouchEndStar(posX) {
this.starLeftOffsetXs.entries();
/* const array1 = ['a', 'b', 'c'];
array1.entries() => [0, "a"] [1, "b"] [2, "c"] */
for (const [idx, offsetX] of offsetArr) {
if (posX < offsetX) {
return idx;
}
}
},
},
};
</script>