完成评分组件
parent
4107ef484c
commit
48c9b0d9bd
|
@ -30,7 +30,7 @@
|
|||
- [x] `wc-passwd`表单组件-文本输入框
|
||||
- [x] `wc-textarea`表单组件-多行文本输入框
|
||||
- [x] `wc-number`表单组件-步进数字输入
|
||||
- [ ] `wc-star`表单组件-评分
|
||||
- [x] `wc-star`表单组件-评分
|
||||
- [x] `wc-radio`表单组件-单选框
|
||||
- [ ] `wc-select`表单组件-下拉选择
|
||||
- [ ] `wc-cascadar`表单组件-多级联动
|
||||
|
|
|
@ -111,11 +111,6 @@ class Button extends Component {
|
|||
w: 192px,
|
||||
h: 52px,
|
||||
f: 16px
|
||||
),
|
||||
xxxxl: (
|
||||
w: 212px,
|
||||
h: 64px,
|
||||
f: 18px
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
/**
|
||||
* {}
|
||||
* @author yutent<yutent.io@gmail.com>
|
||||
* @date 2023/03/21 16:14:10
|
||||
*/
|
||||
|
||||
import { nextTick, css, html, Component, classMap } from '@bd/core'
|
||||
import '../icon/index.js'
|
||||
|
||||
class Star extends Component {
|
||||
static props = {
|
||||
value: 0,
|
||||
text: [],
|
||||
size: 'l',
|
||||
colors: [],
|
||||
'allow-half': false,
|
||||
'show-value': false,
|
||||
disabled: false,
|
||||
clearable: false
|
||||
}
|
||||
|
||||
static styles = [
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
--size: 32px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
color: let(--color-grey-1);
|
||||
cursor: inherit;
|
||||
|
||||
wc-icon {
|
||||
margin: 0 3px;
|
||||
transition: transform 0.15s linear, color 0.15s linear;
|
||||
|
||||
&[name='star'] {
|
||||
color: let(--color-plain-3);
|
||||
}
|
||||
|
||||
&[name='star-full'],
|
||||
&[name='star-half'] {
|
||||
color: let(--color-teal-1);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
padding: 2px 8px 0;
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
`,
|
||||
// 尺寸
|
||||
css`
|
||||
@use 'sass:map';
|
||||
$sizes: (
|
||||
s: (
|
||||
w: 52px,
|
||||
h: 20px,
|
||||
f: 12px
|
||||
),
|
||||
m: (
|
||||
w: 72px,
|
||||
h: 24px,
|
||||
f: 12px
|
||||
),
|
||||
l: (
|
||||
w: 108px,
|
||||
h: 32px,
|
||||
f: 14px
|
||||
)
|
||||
);
|
||||
|
||||
@loop $s, $v in $sizes {
|
||||
:host([size='#{$s}']) {
|
||||
--size: #{map.get($v, 'h')};
|
||||
font-size: map.get($v, 'f');
|
||||
}
|
||||
}
|
||||
`
|
||||
]
|
||||
|
||||
#width = 32
|
||||
#value = { i: 0, f: 0 }
|
||||
#stars = []
|
||||
|
||||
/**
|
||||
* 更新图标渲染
|
||||
* i: int
|
||||
* f: float
|
||||
*/
|
||||
#updateDraw(i, f = 0) {
|
||||
let _last = 'star-half'
|
||||
|
||||
let value = this.value
|
||||
let tmp = this.#value
|
||||
|
||||
if (i === -1) {
|
||||
i = Math.floor(value)
|
||||
f = +(value % 1).toFixed(1)
|
||||
if (i > 0 && i === value) {
|
||||
i--
|
||||
f = 1
|
||||
}
|
||||
} else {
|
||||
f = f < 0.5 ? 0.5 : 1
|
||||
}
|
||||
|
||||
if (!this['allow-half']) {
|
||||
f = f > 0 ? 1 : 0
|
||||
}
|
||||
// 减少DOM操作
|
||||
if (i === tmp.i && f === tmp.f) {
|
||||
return
|
||||
}
|
||||
|
||||
if (f > 0.5) {
|
||||
_last = 'star-full'
|
||||
}
|
||||
|
||||
this.#stars.forEach((it, k) => {
|
||||
it.name = k < i ? 'star-full' : 'star'
|
||||
it.style.color = k < i ? this.color || 'var(--color-teal-1)' : ''
|
||||
})
|
||||
|
||||
if (f > 0) {
|
||||
this.#stars[i].name = _last
|
||||
this.#stars[i].style.color = this.color || 'var(--color-teal-1)'
|
||||
}
|
||||
|
||||
// 缓存结果
|
||||
this.#value = { i, f }
|
||||
}
|
||||
|
||||
handleMove(ev) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ev.target.tagName === 'WC-ICON') {
|
||||
let idx = +ev.target.dataset.idx
|
||||
this.#updateDraw(idx, +(ev.offsetX / this.#width).toFixed(1))
|
||||
}
|
||||
}
|
||||
|
||||
handleLeave() {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
this.#updateDraw(-1)
|
||||
}
|
||||
|
||||
handleClick(ev) {
|
||||
let tmp = this.#value
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (ev.target.tagName === 'WC-ICON') {
|
||||
if (this.clearable && this.value === tmp.i + tmp.f) {
|
||||
tmp.i = 0
|
||||
tmp.f = 0
|
||||
this.value = 0
|
||||
this.#stars.forEach(it => ((it.name = 'star'), (it.style.color = '')))
|
||||
} else {
|
||||
this.value = tmp.i + tmp.f
|
||||
}
|
||||
this.$emit('change', { value: this.value })
|
||||
}
|
||||
}
|
||||
|
||||
mounted() {
|
||||
this.#stars = [...this.$refs.box.children]
|
||||
this.#width = this.#stars[0].clientWidth
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<label
|
||||
ref="box"
|
||||
@mousemove=${this.handleMove}
|
||||
@mouseleave=${this.handleLeave}
|
||||
@click=${this.handleClick}
|
||||
>
|
||||
<wc-icon data-idx="0" name="star"></wc-icon>
|
||||
<wc-icon data-idx="1" name="star"></wc-icon>
|
||||
<wc-icon data-idx="2" name="star"></wc-icon>
|
||||
<wc-icon data-idx="3" name="star"></wc-icon>
|
||||
<wc-icon data-idx="4" name="star"></wc-icon>
|
||||
<span class="text">${this['show-value'] ? this.value : ''}</span>
|
||||
</label>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
Star.reg('star')
|
|
@ -57,8 +57,7 @@ class Icon extends Component {
|
|||
'l': 32px,
|
||||
'xl': 36px,
|
||||
'xxl': 44px,
|
||||
'xxxl': 52px,
|
||||
'xxxxl': 64px
|
||||
'xxxl': 52px
|
||||
);
|
||||
|
||||
@loop $k, $v in $gaps {
|
||||
|
|
5
开发规范.md
5
开发规范.md
|
@ -13,15 +13,14 @@
|
|||
- `type=help` 灰色
|
||||
|
||||
3. 尺寸, 主要指 高度
|
||||
> 需要注意的是, 这里的高度, 仅为组件本身应该占的高度, 而非"可视内容"的真实高度, 比如 开头按钮, 实际上就可以不需要那么大。
|
||||
> 需要注意的是, 这里的高度, 仅为组件本身应该占的高度, 而非"可视内容"的真实高度, 比如 开关按钮, 实际上就可以不需要那么大。
|
||||
|
||||
- `size=s` 小号, 20px
|
||||
- `size=m` 中号, 24px
|
||||
- `size=l` 大号, 32px (默认值)
|
||||
- `size=xl` 加大号, 36px
|
||||
- `size=xxl` 加加大号, 44px
|
||||
- `size=xxxl` 加加加加大号, 52px
|
||||
- `size=xxxxl` 特大号, 64px
|
||||
- `size=xxxl` 加加加大号, 52px
|
||||
|
||||
4. 自带点击事件的组件, 统一增加"节流/防抖"逻辑
|
||||
> 统一为增加 `lazy="1000"` 属性实现
|
Loading…
Reference in New Issue