slider —— المنزلق
يحوّل المنزلق اختيار الأرقام إلى عملية مكانية: فالسحب أزيد مباشرة من الإدخال، ويرى المستخدم موضع القيمة ضمن المجال بنظرة واحدة. ويتولّى core/slider التحويل في اتجاهين بين «القيمة ↔ الموضع»، والالتقاط وفق الخطوة، والقيمتين الابتدائيتين في وضع النطاق (range)، إضافة إلى دلالة slider وفق APG.
متى يُستخدم
Section titled “متى يُستخدم”- تُنجزه الأطراف على هيئة
LhSlider: مستوى الصوت، مجال الأسعار، ضبط درجة الشفافية. - المجال متواصل أو الخطوة متقطّعة بدرجة خشنة.
- لا ينبغي استخدامه: لإدخال قيم دقيقة (استخدم
input-number، فالمنزلق لا يستطيع التعبير عن قيمة غير مضاعفة للخطوة مثل «37»).
طريقة الاستيراد
Section titled “طريقة الاستيراد”import { snapToStep, clampAndSnap, getValueFromPosition, getPositionFromValue, getSliderClassNames, getInitialValue, buildMarksList, getSliderThumbAria,} from '@lh-ui/share/core/slider'import type { LhSliderState, LhSliderMark } from '@lh-ui/share/core/slider'القصد التصميمي
Section titled “القصد التصميمي”عندما يكون step غير منتهٍ أو <= 0 يُعيد snapToStep القيمة كما هي بدلاً من إعادة NaN — فالقيمة step: 0 تجعل عملية باقي القسمة تنتج NaN، وهنا يُعامَل «الخطوة غير الصحيحة» على أنها «التقاط غير مفعَّل»، ويُترك كلاء الحدود لـ clampAndSnap. فصل المسؤوليات: الالتقاط والكلاء أمران مستقلان.
وإعادة getPositionFromValue للقيمة 0 عند max === min هي تجنُّب للقسمة على صفر: فعندما يتدهور المجال إلى نقطة واحدة، يكون المنزلق بطبيعة الحال عند نقطة البداية.
ويُعيد getInitialValue في وضع النطاق القيمتين [كلاء min، كلاء (min+max)/2] — أي يبدأ المنزلق الثاني عند النقطة الوسطى لا عند max، وذلك لاعتبار بصري (فالمنزلقان متلاصقان يبدوان وكأنهما علة).
جدول الدوال
Section titled “جدول الدوال”| الدالة | التوقيع | الإرجاع | الوظيفة |
|---|---|---|---|
snapToStep |
(value: number, min: number, step: number) => number |
قيمة ملتقطة | محاذاة أقرب عقدة وفق step |
clampAndSnap |
(value: number, min: number, max: number, step: number) => number |
قيمة موحَّدة | التقاط ثم كلاء |
getValueFromPosition |
(pct: number, min: number, max: number, step: number) => number |
قيمة عددية | النسبة المئوية ← القيمة |
getPositionFromValue |
(value: number, min: number, max: number) => number |
نسبة مئوية [0,1] | القيمة ← الموضع |
getSliderClassNames |
(state: LhSliderState) => string[] |
أسماء أصناف | disabled/range/size |
getInitialValue |
(state: LhSliderState) => number | [number, number] |
قيمة ابتدائية | يُعيد قيمتين في وضع النطاق |
buildMarksList |
(marks?: Record<number, string>) => LhSliderMark[] |
مصفوفة علامات | ترتيب تصاعدي حسب value |
getSliderThumbAria |
(options: { value, min, max, vertical?, disabled?, ariaValueText? }) => LhAriaAttrs |
حزمة سمات aria | دلالة slider |
تعريفات الأنواع
Section titled “تعريفات الأنواع”export interface LhSliderMark { label: string value: number}
export interface LhSliderState { value: number | [number, number] | null min: number max: number step: number disabled: boolean range: boolean // وضع النطاق (منزلقان) showInput: boolean // إقران مع input-number size: LhComponentSize marks: Record<number, string> | undefined}إمكانية الوصول
Section titled “إمكانية الوصول”يُخرِج getSliderThumbAria دلالة slider وفق APG. وفي وضع النطاق يجب استدعاؤها لكل منزلق على حدة:
getSliderThumbAria({ value: 30, min: 0, max: 100 })// { role: 'slider', 'aria-valuenow': 30, 'aria-valuemin': 0, 'aria-valuemax': 100 }
getSliderThumbAria({ value: 60, min: 0, max: 100, vertical: true, disabled: true })// { role: 'slider', 'aria-valuenow': 60, 'aria-valuemin': 0, 'aria-valuemax': 100,// 'aria-orientation': 'vertical', 'aria-disabled': true }- يُخرِج
verticalالقيمةaria-orientation: 'vertical'(أما الأفقي فهو الاتجاه الافتراضي ولا يُصرَّح به). - ويُخرِج
ariaValueTextالقيمةaria-valuetext— ويُستخدم عندما تحتاج القيمة إلى تعبير دلالي (مثل «30%» أو «بطيء»)، وله أولوية في الإعلان على valuenow. - تفاعل لوحة المفاتيح (طبقة UI): يزيد ←/→ أو ↓/↑ بمقدار step، وينتقل Home/End إلى min/max، ويتحرك PageUp/Down بخطوة أكبر.
أمثلة الاستخدام
Section titled “أمثلة الاستخدام”import { getValueFromPosition, getPositionFromValue, snapToStep } from '@lh-ui/share/core/slider'
getValueFromPosition(0.5, 0, 100, 1) // 50getValueFromPosition(0.333, 0, 100, 5) // 35 (يلتقط إلى مضاعفات 5)getPositionFromValue(30, 0, 100) // 0.3getPositionFromValue(150, 0, 100) // 1 (مكلَّاة)getPositionFromValue(50, 50, 50) // 0 (تجنُّب القسمة على صفر عند max===min)snapToStep(7, 0, 5) // 5snapToStep(8, 0, 5) // 10snapToStep(7, 0, 0) // 7 (خطوة غير صحيحة بلا التقاط)buildMarksList({ 0: 'منخفض', 100: 'مرتفع' }) // [{ label: 'منخفض', value: 0 }, { label: 'مرتفع', value: 100 }]<!-- Vue3 --><div :class="getSliderClassNames({ value, min, max, step, disabled, range, showInput, size, marks })"> <div class="lh-slider__track"> <div class="lh-slider__bar" :style="{ width: pct + '%' }" /> <div class="lh-slider__button-wrapper" :style="{ left: pct + '%' }" v-bind="getSliderThumbAria({ value, min, max, disabled })" @pointerdown="startDrag" > <div class="lh-slider__button" /> </div> <template v-if="marks"> <div v-for="mark in buildMarksList(marks)" :key="mark.value" class="lh-slider__marks"> <span class="lh-slider__mark" :style="{ left: getPositionFromValue(mark.value, min, max) * 100 + '%' }"> {{ mark.label }} </span> </div> </template> </div></div>// React: السحب بـ pointer events + getBoundingClientRect لحساب النسبة المئوية// const pct = (clientX - rect.left) / rect.width// onChange(getValueFromPosition(pct, min, max, step))// uniapp: <slider> مكوّن مدمج (منزلق واحد)، يدعم min/max/step/show-value؛// ووضع النطاق والعلامات يحتاجان إلى تخصيص بـ view، والسحب بـ @touchmoveالأنماط والرموز
Section titled “الأنماط والرموز”| اسم الصنف | الدلالة |
|---|---|
.lh-slider |
الصنف الأساسي |
.lh-slider--{small|large} |
درجة الحجم (حجم المنزلق) |
.lh-slider--disabled |
تعطيل |
.lh-slider--range |
وضع النطاق (منزلقان + مقطع مُبرَز في الوسط) |
.lh-slider__track |
المسار |
.lh-slider__bar |
المجال المحدد (المقطع المُبرَز) |
.lh-slider__button-wrapper / __button |
المقبض |
.lh-slider__marks / __mark |
العلامات |
.lh-slider__input / __input-text |
حقل الإدخال المُقترَن |
لون المسار --lh-fill-color، والمقطع المحدد --lh-primary-color.
ملاحظات
Section titled “ملاحظات”- يُعيد
getPositionFromValueعدداً عشرياً في [0,1]، وتُضاف طبقة UI الرمز%؛ فلا تظن أنه يُعيد نسبة مئوية. - محاذاة الالتقاط مع العلامات: يجب أن تكون قيمة
marksمضاعفاً لـ step، وإلا وقعت العلامة بين قيمتي التقاط، فلا يستطيع المستخدم السحب إليها. - تقاطع المنزلقين في وضع النطاق: يمكن للمنزلقين أن يعبر كلٌّ منهما الآخر (وتمنعه طبقة UI عادةً، أو تُبدِّلهما تلقائياً)، ولم يُعالِج
clampAndSnapهذه الدلالة. - الوضع العمودي: في الوضع
verticalيحل ارتفاع المسار محل عرضه، فيتغيَّر مقام التحويل؛ أماgetValueFromPositionفي core فهو مستقل عن المحور (يستقبل نسبة مئوية)، وتحسب طبقة UI قيمة pct. - اقتران
showInput: يجب أن تتطابق قيم min/max/step فيinput-numberمع slider، وإذا لم تتطابق اختلف مجال القيم بينهما.
@lh-ui/share/core/slider → getValueFromPosition( )(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue