diff --git a/src/components/rate/index.js b/src/components/rate/index.js new file mode 100644 index 00000000..24e54060 --- /dev/null +++ b/src/components/rate/index.js @@ -0,0 +1,2 @@ +import Rate from './rate.vue'; +export default Rate; \ No newline at end of file diff --git a/src/components/rate/rate.vue b/src/components/rate/rate.vue new file mode 100644 index 00000000..e2c64c9b --- /dev/null +++ b/src/components/rate/rate.vue @@ -0,0 +1,99 @@ +<template> + <div :class="classes" @mouseleave="handleMouseleave"> + <div v-for="item in count" :class="starCls(item)"> + <span + :class="[prefixCls + '-star-content']" + @mousemove="handleMousemove(item, $event)" + @click="handleClick(item)"></span> + </div> + </div> +</template> +<script> + const prefixCls = 'ivu-rate'; + + export default { + props: { + count: { + type: Number, + default: 5 + }, + value: { + type: Number, + default: 0 + }, + allowHalf: { + type: Boolean, + default: false + }, + disabled: { + type: Boolean, + default: false + } + }, + data () { + return { + prefixCls: prefixCls, + hoverIndex: -1 + }; + }, + computed: { + classes () { + return [ + `${prefixCls}`, + { + [`${prefixCls}-disabled`]: this.disabled + } + ] + } + }, + methods: { + starCls (value) { + const hoverIndex = this.hoverIndex; + let full = false; + + if (hoverIndex >= value) { + full = true; + } + + return [ + `${prefixCls}-star`, + { + [`${prefixCls}-star-full`]: full, + [`${prefixCls}-star-zero`]: !full + } + ] + }, + handleMousemove(value, event) { + if (this.disabled) return; + + if (this.allowHalf) { +// let target = event.target; +// if (hasClass(target, 'el-rate__item')) { +// target = target.querySelector('.el-rate__icon'); +// } +// if (hasClass(target, 'el-rate__decimal')) { +// target = target.parentNode; +// } +// this.pointerAtLeftHalf = event.offsetX * 2 <= target.clientWidth; +// this.currentValue = this.pointerAtLeftHalf ? value - 0.5 : value; + } else { + this.currentValue = value; + } + this.hoverIndex = value; + }, + handleMouseleave () { + if (this.disabled) { + return; + } + if (this.allowHalf) { +// this.pointerAtLeftHalf = this.value !== Math.floor(this.value); + } +// this.currentValue = this.value; + this.hoverIndex = -1; + }, + handleClick (value) { + + } + } + }; +</script> \ No newline at end of file diff --git a/src/index.js b/src/index.js index 6756a5be..944a1645 100644 --- a/src/index.js +++ b/src/index.js @@ -27,6 +27,7 @@ import Page from './components/page'; import Poptip from './components/poptip'; import Progress from './components/progress'; import Radio from './components/radio'; +import Rate from './components/rate'; import Slider from './components/slider'; import Spin from './components/spin'; import Steps from './components/steps'; @@ -83,6 +84,7 @@ const iview = { Progress, Radio, RadioGroup: Radio.Group, + Rate, Row, iSelect: Select, Slider, diff --git a/src/styles/components/index.less b/src/styles/components/index.less index 07baccd4..10f81742 100644 --- a/src/styles/components/index.less +++ b/src/styles/components/index.less @@ -34,4 +34,5 @@ @import "menu"; @import "date-picker"; @import "time-picker"; -@import "form"; \ No newline at end of file +@import "form"; +@import "rate"; \ No newline at end of file diff --git a/src/styles/components/rate.less b/src/styles/components/rate.less new file mode 100644 index 00000000..82002ffd --- /dev/null +++ b/src/styles/components/rate.less @@ -0,0 +1,66 @@ +@rate-prefix-cls: ~"@{css-prefix}rate"; + +.@{rate-prefix-cls} { + display: inline-block; + margin: 0; + padding: 0; + font-size: 20px; + vertical-align: middle; + font-weight: normal; + font-style: normal; + font-family: 'Ionicons'; + + &-disabled &-star { + &:before, + &-content:before { + cursor: default; + } + &:hover { + transform: scale(1); + } + } + + &-star { + display: inline-block; + margin: 0; + padding: 0; + margin-right: 8px; + position: relative; + transition: all 0.3s ease; + + &:hover { + transform: scale(1.1); + } + + &:before, + &-content:before { + color: #e9e9e9; + cursor: pointer; + content: "\F4B3"; + transition: all @transition-time @ease-in-out; + display: block; + } + + &-content { + position: absolute; + left: 0; + top: 0; + width: 50%; + height: 100%; + overflow: hidden; + &:before { + color: transparent; + } + } + + &-half &-content:before, + &-full:before { + color: @rate-star-color; + } + + &-half:hover &-content:before, + &-full:hover:before { + color: tint(@rate-star-color, 20%); + } + } +} \ No newline at end of file diff --git a/src/styles/themes/default/custom.less b/src/styles/themes/default/custom.less index ba7236e1..fb3367f3 100644 --- a/src/styles/themes/default/custom.less +++ b/src/styles/themes/default/custom.less @@ -14,6 +14,7 @@ @selected-color : fade(@primary-color, 90%); @tooltip-color : #fff; @subsidiary-color : #9ea7b4; +@rate-star-color : #f5a623; // Base @body-background : #fff; diff --git a/test/app.vue b/test/app.vue index 3dfec764..0a1e3cff 100644 --- a/test/app.vue +++ b/test/app.vue @@ -47,6 +47,7 @@ li + li { <li><a v-link="'/menu'">Menu</a></li> <li><a v-link="'/date'">Date</a></li> <li><a v-link="'/form'">Form</a></li> + <li><a v-link="'/rate'">Rate</a></li> </ul> </nav> <router-view></router-view> diff --git a/test/main.js b/test/main.js index 363135f9..6805f1cc 100644 --- a/test/main.js +++ b/test/main.js @@ -134,6 +134,11 @@ router.map({ require(['./routers/form.vue'], resolve); } }, + '/rate': { + component: function (resolve) { + require(['./routers/rate.vue'], resolve); + } + }, }); router.beforeEach(function () { diff --git a/test/routers/rate.vue b/test/routers/rate.vue new file mode 100644 index 00000000..5a7d769a --- /dev/null +++ b/test/routers/rate.vue @@ -0,0 +1,15 @@ +<template> + <div style="margin: 100px"> + <Rate></Rate> + </div> +</template> +<script> + export default { + props: {}, + data () { + return {}; + }, + computed: {}, + methods: {} + }; +</script> \ No newline at end of file