我正在尝试使用2个处理程序进行范围输入,但是我找到了一个javascript和css文件,问题是当我运行项目时,出现了自定义范围输入,并在1秒钟后传递给默认值。通过运行项目并注意范围输入并刷新页面,可以在此Github repository中看到此问题。
这是显示此范围输入的提示:
但是,正如我所说,会发生的是它在运行项目后的最初几毫秒内显示,然后传递给默认值。
HTML代码:
<input type="range" multiple value="0,100" />
CSS代码:
@supports (--css: variables) {
input[type="range"].multirange {
padding: 0;
margin: 0;
display: inline-block;
vertical-align: top;
}
input[type="range"].multirange.original {
position: absolute;
}
input[type="range"].multirange.original::-webkit-slider-thumb {
position: relative;
z-index: 2;
}
input[type="range"].multirange.original::-moz-range-thumb {
transform: scale(1); /* FF doesn't apply position it seems */
z-index: 1;
}
input[type="range"].multirange::-moz-range-track {
border-color: transparent; /* needed to switch FF to "styleable" control */
}
input[type="range"].multirange.ghost {
position: relative;
background: var(--track-background);
--track-background: linear-gradient(to right, transparent var(--low), var(--range-color) 0, var(--range-color) var(--high), transparent 0 ) no-repeat 0 45% / 100% 40%;
--range-color: hsl(190, 80%, 40%);
}
input[type="range"].multirange.ghost::-webkit-slider-runnable-track {
background: var(--track-background);
}
input[type="range"].multirange.ghost::-moz-range-track {
background: var(--track-background);
}
}
JavaScript代码:
(function () {
"use strict";
var supportsMultiple = self.HTMLInputElement && "valueLow" in HTMLInputElement.prototype;
var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value");
var multirange = function (input) {
if (supportsMultiple || input.classList.contains("multirange")) {
return;
}
var value = input.getAttribute("value");
var values = value === null ? [] : value.split(",");
var min = +(input.min || 0);
var max = +(input.max || 100);
var ghost = input.cloneNode();
input.classList.add("multirange", "original");
ghost.classList.add("multirange", "ghost");
input.value = values[0] || min + (max - min) / 2;
ghost.value = values[1] || min + (max - min) / 2;
input.parentNode.insertBefore(ghost, input.nextSibling);
Object.defineProperty(input, "originalValue", descriptor.get ? descriptor : {
// Fuck you Safari >:(
get: function () { return this.value; },
set: function (v) { this.value = v; }
});
Object.defineProperties(input, {
valueLow: {
get: function () { return Math.min(this.originalValue, ghost.value); },
set: function (v) { this.originalValue = v; },
enumerable: true
},
valueHigh: {
get: function () { return Math.max(this.originalValue, ghost.value); },
set: function (v) { ghost.value = v; },
enumerable: true
}
});
if (descriptor.get) {
// Again, fuck you Safari
Object.defineProperty(input, "value", {
get: function () { return this.valueLow + "," + this.valueHigh; },
set: function (v) {
var values = v.split(",");
this.valueLow = values[0];
this.valueHigh = values[1];
update();
},
enumerable: true
});
}
if (typeof input.oninput === "function") {
ghost.oninput = input.oninput.bind(input);
}
function update() {
ghost.style.setProperty("--low", 100 * ((input.valueLow - min) / (max - min)) + 1 + "%");
ghost.style.setProperty("--high", 100 * ((input.valueHigh - min) / (max - min)) - 1 + "%");
}
ghost.addEventListener("mousedown", function passClick(evt) {
// Are the ghost and input elements inverted? (ghost is lower range)
var isInverted = input.valueLow == ghost.value;
// Find the horizontal position that was clicked (as a percentage of the element's width)
var clickPoint = evt.offsetX / this.offsetWidth;
// Map the percentage to a value in the range (note, assumes a min value of 0)
var clickValue = max * clickPoint;
// Get the distance to both high and low values in the range
var highDiff = input.valueHigh - clickValue;
var lowDiff = Math.abs(input.valueLow - clickValue);
if (isInverted ? highDiff < lowDiff : lowDiff < highDiff) {
// The low value is closer to the click point than the high value
// We should update the low value input
var passEvent = new MouseEvent("mousedown", evt);
// Pass a new event to the low "input" element (which is obscured by the
// higher "ghost" element, and doesn't get mouse events outside the drag handle
input.dispatchEvent(passEvent);
// The higher "ghost" element should not respond to this event
evt.preventDefault();
return false;
}
});
input.addEventListener("input", update);
ghost.addEventListener("input", update);
update();
}
multirange.init = function () {
[].slice.call(document.querySelectorAll("input[type=range][multiple]:not(.multirange)")).forEach(multirange);
}
if (typeof module === "undefined") {
self.multirange = multirange;
if (document.readyState == "loading") {
document.addEventListener("DOMContentLoaded", multirange.init);
}
else {
multirange.init();
}
} else {
module.exports = multirange;
}
})();
感谢您的关注。
答案 0 :(得分:2)
我已经拿走了提供的CSS,并将其应用于没有JavaScript的Blazor。
下面是一个概念证明(需要在CSS上做更多的工作-特别是围绕焦点轮廓),您可以以此为基础。
它与提供的JS版本略有不同,因为我不喜欢MouseDown的处理-感觉很笨拙。
使用此示例控件,如下所示:
<RangeControl @bind-ValueHigh="ValueHigh" @bind-ValueLow="ValueLow"></RangeControl>
<span>@ValueLow</span>-<span>@ValueHigh</span>
@code {
int ValueHigh=75;
int ValueLow=25;
}
创建一个RangeControl.razor文件并将其放入其中 注意:标记/ CSS /代码全部放在一个文件中,以便于在此处发布,在现实生活中,您可能希望将其中一些分开(或者您可能不愿意-使用Blazor,这是您的选择)
<div id="rc-@ID">
@(new MarkupString($@"<style>
#rc-{ID} {{
position: relative;
width: {Width}px;
}}
#rc-{ID} > input[type='range'] {{
padding: 0;
margin: 0;
display: inline-block;
vertical-align: top;
width: 100%;
--range-color: hsl(190, 80%, 40%);
background: var(--track-background);
}}
#rc-{ID} > input[type='range']::-moz-range-track {{
border-color: transparent; /* needed to switch FF to 'styleable' control */
}}
#rc-{ID} > input[name='low-range'] {{
position: absolute;
--track-background: linear-gradient(to right, transparent {100 * (ValueLow - MinValue) / (MaxValue - MinValue) + 1}%, var(--range-color) 0, var(--range-color) {100 * (ValueHigh - MinValue) / (MaxValue - MinValue) - 1}%, transparent 0 ) no-repeat 0 45% / 100% 40%;
}}
#rc-{ID} > input[name='low-range']::-webkit-slider-thumb {{
position: relative;
z-index: 2;
}}
#rc-{ID} > input[name='low-range']::-moz-range-thumb {{
transform: scale(1); /* FF doesn't apply position it seems */
z-index: 1;
}}
#rc-{ID} > input[name='high-range'] {{
position: relative;
--track-background: linear-gradient(to right, transparent {100 * (ValueLow - MinValue) / (MaxValue - MinValue) + 1}%, var(--range-color) 0, var(--range-color) {100 * (ValueHigh - MinValue) / (MaxValue - MinValue) - 1}%, transparent 0 ) no-repeat 0 45% / 100% 40%;
clip-path: polygon({50 * (ValueLow + ValueHigh) / (MaxValue - MinValue) + 1}% 0, 100% 0, 100% 100%, {50 * (ValueLow + ValueHigh) / (MaxValue - MinValue) + 1}% 100%);
}}
#rc-{ID} > input[type='range']::-webkit-slider-runnable-track {{
background: var(--track-background);
}}
#rc-{ID} > input[type='range']::-moz-range-track {{
background: var(--track-background);
}}
</style>"))
<input name="low-range" type="range" min="@MinValue" max="@MaxValue" @bind="@ValueLow" @bind:event="oninput" />
<input name="high-range" type="range" min="@MinValue" max="@MaxValue" @bind="@ValueHigh" @bind:event="oninput" />
</div>
@code
{
int _valueLow = 0;
int _valueHigh = 100;
[Parameter] public int Width { get; set; } = 200;
[Parameter] public int MinValue { get; set; } = 0;
[Parameter] public int MaxValue { get; set; } = 100;
[Parameter] public int ValueLow {
get => Math.Min(_valueLow,_valueHigh);
set {
if (_valueLow.Equals(value))
return;
_valueLow = value;
if (_valueLow >= _valueHigh)
{
_valueLow = _valueHigh;
_valueHigh = value;
ValueHighChanged.InvokeAsync(_valueHigh);
}
ValueLowChanged.InvokeAsync(_valueLow);
}
}
[Parameter] public int ValueHigh {
get => Math.Max(_valueLow,_valueHigh);
set {
if (_valueHigh.Equals(value))
return;
_valueHigh = value;
if (_valueLow >= _valueHigh)
{
_valueHigh = _valueLow;
_valueLow = value;
ValueLowChanged.InvokeAsync(_valueLow);
}
ValueHighChanged.InvokeAsync(_valueHigh);
}
}
[Parameter] public EventCallback<int> ValueLowChanged { get; set; }
[Parameter] public EventCallback<int> ValueHighChanged { get; set; }
string ID = Guid.NewGuid().ToString().Replace("-", "").Substring(15);
}