From 524702ec5a4078cad817cab70cc08517774e6c1c Mon Sep 17 00:00:00 2001 From: dongchyeon Date: Sat, 18 May 2024 02:30:13 +0900 Subject: [PATCH 1/2] =?UTF-8?q?#75=20Feat=20:=20=EB=85=B8=ED=8A=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EC=84=A4=EC=A0=95=EB=90=9C=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EA=B0=92=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?thumb=20=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamwiney/ui/components/ColorSlider.kt | 63 ++++++++++++++++++- .../NoteWineInfoColorAndFlavorScreen.kt | 8 ++- .../teamwiney/notewrite/NoteWriteContract.kt | 1 + .../teamwiney/notewrite/NoteWriteViewModel.kt | 4 +- 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt b/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt index 7d34b1fd..3d355298 100644 --- a/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt +++ b/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt @@ -38,6 +38,7 @@ import java.lang.Integer.min @Composable fun ColorSlider( + initialColor: Color, onValueChange: (Color) -> Unit, modifier: Modifier = Modifier, thumbColor: Color = Color.White, @@ -59,7 +60,7 @@ fun ColorSlider( trackHeight: Dp, thumbSize: Dp ) { - var thumbX by remember { mutableFloatStateOf(0f) } + var thumbX by remember { mutableFloatStateOf(-1f) } var isDragging by remember { mutableStateOf(false) } Box( @@ -111,6 +112,11 @@ fun ColorSlider( ) { val height = size.height + if (thumbX == -1f) { + // 최초 1회 initialColor에 해당하는 thumbX 계산 + thumbX = calculatePositionForColor(initialColor, size.width, barColors) + } + drawCircle( color = thumbColor, radius = thumbSize.toPx() / 2, @@ -123,6 +129,7 @@ fun ColorSlider( private fun isInCircle(x: Float, y: Float, centerX: Float, centerY: Float, radius: Float): Boolean { val dx = x - centerX val dy = y - centerY + return (dx * dx + dy * dy) <= (radius * radius) } @@ -138,10 +145,61 @@ private fun calculateColorForPosition( return lerp(startColor, endColor, fraction * (barColors.size - 1) - colorPosition) } +private fun calculatePositionForColor( + color: Color, + width: Float, + barColors: List +): Float { + var minDistance = Float.MAX_VALUE + var closestFraction = -1f + + for (i in 0 until barColors.size - 1) { + val startColor = barColors[i] + val endColor = barColors[i + 1] + val interpolatedColor = lerp(startColor, endColor, 0.5f) // 중간 색상을 보간하여 사용 + val distance = calculateColorDistance(color, interpolatedColor) + + if (distance < minDistance) { + minDistance = distance + val fraction = i.toFloat() / (barColors.size - 1) + closestFraction = adjustFraction(fraction, i, barColors) + } + } + + return closestFraction * width +} + +/*** + * 두 색상 사이의 거리를 고려하여 보정된 fraction을 반환합니다. + */ +private fun adjustFraction( + fraction: Float, + colorIndex: Int, + barColors: List +): Float { + val previousColor = if (colorIndex > 0) barColors[colorIndex - 1] else barColors[colorIndex] + val nextColor = if (colorIndex < barColors.size - 1) barColors[colorIndex + 1] else barColors[colorIndex] + + val distance = calculateColorDistance(previousColor, nextColor) + val adjustedFraction = fraction + (1f / (barColors.size - 1)) * distance + return adjustedFraction.coerceIn(0f, 1f) +} + + +/** + * 두 색상 사이의 유클리드 거리를 계산합니다. + */ +private fun calculateColorDistance(color1: Color, color2: Color): Float { + val deltaL = color2.red - color1.red + val deltaA = color2.green - color1.green + val deltaB = color2.blue - color1.blue + return kotlin.math.sqrt(deltaL * deltaL + deltaA * deltaA + deltaB * deltaB) +} + @Preview @Composable fun PreviewColorSlider() { - var barColors = listOf( + val barColors = listOf( Color(0xFF59002B), Color(0xFF6B3036), Color(0xFF852223), @@ -179,6 +237,7 @@ fun PreviewColorSlider() { ) ColorSlider( + initialColor = barColors[6], onValueChange = { currentColor = it }, barColors = barColors, trackHeight = 10.dp, diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt index 5413b200..979cdc4f 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWineInfoColorAndFlavorScreen.kt @@ -102,9 +102,12 @@ fun NoteWineInfoColorAndSmellScreen( verticalArrangement = Arrangement.Center, ) { WineColorPicker( + initialColor = uiState.initialColor, currentColor = uiState.wineNote.color, barColors = uiState.barColors - ) { viewModel.updateColor(it) } + ) { + viewModel.updateColor(it) + } HeightSpacer(35.dp) WineFlavorPicker( wineSmellKeywords = uiState.wineSmellKeywords, @@ -200,7 +203,6 @@ private fun WineFlavorPicker( } } -@OptIn(ExperimentalLayoutApi::class) @Composable private fun WineSmellContainer( wineSmellKeyword: WineSmellKeyword, @@ -234,6 +236,7 @@ private fun WineSmellContainer( @Composable private fun WineColorPicker( + initialColor: Color, currentColor: Color, barColors: List, updateCurrentColor: (Color) -> Unit, @@ -286,6 +289,7 @@ private fun WineColorPicker( ) ColorSlider( + initialColor = initialColor, onValueChange = updateCurrentColor, barColors = barColors, trackHeight = 10.dp, diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt index fe3cd9d7..12f30680 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteContract.kt @@ -46,6 +46,7 @@ class NoteWriteContract { Color(0xFFF1FBCB), Color(0xFFD5DBB5) ), + val initialColor: Color = barColors[0], val searchWinesCount: Long = 0, val selectedWine: SearchWine = SearchWine.default(), val selectedWineInfo: Wine = Wine.default(), diff --git a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt index fc5e0600..5cbd6240 100644 --- a/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt +++ b/feature/note/src/main/java/com/teamwiney/notewrite/NoteWriteViewModel.kt @@ -36,10 +36,9 @@ class NoteWriteViewModel @Inject constructor( ) : BaseViewModel( initialState = NoteWriteContract.State() ) { - private val noteId: Int + private val noteId: Int = savedStateHandle.get("noteId")?.toInt() ?: -1 init { - noteId = savedStateHandle.get("noteId")?.toInt() ?: -1 updateState(currentState.copy(mode = if (noteId == -1) EditMode.ADD else EditMode.UPDATE)) } @@ -65,6 +64,7 @@ class NoteWriteViewModel @Inject constructor( updateState( currentState.copy( + initialColor = Color(result.color.toColorInt()), wineNote = WineNote( wineId = -1L, vintage = result.vintage?.toString() ?: "", From da58dfb13f61b35ca412f49ba124be5bb758fa4c Mon Sep 17 00:00:00 2001 From: dongchyeon Date: Sat, 18 May 2024 02:30:36 +0900 Subject: [PATCH 2/2] =?UTF-8?q?#75=20Feat=20:=20=ED=84=B0=EC=B9=98=20?= =?UTF-8?q?=EC=98=81=EC=97=AD=201.5=EB=B0=B0=20=ED=99=95=EB=8C=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/com/teamwiney/ui/components/ColorSlider.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt b/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt index 3d355298..21a118c6 100644 --- a/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt +++ b/core/design/src/main/java/com/teamwiney/ui/components/ColorSlider.kt @@ -130,7 +130,8 @@ private fun isInCircle(x: Float, y: Float, centerX: Float, centerY: Float, radiu val dx = x - centerX val dy = y - centerY - return (dx * dx + dy * dy) <= (radius * radius) + // 원의 반지름의 1.5배 이내에 있는지 확인 (터치 영역 개선을 위해 1.5배로 설정) + return (dx * dx + dy * dy) <= (radius * radius * 1.5f) } private fun calculateColorForPosition(