![找茬小游戏,uniapp小程序端+pc端操作静态页_第1张图片](http://img.e-com-net.com/image/info8/2802b95865134051a76db6d062be5e71.jpg)
需求:
做一个类似找茬的答题小程序;
提交后根据坐标返回值在图中标识出点对、点错、未点的茬;
pc端页面也要写一个,用于用户设置点位。
难点:
pc端和小程序端宽高比例的问题;
如何判定是否选对;
干扰项:
选择区域不一定从页面0,0的起始位置,需要根据实际情况减去这部分宽高,例如小程序端减了时间所占的高度。
pc端放了2个div,也减了
后端:
后端需要判定圆与圆之间偏移量多大视为选中,如图所示,xy偏移量为25,这里前端不去做判断,只需要后端给type就行
![找茬小游戏,uniapp小程序端+pc端操作静态页_第2张图片](http://img.e-com-net.com/image/info8/c25d7b5d196241139cd470cffb26b1ba.jpg)
<template>
<view>
<view class="time">
03:12
</view>
<view class="edit" @tap="xy" :style="{'width':trans(pcW)+'px','height':trans(pcH)+'px'}">
<view class="editMask" :style="{'width':trans(pcW)+'px','height':trans(pcH)+'px'}">
<view :class="item.type===1?'green':item.type==2?'red':'yellow'" v-for="(item,idx) in xyArr[index]" :key="idx"
:style="{
'left': (item.x - trans(pcRoundMargin))+'px',
'top':(item.y - trans(pcRoundMargin))+'px',
'width':trans(pcRoundW)+'px',
'height':trans(pcRoundW)+'px',
'border-color':trans(pcBorder)+'px'}">
</view>
</view>
<image :src="imgs[index]" :style="{'height':trans(pcH)+'px'}"></image>
</view>
<view class="operat">
<u-button type="primary" text="上一题" @tap="tapIndex(0)" :disabled="index?false:true" plain
custom-style="width:180rpx"></u-button>
<u-button type="primary" text="下一题" @tap="tapIndex(1)" :disabled="index === total?true:false" plain
custom-style="width:180rpx"></u-button>
<u-button type="primary" text="提交" @tap="submit" custom-style="width:150rpx"></u-button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
timeH: 0, //时间的高度
xyArr: [],//xy的坐标数组
imgs: ['你的图片', '你的图片'],
index: 0, //当前下标
total: 1 ,//总题数
count:0,//(pc可操作窗口宽 - 手机屏宽) / pc可操作窗口宽 = pc每个像素要减的宽度
countApp:0,//(pc可操作窗口宽 - 手机屏宽) / 手机屏宽 = 手机每个像素要减的宽度
time:'',
// type 1【选对】 2【选错】 3【未选】
arr:[[{"x":"176.000","y":"158.000",'type':1},{"x":"649.000","y":"152.000",'type':2},{"x":"153.000","y":"382.000",'type':3}],[{"x":"153.000","y":"382.000",'type':3},{"x":"657.000","y":"377.000",'type':2}]],
pcW:750,//pc端配置项,宽高一致
pcH:450,
pcBorder:4,//线粗
pcRoundW:76,//圆的大小
pcRoundMargin:40//这里xy减30是因为点击起始点为左上角,要减去圆形半径,向上移动
}
},
created() {
},
mounted() {
this.count = (this.pcW - uni.getSystemInfoSync().windowWidth) / this.pcW;//计算pc端和移动端比例
this.countApp = (this.pcW - uni.getSystemInfoSync().windowWidth) / uni.getSystemInfoSync().windowWidth;//计算pc端和移动端比例
this.getXY();
// 距离顶部的高度,用于去除不计算的部分
const query = uni.createSelectorQuery().in(this)
query.select('.time').boundingClientRect(data => {
this.timeH = data.height.toFixed(3);
}).exec();
for(let i = 0;i<=this.total;i++){//给xyArr塞空数组
this.xyArr.push([])
}
},
methods: {
xy(e) {
this.x = e.detail.x.toFixed(3);
this.y = (e.detail.y - this.timeH).toFixed(3);
let x = e.detail.x.toFixed(3);
let y = (e.detail.y - this.timeH).toFixed(3);
this.radius(x, y);
},
radius(x, y) {
this.xyArr[this.index].push({x,y});
},
tapIndex(e) {
if (e) { //下一题
this.index = this.index + 1
} else { //上一题
this.index = this.index - 1
}
},
getXY(){//pc返回值比对
let arr = [];
this.arr.forEach((ele,index)=>{
arr.push([]);
ele.forEach(e=>{
arr[index].push({
x:this.trans(e.x),
y:this.trans(e.y),
type:e.type
})
})
})
this.xyArr = arr;
},
trans(e){//pc转移动的长度
return parseFloat(e - (e * this.count));
},
transApp(e){//将移动端的转成pc端接收的点
return parseFloat(e + (e * this.countApp));
},
submit(){
let arr = [];
this.xyArr.forEach((ele,index)=>{
arr.push([]);
ele.forEach(e=>{
arr[index].push({
x:this.transApp(e.x),
y:this.transApp(e.y)
})
})
})
console.log(JSON.stringify(this.xyArr))
console.log(JSON.stringify(arr))
}
}
}
</script>
<style lang="scss" scoped>
.edit {
// width: 750rpx;
// height: 750rpx;
image {
width: 100%;
height: 100%;
}
.editMask {
// width: 750rpx;
// height: 750rpx;
position: absolute;
z-index: 1;
view {
border-radius: 50%;
// width: 92rpx;
// height: 92rpx;
position: absolute;
}
.red {
border: solid
}
.yellow {
border: solid
}
.green {
border: solid
}
}
}
.time {
text-align: center;
padding: 20rpx;
}
.operat {
padding: 20rpx;
justify-content: space-between;
display: flex;
}
</style>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="这里是vue.js"></script>
</head>
<body>
<div class="app">
<div style="width: 55px;height: 55px;"></div>
<div style="display: flex;">
<div style="width: 55px;height: 55px;"></div>
<div class="edit" @click="xy($event)" ref="edit">
<div class="editMask">
<!--这里xy减30是因为点击起始点为左上角,要减去圆形半径,向上移动-->
<div class="yellow" v-for="(item,idx) in xyArr[index]" :key="idx" :style="{'left':(item.x - 40)+'px','top':(item.y - 40)+'px'}"> </div>
</div>
<image :src="imgs[index]" mode="widthFix"></image>
</div>
</div>
<div class="operat">
<button class="primary" @click="tapIndex(0)" :disabled="index?false:true">
上一题
</button>
<button class="primary" @click="tapIndex(1)" :disabled="index === total?true:false">
下一题
</button>
<button class="primary" @click="submit">
保存
</button>
</div>
</div>
</body>
<script>
new Vue({
el: '.app',
data: {
topH: 0, //距离顶部的高度
leftH: 0, //距离左侧的高度
xyArr: [],
imgs: ['你的图片', '你的图片'],
index: 0, //当前下标
total: 1, //总题数
arr:[[{"x":"176.000","y":"158.000",'type':1},{"x":"136.000","y":"118.000",'type':2},{"x":"649.000","y":"152.000",'type':2},{"x":"153.000","y":"382.000",'type':3}],[{"x":"153.000","y":"382.000",'type':3},{"x":"657.000","y":"377.000",'type':2}]]
},
mounted() {
this.topH = this.$refs.edit.getBoundingClientRect().top - 8;
this.leftH = this.$refs.edit.getBoundingClientRect().left - 8;
for(let i = 0; i <= this.total; i++) { //给xyArr塞空数组
this.xyArr.push([])
}
//this.xyArr = this.arr;
},
methods: {
xy(e) {
let x = (e.x - this.leftH).toFixed(3);
let y = (e.y - this.topH).toFixed(3);
console.log(x)
console.log(y)
this.radius(x, y);
},
radius(x, y) {
this.xyArr[this.index].push({ x, y });
},
tapIndex(e) {
if(e) { //下一题
this.index = this.index + 1
} else { //上一题
this.index = this.index - 1
}
},
submit(){
console.log(this.xyArr)
console.log(JSON.stringify(this.xyArr))
}
}
})
</script>
<style type="text/css">
body{margin: 0;}
.edit {
width: 750px;
height: 450px;
}
.edit img {
width: 100%;
height: 100%;
}
.edit .editMask {
overflow: hidden;
width: 750px;
height: 450px;
position: absolute;
z-index: 1;
}
.edit .editMask div {
border-radius: 50%;
width: 76px;
height: 76px;
position: absolute;
}
.edit .editMask .red {
border: 4px solid
}
.edit .editMask .yellow {
border: 4px solid
}
.edit .editMask .green {
border: 4px solid
}
.time {
text-align: center;
padding: 20px;
}
.operat {
padding: 20px;
justify-content: space-between;
display: flex;
}
.operat .primary{
width: 80px;
}
</style>
</html>