添加新文件
This commit is contained in:
+296
@@ -0,0 +1,296 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../../common/vendor.js");
|
||||
const _sfc_main = {
|
||||
name: "LuckyWheel",
|
||||
props: {
|
||||
prizes: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 600
|
||||
},
|
||||
customStyle: {
|
||||
type: String
|
||||
},
|
||||
styleOpt: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
prizeBgColors: ["#fff0a3", "#fffce6", "#fdba64"],
|
||||
borderColor: "#ffd752"
|
||||
})
|
||||
},
|
||||
innerStyle: {
|
||||
type: String,
|
||||
default: `width: 85%;height:85%`
|
||||
},
|
||||
turns: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 5e3
|
||||
},
|
||||
lightNormalSpeed: {
|
||||
type: Number,
|
||||
default: 1e3
|
||||
},
|
||||
lighFastSpeed: {
|
||||
type: Number,
|
||||
default: 50
|
||||
},
|
||||
lightSize: {
|
||||
type: String,
|
||||
default: `26rpx`
|
||||
},
|
||||
lightColors: {
|
||||
type: Array,
|
||||
default: () => ["#FF0000", "#FFFF00"]
|
||||
},
|
||||
lightImgs: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
prizeBgImages: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rotating: false,
|
||||
// 是否正在旋转
|
||||
rotationAngle: 0,
|
||||
// 当前旋转角度
|
||||
// 设置指针默认指向的位置,现在是默认指向2个扇形之间的边线上
|
||||
rotateAngle: 0,
|
||||
rotateTransition: "",
|
||||
animationInterval: null,
|
||||
lights: [],
|
||||
// 用于存储闪光灯信息
|
||||
currentAnimationStep: 0,
|
||||
lightConfig: {
|
||||
animationSpeed: 1e3,
|
||||
// 初始动画速度,单位毫秒
|
||||
totalLights: 0
|
||||
// 总灯数,将在 mounted 中设置
|
||||
},
|
||||
lotteryIndex: null
|
||||
// 中奖下标
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 计算轮盘样式
|
||||
containerStyle() {
|
||||
let {
|
||||
size,
|
||||
customStyle
|
||||
} = this;
|
||||
size = /\d$/.test(size) ? size + "rpx" : size;
|
||||
return `width: ${size}; height: ${size}; ${customStyle}`;
|
||||
},
|
||||
wheelStyle() {
|
||||
return `
|
||||
padding: ${this.styleOpt.padding};
|
||||
transform: ${this.rotateAngle};
|
||||
transition: ${this.rotateTransition};
|
||||
${this.innerStyle}
|
||||
`;
|
||||
},
|
||||
getCorrectAngle() {
|
||||
return (index) => {
|
||||
const style = {
|
||||
transform: `skewY(${90 - 360 / this.prizes.length}deg) skewX(0deg) rotate(${180 / this.prizes.length}deg)`
|
||||
};
|
||||
if (this.prizes.length == 2) {
|
||||
if (index == 0) {
|
||||
style["transform"] = `rotate(90deg)`;
|
||||
style["bottom"] = 0;
|
||||
} else {
|
||||
style["transform"] = `rotate(0deg)`;
|
||||
style["left"] = 0;
|
||||
style["bottom"] = "-50%";
|
||||
}
|
||||
}
|
||||
return style;
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 计算每个奖项扇形的样式
|
||||
getPrizeItemStyle(index) {
|
||||
const style = {
|
||||
transform: `rotate(${360 / this.prizes.length * index}deg) skewX(0deg) skewY(${360 / this.prizes.length - 90}deg)`
|
||||
};
|
||||
if (this.prizes.length == 2) {
|
||||
style["transform"] = index == 0 ? 0 : `rotate(270deg)`;
|
||||
style["top"] = 0;
|
||||
}
|
||||
if (!this.getPrizeBgImage(index)) {
|
||||
style.backgroundColor = `${this.styleOpt.prizeBgColors[index % this.styleOpt.prizeBgColors.length]}`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
// 开始旋转
|
||||
startRotation(index) {
|
||||
if (this.rotating)
|
||||
return;
|
||||
const duration = this.duration;
|
||||
const length = this.prizes.length;
|
||||
const rotateAngle = this.rotationAngle + this.turns * 360 + 360 - (180 / length + 360 / length * index) - this.rotationAngle % 360;
|
||||
common_vendor.index.__f__("log", "at uni_modules/dengbo-lotteryWheel/components/dengbo-lotteryWheel/dengbo-lotteryWheel.vue:205", "rotateAngle", rotateAngle);
|
||||
this.rotationAngle = rotateAngle;
|
||||
this.rotateAngle = `rotate(${rotateAngle}deg)`;
|
||||
this.rotateTransition = `transform ${duration}ms cubic-bezier(0.250, 0.460, 0.455, 0.995)`;
|
||||
this.rotating = true;
|
||||
this.accelerateLightAnimation();
|
||||
setTimeout(() => {
|
||||
this.$emit("done");
|
||||
this.rotating = false;
|
||||
this.stopSpinningAnimation();
|
||||
this.resetLightAnimation();
|
||||
}, duration + 500);
|
||||
},
|
||||
accelerateLightAnimation() {
|
||||
this.stopLightAnimation();
|
||||
this.lightConfig.animationSpeed = this.lighFastSpeed;
|
||||
this.startLightAnimation();
|
||||
},
|
||||
resetLightAnimation() {
|
||||
this.stopLightAnimation();
|
||||
this.lightConfig.animationSpeed = this.lightNormalSpeed;
|
||||
this.startLightAnimation();
|
||||
},
|
||||
stopSpinningAnimation() {
|
||||
clearInterval(this.animationInterval);
|
||||
},
|
||||
// 对外暴露的启动方法
|
||||
// run(index) {
|
||||
// this.startRotation(index);
|
||||
// },
|
||||
run(index) {
|
||||
this.startRotation(index);
|
||||
},
|
||||
// 设置次数
|
||||
setCount(count) {
|
||||
common_vendor.index.__f__("log", "at uni_modules/dengbo-lotteryWheel/components/dengbo-lotteryWheel/dengbo-lotteryWheel.vue:249", "count", count);
|
||||
this.lotteryIndex = count;
|
||||
},
|
||||
// 初始化闪光灯
|
||||
initLights() {
|
||||
this.lightConfig.totalLights = this.prizes.length * 2;
|
||||
this.lights = Array(this.lightConfig.totalLights).fill().map(() => ({}));
|
||||
},
|
||||
// 获取闪光灯样式
|
||||
getLightStyle(index) {
|
||||
const angle = 360 / this.lights.length * index - 90;
|
||||
const radius = 44.5;
|
||||
const radian = angle * (Math.PI / 180);
|
||||
const x = 50 + radius * Math.cos(radian);
|
||||
const y = 50 + radius * Math.sin(radian);
|
||||
const style = {
|
||||
left: `${x}%`,
|
||||
top: `${y}%`,
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: this.lightSize,
|
||||
height: this.lightSize
|
||||
};
|
||||
if (this.lightImgs.length === 0) {
|
||||
style.backgroundColor = this.getCurrentColor(index);
|
||||
style.boxShadow = `0 0 5px ${this.getCurrentColor(index)}`;
|
||||
}
|
||||
return style;
|
||||
},
|
||||
getCurrentColor(colorIndex) {
|
||||
if (this.lightImgs.length > 0)
|
||||
return "";
|
||||
const totalSteps = this.lightColors.length;
|
||||
const currentStep = this.currentAnimationStep % totalSteps;
|
||||
const currentColorIndex = (colorIndex + currentStep) % totalSteps;
|
||||
return this.lightColors[currentColorIndex];
|
||||
},
|
||||
getCurrentImage(colorIndex) {
|
||||
if (this.lightImgs.length === 0)
|
||||
return "";
|
||||
const totalSteps = this.lightImgs.length;
|
||||
const currentStep = this.currentAnimationStep % totalSteps;
|
||||
const currentImageIndex = (colorIndex + currentStep) % totalSteps;
|
||||
return this.lightImgs[currentImageIndex];
|
||||
},
|
||||
startLightAnimation() {
|
||||
this.animationInterval = setInterval(() => {
|
||||
this.currentAnimationStep++;
|
||||
this.$forceUpdate();
|
||||
}, this.lightConfig.animationSpeed);
|
||||
},
|
||||
stopLightAnimation() {
|
||||
if (this.animationInterval) {
|
||||
clearInterval(this.animationInterval);
|
||||
this.animationInterval = null;
|
||||
}
|
||||
},
|
||||
// 新增:获取扇形背景图
|
||||
getPrizeBgImage(index) {
|
||||
if (this.prizeBgImages.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return this.prizeBgImages[index % this.prizeBgImages.length];
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initLights();
|
||||
this.startLightAnimation();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.stopSpinningAnimation();
|
||||
this.stopLightAnimation();
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return common_vendor.e({
|
||||
a: _ctx.$slots && _ctx.$slots.bg
|
||||
}, _ctx.$slots && _ctx.$slots.bg ? {} : {}, {
|
||||
b: common_vendor.f($props.prizes, (item, index, i0) => {
|
||||
return common_vendor.e({
|
||||
a: $options.getPrizeBgImage(index)
|
||||
}, $options.getPrizeBgImage(index) ? {
|
||||
b: $options.getPrizeBgImage(index)
|
||||
} : {}, {
|
||||
c: common_vendor.t(item.name),
|
||||
d: item.iconUrl,
|
||||
e: "d-" + i0,
|
||||
f: common_vendor.r("d", {
|
||||
item,
|
||||
index
|
||||
}, i0),
|
||||
g: common_vendor.s($options.getCorrectAngle(index)),
|
||||
h: index,
|
||||
i: common_vendor.s($options.getPrizeItemStyle(index))
|
||||
});
|
||||
}),
|
||||
c: common_vendor.s($options.wheelStyle),
|
||||
d: _ctx.$slots && _ctx.$slots.pointer
|
||||
}, _ctx.$slots && _ctx.$slots.pointer ? {
|
||||
e: common_vendor.r("pointer", {
|
||||
class: "pointer-heart"
|
||||
})
|
||||
} : {
|
||||
f: common_vendor.o(($event) => _ctx.$emit("run"))
|
||||
}, {
|
||||
g: common_vendor.f($data.lights, (light, index, i0) => {
|
||||
return common_vendor.e($props.lightImgs.length > 0 ? {
|
||||
a: $options.getCurrentImage(index)
|
||||
} : {}, {
|
||||
b: index,
|
||||
c: common_vendor.s($options.getLightStyle(index))
|
||||
});
|
||||
}),
|
||||
h: $props.lightImgs.length > 0,
|
||||
i: common_vendor.s($options.containerStyle)
|
||||
});
|
||||
}
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-a25e7602"]]);
|
||||
wx.createComponent(Component);
|
||||
//# sourceMappingURL=../../../../../.sourcemap/mp-weixin/uni_modules/dengbo-lotteryWheel/components/dengbo-lotteryWheel/dengbo-lotteryWheel.js.map
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
<view class="lucky-wheel-container data-v-a25e7602" style="{{i}}"><view class="lucky-wheel-bg data-v-a25e7602"><slot wx:if="{{a}}" name="bg"/></view><view class="lucky-wheel data-v-a25e7602" style="{{c}}"><view class="lucky-wheel-wrap data-v-a25e7602"><view wx:for="{{b}}" wx:for-item="item" wx:key="h" class="prize-item data-v-a25e7602" style="{{item.i}}"><view class="prize-content data-v-a25e7602" style="{{item.g}}"><view class="prize-content-bg data-v-a25e7602"><image wx:if="{{item.a}}" class="data-v-a25e7602" src="{{item.b}}" style="width:100%;height:100%"/></view><block wx:if="{{$slots.d}}"><slot name="{{item.e}}"></slot></block><block wx:else><text class="prize-name data-v-a25e7602">{{item.c}}</text><view class="prize-pro data-v-a25e7602"><image class="data-v-a25e7602" src="{{item.d}}" style="width:98rpx;height:70rpx"></image></view></block></view></view></view></view><view class="pointer data-v-a25e7602"><view wx:if="{{d}}" class="pointer-heart data-v-a25e7602"><slot name="pointer"/></view><view wx:else class="pointer-triangle pointer-heart data-v-a25e7602" bindtap="{{f}}"></view></view><view class="lights-container data-v-a25e7602"><view wx:for="{{g}}" wx:for-item="light" wx:key="b" class="light data-v-a25e7602" style="{{light.c}}"><image wx:if="{{h}}" class="data-v-a25e7602" src="{{light.a}}" style="width:100%;height:100%;position:absolute;left:0;right:0"/></view></view></view>
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* 这里是uni-app内置的常用样式变量
|
||||
*
|
||||
* uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
|
||||
* 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
|
||||
*
|
||||
*/
|
||||
/* uni.scss */
|
||||
/**
|
||||
* 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
|
||||
*
|
||||
* 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
|
||||
*/
|
||||
/* 颜色变量 */
|
||||
/* 行为相关颜色 */
|
||||
/* 文字基本颜色 */
|
||||
/* 背景颜色 */
|
||||
/* 边框颜色 */
|
||||
/* 尺寸变量 */
|
||||
/* 文字尺寸 */
|
||||
/* 图片尺寸 */
|
||||
/* Border Radius */
|
||||
/* 水平间距 */
|
||||
/* 垂直间距 */
|
||||
/* 轮盘容器样式 */
|
||||
.lucky-wheel-container.data-v-a25e7602 {
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
.lucky-wheel-bg.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
.lucky-wheel-d.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
width: 90%;
|
||||
height: 90%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
z-index: 0;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
.wheel-image.data-v-a25e7602 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.wheel-image-1.data-v-a25e7602 {
|
||||
animation: blink-1-a25e7602 1000ms infinite linear;
|
||||
}
|
||||
.wheel-image-2.data-v-a25e7602 {
|
||||
animation: blink-2-a25e7602 1000ms infinite linear;
|
||||
}
|
||||
@keyframes blink-1-a25e7602 {
|
||||
0%, 100% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes blink-2-a25e7602 {
|
||||
0%, 100% {
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
/* 轮盘主体样式 */
|
||||
.lucky-wheel.data-v-a25e7602 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin: auto;
|
||||
transition-property: transform;
|
||||
transition-timing-function: cubic-bezier(0.25, 0.46, 0.455, 0.995);
|
||||
}
|
||||
.lucky-wheel-wrap.data-v-a25e7602 {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 奖项扇形样式 */
|
||||
.prize-item.data-v-a25e7602 {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: 50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform-origin: 0 100%;
|
||||
}
|
||||
|
||||
/* 奖项内容样式 */
|
||||
.prize-content.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
padding-top: 16rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: -50%;
|
||||
bottom: -50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
.prize-content-bg.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
/* 奖项图片样式 */
|
||||
.prize-image.data-v-a25e7602 {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
/* 奖项名称样式 */
|
||||
.prize-name.data-v-a25e7602 {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
z-index: 9;
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: #DA402B;
|
||||
}
|
||||
.prize-pro.data-v-a25e7602 {
|
||||
position: relative;
|
||||
}
|
||||
.prize-pro-txt.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-weight: 400;
|
||||
font-size: 14rpx;
|
||||
color: #E26241;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* 指针样式 */
|
||||
.pointer.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
top: 47%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
}
|
||||
.pointer-triangle.data-v-a25e7602 {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 20px solid transparent;
|
||||
border-right: 20px solid transparent;
|
||||
border-bottom: 40px solid #ff0000;
|
||||
/* 红色三角形 */
|
||||
/* 删除 transform: rotate(180deg); 这一行 */
|
||||
}
|
||||
.pointer-heart.data-v-a25e7602 {
|
||||
animation: heart-a25e7602 1s infinite;
|
||||
}
|
||||
@keyframes heart-a25e7602 {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
to {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
.lights-container.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
pointer-events: none;
|
||||
}
|
||||
.light.data-v-a25e7602 {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
}
|
||||
Reference in New Issue
Block a user