送你一颗小星星~
效果
收藏类型
评星类型
环境
- 微信小程序 typescript + scss
代码
下载地址
https://download.csdn.net/download/linyisonger/85169692
收藏类型
组件
index.ts
Component({
properties: {
checked: {
type: Object,
value: undefined
}
},
})
index.wxml
<view class="star {{checked == null ? '' : checked == true ? 'fill' : 'none' }}">
<view class="iconfont icon-star"></view>
<view class="iconfont icon-star-fill"></view>
<view class="bling"></view>
<view class="bling"></view>
<view class="bling"></view>
</view>
index.scss
:host {
display: inline-flex;
}
@font-face {
font-family: "iconfont";
/* Project id 3330476 */
src: url('//at.alicdn.com/t/font_3330476_y264o31cfs8.woff2?t=1649984479172') format('woff2'),
url('//at.alicdn.com/t/font_3330476_y264o31cfs8.woff?t=1649984479172') format('woff'),
url('//at.alicdn.com/t/font_3330476_y264o31cfs8.ttf?t=1649984479172') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-star:before {
content: "\e7df";
}
.icon-star-fill:before {
content: "\e86a";
}
.star {
position: relative;
--width: 20rpx;
--height: 4rpx;
--font-size: 50rpx;
--color: #bbbbbb;
--fill-color: goldenrod;
--left: 200rpx;
--top: -100rpx;
.icon-star {
color: var(--color);
font-size: var(--font-size);
}
.icon-star-fill {
position: absolute;
font-size: var(--font-size);
top: 0;
left: 0;
color: var(--fill-color);
opacity: 0;
}
.bling {
position: absolute;
width: var(--width);
height: var(--height);
border-radius: calc(var(--width) / 2);
background-color: var(--fill-color);
top: calc(50% - calc(var(--height) / 2));
left: calc(50% - calc(var(--width) / 2));
box-shadow: var(--font-size) calc(var(--height) / -.5) 0px var(--fill-color), calc(-1 * var(--font-size)) calc(var(--height) / -.5) 0px var(--fill-color);
opacity: 0;
}
&.fill {
.icon-star-fill {
animation-name: star-fill-add;
animation-duration: 1s;
transition-timing-function: ease-in-out;
opacity: 1;
}
.icon-star {
animation-name: star-add;
animation-delay: 1s;
animation-duration: 1s;
transition-timing-function: linear;
}
.bling {
animation-delay: 1s;
animation-duration: 1s;
transition-timing-function: ease-in-out;
opacity: 0;
&:nth-of-type(3) {
animation-name: star-bling-1;
}
&:nth-of-type(4) {
animation-name: star-bling-2;
}
&:nth-of-type(5) {
animation-name: star-bling-3;
}
}
}
&.none {
.icon-star-fill {
animation-name: star-fill-subtract;
animation-duration: 1s;
transition-timing-function: linear;
}
.icon-star {
animation-name: star-subtract;
animation-duration: 1s;
transition-timing-function: linear;
}
}
}
@keyframes star-add {
0% {
color: var(--fill-color);
transform: scale(1);
}
100% {
transform: scale(1.5);
opacity: 0;
}
}
@keyframes star-fill-add {
0% {
left: var(--left);
top: var(--top);
font-size: calc(var(--font-size) / 2.5);
transform: rotate(720deg);
}
100% {
left: 0;
top: 0;
font-size: var(--font-size);
}
}
@keyframes star-bling-1 {
0% {
color: var(--fill-color);
opacity: 0;
transform: scale(.8) rotate(-45deg);
}
50% {
opacity: 1;
}
100% {
transform: scale(1) rotate(-45deg);
opacity: 0;
}
}
@keyframes star-bling-2 {
0% {
color: var(--fill-color);
transform: scale(.8) rotate(45deg);
}
50% {
opacity: 1;
}
100% {
transform: scale(1) rotate(45deg);
opacity: 0;
}
}
@keyframes star-bling-3 {
0% {
color: var(--fill-color);
transform: scale(.8);
}
50% {
opacity: 1;
}
100% {
transform: scale(1);
opacity: 0;
}
}
@keyframes star-subtract {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@keyframes star-fill-subtract {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
引用
index.json
{
"usingComponents": {
"star": "../../components/star/index"
}
}
index.scss
加个边距
.collect {
margin: 40px;
}
index.wxml
<star class="collect" checked="{{collect}}" bindtap="collectClick"></star>
index.ts
Page({
data: {
collect: undefined as undefined | boolean
},
collectClick(e: any) {
this.setData({ collect: !this.data.collect });
}
})
评星类型
组件
index.json
{
"component": true,
"usingComponents": {
"star": "../star/index"
}
}
index.scss
这个看你需求而定,我这里随便写的。
.stars {
display: flex;
padding: 10rpx 50rpx;
position: relative;
star {
padding: 0 20rpx;
}
}
index.wxml
<view class="stars">
<block wx:for="{{checkeds}}" wx:key="unique">
<star checked="{{item}}" bindtap="tap" data-i="{{index}}"></star>
</block>
</view>
index.ts
// components/star-item/index.ts
Component({
properties: {
score: {
type: Number,
value: 0,
},
disabled: {
type: Boolean,
value: false
},
delay: {
type: Number,
value: 500
}
},
data: {
checkeds: [undefined, undefined, undefined] as (boolean | undefined)[],
},
methods: {
tap(e: any) {
let i = e.target.dataset.i;
this.triggerEvent('score', i + 1);
}
},
observers: {
"score": function (n) {
let o = this.data.checkeds.filter(a => a).length;
/** 是正数? */
let p = n > o;
/** 方向 */
let d = p ? 1 : -1;
for (let i = p ? o : o - 1, t = 0; p ? i < n : i >= n; i += d, t++) {
setTimeout(() => {
this.setData({ [`checkeds[${i}]`]: p })
}, t * this.data.delay);
}
}
}
})
引用
index.json
{
"usingComponents": {
"stars": "../../components/stars/index"
}
}
index.wxml
<stars score="{{score}}" bind:score="scoreChange"></stars>
index.ts
Page({
data: {
score: 0,
},
scoreChange(e: any) {
this.setData({ score: e.detail })
}
})