diff --git a/src/components/slider/README.md b/src/components/slider/README.md
index 93e314e..f8c3136 100644
--- a/src/components/slider/README.md
+++ b/src/components/slider/README.md
@@ -3,6 +3,7 @@
工作职责:
- 滑块空间
+- 滑块拖动后返回value值
## 类型包括:
@@ -11,28 +12,56 @@
```
```
-
-2. 滑块中小球左侧进行填充 --- `filled`
+2. `coverWidth` --- 初始填充
```
-
+
+
```
-3. 禁用滑块 --- `disabled`
+3. `disabled` --- 禁用滑块
```
+
```
-
-4. 分格滑块 --- `Tick`
+4. `unfilled` --- 滑块中小球左侧不进行填充
```
-
-
+
+
+
```
-5. 左侧图标|滑块|右侧图标
+
+5. `Tick` --- 分格滑块(默认是unfilled属性)
+ min=0,mix=100,按照需求填写step(每一格)的大小
+ example :
+ step="25" 表示把slider分为4块
+ coverWidth="40%" 表示初始小球落在第二格上
+
+
+
```
-
+
+
```
+6. `vertical` --- 垂直slider
+
+```
+
+
+
+```
+7. 左侧图标|滑块|右侧图标
+
+```
+
+
+
+```
+
+## 后续需解决的问题:
+- tick 属性中小球不能完全覆盖step
+- vertical 属性变化太快
diff --git a/src/components/slider/slider-styles.ts b/src/components/slider/slider-styles.ts
index 237be0a..ec59347 100644
--- a/src/components/slider/slider-styles.ts
+++ b/src/components/slider/slider-styles.ts
@@ -1,16 +1,38 @@
import {css, CSSResult} from 'lit'
export const sharedStyles: CSSResult = css`
:host {
- --cover-width: 100px;
- --dot-move: 87px;
+ --cover-width: 0px;
+ --dot-move: 0px;
+ --vWidth: 8px;
}
.content {
- margin: 5px 5px;
+ height: 2px;
+ margin: 50px;
position: relative;
- padding: 50px 50px;
- border: 1px solid skyblue;
+ padding: 8px;
+ /*border: 1px solid skyblue;*/
border-radius: 5px;
}
+ .v-content {
+ width: 2px;
+ margin: 0px 2px;
+ position: relative;
+ padding: 200px 10px;
+ /*border: 1px solid skyblue;*/
+ border-radius: 5px;
+ }
+
+ .v-sliderBar {
+ position: absolute;
+ width: var(--vWidth);
+ height: 80%;
+ left: calc(50% - var(--vWidth) / 2);
+ top: 0px;
+ background: rgba(0, 0, 0, 0.08);
+ border-radius: 20px;
+ overflow: hidden;
+ }
+
.sliderBar {
position: absolute;
width: 100%;
@@ -18,32 +40,93 @@ export const sharedStyles: CSSResult = css`
left: 0px;
right: 0px;
top: calc(50% - 6px / 2);
- background: rgba(0, 0, 0, 0.06);
- border-radius: 5px;
+ background: rgba(0, 0, 0, 0.08);
+ border-radius: 8px;
+ }
+ .v-progress {
+ position: absolute;
+ width: var(--vWidth);
+ height: var(--cover-width);
+ left: 0px;
+ bottom: 0px;
+ border-radius: 0 0 20px 20px;
+ background: #404040;
}
.progress {
position: absolute;
width: var(--cover-width);
- /*width: 100px;*/
height: 6px;
left: 0px;
right: 0px;
top: calc(50% - 6px / 2);
background: #4d4d4d;
- border-radius: 5px;
+ border-radius: 5px 0 0 5px;
}
.dot {
position: absolute;
left: var(--dot-move);
- width: 26px;
- height: 26px;
- top: calc(50% - 26px / 2);
+ width: 20px;
+ height: 20px;
+ top: calc(50% - 20px / 2);
background: #544f4f;
border-radius: 50%;
+ z-index: 1;
}
p {
position: absolute;
right: 5px;
top: 1px;
}
+ :host([disabled]) .progress {
+ background: #c0c0c0;
+ }
+ :host([disabled]) .v-progress {
+ background: #c0c0c0;
+ }
+ :host([disabled]) .step {
+ background: #c0c0c0;
+ }
+ :host([tick]) .step {
+ background: #c0c0c0;
+ }
+ :host([tick]) .sliderBar {
+ background: #c0c0c0;
+ border-radius: 0 0 0 0;
+ height: 4px;
+ }
+ :host([disabled]) .dot {
+ background: #c0c0c0;
+ }
+ :host([unfilled]) .progress {
+ background: none;
+ }
+ :host([tick]) .progress {
+ background: none;
+ }
+ .step {
+ position: absolute;
+ left: calc(var(--i) * 99.3%);
+ top: calc(50% - 10px / 2);
+ width: 3px;
+ height: 10px;
+ background-color: #d5d5d5;
+ border-radius: 3px;
+ }
+ ::slotted(span)::before {
+ font-size: 27px;
+ font-family: 'gaia-icons';
+ content: attr(data-icon);
+ text-align: center;
+ position: relative;
+ top: 357px;
+ }
+ ::slotted(p)::before {
+ font-size: 27px;
+ font-family: 'gaia-icons';
+ content: attr(data-icon);
+ text-align: center;
+ position: relative;
+ top: 74px;
+ left: 5px;
+ }
`
diff --git a/src/components/slider/slider.ts b/src/components/slider/slider.ts
index fa55319..5d6ae0c 100644
--- a/src/components/slider/slider.ts
+++ b/src/components/slider/slider.ts
@@ -1,9 +1,7 @@
-import {html, LitElement, CSSResultArray} from 'lit'
+import {html, LitElement, CSSResultArray, PropertyValueMap} from 'lit'
import {customElement, property, query} from 'lit/decorators.js'
import {sharedStyles} from './slider-styles'
-export const variants = ['filled', 'tick']
-
@customElement('star-slider')
export class StarSlider extends LitElement {
_coverWidth: string = ''
@@ -14,21 +12,28 @@ export class StarSlider extends LitElement {
@query('.content') content!: HTMLDivElement
@query('.sliderBar') sliderBar!: HTMLDivElement
@query('.progress') progress!: HTMLDivElement
+ @query('.v-sliderBar') vSliderBar!: HTMLDivElement
+ @query('.v-progress') vProgress!: HTMLDivElement
@query('.dot') dot!: HTMLDivElement
@query('p') p!: HTMLParagraphElement
+
+ @property({type: Boolean}) disabled = false
+ @property({type: Boolean}) tick = false
+ @property({type: Boolean}) vertical = false
@property({type: Number}) startX = 0
+ @property({type: Number}) startY = 0
@property({type: Number}) touchX = 0
+ @property({type: Number}) touchY = 0
@property({type: Number}) moveX = 0
+ @property({type: Number}) moveY = 0
@property({type: Number}) newX = 0
+ @property({type: Number}) newY = 0
@property({type: Number}) barWidth = 0
@property({type: Number}) dotL = 0
@property({type: Number}) proportion = 0
- @property({type: String}) pValue = ''
- @property({type: Number}) sliderBarLeft = 0
- @property({type: Number}) sliderBarRight = 0
- @property({type: Number}) ball = 0
- @property({type: String}) sliderCoverWidth = ''
- @property({type: String}) ballMove = ''
+ @property({type: Number}) barX = 0
+ @property({type: String}) endValue = ''
+ @property({type: String}) step = ''
@property({type: String})
get coverWidth() {
return this._coverWidth
@@ -36,57 +41,202 @@ export class StarSlider extends LitElement {
set coverWidth(value: string) {
this.style.setProperty('--cover-width', value)
this._coverWidth = value
+ this.style.setProperty('--dot-move', this._coverWidth)
}
render() {
- return html`
-
-
${this.pValue}
-
-
-
+ if (!this.vertical) {
+ return html`
+
+
-
- `
+ `
+ } else {
+ return html`
+
+
+ `
+ }
}
+ protected firstUpdated(
+ _changedProperties: PropertyValueMap
| Map
+ ): void {
+ if (this.vertical) {
+ this.touchStart = this.touchStartVertical
+ this.touchEnd = this.touchEndVertical
+ this.touchMove = this.touchMoveVertical
+ }
+ if (this.tick) {
+ var tickStep = 100 / parseInt(this.step)
+ for (let i = 0; i <= tickStep; i++) {
+ const stepTick = document.createElement('div')
+ stepTick.style.setProperty('--i', String(i / tickStep))
+ stepTick.classList.add('step')
+ this.sliderBar.appendChild(stepTick)
+ }
+ }
+ }
+
private touchStart(evt: TouchEvent) {
- this.barWidth = this.sliderBar.offsetWidth - this.dot.offsetWidth //总长度减去小球覆盖的部分
- this.dotL = this.dot.offsetLeft //小球左侧相对于父元素的左边距
- this.startX = evt.touches[0].clientX //手指点下的 X 坐标
+ if (!this.disabled) {
+ this.touchX = evt.touches[0].clientX //手指触摸的 x 坐标
+ // 黑色覆盖部分
+ this.barX =
+ this.touchX -
+ this.sliderBar.getBoundingClientRect().left -
+ this.dot.offsetWidth * 0.5
+ this.barWidth = this.sliderBar.offsetWidth - this.dot.offsetWidth
+ if (this.barX < 0) {
+ this.barX = 0
+ }
+ if (this.barX >= this.barWidth) {
+ this.barX = this.barWidth
+ }
+ this.proportion = (this.barX / this.barWidth) * 100
+ this.endValue = Math.ceil(this.proportion) + ''
+ if (this.tick) {
+ // tick跳格滑动
+ var tickStep = 100 / parseInt(this.step) //分为几格
+ for (let i = 0; i <= tickStep; i++) {
+ if (this.barX > (this.barWidth * (i + 0.5)) / tickStep) {
+ this.style.setProperty(
+ '--dot-move',
+ (this.barWidth * (i + 1)) / tickStep + 'px'
+ )
+ }
+ if (this.barX == 0) {
+ this.style.setProperty('--dot-move', 0 + 'px')
+ }
+ }
+ } else {
+ this.style.setProperty('--dot-move', this.barX + 'px')
+ this.progress.style.setProperty(
+ 'width',
+ (this.barWidth * Math.ceil(this.proportion)) / 100 + 'px'
+ )
+ }
+ // 重新初始化防止滑块增量
+ this.startX = evt.touches[0].clientX //手指点下的初始 X&Y 坐标
+ this.barWidth = this.sliderBar.offsetWidth - this.dot.offsetWidth //总长度减去小球覆盖的部分
+ this.dotL = this.dot.offsetLeft //小球左侧相对于父元素的左边距
+ }
}
private touchMove(evt: TouchEvent) {
- //阻止默认行为
- evt.preventDefault()
- this.touchX = evt.touches[0].clientX //整个屏幕实时触摸的 X 坐标
- this.moveX = this.touchX - this.startX //手指移动的距离
- //判断最大值和最小值
- this.newX = this.dotL + this.moveX
- if (this.newX < 0) {
- this.newX = 0
+ if (!this.disabled) {
+ //阻止默认行为
+ evt.preventDefault()
+ this.touchX = evt.touches[0].clientX //整个屏幕实时触摸的 X 坐标
+ this.moveX = this.touchX - this.startX //手指移动的距离
+
+ //判断最大值和最小值
+ this.newX = this.dotL + this.moveX
+
+ if (this.newX < 0) {
+ this.newX = 0
+ }
+ if (this.newX >= this.barWidth) {
+ this.newX = this.barWidth
+ }
+ //计算比例
+ this.proportion = (this.newX / this.barWidth) * 100
+ //取整
+ this.endValue = Math.ceil(this.proportion) + ''
+ if (!this.tick) {
+ this.style.setProperty('--dot-move', this.newX + 'px')
+ this.progress.style.setProperty(
+ 'width',
+ (this.barWidth * Math.ceil(this.proportion)) / 100 + 'px'
+ )
+ } else {
+ // tick跳格滑动
+ var tickStep = 100 / parseInt(this.step) //分为几格
+ for (let i = 0; i <= tickStep; i++) {
+ if (this.newX > (this.barWidth * (i + 0.5)) / tickStep) {
+ this.style.setProperty(
+ '--dot-move',
+ (this.barWidth * (i + 1)) / tickStep + 'px'
+ )
+ this.proportion =
+ ((this.barWidth * (i + 1)) / tickStep / this.barWidth) * 100
+ //取整
+ this.endValue = Math.ceil(this.proportion) + ''
+ }
+ if (this.newX == 0) {
+ this.style.setProperty('--dot-move', 0 + 'px')
+ this.endValue = 0 + ''
+ }
+ }
+ }
}
- if (this.newX >= this.barWidth) {
- this.newX = this.barWidth
- }
- //改变dot的left值
- this.style.setProperty('--dot-move', this.newX + 'px')
- //计算比例
- this.proportion = (this.newX / this.barWidth) * 100
- this.pValue = Math.ceil(this.proportion) + ''
- this.progress.style.setProperty(
- 'width',
- (this.barWidth * Math.ceil(this.proportion)) / 100 + 'px'
- )
}
private touchEnd(evt: TouchEvent) {
- return console.log(this.pValue)
+ if (this.tick) {
+ return console.log(10 * Math.round(parseInt(this.endValue) / 10) + '')
+ } else {
+ return console.log(this.endValue)
+ }
+ }
+
+ private touchStartVertical(evt: TouchEvent) {
+ if (!this.disabled) {
+ this.startY = evt.touches[0].clientY //手指点下的初始 Y 坐标
+ this.barWidth = this.vSliderBar.offsetHeight //总长度
+ this.dotL = this.barWidth - this.vProgress.offsetTop //黑条长度
+ //按压音量条变宽
+ this.vSliderBar.style.setProperty('--vWidth', '16px')
+ this.vProgress.style.setProperty('--vWidth', '16px')
+ }
+ }
+ private touchMoveVertical(evt: TouchEvent) {
+ if (!this.disabled) {
+ //阻止默认行为
+ evt.preventDefault()
+ this.touchY = evt.touches[0].clientY //整个屏幕实时触摸的 Y 坐标
+ this.moveY = this.startY - this.touchY //手指移动的距离
+ //判断最大值和最小值
+ this.newY = this.dotL + this.moveY
+ if (this.newY < 0) {
+ // console.log('到底了')
+ this.newY = 0
+ }
+ if (this.newY >= this.barWidth) {
+ // console.log('超了')
+ this.newY = this.barWidth
+ }
+ //计算比例
+ this.proportion = (this.newY / this.barWidth) * 100
+ //取整
+ this.endValue = Math.ceil(this.proportion) + ''
+ this.vProgress.style.setProperty('height', this.newY + 'px')
+ }
+ }
+ private touchEndVertical(evt: TouchEvent) {
+ if (!this.disabled) {
+ this.vProgress.style.setProperty('--vWidth', '8px')
+ this.vSliderBar.style.setProperty('--vWidth', '8px')
+ return console.log(this.endValue)
+ }
}
}
-
declare global {
interface HTMLElementTagNameMap {
'star-slider': StarSlider
diff --git a/src/test/panels/slider/slider.ts b/src/test/panels/slider/slider.ts
index fa301f0..8933900 100644
--- a/src/test/panels/slider/slider.ts
+++ b/src/test/panels/slider/slider.ts
@@ -1,29 +1,68 @@
import {html, LitElement, css} from 'lit'
-import {customElement} from 'lit/decorators.js'
+import {customElement, property} from 'lit/decorators.js'
+import '../icon/icon'
@customElement('panel-slider')
export class PanelSlider extends LitElement {
+ @property({type: String}) icon = ''
+
static styles = css`
div {
position: relative;
- border: 1px solid;
margin: 50px 50px;
border-radius: 5px;
}
+ #a {
+ position: absolute;
+ left: 100px;
+ top: 45px;
+ }
+ #b {
+ position: absolute;
+ left: 200px;
+ top: 45px;
+ }
`
render() {
return html`
-
default
-
-
初始化覆盖长度
-
-
+
vertical
+
+
+
+
+
+
+
+
+
+
default - 默认
+
+
+
+
coverWidth - 初始覆盖长度
+
+
+
+
+
+
disabled
-
-
-
+
+
+
unfilled - 无覆盖
+
+
+
tick
+
step="10"
+
+
step="20"
+
+
step="50"
+
+
step="25"
+
`
}