见下述效果图,本文话少纯干货
<template>
<view class="main" :style="state.backgroundStyle" @click="state.showOpts = !state.showOpts">
<text class="barrage-text" :style="{
color: state.textColor, fontSize: state.textFontSize,
fontWeight: state.textFontWeight, animation: state.textAnimation
}">{{ state.barrageText }}</text>
</view>
<view class="opts" v-show="state.showOpts">
<uni-segmented-control :current="state.tabCurrent"
:values="state.tabCurrents" style-type="text" @clickItem="(e) => {
if (e.currentIndex != state.tabCurrent) state.tabCurrent = e.currentIndex; }" />
<view v-if="state.tabCurrent == 0">
<uni-section title="弹幕内容" type="line">
<template v-slot:right>
<uni-easyinput v-model="state.barrageText" placeholder="请输入弹幕内容" :clearable="false"/>
</template>
</uni-section>
<uni-section title="方向" type="line">
<template v-slot:right>
<uni-data-checkbox mode="button" v-model="state.direction" :localdata="state.directions"
@change="(e) => state.textAnimation = `barrage-${e.detail.value} ${state.speed == 0? 0: 20 - state.speed}s linear infinite`"/>
</template>
</uni-section>
</view>
<view v-if="state.tabCurrent == 1">
<uni-section title="加粗" type="line">
<template v-slot:right>
<switch color="#d6ba44" style="transform:scale(0.7)"
@change="(e) => state.textFontWeight = e.detail.value? 'bold': 'revert'"/>
</template>
</uni-section>
<uni-section title="大小" type="line">
<template v-slot:right>
<slider :value="state.textSize" min="1" max="350"
@changing="(e) => state.textFontSize = e.detail.value + 'px'" />
</template>
</uni-section>
</view>
<view v-if="state.tabCurrent == 2" class="color-opt">
<view v-for="(textColor, index) in state.textColors" :key="index" class="change-colors"
@click="() => state.textColor = `rgb(${textColor.r},${textColor.g},${textColor.b})`"
:style="'background-color: rgb(' + textColor.r + ', ' + textColor.g + ', ' + textColor.b + ')'">
<text>{{ textColor.name }}</text>
</view>
</view>
<view v-if="state.tabCurrent == 3">
<uni-section title="速度" type="line">
<template v-slot:right>
<slider :value="state.speed" min="0" max="19"
@changing="(e) => state.textAnimation =
`barrage-${state.direction} ${e.detail.value == 0? 0: 20 - e.detail.value}s linear infinite`" />
</template>
</uni-section>
</view>
<view class='btns'>
<button type="primary" size="mini" @click="reset">重置</button>
<button type="primary" size="mini" @click="saveQuit">保存并退出</button>
</view>
</view>
</template>
<script setup>
import { onLoad, onShareAppMessage } from "@dcloudio/uni-app";
import { reactive, getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance();
onShareAppMessage(() => proxy.$shareApp);
const storageDataKey = "handBarrage-info";
let state = reactive({
barrageText: '哇!是954L!', textSize: 128, speed: 15, direction: 'r2l',
directions: [{ text: '从左到右', value: 'l2r' }, { text: '从右到左', value: 'r2l' }],
backgroundStyle: { 'background-color': '#000', 'height': proxy.$systemInfo.screenHeight + 'px' },
textColor: 'rgb(255,255,255)', textFontSize: '128rpx', textFontWeight: 'revert',
textAnimation: 'barrage-r2l 5s linear infinite',
showOpts: true, textReversal: false, tabCurrent: 0, tabCurrents: ['文字', '字号', '颜色', '速度'],
textColors: [ { name: '白色', r: '255', g: '255', b: '255' }, { name: '深红', r: '200', g: '0', b: '2' },
{ name: '红色', r: '255', g: '0', b: '0' }, { name: '钴蓝', r: '0', g: '75', b: '115' },
{ name: '靛青', r: '51', g: '143', b: '178' }, { name: '蓝色', r: '4', g: '107', b: '255' },
{ name: '天蓝', r: '68', g: '142', b: '219' }, { name: '青蓝', r: '0', g: '191', b: '243' } ]
});
const reset = () => { uni.removeStorageSync(storageDataKey);
state = Object.assign(state, JSON.parse(oldState)); proxy.$showSuccessToast('重置成功!'); }
const saveQuit = () => {
uni.setStorageSync(storageDataKey, JSON.stringify(state));
proxy.$navigateBack();
}
let oldState;
onLoad(() => {
oldState = JSON.stringify(state);
const info = uni.getStorageSync(storageDataKey);
if (info != null) state = Object.assign(state, JSON.parse(info));
})
</script>
<style lang="scss">
@keyframes barrage-l2r {
from{ transform: rotate(90deg) translateX(-100%); }
to{ transform: rotate(90deg) translateX(100%); }
}
@keyframes barrage-r2l {
from{ transform: rotate(90deg) translateX(100%); }
to{ transform: rotate(90deg) translateX(-100%); }
}
</style>
<style lang="scss" scoped >
.main { display: flex; align-items: center; justify-content: center; position: relative; }
.barrage-text { transform: rotate(90deg); display: flex; white-space: nowrap; position: absolute; }
.opts ::v-deep {
position: absolute; bottom: 5%; width: 100%; height: 350rpx;
.is-checked { border-color: #d6ba44 !important; }
.checklist-box .checklist-text { color: gray !important; }
.uni-section { background-color: transparent !important; }
.segmented-control__text, .uni-section__content-title { color: gray !important; }
.segmented-control__item--text { color: #bda131 !important; }
.uni-section-header__content { flex: none !important; width: 20%; }
.uni-section-header__slot-right { width: 100%; }
.uni-easyinput__content { border-color: transparent !important;
background-color: #272727c2 !important; input { color: #d6ba44 !important; } }
.color-opt { height: 55%; display: flex; align-items: center; justify-content: center;
.change-colors {
vertical-align: middle; display: inline-block;
border-radius: 12rpx; width: 60rpx; height: 60rpx;
position: relative; margin: 0 10rpx 0 10rpx; border: 1rpx solid #dddddd;
> text { color: gray; font-size: 22rpx; position: absolute;
width: 60rpx; text-align: center; bottom: -35rpx; }
}
}
.btns { position: fixed; bottom: 2%; text-align: center; button { margin-top: 20rpx !important;
margin-left: 100rpx !important; margin-right: 100rpx !important; } }
}
</style>