Vue3+Vite实训:图片滑块验证
创建项目
使用Vite创建项目:npm create cite my-app
选择vue框架
全局安装yarn:npm install -g yarn
yarn安装依赖
运行:yarn dev
ImgCheck.Vue
完成基本样式
在components创建ImgCheck.Vue
在template中写入页面样式
导入两张图片:大图及拼块图
创建蓝色滑动方块
写css 对整个界面进行润色
完成实现功能
在setup拿到关键信息
引入reactive 声明data 声明初始位置
声明props 传递top 设置类型和默认值 运用.语法可以访问top 在APP.Vue可以let一个top 使服务端随着图片生成的
绑定滑块事件 实现整个滑动验证流程
btnMouseDown:鼠标按下 绑定给方块
添加事件mousemove 执行事件为btnMouseMove 使按下才开始计算滑动
计算出鼠标按下的位置-btn距离窗口的位置=鼠标位置距离btn的边距
引用btnref为鼠标位置距离btn的边距 在data中初始为null 在btn中ref值为btnref
用const将btnref解构为data对象 可以直接得到btnref 可以直接用offset...得到具体属性
data.btnleft=e.pageX - data.btnref.offsetLeft;
btnMouseMove:按着移动 滑动时只要求鼠标没松开 绑定给border-使用生命周期onMounted
按下 才计算滑动
拿到位置 让data.left等于位置
让btn插入一样的style便可一起和拼块图滑动
在onMounted就应该能偶取得data.btnref.offsetLeft 否则会产生回弹 在data初始ImgRef为0 绑定在大图盒子里 并解构出来 onMouted拿到的便是data.btnleft=ImgRef的left属性
在btnMouseMove中就是x = e.pageX - data.offsetLeft - data.btnleft 这也就不会产生回弹
btnMouseUp:鼠标松开 绑定给方块
移除事件 mousemove 松开 停止计算滑动
让控制台显示松开位置 注意取值的边界判断
ImgCheck.Vue代码
<template>
<div class="box">
<h3>拖动下方滑块完成拼图</h3>
<div ref="bgImgref" class="img-box">
<img class="bg" src="../assets/hycdn.jpeg" alt="">
<img class="hd"
src="../assets/hycdn.png"
:style="{left:data.left+'px' ,top:data.top+'px'}"
alt="">
</div>
<div class="btn-box">
<div
ref="btnref"
class="btn"
:style="{left:data.left+'px' }"
@mousedown="btnMouseDown"
@mouseup="btnMouseUp"
>|||</div>
</div>
</div>
</template>
<script setup>
import { reactive,onMounted,toRefs } from 'vue';
let $props=defineProps({
top:{
type:Number,
default:45,
}
});
let $emit = defineEmits(['getPosition'])
const data = reactive({
left:28,
top:$props.top,
btnleft:0,
btnref:null,
offsetLeft:0,
bgImgref:null
});
const{ btnref,bgImgref } = toRefs(data);
onMounted(()=>{
data.offsetLeft = data.bgImgref.offsetLeft;
console.log("onMounted");
document.body.addEventListener("mouseup",btnMouseUp);
})
var btnMouseDown=(e)=>{
// console.log(e);
//计算出鼠标按下位置 pagex-btn距离窗口的位置=鼠标位置距离btn的边距
data.btnleft=e.pageX - data.btnref.offsetLeft;
document.body.addEventListener("mousemove",btnMouseMove);
}
//滑动时只要求鼠标不松开
var btnMouseMove=(e)=>{
// console.log("滑动");
//left=pageX - data.btnref.offsetLeft
let x = e.pageX - data.offsetLeft - data.btnleft
if(x<=0)x=0
else if(x>=285)x=285
data.left = x;
}
var btnMouseUp=(e)=>{
//console.log(data.left);
$emit("getPosition",data.left)
document.body.removeEventListener("mousemove",btnMouseMove)
};
</script>
<style scoped>
html,
body {
width: 100%;
height: 100%;
user-select: none;
}
.box {
width: 340px;
height: 300px;
border: 1px solid #ccc;
margin: 0 auto;
padding: 10px;
}
.img-box {
position: relative;
}
.bg {
width: 100%;
}
.hd {
position: absolute;
height: 68px;
width: 68px;
/* top: 45px; */
left: 26px;
cursor: pointer;
}
.btn-box {
width: 100%;
height: 10px;
border-radius: 5px;
background: #e4e4e4;
margin-top: 15px;
}
.btn {
position: relative;
top: -10px;
left: 26px;
width: 55px;
height: 30px;
text-align: center;
letter-spacing: 5px;
line-height: 30px;
color: #fff;
border-radius: 15px;
background-color: rgb(26, 121, 255);
box-shadow: rgb(26 121 255 / 52%) 0px 0px 10px 1px;
cursor: pointer;
}
</style>
App.Vue
left的值给到服务端 在script中写getPosition得到x值 弹窗“成功”
在ImgCheck的div中注册事件getPosition
在App.Vue利用emit标记一个只可读对象得到getPosition
在松开事件中用emit促发getPosition得到的是data.left
App.Vue代码
<script setup>
// import HelloWorld from './components/HelloWorld.vue'
import ImgCheck from './components/imgCheck.vue'
let top = 45;
const getPosition = (x)=>{
console.log(x,"http");
if(x>=225&&x<=250){
window.alert("成功!");
}
}
</script>
<template>
<!-- <div>
<a href="https://vitejs.dev" target="_blank">
<img src="/vite.svg" class="logo" alt="Vite logo" />
</a>
<a href="https://vuejs.org/" target="_blank">
<img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
</a>
</div> -->
<!-- <HelloWorld msg="Vite + Vue" /> -->
<div><ImgCheck @getPosition= "getPosition" :top="top" /></div>
</template>
<style scoped>
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
filter: drop-shadow(0 0 2em #42b883aa);
}
</style>