2-8请老师检查下代码,以及一些问题
1,如果不设置定位,X,Y坐标轴原点是HTML页面的左上角点。此时movepoint.x和movepoint.y相当于元素距离整个页面的left和top值,实现不超出边界只需要判断movepoint.x和movepoint.y?
2,如果设置固定定位,然后使用translate3d属性(性能更好)进行移动,因为以自身为原点进行移动+定位后的right、bottom值,向左移动movepoint.x是负值,向上移动movepoint.y是负值,试了下感觉不好判断是否超出边界。该如何实现不超出边界?
3,或者设置定位后使用right和bottom进行移动?会不会更好判断些?
4,实际开发中,像这种移动按钮的使用最多的方案是那种呢?
相关代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.box {
/* position: fixed;
right: 20px;
bottom: 20px; */
width: 40px;
height: 40px;
background-color: red;
-webkit-tap-highlight-color: transparent;
/* transform: translate3d(x,y,0); */
}
body {
background-color: pink;
height: 2000px;
}
</style>
</head>
<body>
<div class="box" id="box"></div>
<script>
const box = document.getElementById('box');
function drag(el, options) {
// 判断传入进来的x,y,如果没传默认x为true,y为false.
options.x = typeof options.x !== 'undefined' ? options.x : true;
options.y = typeof options.y !== 'undefined' ? options.y : false;
// 如果x,y轴都是false,即不允许x,y移动,所以直接返回
if (!options.x && !options.y) return;
// 创建当前位置,开始位置
const curpoint = { x: 0, y: 0 };
const startpoint = {};
// 标志位,本次触摸是否移动,默认是false
let is_touch_move = false;
// 绑定事件处理函数
el.addEventListener('touchstart', handle_start, false);
el.addEventListener('touchmove', handle_move, false);
el.addEventListener('touchend', handle_end, false);
// 触摸开始事件,记录开始位置
function handle_start(event) {
let touch = event.changedTouches[0];
startpoint.x = touch.pageX;
startpoint.y = touch.pageY;
};
// 触摸移动事件
function handle_move(event) {
let touch = event.changedTouches[0];
// 阻止浏览器默认行为(移动滚动条)
event.preventDefault();
// 获取整张页面的宽度、高度,元素的宽度、高度。
const doc_width = document.documentElement.offsetWidth;
const doc_height = document.documentElement.offsetHeight;
const el_width = el.clientWidth || el.getBoundingClientRect().width;
const el_height = el.clientHeight || el.getBoundingClientRect().height;
// const doc_width = window.innerWidth || document.documentElement.clientWidth;
// const doc_height = window.innerHeight || document.documentElement.clientHeight;
// const el_left = el.getBoundingClientRect().left;
// const el_top = el.getBoundingClientRect().top;
// 进行过移动,改变标志位状态
is_touch_move = true;
// 计算差值,为后续移动函数提供数据,因为translate3d以自身为基准点。
let diffpoint = {};
diffpoint.x = touch.pageX - startpoint.x;
diffpoint.y = touch.pageY - startpoint.y;
// 计算移动距离,默认是X,Y都是0
let movepoint = {
x: 0,
y: 0
}
// 如果允许移动,X轴的移动距离为本次差值加上当前位置
if (options.x) {
movepoint.x = diffpoint.x + curpoint.x;
// 判断是否超出边界,movepoint.x相当于元素距离页面的left值
if (movepoint.x <= 0) {
movepoint.x = 0;
} else if (movepoint.x >= doc_width - el_width) {
movepoint.x = doc_width - el_width;
};
}
// 如果允许移动,Y轴的移动距离为本次差值加上当前位置
if (options.y) {
movepoint.y = diffpoint.y + curpoint.y;
// 判断是否超出边界,movepoint.y相当于元素距离页面的top值
if (movepoint.y <= 0) {
movepoint.y = 0;
} else if (movepoint.y >= doc_height - el_height) {
movepoint.y = doc_height - el_height;
};
}
// 调用移动函数,目标进行移动
move(el, movepoint.x, movepoint.y);
};
// 触摸结束事件
function handle_end(event) {
// 判断是否进行过移动,如果没有移动,不需要更新当前位置,直接返回
if (!is_touch_move) return;
let touch = event.changedTouches[0];
// 更新当前位置,当前位置=上次当前位置+本次移动距离(结束位置-开始位置)
curpoint.x += touch.pageX - startpoint.x;
curpoint.y += touch.pageY - startpoint.y;
// 更新完位置后,改变标志位状态
is_touch_move = false;
};
// 使用translate3d使目标移动,translate3d是以自身为基准点
function move(el, x = 0, y = 0) {
el.style.transform = `translate3d(${x}px,${y}px,0)`;
}
}
drag(box, { x: true, y: true });
</script>
</body>
</html>
正在回答
同学你好,代码实现效果没问题。关于同学的疑问解答如下:
1、如果不设置定位,X、Y坐标轴原点是HTML页面的左上角点。
代码中定义的movepoint.x和movepoint.y,计算的就是当前移动元素的原点距离HTML页面原点的left和top值,所以实现不超出边界只需要判断movepoint.x和movepoint.y即可。
2、设置固定定位,然后使用right和bottom进行移动,或者使用translate3d属性进行移动,这是元素进行移动的两种方式,只需要选择其中一种即可,不建议一起使用,计算起来会很麻烦。
3、可以通过定位之后,再使用right和bottom进行移动,此时就不要再使用translate3d属性,二者选其一,此时判断边界的思路与使用translate3d属性是一样的,只要保证right和bottom值在边界范围内即可
4、实际开发中,建议根据项目需求选择定位或者translate3d属性,这两种方案都比较常用。
祝学习愉快!
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星