Slider with integer steps?

Is it possible to have a slider with discrete / integer steps?

I have tried UserStep but it didn’t seem to work.

I have also tried setting the slider value to a rounded version of its own value in the ValueChanged event. This kind of works but if I move the slider quickly left and right something strange happens and the slider starts to issue continuous events without stopping, even after I stop moving the slider.

Not quite sure why this is, but in any case it seems like a bit of a hack.

Is there a better way?

Thanks!

Please include a complete, minimal reproduction to show what you’ve tried so far, otherwise it’s impossible to help.

Related: there is an example using RangeControl with UserStep.

Hello, sorry for the delayed reply with this.

I looked at the clock example (which is nice btw) and the Fuse docs and have tried to produce something similar but for a linear slider, eg.

<App>
  <StackPanel Padding="20">
    <Panel Padding="10,9,10,9">
      <RangeControl Minimum="0" Maximum="50" UserStep="10">
        <LinearRangeBehavior ux:Name="slide"/>
        <Rectangle Layer="Background" Color="#808080" Height="2">
          <Circle ux:Name="indicator" Anchor="50%,50%" Alignment="Left" Color="#ff0000"
           Width="20" Height="20"/>
        </Rectangle>
        <ProgressAnimation>
          <Move Target="indicator" X="1" RelativeTo="ParentSize" />
        </ProgressAnimation>
        <!--Attractor
          Target="indicator.X"
          Value="{ReadProperty slide.Value}"
          Type="SmoothSnap" /-->
      </RangeControl>
    </Panel>
  </StackPanel>
</App>

The effect I want to achieve (as in the clock demo) is a snapping of the slider to the steps in the range, ie. the clock snaps to every 5 minute step.

I think I need an Attractor (as is used in the clock) but I can’t figure out how to use it. The clock version is part of <ClockHand> so it’s tricky to see how it fits in with a linear slider.

Can you help me out?

Thanks!

Just FYI, I also tried this:

<Slider Minimum="0" Maximum="2" UserStep="1" />

But this doesn’t move in steps, it just moves in fractional values. Hence I have tried to rebuild a custom slider control that will move in steps (with an Attractor).

Hi again,

after a little joint effort, we’ve come up with a pretty neat solution for a “stepped slider”. There’s a bit of hard-coded math, but I’m sure you’ll figure out how to make it more abstract :slight_smile:

<App>
    <Panel Padding="24">
        <JavaScript>
        var Observable = require("FuseJS/Observable");
        var progress = Observable(0.5);
        var quantized = progress.map(function(x) {
            var res = x * 100;
            res = Math.round(res / 10) * 10;
            return res / 100;
        });
        module.exports = {
            progress: progress,
            quantized: quantized
        };
        </JavaScript>

        <AttractorConfig Unit="Points" Type="SmoothSnap" Duration="0.24" ux:Global="snapConfig" />

        <RangeControl ux:Name="rangeControl" Value="{progress}" Minimum="0" Maximum="1">
            <LinearRangeBehavior ux:Name="slide"/>
            <Rectangle ux:Name="bgRect" Layer="Background" Color="#808080" Height="2">
                <Circle ux:Name="indicator" Anchor="50%,50%" Alignment="Left" Color="#ff0000"
                    Width="20" Height="20" X="attract({quantized} * width(bgRect), snapConfig)" />
            </Rectangle>
        </RangeControl>
    </Panel>
</App>

Hi, thanks for this - that’s great. I think I would have struggled to figure that one out myself!

In case anyone is interested I’ll just post my modified version which works as a reusable component.

Cheers.

<Panel ux:Class="SnapSlider" Padding="12,11,12,11">
  <int ux:Property="Maximum" />
  <int ux:Property="Value" />
  <JavaScript>
    var Observable = require("FuseJS/Observable")
    var progress = Observable(this.Value.value)
    var quantized = progress.map(x => Math.round(x))
    quantized.onValueChanged(module, item => { this.Value.value = item })
    module.exports = {
      progress: progress,
      quantized: quantized
    }
  </JavaScript>
  <AttractorConfig Unit="Points" Type="SmoothSnap" Duration="0.1" ux:Global="snap" />
  <RangeControl ux:Name="rangeControl" Value="{progress}" Minimum="0"
    Maximum="{ReadProperty Maximum}" IsEnabled="{Property IsEnabled}">
    <LinearRangeBehavior />
    <Rectangle ux:Name="groove" Layer="Background" Color="#c0c0c0" Height="2">
      <Circle ux:Name="circle" Anchor="50%,50%" Color="#606060" Width="24" Height="24"
        X="attract({quantized} / {ReadProperty Maximum} * width(groove), snap)" />
        <WhileFalse Value="{Property IsEnabled}">
          <Change rangeControl.Opacity="0.2" />
        </WhileFalse>
    </Rectangle>
  </RangeControl>
</Panel>