效果图:
基本思路
通过监听组件touch事件,来改变组件的left和top的样式
1.首先,touchstart时,拿到组件初始状态时的位置
2.touchmove,实时拿到组件的位置,并修改组件的left和top的值
3.如果要求吸附到旁边,在touchend时,看最后组件的位置是偏向于左边还是右边,如果偏向于左边,left设置为0,否则就是可移动的最大屏幕宽距
代码
drag.js
var template = `
<div id="default_drag_comp"
@touchstart="down"
@touchmove="move"
@touchend="end"
>
<span>拖我移动看看</span>
</div>
`
Vue.component('drag-comp', {
template: template,
data() {
return {
flags: false,
position: {
x: 0,
y: 0
},
nx: "", // 移动后,组件的x轴位置
ny: "",
dx: "", //初始状态时,组件的位置
dy: "",
}
},
props: {
isStiky: Boolean
},
methods: {
// 实现移动端拖拽
down() {
let default_drag_comp = document.querySelector("#default_drag_comp");
this.flags = true;
var touch;
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
console.log(touch.clientX);
console.log(touch.clientY);
this.maxW = document.body.clientWidth - default_drag_comp.offsetWidth;
this.maxH = document.body.clientHeight - default_drag_comp.offsetHeight;
this.position.x = touch.clientX - default_drag_comp.offsetLeft;
this.position.y = touch.clientY - default_drag_comp.offsetTop;
this.dx = touch.clientX;
this.dy = touch.clientY;
},
move(event) {
event.preventDefault();
let default_drag_comp = document.querySelector("#default_drag_comp");
if (this.flags) {
var touch;
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
this.nx = touch.clientX - this.position.x;
this.ny = touch.clientY - this.position.y;
if (this.nx < 0) {
this.nx = 0;
} else if (this.nx > this.maxW) {
this.nx = this.maxW;
}
if (this.ny < 0) {
this.ny = 0;
} else if (this.ny >= this.maxH) {
this.ny = this.maxH;
}
default_drag_comp.style.left = this.nx + "px";
default_drag_comp.style.top = this.ny + "px";
//阻止页面的滑动默认事件;如果碰到滑动问题,1.2 请注意是否获取到 touchmove
document.addEventListener(
"touchmove",
function () {
// event.preventDefault();
},
false
);
}
},
//鼠标释放时候的函数
end() {
let default_drag_comp = document.querySelector("#default_drag_comp");
if (this.isStiky) {
if (this.nx > this.maxW / 2) {
// 右边
this.nx = this.maxW
default_drag_comp.style.left = this.nx + "px";
} else {
// 左边
this.nx = 0
default_drag_comp.style.left = this.nx + "px";
}
}
this.flags = false;
}
}
});
<script src="__static__/common/script/drag.js"></script>
<div id="app">
<div class="area aui-text-center aui-padded-t-15">
<div>是否可吸附至左右两侧</div>
<div style="display: flex; flex-direction: row; align-items: center; justify-content: space-around;margin-top: 20px;">
<div class="btn" :class="isStiky?'active':''" @click="isStiky=true">是</div>
<div class="btn" :class="isStiky?'':'active'" @click="isStiky=false">否</div>
</div>
<drag-comp :is-stiky="isStiky" />
</div>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
isStiky:false
},
methods: {
},
mounted: function () {
}
});
</script>
html,
body,
#app {
height: 100%;
background-color: #ffffff;
}
#default_drag_comp {
width: 56px;
height: 56px;
padding:3px;
border-radius: 50%;
border: 2px solid #ffffff;
box-shadow: 0 0 10px 2px #d3d3d3;
background: #ff9966;
position: fixed;
z-index: 1000;
bottom: 66px;
right: 8px;
display: flex;
justify-content: center;
align-items: center;
}
#default_drag_comp span {
color: #ffffff;
font-size: 12px;
}
.btn{
width: 30%;
padding: 3px 5px;
border: 1px solid;
border-radius: 5px;
}
.active{
color: red;
}