公司有一个新的需求 是需要悬浮球在一侧上下滑动 其实是很简单的 而且网上都有各种案例,但是 偏偏是横屏状态下 ,而且不是手机横屏 是用css强制旋转屏幕90度之后的横屏,所以就会出现坐标系的紊乱,然后我这个功能一开始做成的效果就是触摸上下滑动的时候 ,悬浮球是左右走(目前的这个图片的上下左右),当时非常的苦恼,接下来贴上我的代码,大家可以参考,有问题可以评论指出,谢谢!我先把我的基本布局拿过来,用的js是flexible.js 写的移动端的布局;
因为代码是有一阵子了 我也是从网上找的相关的正常悬浮球的移动的案例 之后再研究的横屏下的悬浮球移动;如涉及侵权,请谅解 或者指出 我会标明出处;感谢配合;

下面的是html
图片那里大家可以自行更换
<body> <div id="example"> <!-- 侧边的悬浮球 --> <div class="sideDown"> <ul class="smallDown"> <img class="suspBall" src="./images/sideDownLogo.png" alt=""> <li class="comeOut"> <p class="Take_back"><img src="./images/putAway.png" alt=""></p> <p class="save_game"> <img src="./images/saveLogo.png" alt=""> <i>保存</i> </p> <p class="down_game"> <img src="./images/downLogo.png" alt=""> <i>下载</i> </p> </li> </ul> </div> </div> </body>
下面的是css 因为我当时写这个的时候是依赖于一个云项目中的SDK 自带的样式 它的样式就是这么强制横屏的 所以我当时为了测试,就自己先写在了自己的样式里面 仅供参考 如有更好的 大家可以尽可能的提出!
#example {
width: 100%;
height: 100%;
position: relative;
/* 这是分割线 以下是为了屏幕旋转成横屏 仅供参考 */
width: 667px;
height: 375px;
left: -146px;
top: 146px;
-moz-transform: rotate(90deg);
-webkit-transform: rotate(90deg);
-o-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
-moz-transform-origin: center center;
-webkit-transform-origin: center center;
-o-transform-origin: center center;
-ms-transform-origin: center center;
transform-origin: center center
}
/* 侧边的悬浮球 */
.sideDown {
width: 1rem;
height: 100%;
position: absolute;
z-index: 444;
right: 0;
display: block;
}
.sideDown ul {
width: 1rem;
height: 1rem;
display: flex;
align-items: center;
position: absolute;
top: 20px;
right: 0;
opacity: 1;
}
.sideDown ul img.suspBall {
display: inline-block;
width: 1rem;
height: 1rem;
z-index: 333;
}
.sideDown li {
position: absolute;
z-index: 222;
right: 0.15rem;
width: 3.3rem;
height: 0.60rem;
background: rgba(255, 230, 0, 1);
border-radius: 0.35rem;
opacity: 0.9;
display: flex;
align-items: center;
}
.sideDown li p {
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin-left: 0.5rem;
}
.sideDown li p img {
display: inline-block;
width: 0.29rem;
height: 0.29rem;
}
.sideDown li p:first-child {
width: 0.2rem;
height: 0.2rem;
margin-left: 0.16rem;
}
.sideDown li p:first-child img {
display: inline-block;
width: 0.2rem;
height: 0.2rem;
}
.sideDown li p:first-child img {
display: inline-block;
width: 0.2rem;
height: 0.2rem;
}
.sideDown li p i {
display: inline-block;
font-size: 0.17rem;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: rgba(51, 51, 51, 1);
}
以下是重点 js代码
<script>
window.onload = function () {
var flag = 0; //标记是拖曳还是点击
var disX, disY;
var targetW = 0;//刚进来的时候悬浮球左边的宽度是正常的;
// 获取元素
var bigBox = document.querySelector(".sideDown");
var sBox = document.querySelector(".smallDown");
var sBoxImg = document.querySelector(".suspBall");
// console.log('获取元素', bigBox, sBox)
// 获取大盒子的大小
var bigbox_w = bigBox.offsetHeight;
var bigbox_h = bigBox.offsetWidth;
// console.log('获取大盒子的大小', bigbox_w, bigbox_h)
// 获取小盒子的大小
var sbox_w = sBox.offsetHeight;
var sbox_h = sBox.offsetWidth ;
// console.log('获取小盒子的大小', sbox_w, sbox_h)
// 获取大盒子的间距
var bigBox_l = bigBox.offsetLeft;
var bigBox_t = bigBox.offsetTop ;
// console.log('获取大盒子的间距', bigBox_l, bigBox_t)
// 小盒子鼠标按下才触发事件
sBoxImg.addEventListener('touchstart', function (ev) {
flag = 0;
ev = ev || window.event;
ev.preventDefault();//阻止触摸时页面的滚动,缩放
// 获取鼠标在盒子中的位置
// 触点位置减去小盒子的间距就是鼠标在小盒子中的位置
disX = bigbox_w - ev.touches[0].pageX - sBox.offsetTop;
disY = ev.touches[0].pageY - bigBox_l;
console.log('获取触点位置', ev.touches[0].pageY, ev.touches[0].pageX)
console.log('小盒子的左和上间距', sBox.offsetLeft, sBox.offsetTop)
console.log('获取鼠标在盒子中的位置', disX, disY)
})
sBoxImg.addEventListener('touchmove', function (e) {
flag = 1;
e = e || window.event;
// 用这次获取到的鼠标的位置减去上次鼠标在小盒子的位置就是小盒子的左和上间距
var moveX = bigbox_w - e.touches[0].pageX - disX;
var moveY = e.touches[0].pageY - disY;
// console.log('移动的时候~~获取触点位置', e.touches[0].pageX, e.touches[0].pageY)
// console.log('获取上次鼠标在盒子中的位置', disX, disY)
// console.log('小盒子的左和上间距', moveX, moveY)
if (moveX < 0) {
moveX = 0;
}
if (moveY < 0) {
moveY = 0;
}
if (moveX > bigbox_w - sbox_w) {
moveX = bigbox_w - sbox_w;
}
if (moveY > bigbox_h - sbox_h) {
moveY = bigbox_h - sbox_h;
}
sBox.style.top = moveX + 'px';
sBox.style.left = moveY + 'px';
})
sBoxImg.addEventListener('touchend', function (e) {
// console.log('结束')
//判断滑动方向
if (flag === 0) {//点击
// console.log('点击了');
if (targetW == 0) {
console.log('收回去了', targetW)
$(".comeOut").animate({ width: '0.3rem', opacity: '0.5', }, 'slow', function () {
targetW = 1; //改变悬浮球左边大小的时候 改变这个值 以便于后面的判断;
})
}
if (targetW == 1) {
console.log('放出来了', targetW)
$(".comeOut").animate({ width: '3.3rem', opacity: '0.9', }, 'slow', function () {
targetW = 0;
})
}
}
});
$(".Take_back").click(function (event) {
console.log('点击箭头', targetW)
$(".comeOut").animate({ width: '0.3rem', opacity: '0.5', }, 'slow', function () {
targetW = 1; //改变悬浮球左边大小的时候 改变这个值 以便于后面的判断;
})
event.stopPropagation()
});
}
</script>
下面进行详细的解说:
var bigbox_w = bigBox.offsetHeight; var bigbox_h = bigBox.offsetWidth;
这两句 按正常的竖屏的话应该是
var bigbox_w = bigBox.offsetWidth; var bigbox_h = bigBox.offsetHeight; offsetWidth 显示的是盒子正常的宽 (也就是你css里面写的宽) offsetHeight 显示的是盒子正常的高 (也就是你css里面写的高)
但是 由于横屏 你的视觉中看到的就是一下左图中 宽 高
这就是需要把 offsetWidth 和 offsetHeight 换一下 才是右图中打印出来的宽高 才是视觉中的宽高;
同理 小盒子的大小(16,17行)也需要换一下,尽管小盒子是一个正方形的 ;[/code]


这个是大盒子的间距; offsetLeft 和 offsetTop 也不是视觉中的left和top
var bigBox_l = bigBox.offsetLeft; var bigBox_t = bigBox.offsetTop ;
此时的大盒子的 offsetTop 为0 我就不在图中标出来了;大家应该明白 就是图中的右边距离;

手机按下事件 这里就不多说了 基本上就是按下(touchstart) 移动(touchmove) 抬起 (touchend)
整体的逻辑 就是按下的时候 记录一下鼠标在小盒子里面的位置
以下就是关键,弄不好鼠标的位置就记录错了,我也是反反复复的想 才想明白;
我会用图向大家解说
disX = bigbox_w - ev.touches[0].pageX - smallBox.offsetTop; disY = ev.touches[0].pageY - bigBox_l;


鼠标按下的值已经记录完毕 然后就是鼠标移动的时候 小球也要跟着动
var moveX = bigbox_w - e.touches[0].pageX - disX; var moveY = e.touches[0].pageY - disY;


最后就是赋值
当然了 临界值的话 比较好判断 这里就不多说了;
smallBox.style.top = moveX + 'px'; smallBox.style.left = moveY + 'px';
这里需要注意的是 小盒子的top值 其实是你最后算出来的moveX 值;left值 就是moveY 值;写了好久了 自己的能力有限 如果有更好的或者可以改进的方式 随时等待大家的评论来指点,谢谢大家;