با مجموعهها، منظم بمانید
ذخیره و دستهبندی محتوا براساس اولویتهای شما.
HTML
<label for="switch-1" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-1">
</label>
<label for="switch-2" class="gui-switch">
Indeterminate
<input type="checkbox" role="switch" id="switch-2">
<!-- TODO: Devsite - Removed inline handlers -->
<!-- <script>document.getElementById('switch-2').indeterminate = true</script> -->
</label>
<label for="switch-3" class="gui-switch">
Disabled
<input type="checkbox" role="switch" id="switch-3" disabled>
</label>
<label for="switch-4" class="gui-switch">
Disabled (checked)
<input type="checkbox" role="switch" id="switch-4" disabled checked>
</label>
<label for="switch-vertical" class="gui-switch -vertical">
Vertical
<input type="checkbox" role="switch" id="switch-vertical">
</label>
CSS
.gui-switch {
--thumb-size: 2rem;
--thumb: hsl(0 0% 100%);
--thumb-highlight: hsl(0 0% 0% / 25%);
--track-size: calc(var(--thumb-size) * 2);
--track-padding: 2px;
--track-inactive: hsl(80 0% 80%);
--track-active: hsl(80 60% 45%);
--thumb-color: var(--thumb);
--thumb-color-highlight: var(--thumb-highlight);
--track-color-inactive: var(--track-inactive);
--track-color-active: var(--track-active);
--isLTR: 1;
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
@media (prefers-color-scheme: dark) {
--thumb: hsl(0 0% 5%);
--thumb-highlight: hsl(0 0% 100% / 25%);
--track-inactive: hsl(80 0% 35%);
--track-active: hsl(80 60% 60%);
}
&:dir(rtl) {
--isLTR: -1;
}
&.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(calc(90deg * var(--isLTR) * -1));
touch-action: pan-x;
}
}
& > input {
--thumb-position: 0%;
--thumb-transition-duration: .25s;
padding: var(--track-padding);
background: var(--track-color-inactive);
inline-size: var(--track-size);
block-size: var(--thumb-size);
border-radius: var(--track-size);
appearance: none;
pointer-events: none;
touch-action: pan-y;
border: none;
outline-offset: 5px;
box-sizing: content-box;
flex-shrink: 0;
display: grid;
align-items: center;
grid: [track] 1fr / [track] 1fr;
transition: background-color .25s ease;
&::before {
--highlight-size: 0;
content: "";
cursor: pointer;
pointer-events: auto;
grid-area: track;
inline-size: var(--thumb-size);
block-size: var(--thumb-size);
background: var(--thumb-color);
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
border-radius: 50%;
transform: translateX(var(--thumb-position));
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
&:not(:disabled):hover::before {
--highlight-size: .5rem;
}
&:checked {
background: var(--track-color-active);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
&:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
&:disabled {
cursor: not-allowed;
--thumb-color: transparent;
&::before {
cursor: not-allowed;
box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);
@media (prefers-color-scheme: dark) {
box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
}
}
}
}
}
JS
const elements = document.querySelectorAll('.gui-switch')
const switches = new WeakMap()
const state = {
activethumb: null,
recentlyDragged: false,
}
const getStyle = (element, prop) =>
parseInt(
window.getComputedStyle(element)
.getPropertyValue(prop))
const getPseudoStyle = (element, prop) =>
parseInt(
window.getComputedStyle(element, ':before')
.getPropertyValue(prop))
const dragInit = event => {
if (event.target.disabled) return
state.activethumb = event.target
state.activethumb.addEventListener('pointermove', dragging)
state.activethumb.style.setProperty('--thumb-transition-duration', '0s')
}
const dragging = event => {
if (!state.activethumb) return
let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
let directionality = getStyle(state.activethumb, '--isLTR')
let track = (directionality === -1)
? (state.activethumb.clientWidth * -1) + thumbsize + padding
: 0
let pos = Math.round(event.offsetX - thumbsize / 2)
if (pos < bounds.lower) pos = 0
if (pos > bounds.upper) pos = bounds.upper
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}
const dragEnd = event => {
if (!state.activethumb) return
state.activethumb.checked = determineChecked()
if (state.activethumb.indeterminate)
state.activethumb.indeterminate = false
state.activethumb.style.removeProperty('--thumb-transition-duration')
state.activethumb.style.removeProperty('--thumb-position')
state.activethumb.removeEventListener('pointermove', dragging)
state.activethumb = null
padRelease()
}
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
const labelClick = event => {
if (
state.recentlyDragged ||
!event.target.classList.contains('gui-switch') ||
event.target.querySelector('input').disabled
) return
let checkbox = event.target.querySelector('input')
checkbox.checked = !checkbox.checked
event.preventDefault()
}
const determineChecked = () => {
let {bounds} = switches.get(state.activethumb.parentElement)
let curpos =
Math.abs(
parseInt(
state.activethumb.style.getPropertyValue('--thumb-position')))
if (!curpos) {
curpos = state.activethumb.checked
? bounds.lower
: bounds.upper
}
return curpos >= bounds.middle
}
elements.forEach(guiswitch => {
let checkbox = guiswitch.querySelector('input')
let thumbsize = getPseudoStyle(checkbox, 'width')
let padding = getStyle(checkbox, 'padding-left') + getStyle(checkbox, 'padding-right')
checkbox.addEventListener('pointerdown', dragInit)
checkbox.addEventListener('pointerup', dragEnd)
checkbox.addEventListener('click', preventBubbles)
guiswitch.addEventListener('click', labelClick)
switches.set(guiswitch, {
thumbsize,
padding,
bounds: {
lower: 0,
middle: (checkbox.clientWidth - padding) / 4,
upper: checkbox.clientWidth - thumbsize - padding,
},
})
})
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
جز در مواردی که غیر از این ذکر شده باشد،محتوای این صفحه تحت مجوز Creative Commons Attribution 4.0 License است. نمونه کدها نیز دارای مجوز Apache 2.0 License است. برای اطلاع از جزئیات، به خطمشیهای سایت Google Developers مراجعه کنید. جاوا علامت تجاری ثبتشده Oracle و/یا شرکتهای وابسته به آن است.
تاریخ آخرین بهروزرسانی 2023-10-25 بهوقت ساعت هماهنگ جهانی.
[[["درک آسان","easyToUnderstand","thumb-up"],["مشکلم را برطرف کرد","solvedMyProblem","thumb-up"],["غیره","otherUp","thumb-up"]],[["اطلاعاتی که نیاز دارم وجود ندارد","missingTheInformationINeed","thumb-down"],["بیشازحد پیچیده/ مراحل بسیار زیاد","tooComplicatedTooManySteps","thumb-down"],["قدیمی","outOfDate","thumb-down"],["مشکل ترجمه","translationIssue","thumb-down"],["مشکل کد / نمونهها","samplesCodeIssue","thumb-down"],["غیره","otherDown","thumb-down"]],["تاریخ آخرین بهروزرسانی 2023-10-25 بهوقت ساعت هماهنگ جهانی."],[],[]]