parent
f4fb4fedbb
commit
6fc3c2c9f1
@ -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