范围滑块

范围滑块布局

单一范围

单范围滑块布局非常简单

<!-- Range Slider element -->
<div class="range-slider">
  <!-- range input -->
  <input type="range" min="0" max="100" step="1" value="10" />
</div>

双重范围

双范围滑块更简单,因为它不需要输入元素,因为 input:range 不支持双范围。

<!-- Range Slider element -->
<div class="range-slider"></div>

范围滑块颜色

范围滑块支持所有默认颜色。所以,只需在范围滑块元素中添加 color-[color] 类即可更改其颜色。

<!-- red range -->
<div class="range-slider color-red">...</div>

<!-- orange range -->
<div class="range-slider color-orange">...</div>

范围滑块 App 方法

我们来看看相关的 App 方法来使用范围滑块

app.range.create(parameters)- 创建范围滑块实例

  • parameters - object。具有范围滑块参数的对象

此方法返回所创建范围滑块的实例

app.range.destroy(el)- 销毁范围滑块实例

  • el - HTMLElementstring (带 CSS 选择器) 或 object。要销毁的范围滑块元素或范围滑块实例。

app.range.get(el)- 通过 HTML 元素获取范围滑块实例

  • el - HTMLElementstring (带 CSS 选择器)。范围滑块元素。

此方法返回范围滑块的实例

app.range.getValue(el)- 获取范围滑块值

  • el - HTMLElementstring (带 CSS 选择器)。范围滑块元素。

此方法返回范围滑块值

app.range.setValue(el, value)- 设置新的范围滑块值

  • el - HTMLElementstring (带 CSS 选择器)。范围滑块元素。
  • value - number(对于单一范围)或 array 的值(对于双范围)

此方法返回范围滑块的实例

范围滑块参数

现在我们来看看创建范围滑块所需的可用参数列表

参数类型默认描述
elHTMLElement
string
范围滑块元素。范围滑块元素的 HTMLElement 或带有 CSS 选择器的字符串
inputElHTMLElement
string
范围滑块输入元素或输入元素的 CSS 选择器。如果没有指定,将尝试在范围滑块元素中查找 input type="range"
dualbooleanfalse启用双范围滑块
stepnumber1值之间的最小步长
labelbooleanfalse启用范围滑块旋钮周围的附加标签
formatLabelfunction(value)此方法必须返回格式化的范围旋钮标签文本。它接收标签值作为参数
minnumber最小值
maxnumber最大值
valuenumber
array
初始值。对于单一范围是数字,对于双范围是值的数组
draggableBarbooleantrue启用后,还可以通过单击范围条和滑动来与范围滑块进行交互(更改值)。
verticalbooleanfalse启用垂直范围滑块
verticalReversedbooleanfalse使垂直范围滑块反转(还必须启用 vertical
scalebooleanfalse启用范围滑块刻度
scaleStepsnumber5刻度步骤数
scaleSubStepsnumber0刻度细分步数(每个步长将被此值除)
formatScaleLabel函数 (value)该方法必须返回格式化的刻度值。它作为参数接收当前刻度步长值。对于每个刻度步长,都将调用此方法。
limitKnobPositionboolean将滑块位置限制在范围栏的大小内。该项在 iOS 主题中默认启用。
on对象

带有事件处理程序的对象。例如

var range = app.range.create({
  el: '.range-slider',
  on: {
    change: function () {
      console.log('Range Slider value changed')
    }
  }
})

滑块范围的方法和属性

所以为了创建范围滑块,我们必须调用

var range = app.range.create({ /* parameters */ })

在此之后,我们获得了它的初始化实例(如同以上示例中的 range 变量)以及有用的方法和属性

属性
range.app链接到全局应用实例
range.el滑块范围 HTML 元素
range.$el带有滑块范围 HTML 元素的 Dom7 实例
range.inputEl滑块范围输入 HTML 元素
range.$inputEl带有滑块范围输入 HTML 元素的 Dom7 实例
range.rangeWidth滑块范围宽度(以像素为单位)
range.dual指示其是否为双重的布尔型属性
range.min范围最小值
range.max范围最大值
range.value范围值
range.scale指示 scale 是否启用的布尔型属性
range.scaleSteps刻度步骤数
range.scaleSubSteps刻度细分步数
range.$scaleEl带有已生成的刻度 HTML 元素的 Dom7 实例
range.knobs其中每个元素都表示所创建范围滑块的一个 HTMLElement(在双滑块的情况下为 2 个滑块)的数组
range.labels其中每个元素都表示所创建范围滑块标签的一个 HTMLElement(在双滑块的情况下为 2 个标签)的数组
range.vertical指示其是否为垂直的布尔型属性
range.verticalReversed指示其是否为垂直且反转的布尔型属性
range.params滑块范围的参数
方法
range.getValue()返回滑块范围值
range.setValue(value)设置新的滑块范围值
range.updateScale()重新计算并重新渲染滑块刻度
range.destroy()销毁滑块范围实例
range.on(event, handler)添加事件处理程序
range.once(event, handler)添加将在触发后被移除的事件处理程序
range.off(event, handler)移除事件处理程序
range.off(event)移除指定事件的所有处理程序
range.emit(event, ...args)触发实例上的事件

滑块范围事件

滑块范围将在范围元素以及应用程序和范围实例上触发以下 DOM 事件和事件

DOM 事件

事件目标描述
range:change范围滑块元素 <div class="range-slider">当范围滑块的值发生更改时,将触发事件
range:changed范围滑块元素 <div class="range-slider">值更改后将触发滑块旋钮释放事件
range:beforedestroy范围滑块元素 <div class="range-slider">在范围滑块实例被销毁之前将触发事件

应用程序和范围滑块实例事件

范围滑块实例同时在自身实例和应用程序实例上发出事件。应用程序实例事件具有相同名称,前缀为 range

事件参数目标描述
change(range, value)range当范围值发生更改时,将触发事件。作为参数,事件处理程序接收范围实例
rangeChange(range, value)app
changed(range, value)range值更改后将触发滑块旋钮释放事件。作为参数,事件处理程序接收范围实例
rangeChanged(range, value)app
beforeDestroy(range)range在范围滑块实例被销毁之前将触发事件。作为参数,事件处理程序接收范围实例
rangeBeforeDestroy(range)app

范围滑块自动初始化

如果你不需要使用范围滑块 API,并且你的范围滑块在页面内部,并在页面初始化时显示在 DOM 中,那么只需添加额外的 range-slider-init 类,就可以自动初始化它

<!-- Add range-slider-init class -->
<div class="range-slider range-slider-init">
  <input type="range" min="0" max="100" step="1" value="10" />
</div>

在这种情况下,如果你需要访问已创建的范围滑块实例,可以使用 app.range.get 应用程序方法

var range = app.range.get('.range-slider');

if (range.value > 50) {
  // do something
}

使用自动初始化时,可能需要传递额外的参数。这可以通过两种方式完成

CSS 变量

下面是相关 CSS 变量(CSS 自定义属性)的列表。

请注意,带注释的变量未按默认指定,且在这种情况下它们的值是回退值。

:root {
  /*
  --f7-range-bar-active-bg-color: var(--f7-theme-color);
  --f7-range-scale-bg-color: var(--f7-range-bar-bg-color);
  --f7-range-scale-substep-bg-color: var(--f7-range-bar-bg-color);
  */
  --f7-range-scale-step-height: 5px;
  --f7-range-scale-substep-width: 1px;
  --f7-range-scale-substep-height: 4px;
  --f7-range-bar-bg-color: rgba(0, 0, 0, 0.2);
}
:root .dark,
:root.dark {
  --f7-range-bar-bg-color: rgba(255, 255, 255, 0.2);
}
.ios {
  --f7-range-size: 28px;
  --f7-range-bar-size: 4px;
  --f7-range-bar-border-radius: 2px;
  --f7-range-knob-size: 28px;
  --f7-range-knob-color: #fff;
  --f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  --f7-range-label-size: 24px;
  --f7-range-label-text-color: #000;
  --f7-range-label-bg-color: #fff;
  --f7-range-label-font-size: 12px;
  --f7-range-label-font-weight: 500;
  --f7-range-label-border-radius: 5px;
  --f7-range-label-padding: 0px 2px;
  --f7-range-scale-text-color: #666;
  --f7-range-scale-step-width: 1px;
  --f7-range-scale-font-size: 12px;
  --f7-range-scale-font-weight: 400;
  --f7-range-scale-label-offset: 4px;
}
.md {
  --f7-range-size: 20px;
  --f7-range-bar-size: 2px;
  --f7-range-bar-border-radius: 0px;
  --f7-range-knob-size: 12px;
  --f7-range-knob-box-shadow: none;
  --f7-range-label-size: 26px;
  --f7-range-label-font-weight: normal;
  --f7-range-label-font-size: 10px;
  --f7-range-label-border-radius: 50%;
  --f7-range-label-padding: 0px;
  --f7-range-scale-step-width: 2px;
  --f7-range-scale-font-size: 12px;
  --f7-range-scale-font-weight: 400;
  --f7-range-scale-label-offset: 4px;
}
.md,
.md .dark,
.md [class*='color-'] {
  --f7-range-knob-color: var(--f7-theme-color);
  --f7-range-label-text-color: var(--f7-md-on-primary);
  --f7-range-label-bg-color: var(--f7-theme-color);
  --f7-range-scale-text-color: var(--f7-md-on-surface-variant);
}

示例

range.html
<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="title">Range Slider</div>
      </div>
    </div>
    <div class="page-content">
      <div class="block-title">Volume</div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">speaker_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">volume_mute</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init">
                <input type="range" min="0" max="100" step="1" value="10" />
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">speaker_3_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">volume_up</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">Brightness</div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">sun_min</i>
              <i class="icon material-icons md-only" style="width: 24px">brightness_low</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init color-orange" data-label="true">
                <input type="range" min="0" max="100" step="1" value="50" />
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">sun_max_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">brightness_high</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title display-flex justify-content-space-between">
        Price Filter <span class="price-value">$${priceMin} - $${priceMax}</span>
      </div>
      <div class="list list-strong-ios list-outline-ios simple-list">
        <ul>
          <li class="item-row">
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">money_dollar_circle</i>
              <i class="icon material-icons md-only" style="width: 24px">attach_money</i>
            </div>
            <div style="width: 100%; margin: 0 16px">
              <div class="range-slider range-slider-init color-green" @range:change=${onPriceChange} data-label="true"
                data-dual="true" data-min="0" data-max="500" data-step="1" data-value-left="200" data-value-right="400">
              </div>
            </div>
            <div>
              <i class="icon f7-icons if-not-md" style="width: 28px">money_dollar_circle_fill</i>
              <i class="icon material-icons md-only" style="width: 24px">monetization_on</i>
            </div>
          </li>
        </ul>
      </div>
      <div class="block-title">With Scale</div>
      <div class="block block-strong-ios block-outline-ios">
        <div class="range-slider range-slider-init" data-min="0" data-max="100" data-label="true" data-step="5"
          data-value="25" data-scale="true" data-scale-steps="5" data-scale-sub-steps="4"></div>
      </div>
      <div class="block-title">Vertical</div>
      <div class="block block-strong-ios block-outline-ios display-flex justify-content-center">
        <div class="range-slider range-slider-init margin-right" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="25" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-horizontal" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="50" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-horizontal" data-vertical="true" data-min="0" data-max="100"
          data-label="true" data-step="1" data-value="75" style="height: 160px"></div>
        <div class="range-slider range-slider-init margin-left" data-dual="true" data-vertical="true" data-min="0"
          data-max="100" data-label="true" data-step="1" data-value-left="25" data-value-right="75"
          style="height: 160px"></div>
      </div>
      <div class="block-title">Vertical Reversed</div>
      <div class="block block-strong-ios block-outline-ios display-flex justify-content-center">
        <div class="range-slider range-slider-init color-red margin-right" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="25"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-horizontal" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="50"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-horizontal" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value="75"
          style="height: 160px"></div>
        <div class="range-slider range-slider-init color-red margin-left" data-dual="true" data-vertical="true"
          data-vertical-reversed="true" data-min="0" data-max="100" data-label="true" data-step="1" data-value-left="25"
          data-value-right="75" style="height: 160px"></div>
      </div>
    </div>
  </div>
</template>
<script>
  export default (props, { $f7, $el, $update }) => {
    let priceMin = 200;
    let priceMax = 400;

    const onPriceChange = (e) => {
      const range = $f7.range.get(e.target);
      priceMin = range.value[0];
      priceMax = range.value[1];
      $update();
    };

    return $render;
  };
</script>