연결된 값이 항상 총 100 % 인 X 백분율 슬라이더를 표시하는 UI 알고리즘


11

내가 만들고있는 시스템에는 각각 0-100의 스케일로 UI 슬라이더 세트 (숫자가 다릅니다)가 포함되어 있습니다. 슬라이더 란 볼륨 컨트롤처럼 요소를 잡고 위아래로 드래그하는 UI를 의미합니다. 그것들은 항상 총 100을 보장하는 알고리즘으로 연결되어 있습니다. 따라서 하나의 슬라이더가 위로 움직이면 다른 하나는 모두 0으로 내려갑니다. 하나가 아래로 이동하면 다른 하나가 위로 이동합니다. 항상 총계는 100이어야합니다. 따라서 슬라이더에는 다양한 값이 있지만 총 100 %입니다.

----O------ 40
O----------  0
--O-------- 20
--O-------- 20
--O-------- 20

그런 다음 첫 번째 슬라이더가 40에서 70으로 위로 이동하면 다른 슬라이더는 값을 아래로 이동해야합니다 (슬라이더를 끌 때). 3 개의 슬라이더가 20에서 10으로 변경되었으며 하나는 더 낮아질 수 없으므로 0으로 유지되었습니다.

-------O--- 70
O----------  0
-O--------- 10
-O--------- 10
-O--------- 10

물론 슬라이더가 0 또는 100에 도달하면 더 이상 움직일 수 없으므로 머리가 아프기 시작합니다. 따라서 슬라이더가 더 높게 움직이면 다른 것이 더 낮아 지지만, 0에 도달하면 아직 0에 도달하지 않은 나머지 것만 더 낮아질 수 있습니다.

이 질문은 구현이 아닌 알고리즘에만 해당되므로 여기에서 묻습니다. FWIW 플랫폼은 Android Java이지만 특별히 관련이 없습니다.

첫 번째 찌르기로 취한 접근법은 움직 인 슬라이더의 백분율 변화를 계산하는 것이 었습니다. 그런 다음 해당 변경 사항을 분할하고 다른 방향으로 다른 슬라이더 값에 적용했습니다. 문제는 백분율과 곱셈을 사용하여 슬라이더가 0에 도달하면 다시 0에서 다시 증가 할 수 없다는 것입니다. 그 결과로 개별 슬라이더가 0에 고정됩니다. 반올림 문제를 피하기 위해 0-1,000,000 범위의 슬라이더를 사용했지만 도움이되는 것처럼 보이지만 아직 모든 시나리오를 잘 처리하는 알고리즘을 만들지 않았습니다.


2
IMHO는 특히 만족스러운 답변을 얻지 못했지만 UX 사이트에서도 비슷한 질문제기 되었습니다. 좋은 해결책이 있는지 궁금합니다. 솔직히 말하지만 슬라이더를 서로 연결하면 사용자에게도 가치가있는 것보다 더 많은 문제가 발생한다는 것을 알았습니다. 이미 입력 한 값을 계속 변경하기 때문에 원하는 분포로 끝내기가 어려워집니다 가다.
Daniel B

1
한 가지 제안은 사용자가 두 가지 모드 사이를 전환 할 수 있도록하는 것입니다. 하나는 슬라이더가 서로 연결되어 있고 다른 하나는 그렇지 않은 모드입니다 ( "상대 모드"로 다시 전환하면 분포가 정규화됩니다). 이렇게하면 언급 한 문제 중 일부를 회피 할 수 있지만 UI에 너무 많은 복잡성을 추가하여 사용자가 값을 입력하기가 더 쉬울 수 있습니다.
Daniel B

당신은 확실히 맞습니다. 사용자 측에서 많은 조정이 필요하지만이 경우 슬라이더가 문제를 나타내는 설문 조사 응용 프로그램의 형태이므로 값의 상대 가중치에 대한 모든 질문이 있습니다.
Ollie C

1
이해합니다 ... 내 문제는 60 / 30 / 10 분할과 같은 것을 표현하는 데 3 이상의 작업 이 필요하다는 것입니다 .30 / 10 부분을 조정할 때 60이 계속 움직이므로. 목록이 클수록 점점 더 나 빠지고 매우 모호한 입력에만 적합합니다. 왜냐하면 머리에있는 숫자에 도달하지 않기 때문입니다.
Daniel B

2
당신의 UX 지점에서, 슬라이더의 측면에서 총 점수가 큰 숫자로 표시되도록 제안합니다. 한 슬라이더를 위로 올리면 총 점수가 "100"이상으로 증가하고 사용자가 다른 슬라이더를 아래로 밀어서 총 점수를 낮추기 전까지는 "다음"단추가 비활성화됩니다. 사용자가 하나의 슬라이더를 위로 밀 때 다른 4 개의 슬라이더 중 어느 것을 줄이고 싶은지 절대 알 수 없으므로 시도하지 마십시오.
Graham

답변:


10

욕심 알고리즘

슬라이더가 위로 움직이면 (아래로) 다른 모든 것은 아래로 움직여야합니다 (위로). 각각은 움직일 수있는 공간이 있습니다 (아래쪽-위 : 100 위치).

따라서 하나의 슬라이더가 움직일 때 다른 슬라이더를 가져 가서 이동할 수있는 공간을 기준으로 정렬 한 다음 간단히 반복합니다.

각 반복에서 슬라이더를 필요한 방향으로 (대기열에서 왼쪽으로 이동 / 슬라이더를 왼쪽으로 이동) 또는 이동할 수있는 거리 중 더 작은 거리로 이동하십시오.

이것은 복잡성에있어 선형 적입니다 (정렬 된 후에는 동일한 정렬 된 큐를 계속해서 사용할 수 있기 때문에).

이 시나리오에서는 슬라이더가 걸리지 않으며 모두 슬라이더를 최대한 많이 움직이려고하지만 공정한 비율까지만 이동하려고합니다.

가중 이동

다른 접근법은 그들이해야 할 움직임에 가중치를 두는 것입니다. 나는 이것이 당신이 "슬라이더가 0에 붙어있다"고 판단하여 당신이 시도한 것이라고 생각 합니다. IMHO 이것은 더 자연 스럽습니다. 더 많은 조정을해야합니다.

다시 한 번 말하지만, 다른 슬라이더의 움직임을 위치별로 가중치를 부여하려고합니다 (이것은 0에서 멈추는 것으로 직접 해석됩니다). 그러나 처음부터 끝까지 다른 방향으로 슬라이더 위치를 볼 수 있습니다. 감소 할 때 시작 위치부터 무게를 늘리고 증가 할 때 끝 위치를 기준으로 가중치를 부여하면 문제를 피해야합니다.

이것은 이전 부분과 용어의 측면에서 매우 유사 합니다. 슬라이더 의 위치 에 따라 이동에 가중치를 부여하지 말고 해당 방향으로 이동하기 위해 남겨둔 공간 만큼 가중치를 적용하십시오 .


1
나는 더 깊게 보았고 "고착 된"것이 붙어 있지 않은 것으로 나타 났지만, 단순히 낮은 값을 가지면 백분율 변화는 거의 영향을 미치지 않습니다. 슬라이더의 이동량은 그 값에 비례합니다. 반대 값을 사용하라는 제안이 오히려 더 효과적이라고 생각합니다. 값을 100으로 유지하면됩니다. 명확성을 주입 해 주셔서 감사합니다.
Ollie C

1

내가 취하는 접근법은 약간 다르며 각 슬라이더의 다른 내부 표현을 사용합니다.

  1. 각 슬라이더는 해당 슬라이더 의 가중치 로 사용되는 0..100 (X)의 값을 가질 수 있습니다 (% 아님).

  2. 총 슬라이더 (T)를 얻기 위해 모든 슬라이더 값을 합산

  3. 각 슬라이더의 표시 값을 결정하려면 ROUND (X * 100 / T)를 사용하십시오.

  4. 슬라이더를 위나 아래로 이동 하면 하나의 슬라이더 값만 변경합니다 . 해당 슬라이더의 가중치는 다른 모든 슬라이더에 비해 증가 또는 감소하며, 위의 계산은 다른 모든 슬라이더에 대한 변경 사항이 가능한 한 고르게 분산되도록합니다.


사용자가 다소 정확한 분수를 만드는 것에 관심이 있다면 이것은 좋은 인터페이스가 될 것입니다. 그러나 다른 슬라이드가 해당 위치에 비례하여 움직이는 것과 이것이 기능적으로 어떻게 다른지 알 수 없습니다.
Ordous

1

'이동 한'슬라이더 변경 비율에 따라 현재 값을 조정하여 비율을 백분율로 표시하여 반올림 오류가 발생하여 과도하게 복잡하게 생각합니다.

총 100의 값만 처리한다는 것을 알고 있으므로 반올림에 대한 심각한 혼란을 피하면서 정수로 유지하고 100에서 거꾸로 작업합니다. (아래 예제에서는 모든 정수를 끝에서 정수로 처리합니다)

내 기술은 슬라이더를 간단한 0-100으로 설정하는 것입니다. 재분배 할 양을 계산하기 위해 100에서 '새로운'값을 빼고 무게에 따라 다른 슬라이더 사이에 분산시킨 다음 정리하십시오)

이것은 내가 아는 한 유효한 Android 코드가 아닙니다 : p

// see how much is "left" to redistribute
amountToRedistribute = 100 - movedSlider.value

//What proportion of the original 100% was contained in the other sliders (for weighting)
allOtherSlidersTotalWeight = sum(other slider existing values)

//Approximately redistribute the amount we have left between the other sliders, adjusting for their existing weight
for each (otherSlider)
    otherSlider.value = floor(otherSlider.value/allOtherSlidersWeight * amountToRedistribute)
    amountRedistributed += otherSlider.value

//then clean up because the floor() above might leave one or two leftover... How much still hasn't been redistributed?
amountLeftToRedistribute -= amountRedistributed

//add it to a slider (you may want to be smarter and add in a check if the slider chosen is zero, or add it to the largest remaining slider, spread it over several sliders etc, I'll leave it fairly simple here)
otherSlider1.value += amountLeftToRedistribute 

이것은 본질적으로 0 또는 100 값을 처리해야합니다


0

라운드 로빈 접근 방식은 어떻습니까? 하나의 슬라이더에 값을 추가하면 해당 피어에서 값이 줄어들도록하는 트랜잭션을 만듭니다. 그 반대.

그런 다음 슬라이더 변경이 다른 피어 슬라이더로 트랜잭션을 실행할 때마다 (피어 슬라이더를 차례로 반환하는 반복자를 만듭니다). 피어 슬라이더가 0이면 다음 슬라이더로 진행하십시오.


0

@Ordous의 위대한 Greedy Algorithm 답변을 자세히 설명하십시오. 단계는 다음과 같습니다.

  1. 슬라이더 이동
  2. 차이를 저장 newValue - oldValue 로 이동 한 양
  3. differenceAmount 가 양수 또는 음수로 요구되는 방향으로 이동할 수 있는 최소 거리 에서 대부분거리 까지 목록 의 다른 것들을 정렬합니다 .
  4. 설정 amountToMove = differenceAmount / 남은 OthersCount을
  5. 루프 통해 각 슬라이더를 이동 하거나 그 양 움직이거나 amountToMove . 둘 중입니다 작은
  6. 하여 슬라이더를 양 빼기 이동 한 에서 amountToMove 바이와 격차 새로운 나머지 OthersCount을
  7. 완료되면 다른 슬라이더간에 differenceAmount 를 성공적으로 분배했습니다 .

환상적인 답변입니다. stackoverflow.com/a/44369773/4222929
Sean

-3

한 가지 간단한 기술은 슬라이더 값의 합계를 기준으로 슬라이더 값의 백분율을 계산 한 다음 슬라이더 값을 계산 된 각 백분율로 다시 할당하는 것입니다. 이 방법으로 슬라이더 값이 재조정됩니다. 예 :

slider1.value = (slider1.value / sumOfSliderValues) * 100 ;
slider2.value = (slider2.value / sumOfSliderValues) * 100 ;
slider3.value = (slider3.value / sumOfSliderValues) * 100 ;

반올림 오류가 발생하지만 슬라이더 값이 정확하고 항상 100까지 합산되어야하는 경우 처리 할 수 ​​있습니다.

angularjs를 사용하여 이것을 보여주기 위해 바이올린을 설정했습니다. 데모를 방문하십시오


2
... 제프리의 대답입니다. 중복을 방지하기 위해 다른 답변을 먼저 읽으십시오.
Jan Doggen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.