wangxueliang
7 years ago
9 changed files with 358 additions and 0 deletions
@ -0,0 +1,119 @@ |
|||||||
|
<template> |
||||||
|
<ul |
||||||
|
:class="[prefixCls, disabled ? `${prefixCls}-disabled` : '', className]" |
||||||
|
@mouseleave="onMouseLeave"> |
||||||
|
<template v-for="i in count"> |
||||||
|
<Star |
||||||
|
ref="stars" |
||||||
|
:index="i" |
||||||
|
:disabled="disabled" |
||||||
|
:prefix-cls="`${prefixCls}-star`" |
||||||
|
:allowHalf="allowHalf" |
||||||
|
:value="currentValue" |
||||||
|
@onClick="onClick" |
||||||
|
@onHover="onHover" |
||||||
|
:key="i"> |
||||||
|
<template slot-scope="props"> |
||||||
|
<slot> |
||||||
|
<Icon type="star"/> |
||||||
|
</slot> |
||||||
|
</template> |
||||||
|
</Star> |
||||||
|
</template> |
||||||
|
</ul> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Star from './Star.vue'; |
||||||
|
import Icon from '../icon/index'; |
||||||
|
import { getOffsetLeft } from '../util/util'; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'Rate', |
||||||
|
props: { |
||||||
|
count: { |
||||||
|
type: Number, |
||||||
|
default: 5, |
||||||
|
}, |
||||||
|
value: { |
||||||
|
type: Number, |
||||||
|
default: 0, |
||||||
|
}, |
||||||
|
defaultValue: { |
||||||
|
type: Number, |
||||||
|
default: 0, |
||||||
|
}, |
||||||
|
onChange: { |
||||||
|
type: Function, |
||||||
|
default: () => {}, |
||||||
|
}, |
||||||
|
onHoverChange: { |
||||||
|
type: Function, |
||||||
|
default: () => {}, |
||||||
|
}, |
||||||
|
allowHalf: { |
||||||
|
type: Boolean, |
||||||
|
default: false, |
||||||
|
}, |
||||||
|
disabled: { |
||||||
|
type: Boolean, |
||||||
|
default: false, |
||||||
|
}, |
||||||
|
className: String, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
prefixCls: 'ant-rate', |
||||||
|
hoverValue: undefined, |
||||||
|
currentValue: undefined, |
||||||
|
markValue: undefined, |
||||||
|
} |
||||||
|
}, |
||||||
|
created () { |
||||||
|
this.currentValue = this.markValue = this.value || this.defaultValue |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
hoverValue(val) { |
||||||
|
if(val === undefined) { |
||||||
|
this.currentValue = this.markValue; |
||||||
|
return; |
||||||
|
} |
||||||
|
this.currentValue = val; |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
onClick(event, index) { |
||||||
|
let clValue = this.getStarValue(index, event.pageX); |
||||||
|
this.markValue = clValue; |
||||||
|
this.onMouseLeave(); |
||||||
|
this.onChange(clValue); |
||||||
|
}, |
||||||
|
onHover(event, index) { |
||||||
|
this.hoverValue = this.getStarValue(index, event.pageX); |
||||||
|
this.onHoverChange(this.hoverValue); |
||||||
|
}, |
||||||
|
getStarDOM (index) { |
||||||
|
return this.$refs.stars[index].$el |
||||||
|
}, |
||||||
|
getStarValue (index, x) { |
||||||
|
let value = index; |
||||||
|
if (this.allowHalf) { |
||||||
|
const leftEdge = getOffsetLeft(this.getStarDOM(0)) |
||||||
|
const width = getOffsetLeft(this.getStarDOM(1)) - leftEdge |
||||||
|
if ((x - leftEdge - width * (index-1)) < width / 2) { |
||||||
|
value -= 0.5 |
||||||
|
} |
||||||
|
} |
||||||
|
return value |
||||||
|
}, |
||||||
|
onMouseLeave() { |
||||||
|
this.hoverValue = undefined |
||||||
|
this.onHoverChange(undefined); |
||||||
|
}, |
||||||
|
}, |
||||||
|
components: { |
||||||
|
Star, |
||||||
|
Icon, |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,52 @@ |
|||||||
|
<template> |
||||||
|
<li |
||||||
|
:class="getClassName()" |
||||||
|
@click="onClick" |
||||||
|
@mousemove="onHover"> |
||||||
|
<div :class="`${this.prefixCls}-first`"><slot></slot></div> |
||||||
|
<div :class="`${this.prefixCls}-second`"><slot></slot></div> |
||||||
|
</li> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
export default { |
||||||
|
name: 'Star', |
||||||
|
props: { |
||||||
|
index: Number, |
||||||
|
disabled: Boolean, |
||||||
|
prefixCls: String, |
||||||
|
allowHalf: Boolean, |
||||||
|
value: Number, |
||||||
|
}, |
||||||
|
data() { |
||||||
|
return { |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
getClassName() { |
||||||
|
const { prefixCls, index, value, allowHalf } = this; |
||||||
|
const starValue = index; |
||||||
|
if (allowHalf && value + 0.5 === starValue) { |
||||||
|
return `${prefixCls} ${prefixCls}-half ${prefixCls}-active`; |
||||||
|
} |
||||||
|
return starValue <= value ? `${prefixCls} ${prefixCls}-full` : `${prefixCls} ${prefixCls}-zero`; |
||||||
|
}, |
||||||
|
onClick(e) { |
||||||
|
if(this.disabled) return; |
||||||
|
this.$emit("onClick", e, this.index); |
||||||
|
}, |
||||||
|
onHover(e) { |
||||||
|
if(this.disabled) return; |
||||||
|
this.$emit("onHover", e, this.index); |
||||||
|
}, |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
}, |
||||||
|
commponents: { |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
@ -0,0 +1,3 @@ |
|||||||
|
import Rate from './Rate'; |
||||||
|
|
||||||
|
export default Rate; |
@ -0,0 +1,2 @@ |
|||||||
|
import '../../style/index.less'; |
||||||
|
import './index.less'; |
@ -0,0 +1,73 @@ |
|||||||
|
@import "../../style/themes/default"; |
||||||
|
@import "../../style/mixins/index"; |
||||||
|
|
||||||
|
@rate-prefix-cls: ~"@{ant-prefix}-rate"; |
||||||
|
|
||||||
|
.@{rate-prefix-cls} { |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
list-style: none; |
||||||
|
font-size: 20px; |
||||||
|
display: inline-block; |
||||||
|
vertical-align: middle; |
||||||
|
|
||||||
|
&-disabled &-star { |
||||||
|
cursor: not-allowed; |
||||||
|
&:hover { |
||||||
|
transform: scale(1); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&-star { |
||||||
|
margin: 0; |
||||||
|
padding: 0; |
||||||
|
display: inline-block; |
||||||
|
margin-right: 8px; |
||||||
|
position: relative; |
||||||
|
transition: all .3s; |
||||||
|
color: @rate-star-bg; |
||||||
|
cursor: pointer; |
||||||
|
|
||||||
|
&-first, |
||||||
|
&-second { |
||||||
|
user-select: none; |
||||||
|
transition: all .3s; |
||||||
|
} |
||||||
|
|
||||||
|
&:hover { |
||||||
|
transform: scale(1.1); |
||||||
|
} |
||||||
|
|
||||||
|
&-first { |
||||||
|
position: absolute; |
||||||
|
left: 0; |
||||||
|
top: 0; |
||||||
|
width: 50%; |
||||||
|
height: 100%; |
||||||
|
overflow: hidden; |
||||||
|
opacity: 0; |
||||||
|
} |
||||||
|
|
||||||
|
&-half &-first, |
||||||
|
&-half &-second { |
||||||
|
opacity: 1; |
||||||
|
} |
||||||
|
|
||||||
|
&-half &-first, |
||||||
|
&-full &-second { |
||||||
|
color: @rate-star-color; |
||||||
|
} |
||||||
|
|
||||||
|
&-half:hover &-first, |
||||||
|
&-full:hover &-second { |
||||||
|
color: tint(@rate-star-color, 20%); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&-text { |
||||||
|
margin-left: 8px; |
||||||
|
vertical-align: middle; |
||||||
|
display: inline-block; |
||||||
|
font-size: @font-size-base; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,40 @@ |
|||||||
|
function getScroll(w, top) { |
||||||
|
let ret = top ? w.pageYOffset : w.pageXOffset; |
||||||
|
const method = top ? 'scrollTop' : 'scrollLeft'; |
||||||
|
if (typeof ret !== 'number') { |
||||||
|
const d = w.document; |
||||||
|
// ie6,7,8 standard mode
|
||||||
|
ret = d.documentElement[method]; |
||||||
|
if (typeof ret !== 'number') { |
||||||
|
// quirks mode
|
||||||
|
ret = d.body[method]; |
||||||
|
} |
||||||
|
} |
||||||
|
return ret; |
||||||
|
} |
||||||
|
|
||||||
|
function getClientPosition(elem) { |
||||||
|
let box; |
||||||
|
let x; |
||||||
|
let y; |
||||||
|
const doc = elem.ownerDocument; |
||||||
|
const body = doc.body; |
||||||
|
const docElem = doc && doc.documentElement; |
||||||
|
box = elem.getBoundingClientRect(); |
||||||
|
x = box.left; |
||||||
|
y = box.top; |
||||||
|
x -= docElem.clientLeft || body.clientLeft || 0; |
||||||
|
y -= docElem.clientTop || body.clientTop || 0; |
||||||
|
return { |
||||||
|
left: x, |
||||||
|
top: y, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
export const getOffsetLeft = (el) => { |
||||||
|
const pos = getClientPosition(el); |
||||||
|
const doc = el.ownerDocument; |
||||||
|
const w = doc.defaultView || doc.parentWindow; |
||||||
|
pos.left += getScroll(w); |
||||||
|
return pos.left; |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
基本 |
||||||
|
<Rate className="custom"></Rate> |
||||||
|
</br> |
||||||
|
半星 |
||||||
|
<Rate :allowHalf="allowHalf"></Rate> |
||||||
|
</br> |
||||||
|
默认3颗星 |
||||||
|
<Rate :value="initValue"></Rate> |
||||||
|
</br> |
||||||
|
只读 |
||||||
|
<Rate :value="initValue" :disabled="disabled"></Rate> |
||||||
|
</br> |
||||||
|
回调函数 |
||||||
|
<Rate |
||||||
|
:onChange="onChange" |
||||||
|
:onHoverChange="onHoverChange"></Rate> |
||||||
|
<span v-if="hoverValue">{{hoverValue}}stars</span> |
||||||
|
<span v-if="rValue">{{rValue}}stars</span> |
||||||
|
<br/> |
||||||
|
<Rate |
||||||
|
:allowHalf="allowHalf" |
||||||
|
:onHoverChange="onHoverChangeAH"></Rate> |
||||||
|
<span v-if="hoverValueAH">{{hoverValueAH}}stars</span> |
||||||
|
</br> |
||||||
|
自定义 |
||||||
|
<Rate :value="initValue"> |
||||||
|
<template slot-scope="props"> |
||||||
|
<span>A</span> |
||||||
|
</template> |
||||||
|
</Rate> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import { Rate } from '../components/index' |
||||||
|
export default { |
||||||
|
data () { |
||||||
|
return { |
||||||
|
allowHalf: true, |
||||||
|
initValue: 3, |
||||||
|
disabled: true, |
||||||
|
hoverValue: undefined, |
||||||
|
rValue: undefined, |
||||||
|
hoverValueAH: undefined, |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
onHoverChange(val) { |
||||||
|
this.hoverValue = val; |
||||||
|
}, |
||||||
|
onChange(val) { |
||||||
|
this.rValue = val; |
||||||
|
}, |
||||||
|
onHoverChangeAH(val) { |
||||||
|
this.hoverValueAH = val; |
||||||
|
} |
||||||
|
}, |
||||||
|
components: { |
||||||
|
Rate |
||||||
|
}, |
||||||
|
} |
||||||
|
</script> |
Loading…
Reference in new issue