记录一段实现可拖拽、可自动吸附到边界的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<style>
body {
overflow: hidden;
}
#pane {
position: absolute;
width: 45%;
height: 45%;
top: 20%;
left: 20%;
margin: 0;
padding: 0;
z-index: 99;
border: 2px solid purple;
background: #fefefe;
}
#title {
font-family: monospace;
background: purple;
color: white;
font-size: 16px;
height: 22px;
text-align: center;
}
#ghostpane {
background: #999;
opacity: 0.2;
width: 45%;
height: 45%;
top: 20%;
left: 20%;
position: absolute;
margin: 0;
padding: 0;
z-index: 98;
-webkit-transition: all 0.25s ease-in-out;
-moz-transition: all 0.25s ease-in-out;
-ms-transition: all 0.25s ease-in-out;
-o-transition: all 0.25s ease-in-out;
transition: all 0.25s ease-in-out;
}
</style>
<title>测试div可拖拽</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<div>
这里是测试文本
</div>
<div id="pane">
<div id="title">属性配置</div>
</div>
<div id="ghostpane"></div>
<script>
// Minimum resizable area
var minWidth = 400;
var minHeight = 200;
// Thresholds
var FULLSCREEN_MARGINS = -10;
var MARGINS = 4;
// End of what's configurable.
var clicked = null;
var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
var rightScreenEdge, bottomScreenEdge;
var preSnapped;
var b, x, y;
var redraw = false;
var pane = document.getElementById('pane');
var ghostpane = document.getElementById('ghostpane');
function setBounds(element, x, y, w, h) {
element.style.left = x + 'px';
element.style.top = y + 'px';
element.style.width = w + 'px';
element.style.height = h + 'px';
}
function hintHide() {
setBounds(ghostpane, b.left, b.top, b.width, b.height);
ghostpane.style.opacity = 0;
}
// Mouse events
pane.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
// Touch events
pane.addEventListener('touchstart', onTouchDown);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', onTouchEnd);
function onTouchDown(e) {
onDown(e.touches[0]);
e.preventDefault();
}
function onTouchMove(e) {
onMove(e.touches[0]);
}
function onTouchEnd(e) {
if (e.touches.length === 0) onUp(e.changedTouches[0]);
}
function onMouseDown(e) {
onDown(e);
e.preventDefault();
}
function onDown(e) {
calc(e);
var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;
clicked = {
x: x,
y: y,
cx: e.clientX,
cy: e.clientY,
w: b.width,
h: b.height,
isResizing: isResizing,
isMoving: !isResizing && canMove(),
onTopEdge: onTopEdge,
onLeftEdge: onLeftEdge,
onRightEdge: onRightEdge,
onBottomEdge: onBottomEdge
};
}
function canMove() {
return x > 0 && x < b.width && y > 0 && y < b.height && y < 30;
}
function calc(e) {
b = pane.getBoundingClientRect();
x = e.clientX - b.left;
y = e.clientY - b.top;
onTopEdge = y < MARGINS;
onLeftEdge = x < MARGINS;
onRightEdge = x >= b.width - MARGINS;
onBottomEdge = y >= b.height - MARGINS;
rightScreenEdge = window.innerWidth - MARGINS;
bottomScreenEdge = window.innerHeight - MARGINS;
}
let e;
function onMove(ee) {
calc(ee);
e = ee;
redraw = true;
}
function animate() {
requestAnimationFrame(animate);
if (!redraw) return;
redraw = false;
if (clicked && clicked.isResizing) {
if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';
if (clicked.onLeftEdge) {
var currentWidth = Math.max(clicked.cx - e.clientX + clicked.w, minWidth);
if (currentWidth > minWidth) {
pane.style.width = currentWidth + 'px';
pane.style.left = e.clientX + 'px';
}
}
if (clicked.onTopEdge) {
var currentHeight = Math.max(clicked.cy - e.clientY + clicked.h, minHeight);
if (currentHeight > minHeight) {
pane.style.height = currentHeight + 'px';
pane.style.top = e.clientY + 'px';
}
}
hintHide();
return;
}
if (clicked && clicked.isMoving) {
if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
// hintFull();
setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.top < MARGINS) {
// hintTop();
setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight / 2);
ghostpane.style.opacity = 0.2;
} else if (b.left < MARGINS) {
// hintLeft();
setBounds(ghostpane, 0, 0, window.innerWidth / 2, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.right > rightScreenEdge) {
// hintRight();
setBounds(ghostpane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.bottom > bottomScreenEdge) {
// hintBottom();
setBounds(ghostpane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
ghostpane.style.opacity = 0.2;
} else {
hintHide();
}
if (preSnapped) {
setBounds(pane,
e.clientX - preSnapped.width / 2,
e.clientY - Math.min(clicked.y, preSnapped.height),
preSnapped.width,
preSnapped.height
);
return;
}
// moving
pane.style.top = (e.clientY - clicked.y) + 'px';
pane.style.left = (e.clientX - clicked.x) + 'px';
return;
}
// This code executes when mouse moves without clicking
// style cursor
if (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge) {
pane.style.cursor = 'nwse-resize';
} else if (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge) {
pane.style.cursor = 'nesw-resize';
} else if (onRightEdge || onLeftEdge) {
pane.style.cursor = 'ew-resize';
} else if (onBottomEdge || onTopEdge) {
pane.style.cursor = 'ns-resize';
} else if (canMove()) {
pane.style.cursor = 'move';
} else {
pane.style.cursor = 'default';
}
}
animate();
function onUp(e) {
calc(e);
if (clicked && clicked.isMoving) {
// Snap
var snapped = {
width: b.width,
height: b.height
};
if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
// hintFull();
setBounds(pane, 0, 0, window.innerWidth, window.innerHeight);
preSnapped = snapped;
} else if (b.top < MARGINS) {
// hintTop();
setBounds(pane, 0, 0, window.innerWidth, window.innerHeight / 2);
preSnapped = snapped;
} else if (b.left < MARGINS) {
// hintLeft();
setBounds(pane, 0, 0, window.innerWidth / 2, window.innerHeight);
preSnapped = snapped;
} else if (b.right > rightScreenEdge) {
// hintRight();
setBounds(pane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
preSnapped = snapped;
} else if (b.bottom > bottomScreenEdge) {
// hintBottom();
setBounds(pane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
preSnapped = snapped;
} else {
preSnapped = null;
}
hintHide();
}
clicked = null;
}
</script>
</body>
</html>
效果展示:
吸附效果:
结语
不得不说css和js用的好的话是可以实现很多好玩的功能的,只是我自己对这俩用的还没那么精通。
看到这个好玩的代码就赶紧记录下来,希望能帮助到需要的人吧。