TASK: #109540 行slider中tick属性结构样式改变、跳格运动以及跟手跳格。

This commit is contained in:
duanzhijiang 2022-09-14 20:12:43 +08:00
parent 6b4408e0a3
commit 7bf0619903
4 changed files with 147 additions and 83 deletions

View File

@ -3,6 +3,7 @@
工作职责:
- 滑块空间
- 滑块拖动后返回value值
## 类型包括:
@ -33,11 +34,18 @@
```
5. `Tick` --- 分格滑块
5. `Tick` --- 分格滑块(默认是unfilled属性)
min=0,mix=100按照需求填写step(每一格)的大小<br>
example : <br>
step="25" 表示把slider分为4块<br>
coverWidth="40%" 表示初始小球落在第二格上
```
<star-slider tick step="10"></star-slider>
<star-slider tick step="10" unfilled coverWidth="30%" disabled></star-slider>
<star-slider tick step="20" coverWidth="40%" disabled></star-slider>
```
6. `vertical` --- 垂直slider
@ -49,5 +57,11 @@
7. 左侧图标|滑块|右侧图标
```
<star-slider ><slot></slot></star-slider>
<star-slider>
<p class="left" data-icon="brightness"></p>
</star-slider>
```
## 后续需解决的问题:
- tick 属性中小球不能完全覆盖step
- vertical 属性变化太快

View File

@ -25,11 +25,12 @@ export const sharedStyles: CSSResult = css`
.v-sliderBar {
position: absolute;
width: var(--vWidth);
height: 100%;
left: calc(50% - 8px / 2);
height: 80%;
left: calc(50% - var(--vWidth) / 2);
top: 0px;
background: rgba(0, 0, 0, 0.08);
border-radius: 20px;
overflow: hidden;
}
.sliderBar {
@ -69,6 +70,7 @@ export const sharedStyles: CSSResult = css`
top: calc(50% - 20px / 2);
background: #544f4f;
border-radius: 50%;
z-index: 1;
}
p {
position: absolute;
@ -84,19 +86,47 @@ export const sharedStyles: CSSResult = css`
: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: #d5d5d5;
background: #c0c0c0;
}
:host([unfilled]) .progress {
background: none;
}
:host([tick]) .progress {
background: none;
}
.step {
position: absolute;
left: calc(var(--i) * 100%);
left: calc(var(--i) * 99.3%);
top: calc(50% - 10px / 2);
width: 3px;
height: 10px;
background-color: #544f4f;
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;
}
`

View File

@ -47,24 +47,23 @@ export class StarSlider extends LitElement {
render() {
if (!this.vertical) {
return html`
<slot></slot>
<div
class="content"
id="content"
@touchstart=${this.touchStart}
@touchend=${this.touchEnd}
@touchmove=${this.touchMove}
>
<div class="sliderBar">
<div class="progress"></div>
<div
class="dot"
?disabled="${this.disabled}"
?tick="${this.tick}"
></div>
<div class="dot"></div>
</div>
</div>
`
} else {
return html`
<slot></slot>
<div
class="v-content"
@touchstart=${this.touchStartVertical}
@ -72,12 +71,7 @@ export class StarSlider extends LitElement {
@touchmove=${this.touchMoveVertical}
>
<div class="v-sliderBar">
<div
class="v-progress"
?disabled="${this.disabled}"
?vertical="${this.vertical}"
?tick="${this.tick}"
></div>
<div class="v-progress"></div>
</div>
</div>
`
@ -86,9 +80,14 @@ export class StarSlider extends LitElement {
protected firstUpdated(
_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>
): 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 = 1; i < tickStep; i++) {
for (let i = 0; i <= tickStep; i++) {
const stepTick = document.createElement('div')
stepTick.style.setProperty('--i', String(i / tickStep))
stepTick.classList.add('step')
@ -112,13 +111,30 @@ export class StarSlider extends LitElement {
if (this.barX >= this.barWidth) {
this.barX = this.barWidth
}
this.style.setProperty('--dot-move', this.barX + 'px')
this.proportion = (this.barX / this.barWidth) * 100
this.endValue = Math.ceil(this.proportion) + ''
this.progress.style.setProperty(
'width',
(this.barWidth * Math.ceil(this.proportion)) / 100 + 'px'
)
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 //小球左侧相对于父元素的左边距
@ -130,32 +146,54 @@ export class StarSlider extends LitElement {
evt.preventDefault()
this.touchX = evt.touches[0].clientX //整个屏幕实时触摸的 X 坐标
this.moveX = this.touchX - this.startX //手指移动的距离
// console.log(this.moveX)
//判断最大值和最小值
this.newX = this.dotL + this.moveX
if (this.newX < 0) {
// console.log('到0了')
this.newX = 0
}
if (this.newX >= this.barWidth) {
// console.log('超了')
this.newX = this.barWidth
}
//改变dot的left值
//计算比例
this.proportion = (this.newX / this.barWidth) * 100
//取整
this.endValue = Math.ceil(this.proportion) + ''
this.style.setProperty('--dot-move', this.newX + 'px')
this.progress.style.setProperty(
'width',
(this.barWidth * Math.ceil(this.proportion)) / 100 + 'px'
)
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 + ''
}
}
}
}
}
private touchEnd(evt: TouchEvent) {
return console.log(this.endValue)
if (this.tick) {
return console.log(10 * Math.round(parseInt(this.endValue) / 10) + '')
} else {
return console.log(this.endValue)
}
}
private touchStartVertical(evt: TouchEvent) {
@ -164,8 +202,8 @@ export class StarSlider extends LitElement {
this.barWidth = this.vSliderBar.offsetHeight //总长度
this.dotL = this.barWidth - this.vProgress.offsetTop //黑条长度
//按压音量条变宽
this.vSliderBar.style.setProperty('width', '16px')
this.vProgress.style.setProperty('width', '16px')
this.vSliderBar.style.setProperty('--vWidth', '16px')
this.vProgress.style.setProperty('--vWidth', '16px')
}
}
private touchMoveVertical(evt: TouchEvent) {
@ -193,41 +231,11 @@ export class StarSlider extends LitElement {
}
private touchEndVertical(evt: TouchEvent) {
if (!this.disabled) {
this.vProgress.style.setProperty('width', '8px')
this.vSliderBar.style.setProperty('width', '8px')
this.vProgress.style.setProperty('--vWidth', '8px')
this.vSliderBar.style.setProperty('--vWidth', '8px')
return console.log(this.endValue)
}
}
//点击sliderBar
// @eventOptions({capture: true})
private clickBar(evt: TouchEvent) {
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.style.setProperty('--dot-move', this.barX + 'px')
this.proportion = (this.barX / this.barWidth) * 100
this.endValue = Math.ceil(this.proportion) + ''
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 //小球左侧相对于父元素的左边距
}
}
}
declare global {
interface HTMLElementTagNameMap {

View File

@ -9,19 +9,18 @@ export class PanelSlider extends LitElement {
static styles = css`
div {
position: relative;
border: 1px solid;
margin: 50px 50px;
border-radius: 5px;
}
#a {
position: absolute;
left: 100px;
top: 66px;
top: 45px;
}
#b {
position: absolute;
left: 200px;
top: 66px;
top: 45px;
}
`
@ -29,16 +28,26 @@ export class PanelSlider extends LitElement {
return html`
<div>
<h4>vertical</h4>
<star-slider vertical></star-slider>
<star-slider id="a" vertical disabled coverWidth="30%"></star-slider>
<star-slider id="b" vertical coverWidth="70%"></star-slider>
<!-- <star-slider ver tical disabled coverWidth="50%"></star-slider>
<star-slider vertical coverWidth="30%" tick step="25"></star-slider> -->
<star-slider vertical>
<span data-icon="alarm"></span>
</star-slider>
<star-slider id="a" vertical disabled coverWidth="30%">
<span data-icon="bluetooth-a2dp"></span>
</star-slider>
<star-slider id="b" vertical coverWidth="70%">
<span data-icon="alarm-clock"></span>
</star-slider>
<h4>default - </h4>
<star-slider></star-slider>
<star-slider>
<p class="left" data-icon="brightness"></p>
</star-slider>
<h4>coverWidth - </h4>
<star-slider coverWidth="150px"></star-slider>
<star-slider coverWidth="50%"></star-slider>
<star-slider coverWidth="150px">
<p data-icon="brightness"></p>
</star-slider>
<star-slider coverWidth="50%">
<p data-icon="brightness"></p>
</star-slider>
<h4>disabled</h4>
<star-slider disabled coverWidth="30%"></star-slider>
<star-slider disabled coverWidth="70%"></star-slider>
@ -46,11 +55,14 @@ export class PanelSlider extends LitElement {
<star-slider unfilled coverWidth="20%"></star-slider>
<star-slider unfilled coverWidth="40%"></star-slider>
<h4>tick</h4>
<h5>step="10"</h5>
<star-slider tick step="10"></star-slider>
<h5>step="20"</h5>
<star-slider tick step="20" coverWidth="20%"></star-slider>
<star-slider tick step="50" coverWidth="40%"></star-slider>
<star-slider tick step="50" unfilled coverWidth="60%"></star-slider>
<star-slider tick step="25" disabled coverWidth="80%"></star-slider>
<h5>step="50"</h5>
<star-slider tick step="50" coverWidth="48%"></star-slider>
<h5>step="25"</h5>
<star-slider tick step="25" disabled coverWidth="23%"></star-slider>
</div>
`
}