繁体   English   中英

移动范围拇指时动画范围刻度

[英]Animating range ticks when moving range thumb

我有自定义input type="range" ,显示范围值的span和带有许多pdiv作为刻度。 我将自定义div用于刻度,因为范围内的appearance: none隐藏刻度。 我正在使用 DOM 生成刻度。

我使用 slider 拇指作为弯曲的边框,并使具有范围值的span充当圆形拇指。 它在与 slider 连接的地方不能弯曲,但仍然可以正常工作。


我想在放置它的拇指上为 go 设置动画。 这是预期的结果:

预期结果

这是我的代码和CodePen

 // Creating ticks here to prevent long HTML code var i; const tickContainer = document.getElementById('tickContainer'); for (i = 1; i <= 100; i++) { var p = document.createElement('P'); tickContainer.appendChild(p); } // Position of span that shows range value const range = document.getElementById('range'); const rangeV = document.getElementById('rangeValue'); const setValue = () => { const newValue = Number((range.value - range.min) * 100 / (range.max - range.min)); const newPosition = 35 - (newValue * 0.7); rangeV.style.left = `calc(${newValue}% + (${newPosition}px))`; rangeV.innerHTML = `<span>${range.value}%</span>`; }; // Initialize setValue onload and oninput document.addEventListener("DOMContentLoaded", setValue); range.addEventListener('input', setValue);
 body { font-family: Arial; margin: 50px; }.range-wrap { position: relative; } /* Styling of ticks (lines) over the range */.ticks { display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; position: absolute; width: 100%; }.ticks p { position: relative; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; text-align: center; width: 1px; background: #D3D3D3; height: 10px; line-height: 40px; margin: 0 0 20px 0; } /* Styling the range */ input[type=range] { -webkit-appearance: none; appearance: none; margin: 20px 0; width: 100%; height: 4px; background-image: linear-gradient(125deg, #e0e0e0 34%, #0008d7 100%); outline: none; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-moz-range-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-webkit-slider-thumb { height: 70px; width: 70px; -webkit-transform: translateY(-44.3%) rotate(-45deg); transform: translateY(-44.3%) rotate(-45deg); -webkit-appearance: none; appearance: none; background: #ddd; border: 3px solid transparent; border-color: transparent transparent #fff #fff; border-radius: 50%; cursor: pointer; background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; } input[type=range]::-moz-range-thumb { height: 70px; width: 70px; transform: rotate(45de); appearance: none; background: #ddd; border: 3px solid transparent; border-radius: 50%; cursor: pointer; background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; } /* Range value (label) inside of range thumb */.range-value { position: absolute; top: -50%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; z-index: 99; user-select: none; select: none; pointer-events: none; }.range-value span { width: 50px; height: 50px; line-height: 50px; text-align: center; color: #fff; background: #0008d7; font-size: 18px; display: block; position: absolute; top: 20px; border-radius: 50%; user-select: none; select: none; pointer-events: none; z-index: 100; }
 <div class="range-wrap"> <.-- Ticks (lines) over slider. --> <div class="ticks" id="tickContainer"> </div> <!-- Range value inside of range thumb --> <div class="range-value" id="rangeValue"></div> <!-- Range itself --> <input id="range" type="range" min="1" max="100" value="1" step="1"> </div>

这是一个使用mask的想法。 诀窍是使用背景创建刻度(以避免大量元素),然后我使用蒙版围绕拇指创建曲线形状。 蒙版由radial-gradient (将根据拇指值移动的圆形)和linear-gradient组成,以创建基础

 // Creating ticks here to prevent long HTML code var i; const tickContainer = document.getElementById('tickContainer'); // Position of span that shows range value - not important const range = document.getElementById('range'); const rangeV = document.getElementById('rangeValue'); const setValue = () => { const newValue = Number((range.value - range.min) * 100 / (range.max - range.min)); const newPosition = 35 - (newValue * 0.7); rangeV.style.left = `calc(${newValue}% + (${newPosition}px))`; tickContainer.style.setProperty('--p', `calc(${newValue}%)`); rangeV.innerHTML = `<span>${range.value}%</span>`; }; // Initialize setValue onload and oninput document.addEventListener("DOMContentLoaded", setValue); range.addEventListener('input', setValue);
 body { font-family: Arial; margin: 50px; }.range-wrap { position: relative; } /* Styling of ticks (lines) over the range */.ticks { position: absolute; left: -15px; right: -15px; padding:0 15px; top: -25px; height: 45px; background: repeating-linear-gradient(to right, #D3D3D3 0 2px, transparent 2px 6px); background-clip:content-box; -webkit-mask: radial-gradient(farthest-side at bottom, #fff 98%, transparent) var(--p, 0) 0px/100px 50px, linear-gradient(#fff, #fff) bottom/100% 10px; -webkit-mask-repeat: no-repeat; mask: radial-gradient(farthest-side at bottom, #fff 98%, transparent) var(--p, 0) 0px/100px 50px, linear-gradient(#fff, #fff) bottom/100% 10px; mask-repeat: no-repeat; } /* Styling of the range */ input[type=range] { -webkit-appearance: none; appearance: none; margin: 20px 0; width: 100%; background-image: linear-gradient(125deg, #e0e0e0 34%, #0008d7 100%); outline: none; } input[type=range]:focus { outline: none } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; height: 70px; width: 70px; cursor: pointer; background: #ddd; /* Thumb gradient as slider */ background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; /* Hide bottom half of the circle with white color - as background is */ border: 3px solid transparent; border-color: transparent transparent #fff #fff; border-radius: 50%; transform: translateY(-44.3%) rotate(-45deg); } /* Range value (label) inside of range thumb */.range-value { position: absolute; top: -50%; display: flex; justify-content: center; align-items: center; }.range-value span { width: 50px; height: 50px; line-height: 50px; text-align: center; color: #fff; background: #0008d7; font-size: 18px; display: block; position: absolute; top: 20px; border-radius: 50%; pointer-events: none; z-index: 99; }
 <div class="range-wrap"> <.-- Ticks (lines) over slider, --> <div class="ticks" id="tickContainer"> </div> <.-- Range value inside of range thumb --> <div class="range-value" id="rangeValue"></div> <:-- Range itself --> <input id="range" type="range" min="1" max="100" value="1" step="1"> </div> <p>If slider is not working propertly. your browser doesn't support <code>-webkit</code>. Visit <a href="https://codepen.io/Vepth/pen/zYrPZqv">CodePen</a> with full browser support</p>

要获得间隙,您可以更新掩码,如下所示:

 // Creating ticks here to prevent long HTML code var i; const tickContainer = document.getElementById('tickContainer'); // Position of span that shows range value - not important const range = document.getElementById('range'); const rangeV = document.getElementById('rangeValue'); const setValue = () => { const newValue = Number((range.value - range.min) * 100 / (range.max - range.min)); const newPosition = 35 - (newValue * 0.7); rangeV.style.left = `calc(${newValue}% + (${newPosition}px))`; tickContainer.style.setProperty('--p', `calc(${newValue}%)`); rangeV.innerHTML = `<span>${range.value}%</span>`; }; // Initialize setValue onload and oninput document.addEventListener("DOMContentLoaded", setValue); range.addEventListener('input', setValue);
 body { font-family: Arial; margin: 50px; }.range-wrap { position: relative; } /* Styling of ticks (lines) over the range */.ticks { position: absolute; left: -15px; right: -15px; padding:0 15px; top: -30px; height: 45px; background: repeating-linear-gradient(to right, #D3D3D3 0 2px, transparent 2px 6px); background-clip:content-box; -webkit-mask: radial-gradient(farthest-side at bottom,transparent 75%, #fff 76% 98%, transparent) var(--p) 0px/100px 50px, linear-gradient(#fff, #fff) var(--p) 100%/95px 10px, linear-gradient(#fff, #fff) bottom /100% 10px; -webkit-mask-repeat: no-repeat; -webkit-mask-composite: source-over,destination-out; mask: radial-gradient(farthest-side at bottom,transparent 75%, #fff 76% 98%, transparent) var(--p) 0px/100px 50px, linear-gradient(#fff, #fff) var(--p) 100%/95px 10px, linear-gradient(#fff, #fff) bottom /100% 10px; mask-repeat: no-repeat; mask-composite: exclude; } /* Styling of the range */ input[type=range] { -webkit-appearance: none; appearance: none; margin: 20px 0; width: 100%; background-image: linear-gradient(125deg, #e0e0e0 34%, #0008d7 100%); outline: none; } input[type=range]:focus { outline: none } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; height: 70px; width: 70px; cursor: pointer; background: #ddd; /* Thumb gradient as slider */ background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; /* Hide bottom half of the circle with white color - as background is */ border: 3px solid transparent; border-color: transparent transparent #fff #fff; border-radius: 50%; transform: translateY(-44.3%) rotate(-45deg); } /* Range value (label) inside of range thumb */.range-value { position: absolute; top: -50%; display: flex; justify-content: center; align-items: center; }.range-value span { width: 50px; height: 50px; line-height: 50px; text-align: center; color: #fff; background: #0008d7; font-size: 18px; display: block; position: absolute; top: 20px; border-radius: 50%; pointer-events: none; z-index: 99; }
 <div class="range-wrap"> <.-- Ticks (lines) over slider, --> <div class="ticks" id="tickContainer"> </div> <.-- Range value inside of range thumb --> <div class="range-value" id="rangeValue"></div> <:-- Range itself --> <input id="range" type="range" min="1" max="100" value="1" step="1"> </div> <p>If slider is not working propertly. your browser doesn't support <code>-webkit</code>. Visit <a href="https://codepen.io/Vepth/pen/zYrPZqv">CodePen</a> with full browser support</p>


所有浏览器的完整代码:

 // Creating ticks here to prevent long HTML code var i; const tickContainer = document.getElementById('tickContainer'); // Position of span that shows range value - not important const range = document.getElementById('range'); const rangeV = document.getElementById('rangeValue'); const setValue = () => { const newValue = Number((range.value - range.min) * 100 / (range.max - range.min)); const newPosition = 35 - (newValue * 0.7); rangeV.style.left = `calc(${newValue}% + (${newPosition}px))`; tickContainer.style.setProperty('--p', `calc(${newValue}%)`); rangeV.innerHTML = `<span>${range.value}%</span>`; }; // Initialize setValue onload and oninput document.addEventListener("DOMContentLoaded", setValue); range.addEventListener('input', setValue);
 body { font-family: Arial; margin: 50px; }.range-wrap { position: relative; } /* Styling of ticks (lines) over the range */.ticks { position: absolute; left: -15px; right: -15px; padding:0 15px; top: -30px; height: 45px; background: repeating-linear-gradient(to right, #D3D3D3 0 2px, transparent 2px 6px); background-clip:content-box; -webkit-mask: radial-gradient(farthest-side at bottom,transparent 75%, #fff 76% 98%, transparent) var(--p) 0px/100px 50px, linear-gradient(#fff, #fff) var(--p) 100%/95px 10px, linear-gradient(#fff, #fff) bottom /100% 10px; -webkit-mask-repeat: no-repeat; -webkit-mask-composite: source-over,destination-out; mask: radial-gradient(farthest-side at bottom,transparent 75%, #fff 76% 98%, transparent) var(--p) 0px/100px 50px, linear-gradient(#fff, #fff) var(--p) 100%/95px 10px, linear-gradient(#fff, #fff) bottom /100% 10px; mask-repeat: no-repeat; mask-composite: exclude; } /* Styling the range */ input[type=range] { -webkit-appearance: none; appearance: none; margin: 20px 0; width: 100%; height: 4px; background-image: linear-gradient(125deg, #e0e0e0 34%, #0008d7 100%); outline: none; } input[type=range]::-webkit-slider-runnable-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-moz-range-track { width: 100%; height: 4px; cursor: pointer; border-radius: 25px; } input[type=range]::-webkit-slider-thumb { height: 70px; width: 70px; -webkit-transform: translateY(-44.3%) rotate(-45deg); transform: translateY(-44.3%) rotate(-45deg); -webkit-appearance: none; appearance: none; background: #ddd; border: 3px solid transparent; border-color: transparent; border-radius: 50%; cursor: pointer; background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; } input[type=range]::-moz-range-thumb { height: 63px; width: 63px; appearance: none; background: #ddd; border: 3px solid transparent; border-radius: 50%; cursor: pointer; background-image: linear-gradient(white, white), linear-gradient(to right, #e0e0e0 34%, #0008d7 100%); background-attachment: fixed, fixed; background-clip: padding-box, border-box; } /* Range value (label) inside of range thumb */.range-value { position: absolute; top: -50%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; align-items: center; z-index: 99; user-select: none; select: none; pointer-events: none; }.range-value span { width: 50px; height: 50px; line-height: 50px; text-align: center; color: #fff; background: #0008d7; font-size: 18px; display: block; position: absolute; top: 20px; border-radius: 50%; user-select: none; select: none; pointer-events: none; z-index: 100; }.range-value::after { content: ''; position: absolute; width: 100px; height: 50px; top: 0; left: 0; background: white; user-select: none; select: none; pointer-events: none; transform: translate(-50%, 96%); -webkit-transform: translate(-50%, 92%); }
 <div class="range-wrap"> <.-- Ticks (lines) over slider. --> <div class="ticks" id="tickContainer"> </div> <!-- Range value inside of range thumb --> <div class="range-value" id="rangeValue"></div> <!-- Range itself --> <input id="range" type="range" min="1" max="100" value="1" step="1"> </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM