3

巧用两个type=range input实现区域范围选择

 3 years ago
source link: https://www.zhangxinxu.com/wordpress/2021/02/range-input/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

巧用两个type=range input实现区域范围选择

这篇文章发布于 2021年02月11日,星期四,23:42,归类于 Web综合。 阅读 667 次, 今日 65 次 一条评论

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=9800
本文欢迎分享与聚合,全文转载就不必了,尊重版权,圈子就这么大,若急用可以联系授权。

封面图占位图-区域范围选择

一、自定义样式的range input

type=range类型的<input>输入框在IE、Chrome、Safari、Firefox浏览器下均可以实现样式自定义效果。

具体可以参考我13年整理的这篇文章“伪元素表单控件默认样式重置与自定义大全”。

除了传统的区域选择,range类型的输入框还可以实现类似星星评分的交互效果,纯CSS,且支持滑动选择。

评分功能交互截图示意

具体可以参考阅文前端团队sunseekers写的“震惊,type=range居然可以实现评星功能”这篇文章。

而本文要演示的案例和上面都有所不同,是让两个type=range选择框合二为一,直接在区域中选择某一个范围,而不是选择区域中的某个值。

二、区域中的范围选择

直接先看实现的效果GIF录屏,如下所示:

区域范围选择录屏效果示意

就是直接选择某一个区域内的某一个范围。

浏览器原生是没有这样的组件的,只有选择单个值。

如果多值选择,其实有个很取巧的方法。

那就是拿两个type=range输入框叠在一起,然后叠在上面的选择框的只有中间的拖拽按钮,背后的拖拽背景条直接隐藏,这样,视觉上就是一个背景条,2个拖拽按钮了。

HTML结构大致如下:

<input type="range" max="100" min="0">
<input type="range" max="100" min="0">

隐藏第2个选择框的拖拽条背景,可以这样设置:

[type="range"] + [type="range"]::-webkit-slider-runnable-track {
    background: none;
}
[type="range"] + [type="range"]::-moz-range-track {
    background: none;
}

以上就是区域范围选择实现的核心原理和逻辑。

当然,究其细节样式,还有一些工作要处理。

1. 点击拖拽条选中功能要禁止

如果是单值选择,点击拖拽条非按钮区域自动选择是没有任何问题的,如下GIF交互所示:

单个区域点击选择交互示意

但是如果是多值选择,点击拖拽区域的定位就会有问题,因为有2个thumb按钮,究竟该定位哪一个呢?

就会有逻辑问题,因此,需要禁止掉。

禁止方法直接CSS就可以完成,代码示意如下:

[type="range"] {
    pointer-events: none;
}
[type="range"]::-webkit-slider-thumb {
    pointer-events: auto;
}
[type="range"]::-moz-range-thumb {
    pointer-events: auto;
}

2. 选中范围颜色的高亮

这是个难题,对于单值选择,如果是方方正正,thumb按钮高度和外部滑块轨道高度一致,则纯CSS是可以搞定的。

但是,如果是如上述GIF截图所示的效果,或者Chrome浏览器默认的效果,则无能为力。

因为Chrome浏览器并未暴露选中区域的伪元素,IE浏览器是有的。

这就导致,选中区域的高亮需要借助一点JS来搞定。

主流的做法是把当前的进度值以CSS变量的形式赋给input元素,这样,里面的滑块元素或者按钮元素就可以基于这些CSS变量值进行高亮定位处理了。

由于CSS变量可以轻松地穿越Shadow DOM,因此,可以放心使用。

这里演示单值选择的高亮的处理:

range.addEventListener('input', function () {
    let to = 100 % (this.value - this.min) / (this.max - this.min);
    // 单值选择高亮起始位置一定是0
    this.style.setProperty('--from', 0);
    this.style.setProperty('--to', to);
});

此时,就可以根据设置的CSS自定义属性,让拖拽条在指定的位置处高亮的,可以使用CSS渐变实现,例如:

[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: linear-gradient(to right, gray calc(1% * var(--from)), blue calc(1% * var(--from)) calc(1% * var(--to)), gray 0%);
}

这样,一个背景灰色,高亮蓝色的区域范围选择条效果就实现了。

其中,CSS占据了大约80%的实现,JS出了一点微小的工作。

三、演示与封装

为了使用方便,我们可以对多范围选择range输入框进行一个封装,例如我们部分自定义一个名为<ui-range>的自定义元素,当设置了multiple属性的时候,就是范围选择,当没有multiple属性的时候,还是传统的单值选择。

<ui-range min="0" max="100" value="30, 60" multiple></ui-range>

在实现这个需求的时候,使用的JS就会多很多,因为实现自定义元素的功能还是需要一番处理的。

具体细节不表,大家可以狠狠地点击这里:<ui-range>与input range区域范围选择demo

demo页面截图效果如下:

range范围选择自定义元素封装

是一个典型的使用了Shadow DOM开发的Web Components组件,非常适合新人的学习案例。

当然,还有很多细节没有写上去,例如<ui-range>元素的min, max属性变化时候,里面的range输入框也要跟着变,跟本文内容无关紧要,我就没实现。

如果以<ui-range>自定义元素组件的方式实现范围选择,其实选中区域的高亮效果可以直接写在<ui-range>元素上,好处有2个:

  1. 代码量会省一点,因为Chrome和Firefox自定义的伪元素不一样,写在<ui-range>元素就不需要伪元素区分,代码可以合体;
  2. 现在的实现,两个range输入框的层级是固定的,后面一个一定盖在上面一个之上。如果背景写在共同的祖先元素<ui-range>上,则可以轻松让:active时候,输入框层级较高,就可以保证拖拽的条子永远在上方了,细节会更完美。

但是,这样处理不利于学习,以及没法让开发者脱离<ui-range>元素使用。例如上面的demo,就算没有自定义元素,直接光秃秃的range输入框,效果也是OK的。

今天大年三十除夕夜,结果我只顾着撸代码写文章,没注意到群里老板发的大红包,人均几百的红包,以及其他同事N多红包,上千条消息,被家里领导说了一顿……1f614.svg

唉,抢红包多无聊,还是写文章有劲。

于是我就把手机给领导,自己继续写,估计零点之前可以发布,哦也!

好了,到了祝福的时候了。

祝广大前端同行新年快乐,牛年大吉!

1f389.svg1f389.svg

记得给本文转发点赞哦~

(本篇完)1f44d.svg 是不是学到了很多?可以分享到微信
1f44a.svg 有话要说?点击这里

本文为原创文章,欢迎分享,勿全文转载,如果实在喜欢,可收藏,永不过期,且会及时更新知识点及修正错误,阅读体验也更好。
本文地址:https://www.zhangxinxu.com/wordpress/?p=9800


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK