博主最近在做一款小游戏,不想用canvas去写,就想着用uniapp+vue2去实现,代码很简单,因为是uniapp,可以同时兼容H5和app端
H5端
下面是html的代码
<view class="game-content w-100 d-f f-d-c a-i-c">
<view class="game-main">
<!-- 迷宫图 -->
<view class="game-main-map">
<!-- 控制人物一定用绝对单位 px值 不要用rpx让uniapp去计算 -->
<image v-if="lattice_height >= 0 || character_left >= 0" class="character"
src="@/static/Snipaste_2024-12-16_17-18-31.png"
:style="{ width: lattice_width + 'rpx', height: lattice_height + 'rpx', left: character_left + 'px', top: character_top + 'px' }">
</image>
<view class="map-bg w-100 d-f a-i-c j-c-s-b" v-for="(item, index) in map">
<view class="map-samll-b d-f a-i-c"
:class="[`map-samll-b-${index + 1}-${index1 + 1}`, item1 == 0 ? 'map-samll-b-fideIn-animation' : '']"
:style="{
width: '100%',
height: lattice_height + 'rpx',
background: item1 == 1 ? 'rgb(245, 227, 183)' : '',
animationDelay: item1 == 0 ? `${index1 * 0.03}s` : '',
borderRadius: computedRadius(index, index1, map, item)
}" v-for="(item1, index1) in item">
<image class="w-100 h-100" v-if="item1 == 1" src="@/static/gezi.png" mode=""></image>
</view>
</view>
</view>
</view>
<!-- 控制器 -->
<view class="controller w-100 h-100 d-f j-c-c m-t-30">
<view class="controller-box w-100 h-100 d-f f-d-c j-c-c a-i-c">
<!-- 上 UP -->
<view class="up direction-pressed-animation" @click.stop="pressed('up')">
<image class="direction-image" src="/static/up.png"></image>
</view>
<!-- 左(LEFT) 右(RIGHT) -->
<view class="left_right d-f j-c-s-b">
<view class="direction-pressed-animation" @click.stop="pressed('left')">
<image class="direction-image" src="/static/left.png"></image>
</view>
<view class="direction-pressed-animation" @click.stop="pressed('right')">
<image class="direction-image" src="/static/right.png"></image>
</view>
</view>
<!-- 下(DOWN) -->
<view class="down direction-pressed-animation" @click.stop="pressed('down')">
<image class="direction-image" src="/static/down.png"></image>
</view>
</view>
</view>
</view>
css代码
// 通用颜色表
$_text_color_1: #93A3B7;
$_text_color_2: #FFFFFF;
$_text_color_3: #47D392;
$_card_bg1: #2C3948;
$_card_bg2: #222D3A;
$_footer_bg1: #2E3D4E;
$_partition_bg1: #1D2835;
$_font_size_32: 32rpx;
$_font_size_28: 28rpx;
$_font_size_26: 26rpx;
$_font_size_24: 24rpx;
$_font_size_20: 20rpx;
$_font_family_1: PingFangSC-Medium;
$_font_family_2: PingFangSC-Regular;
$_font_weight_500: 500;
$_font_weight_400: 400;
@font-face {
font-family: '汉仪大隶书简';
src: url('@/common/text-family/汉仪大隶书简.TTF');
}
@font-face {
font-family: 'ALIBABA-PUHUITI-HEAVY';
src: url('@/common/text-family/ALIBABA-PUHUITI-HEAVY.OTF');
}
@font-face {
font-family: 'FZZCHJW';
src: url('@/common/text-family/FZZCHJW.TTF');
}
*{
box-sizing: border-box !important;
}
// 顶部标题样式(固定)
@mixin titleStyle {
background-color: $_card_bg2;
font-family: $_font_family_1;
font-size: $_font_size_32;
color: $_text_color_2;
font-weight: $_font_weight_500;
}
// 卡片文字名称
@mixin titleName {
font-family: $_font_family_2;
font-size: $_font_size_20;
color: $_text_color_1;
font-weight: $_font_weight_400;
}
.datetime-picker{
width: 0%;
background-color: $_card_bg1;
position: absolute;
top: 0px;
left: -1000px;
z-index: 999;
}
// ::v-deep .uni-date-editor{
// opacity: 0;
// }
::v-deep .uni-calendar-item--checked{
background-color: $_text_color_3 !important;
}
::v-deep .uni-datetime-picker--btn{
background-color: $_text_color_3 !important;
}
.uni-calendar__content{
background-color: #242d39 !important;
}
.uni-calendar-item__weeks-box-text{
color: #FFFFFF !important;
}
.uni-calendar-item--disable .uni-calendar-item__weeks-box-text-disable{
color: #464646 !important;
}
.uni-calendar-item__weeks-box .uni-calendar-item--checked{
border-radius: 50% !important;
border: none !important;
background-color: #47D392 !important;
}
.uni-date-changed--time-date{
color: #FFFFFF !important;
}
.uni-datetime-picker-text{
color: #FFFFFF !important;
}
.uni-calendar__header-text{
font-size: 35rpx !important;
color: #FFFFFF !important;
}
.uni-calendar__header-btn{
border-left-color: #47D392 !important;
border-top-color: #47D392 !important;
width: 22rpx !important;
height: 22rpx !important;
border-left-width: 4rpx !important;
border-top-width: 4rpx !important;
}
.uni-calendar__weeks-day-text{
color: #FFFFFF !important;
font-size: 30rpx !important;
}
.uni-calendar__weeks-day{
border: none !important;
}
.uni-datetime-picker-btn-text{
font-size: 35rpx !important;
color: #47D392 !important;
// background-color: #242d39 !important;
}
.uni-date-changed{
border: none !important;
}
.uni-calendar__box{
border-bottom: 2rpx solid #435060 !important;
}
.uni-picker-action-confirm{
color: #47D392 !important;
}
// .uni-picker-view-mask{
// background: linear-gradient(180deg, hsla(212, 24%, 23%, 0.95), hsla(212, 24%, 23%, .6)), linear-gradient(0deg, hsla(212, 24%, 23%, .95), hsla(212, 24%, 23%, .6));
// background-position: top, bottom;
// background-size: 100% 102px;
// background-repeat: no-repeat;
// }
.uni-datetime-picker-view{
height: 220px !important;
width: 350px !important;
}
.uni-calendar-item--isDay{
width: 40px !important;
height: 40px !important;
border: 2px solid $_text_color_1 !important;
left: 50% !important;
top: 0px !important;
right: 0px !important;
transform: translateX(-50%);
background-color: rgba(0,0,0,0) !important;
position: absolute;
}
.zp-main-error-btn{
border: none !important;
}
.loading{
width: 100vw;
height: 100vh;
position: absolute;
top: 0rpx;
z-index: 1000 !important;
}
.u-loading-page__warpper{
width: 200rpx;
height: 200rpx;
background-color: rgba(0,0,0,0.5);
border-radius: 15rpx;
}
.uni-calendar__mask{
z-index: 1002 !important;
}
.uni-calendar__content{
z-index: 1003 !important;
}
.u-loading-page__warpper{
margin-top: 0rpx !important;
}
.statusBar{
width: 100%;
height: var(--status-bar-height);
}
.btn-active{
transition: all .1s ease-in-out;
&:active{
opacity: 0.7;
}
}
.btn-active1{
transition: all .1s ease-in-out;
&:active{
opacity: 0.7;
transform: scale(0.98);
}
}
.partition {
width: 100%;
height: 20rpx;
background-color: $_partition_bg1;
}
.w-100{
width: 100% !important;
}
.h-100{
height: 100% !important;
}
.o-y-s{
overflow-y: scroll;
}
.o-y-s-h{}
.o-y-s-h::-webkit-scrollbar {
display: none
}
.o-h{
overflow: hidden;
}
.d-f{
display: flex;
}
.f-d-c{
flex-direction: column;
}
.a-i-c{
align-items: center;
}
.a-i-s{
align-items: flex-start !important;
}
.a-i-e{
align-items: flex-end;
}
.j-c-c{
justify-content: center;
}
.j-c-s-b{
justify-content: space-between;
}
.j-c-s-a{
justify-content: space-around !important;
}
.j-c-f-s{
justify-content: flex-start;
}
.j-c-f-e{
justify-content: flex-end;
}
.f-w-w{
flex-wrap: wrap;
}
.f-1{
flex: 1;
}
.p-10{
padding: 10rpx;
}
.p-20{
padding: 20rpx;
}
.p-30{
padding: 30rpx;
}
.p-l-10{
padding-left: 10rpx;
}
.p-l-20{
padding-left: 20rpx;
}
.p-l-30{
padding-left: 30rpx;
}
.p-r-10{
padding-right: 10rpx;
}
.p-r-20{
padding-right: 20rpx;
}
.p-r-30{
padding-right: 30rpx;
}
.p-b-10{
padding-bottom: 10rpx;
}
.p-b-20{
padding-bottom: 20rpx;
}
.p-b-30{
padding-bottom: 30rpx;
}
.p-t-10{
padding-top: 10rpx;
}
.p-t-20{
padding-top: 20rpx;
}
.p-t-30{
padding-top: 30rpx;
}
.m-r-10{
margin-right: 10rpx;
}
.m-r-20{
margin-right: 20rpx;
}
.m-r-30{
margin-right: 30rpx;
}
.m-l-10{
margin-left: 10rpx;
}
.m-l-20{
margin-left: 20rpx;
}
.m-l-30{
margin-left: 30rpx;
}
.m-t-10{
margin-top: 10rpx;
}
.m-t-20{
margin-top: 20rpx;
}
.m-t-30{
margin-top: 30rpx;
}
.m-b-10{
margin-bottom: 10rpx;
}
.m-b-20{
margin-bottom: 20rpx;
}
.m-b-30{
margin-bottom: 30rpx;
}
.t-a-l{
text-align: left;
}
.t-a-r{
text-align: right;
}
.t-a-c{
text-align: center;
}
.game-content {
.game-main {
width: 680rpx;
// padding: 15rpx;
// background-image: linear-gradient(180deg, #bb0000 1%, #ce0002 100%);
// border-radius: 28rpx;
// border: 6rpx solid #fff9dc;
overflow: hidden;
.game-main-map {
position: relative;
.map-bg {}
.map-samll-b {
color: #000000;
font-size: 15rpx;
overflow: hidden;
}
.character {
transition: all 0.1s ease-in;
position: absolute;
z-index: 1;
transform: scale(1.5);
}
}
}
}
.controller {
.controller-box {
width: 720rpx;
height: 300rpx;
.direction-image {
width: 112rpx;
height: 112rpx;
}
.left_right {
width: 370rpx;
}
}
}
js代码
首先是封装一个js专门管理地图
// 21 * 21地图
// 入口:21 - 2
// 出口:2 - 21
let ZJSX_MAP = {
map1: { // 鼠
intPut: '21-2',
outPut: '2-21',
array: [ // 鼠
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0],
[1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1],
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1],
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1],
[1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
},
}
export {
ZJSX_MAP
}
下面是页面逻辑
<script>
import {
ZJSX_MAP
} from '@/pages/mazeMap.js';
import _ from 'loadsh';
export default {
data() {
return {
isStart: false, // 游戏是否开始
map: [],
character_left: 0, // 当前游戏人物的left值
character_top: 0, // 当前游戏人物的top值
lattice_width: 31, // 地图每一格的宽度 (包括游戏人物) 人物的宽高必须和格子的宽高一致
lattice_height: 31, // 地图每一格的高度 (包括游戏人物) 人物的宽高必须和格子的宽高一致
_step_x: 0, // 当前人物的x坐标也就是left值
_step_y: 0 // 当前人物的y坐标也就是top值
};
},
onLoad() {},
mounted() {
let str = 'map1';
if (ZJSX_MAP[str]) {
const {
intPut,
outPut,
array
} = ZJSX_MAP['map1'];
this.setCharacterPosition(intPut, outPut);
this.map = array;
}
},
methods: {
setCharacterPosition(intPut, outPut) {
// 根据地图的入口初始化人物的位置
this.$nextTick(() => {
this._step_x = intPut.split('-')[0]; // 第几列
this._step_y = intPut.split('-')[1]; // 第几行
this.updateCharacterPosition();
});
},
computedRadius(index, index1, map, item) {
let radiusStr = '';
if (index === 0) {
radiusStr = index1 === 0 ? '5rpx 0rpx 0rpx 0rpx' : index1 === item.length - 1 ? '0rpx 5rpx 0rpx 0rpx' :
'';
} else if (index === map.length - 1) {
radiusStr = index1 === 0 ? '0rpx 0rpx 0rpx 5rpx' : index1 === item.length - 1 ? '0rpx 0rpx 5rpx 0rpx' :
'';
}
return radiusStr;
},
pressed: _.debounce(function(type = '') {
// 得到当前人物的位置信息
let _now_position = {
_step_x: this._step_x,
_step_y: this._step_y
};
// 按下方向健计算
if (type == 'up') {
// up = y 减去 1
this.searchNextStep(_now_position, {
x: 0,
y: -1,
type: 'up'
});
}
if (type == 'left') {
// left = x 减去 1
this.searchNextStep(_now_position, {
x: -1,
y: 0,
type: 'left'
});
}
if (type == 'right') {
// right = x 加上 1
this.searchNextStep(_now_position, {
x: +1,
y: 0,
type: 'right'
});
}
if (type == 'down') {
// up = y 加上 1
this.searchNextStep(_now_position, {
x: 0,
y: +1,
type: 'down'
});
}
}, 200),
searchNextStep({
_step_x,
_step_y
}, {
x,
y,
type
}) {
// 查找下一个盒子的信息
console.log({
x,
y,
type
});
let _next_position = {
x: Number(_step_x) + x,
y: Number(_step_y) + y
};
// _next_position.y 下一个格子是第几行
// _next_position.x 下一个格子是第几列
console.log(_next_position);
// 得到下一个是否为墙壁或者不是墙壁
let _next = this.map[_next_position.y - 1][_next_position.x - 1];
if (_next == 1) {
// 是墙壁 不允许通过
return;
}
if (_next == 0) {
// 可以通过
this._step_x = _next_position.x; // 第几列
this._step_y = _next_position.y; // 第几行
// 更新方位
this.updateCharacterPosition();
}
console.log('得到下一个盒子的方位', _next_position);
},
updateCharacterPosition() {
// 更新人物的位置信息
let _ele_name = `map-samll-b-${this._step_y}-${this._step_x}`;
let _ele = document.getElementsByClassName(_ele_name)[0];
let _ele_offset_x = _ele.offsetLeft;
let _ele_offset_y = _ele.offsetTop;
this.character_left = _ele_offset_x;
this.character_top = _ele_offset_y;
}
}
};
</script>
附上完整代码
<template>
<!-- 拯救生肖 -->
<z-layout :isShowBackView="true" :isShowBackIcon="false" zLayoutBg="/static/c.png" :isShowLogoIcon="false" sologo=""
:sologoWidth="616" :sologoHeight="300">
<template #z-layout-main>
<view class="game-content w-100 d-f f-d-c a-i-c">
<view class="game-main">
<!-- 迷宫图 -->
<view class="game-main-map">
<!-- 控制人物一定用绝对单位 px值 不要用rpx让uniapp去计算 -->
<image v-if="lattice_height >= 0 || character_left >= 0" class="character"
src="@/static/Snipaste_2024-12-16_17-18-31.png"
:style="{ width: lattice_width + 'rpx', height: lattice_height + 'rpx', left: character_left + 'px', top: character_top + 'px' }">
</image>
<view class="map-bg w-100 d-f a-i-c j-c-s-b" v-for="(item, index) in map">
<view class="map-samll-b d-f a-i-c"
:class="[`map-samll-b-${index + 1}-${index1 + 1}`, item1 == 0 ? 'map-samll-b-fideIn-animation' : '']"
:style="{
width: '100%',
height: lattice_height + 'rpx',
background: item1 == 1 ? 'rgb(245, 227, 183)' : '',
animationDelay: item1 == 0 ? `${index1 * 0.03}s` : '',
borderRadius: computedRadius(index, index1, map, item)
}" v-for="(item1, index1) in item">
<image class="w-100 h-100" v-if="item1 == 1" src="@/static/gezi.png" mode=""></image>
</view>
</view>
</view>
</view>
<!-- 控制器 -->
<view class="controller w-100 h-100 d-f j-c-c m-t-30">
<view class="controller-box w-100 h-100 d-f f-d-c j-c-c a-i-c">
<!-- 上 UP -->
<view class="up direction-pressed-animation" @click.stop="pressed('up')">
<image class="direction-image" src="/static/up.png"></image>
</view>
<!-- 左(LEFT) 右(RIGHT) -->
<view class="left_right d-f j-c-s-b">
<view class="direction-pressed-animation" @click.stop="pressed('left')">
<image class="direction-image" src="/static/left.png"></image>
</view>
<view class="direction-pressed-animation" @click.stop="pressed('right')">
<image class="direction-image" src="/static/right.png"></image>
</view>
</view>
<!-- 下(DOWN) -->
<view class="down direction-pressed-animation" @click.stop="pressed('down')">
<image class="direction-image" src="/static/down.png"></image>
</view>
</view>
</view>
</view>
</template>
</z-layout>
</template>
<script>
import {
ZJSX_MAP
} from '@/pages/mazeMap.js';
import _ from 'loadsh';
export default {
data() {
return {
isStart: false, // 游戏是否开始
map: [],
character_left: 0, // 当前游戏人物的left值
character_top: 0, // 当前游戏人物的top值
lattice_width: 31, // 地图每一格的宽度 (包括游戏人物) 人物的宽高必须和格子的宽高一致
lattice_height: 31, // 地图每一格的高度 (包括游戏人物) 人物的宽高必须和格子的宽高一致
_step_x: 0, // 当前人物的x坐标也就是left值
_step_y: 0 // 当前人物的y坐标也就是top值
};
},
onLoad() {},
mounted() {
let str = 'map1';
if (ZJSX_MAP[str]) {
const {
intPut,
outPut,
array
} = ZJSX_MAP['map1'];
this.setCharacterPosition(intPut, outPut);
this.map = array;
}
},
methods: {
setCharacterPosition(intPut, outPut) {
// 根据地图的入口初始化人物的位置
this.$nextTick(() => {
this._step_x = intPut.split('-')[0]; // 第几列
this._step_y = intPut.split('-')[1]; // 第几行
this.updateCharacterPosition();
});
},
computedRadius(index, index1, map, item) {
let radiusStr = '';
if (index === 0) {
radiusStr = index1 === 0 ? '5rpx 0rpx 0rpx 0rpx' : index1 === item.length - 1 ? '0rpx 5rpx 0rpx 0rpx' :
'';
} else if (index === map.length - 1) {
radiusStr = index1 === 0 ? '0rpx 0rpx 0rpx 5rpx' : index1 === item.length - 1 ? '0rpx 0rpx 5rpx 0rpx' :
'';
}
return radiusStr;
},
pressed: _.debounce(function(type = '') {
// 得到当前人物的位置信息
let _now_position = {
_step_x: this._step_x,
_step_y: this._step_y
};
// 按下方向健计算
if (type == 'up') {
// up = y 减去 1
this.searchNextStep(_now_position, {
x: 0,
y: -1,
type: 'up'
});
}
if (type == 'left') {
// left = x 减去 1
this.searchNextStep(_now_position, {
x: -1,
y: 0,
type: 'left'
});
}
if (type == 'right') {
// right = x 加上 1
this.searchNextStep(_now_position, {
x: +1,
y: 0,
type: 'right'
});
}
if (type == 'down') {
// up = y 加上 1
this.searchNextStep(_now_position, {
x: 0,
y: +1,
type: 'down'
});
}
}, 200),
searchNextStep({
_step_x,
_step_y
}, {
x,
y,
type
}) {
// 查找下一个盒子的信息
console.log({
x,
y,
type
});
let _next_position = {
x: Number(_step_x) + x,
y: Number(_step_y) + y
};
// _next_position.y 下一个格子是第几行
// _next_position.x 下一个格子是第几列
console.log(_next_position);
// 得到下一个是否为墙壁或者不是墙壁
let _next = this.map[_next_position.y - 1][_next_position.x - 1];
if (_next == 1) {
// 是墙壁 不允许通过
return;
}
if (_next == 0) {
// 可以通过
this._step_x = _next_position.x; // 第几列
this._step_y = _next_position.y; // 第几行
// 更新方位
this.updateCharacterPosition();
}
console.log('得到下一个盒子的方位', _next_position);
},
updateCharacterPosition() {
// 更新人物的位置信息
let _ele_name = `map-samll-b-${this._step_y}-${this._step_x}`;
let _ele = document.getElementsByClassName(_ele_name)[0];
let _ele_offset_x = _ele.offsetLeft;
let _ele_offset_y = _ele.offsetTop;
this.character_left = _ele_offset_x;
this.character_top = _ele_offset_y;
}
}
};
</script>
<style scoped lang="scss">
.game-content {
.game-main {
width: 680rpx;
// padding: 15rpx;
// background-image: linear-gradient(180deg, #bb0000 1%, #ce0002 100%);
// border-radius: 28rpx;
// border: 6rpx solid #fff9dc;
overflow: hidden;
.game-main-map {
position: relative;
.map-bg {}
.map-samll-b {
color: #000000;
font-size: 15rpx;
overflow: hidden;
}
.character {
transition: all 0.1s ease-in;
position: absolute;
z-index: 1;
transform: scale(1.5);
}
}
}
}
.controller {
.controller-box {
width: 720rpx;
height: 300rpx;
.direction-image {
width: 112rpx;
height: 112rpx;
}
.left_right {
width: 370rpx;
}
}
}
</style>
其中有个z-layout组件
附上代码
<template>
<view class="z-layout o-y-s">
<!-- 背景图 -->
<image class="z-layout-bg w-100" :src="zLayoutBg"></image>
<!-- 顶部占位 -->
<view class="z-layout-empty-top w-100" v-if="isShowBackView"></view>
<view class="z-layout-logo w-100 h-100">
<view class="home-logo w-100 d-f j-c-c a-i-c" v-if="isShowLogoIcon">
<image class="logo btn-active" src="@/static/home_logo_img_bg@3x.png"></image>
</view>
</view>
<!-- 顶部导航栏 -->
<view class="z-layout-nav w-100 d-f j-c-s-b a-i-c" v-if="isShowBackView">
<view class="back-box h-100 d-f j-c-c a-i-c" v-if="isShowBackIcon" @click.stop="backTo">
<image class="back btn-active" src="@/static/back.png" mode="aspectFit" ></image>
</view>
</view>
<!-- 顶部导航栏占位 -->
<view class="z-layout-nav-empty-box w-100" v-if="isShowBackView"></view>
<view class="home d-f f-d-c a-i-c w-100" v-if="isShowSologo">
<view class="home-title-bg d-f j-c-c a-i-c w-100 ele-fideIn">
<image :style="{ width: sologoWidth + 'rpx', height: sologoHeight + 'rpx' }" class="title-bg" :src="sologo"></image>
</view>
<!-- 图片占位 -->
<view class="home-title-bg-empty w-100" :style="{ width: sologoWidth + 'rpx', height: sologoHeight + 'rpx' }"></view>
</view>
<!-- 内容部分 -->
<slot name="z-layout-main"></slot>
<slot></slot>
</view>
</template>
<script>
export default {
name:"z-layout",
props:{
zLayoutBg:{
type: String,
default: '/static/home_img_bg@3x.png'
},
isShowBackView:{
type: Boolean,
default: true
},
isShowBackIcon:{
type: Boolean,
default: true
},
isShowSologo:{
type: Boolean,
default: true
},
isShowLogoIcon:{
type: Boolean,
default: true
},
sologo:{
type: String,
default: '/static/img_home_title@3x.png'
},
sologoWidth:{
type: Number,
default: 720
},
sologoHeight:{
type: Number,
default: 384
},
},
data() {
return {
};
},
methods:{
backTo(){
uni.navigateBack({
delta: 1,
animationType: 'pop-out'
})
}
}
}
</script>
<style scoped lang="scss">
.z-layout{
width: 100vw;
height: 1624rpx;
overflow: hidden;
&-empty-top{
height: 88rpx;
}
&-bg{
position: absolute;
z-index: -10;
height: 1624rpx;
}
&-logo{
position: absolute;
top: 100rpx;
z-index: -9;
.home-logo{
width: 200rpx;
height: 56rpx;
.logo{
width: 200rpx;
height: 63rpx;
}
}
}
&-nav{
position: fixed;
height: 88rpx;
padding: 0rpx 28rpx;
.back-box{
position: absolute;
z-index: 99;
padding: 0rpx 10rpx;
.back{
width: 40rpx;
height: 40rpx;
}
}
}
.z-layout-nav-empty-box{
height: 88rpx;
}
.home{
.home-title-bg{
height: 384rpx;
position: absolute;
z-index: -9;
.title-bg{
width: 720rpx;
height: 384rpx;
}
}
.home-title-bg-empty{
// height: 384rpx;
}
}
}
</style>
全局的scss动画文件
.btn-pressed-animation{
&:active{
animation: btn-pressed .1s forwards ease-in;
}
}
@keyframes btn-pressed {
0%{
opacity: 0.9;
transform: scale(1);
}
100%{
opacity: 1;
transform: scale(0.95);
}
}
.ele-fideIn{
animation: ele-fideIn .3s forwards ease-in-out;
}
@keyframes ele-fideIn {
0%{
opacity: 0;
}
100%{
opacity: 1;
}
}
.ele-fideOut{
animation: ele-fideOut .3s forwards ease-in-out;
}
@keyframes ele-fideOut {
0%{
opacity: 1;
}
100%{
opacity: 0;
}
}
.sign-btn-fideIn-animation{
animation: sign-btn-fideIn .3s forwards ease-in-out;
}
.sign-btn-fideOut-animation{
animation: sign-btn-fideOut 1s forwards ease-in-out;
animation-delay: .2s;
transform-origin: center center;
}
// 立即签到按钮 出场动画
@keyframes sign-btn-fideIn {
0%{
opacity: 0.4;
transform: translateY(10px);
}
100%{
opacity: 1;
transform: translateY(0px);
}
}
// 立即签到按钮 退场动画
@keyframes sign-btn-fideOut {
0%{
opacity: 1;
transform: translateY(0px);
}
70%{
}
100%{
opacity: 0;
transform: translateY(2500rpx) scale(0.1);
}
}
// 抽奖盒子 动画
.Lottery-box-fideIn-animation{
animation: Lottery-box-fideIn .5s forwards ease-in-out;
}
.Lottery-box-fideOut-animation{
animation: Lottery-box-fideOut 0.6s forwards ease-in-out;
animation-delay: .2s;
transform-origin: center center;
}
// 抽奖盒子 出场动画
@keyframes Lottery-box-fideIn {
0%{
opacity: 0.4;
}
100%{
opacity: 1;
}
}
// 抽奖盒子 退场动画
@keyframes Lottery-box-fideOut {
0%{
transform: translateY(0px);
}
100%{
transform: translateY(950rpx) scale(1.261);
}
}
.Lottery-box-card-fideIn-animation{
animation: Lottery-box-card-fideIn ease-in-out .3s forwards;
animation-delay: 0.8s;
}
// 抽奖盒子 卡片出场动画
@keyframes Lottery-box-card-fideIn {
0%{
opacity: 0;
}
60%{
opacity: 0.8;
}
100%{
z-index: -8;
opacity: 1;
transform: translateY(-260rpx);
}
}
.Lottery-box-card-text-fideIn-animation{
animation: Lottery-box-card-text-fideIn ease-in-out .3s forwards;
animation-delay: 1.1s;
}
// 抽奖盒子 卡片出场动画
@keyframes Lottery-box-card-text-fideIn {
0%{
opacity: 0;
}
60%{
opacity: 0.8;
}
100%{
z-index: -8;
opacity: 1;
}
}
// 活动首页
.activity-box-fideIn-animation{
animation: activity-box-fideIn ease-in-out .3s forwards;
animation-delay: 1.2s;
}
// 抽奖盒子 卡片出场动画
@keyframes activity-box-fideIn {
0%{
opacity: 0;
}
60%{
opacity: 0.8;
}
100%{
opacity: 1;
}
}
// 活动首页
.activity-card-fideIn-animation1{
animation: activity-card-fideIn ease-in-out .3s forwards;
animation-delay: 1.3s;
z-index: 1;
}
// 活动首页
.activity-card-fideIn-animation2{
animation: activity-card-fideIn ease-in-out .3s forwards;
animation-delay: 1.6s;
z-index: 2;
}
// 活动首页
.activity-card-fideIn-animation3{
animation: activity-card-fideIn ease-in-out .3s forwards;
animation-delay: 1.8s;
z-index: 3;
}
// 活动首页
.activity-card-fideIn-animation4{
animation: activity-card-fideIn ease-in-out .3s forwards;
animation-delay: 2s;
z-index: 4;
}
// 抽奖盒子 卡片出场动画
@keyframes activity-card-fideIn {
0%{
opacity: 0.8;
}
100%{
opacity: 1;
}
}
// 方向键按下动画
.direction-pressed-animation{
&:active{
animation: direction-pressed ease-in .1s forwards;
}
}
@keyframes direction-pressed {
0%{
transform: scale(1);
}
100%{
transform: scale(0.8);
}
}
// 迷宫路的动画
.map-samll-b-fideIn-animation{
animation: map-samll-b-fideIn ease-in-out .5s forwards;
// animation-delay: 2s;
}
@keyframes map-samll-b-fideIn {
0%{
opacity: 0.5;
background-color: rgb(245, 227, 183);
border-radius: 50%;
transform: scale(1);
}
50%{
transform: scale(2);
}
100%{
background-color: rgba(107, 115, 0, 0.8);
opacity: 1;
transform: scale(1);
border-radius: 0%;
}
}
.xlsbz-card-bg2-box-fideIn{
animation: xlsbz-card-bg2-box-fideIn ease-in-out .3s forwards;
}
// 降龙十八掌 游戏规则动画
@keyframes xlsbz-card-bg2-box-fideIn {
0%{
height: 0rpx;
}
100%{
height: 1020rpx;
}
}
.xlsbz-start-game-fideIn{
animation: xlsbz-start-game-fideIn ease-in-out .3s forwards;
}
// 降龙十八掌 游戏规则动画
@keyframes xlsbz-start-game-fideIn {
0%{
height: 0rpx;
}
100%{
height: 556rpx;
}
}
@keyframes xlsbz-card-fideIn {
0%{
opacity: 0;
z-index: -10;
top: -1000rpx;
left: -1000rpx;
transform: scale(0.1, 0.1);
}
100%{
opacity: 1;
z-index: 0;
top: 0rpx;
left: 0rpx;
transform: scale(1, 1);
}
}
.submit-shadow-fideIn{
animation: submit-shadow-fideIn ease .2s forwards;
animation-delay: 0.5s;
}
@keyframes submit-shadow-fideIn {
0%{
width: 0rpx;
transform: scale(1, 0.8);
}
100%{
opacity: 1;
width: 320rpx;
transform: scale(1, 1);
}
}
.xyqlz-character-box-animation{
animation: xyqlz-character-box-fideIn ease .3s forwards;
transform: left bottom;
}
@keyframes xyqlz-character-box-fideIn {
0%{
width: 0rpx;
opacity: 0;
transform: scale(1, 0.7);
}
100%{
opacity: 1;
width: 320rpx;
left: 0rpx;
transform: scale(1, 1);
}
}
.xyqlz-character-animation{
animation: xyqlz-character-fideIn ease 3.5s infinite;
transform: left bottom;
}
@keyframes xyqlz-character-fideIn {
0%{
filter: drop-shadow(0px 0px 0rpx #fd392b);
}
50%{
filter: drop-shadow(0px 0px 20rpx #09cdff);
}
100%{
filter: drop-shadow(0px 0px 0rpx #fd7915);
}
}