mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-15 17:31:42 +08:00
206 lines
6.2 KiB
TypeScript
206 lines
6.2 KiB
TypeScript
|
|
|||
|
const throttle = (fn, threshold = 160) => {
|
|||
|
let timeout;
|
|||
|
var start = +new Date;
|
|||
|
return function (...args) {
|
|||
|
let context = this, curTime = +new Date() - 0;
|
|||
|
//总是干掉事件回调
|
|||
|
window.clearTimeout(timeout);
|
|||
|
if (curTime - start >= threshold) {
|
|||
|
//只执行一部分方法,这些方法是在某个时间段内执行一次
|
|||
|
fn.apply(context, args);
|
|||
|
start = curTime;
|
|||
|
}
|
|||
|
else {
|
|||
|
//让方法在脱离事件后也能执行一次
|
|||
|
timeout = window.setTimeout(() => {
|
|||
|
//@ts-ignore
|
|||
|
fn.apply(this, args);
|
|||
|
}, threshold);
|
|||
|
}
|
|||
|
};
|
|||
|
}
|
|||
|
|
|||
|
const eventMap = new Map<HTMLElement, Dragger>();
|
|||
|
|
|||
|
const defaultOptions = {
|
|||
|
inViewport: true
|
|||
|
}
|
|||
|
|
|||
|
class Dragger {
|
|||
|
|
|||
|
private _triggler: HTMLElement = null;
|
|||
|
private _container: HTMLElement = null;
|
|||
|
private _options: any = null;
|
|||
|
private _state: any = null;
|
|||
|
private _isFirst: boolean = true;
|
|||
|
private _style: string = null;
|
|||
|
|
|||
|
constructor(triggler: HTMLElement, container: HTMLElement, dragInViewport: boolean) {
|
|||
|
this._triggler = triggler;
|
|||
|
this._container = container;
|
|||
|
this._options = Object.assign({}, defaultOptions, {
|
|||
|
inViewport: dragInViewport
|
|||
|
});
|
|||
|
this._state = {
|
|||
|
isInDrag: false,
|
|||
|
mX: 0, // mouse x
|
|||
|
mY: 0, // mouse y
|
|||
|
domStartX: 0, // on mousedown, the mouse x
|
|||
|
domStartY: 0, // on mousedown, the mouse y
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
getContainerPos() {
|
|||
|
const rect = this._container.getBoundingClientRect();
|
|||
|
return {
|
|||
|
left: rect.left,
|
|||
|
top: rect.top
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
onMousedown = (e) => {
|
|||
|
const state = this._state;
|
|||
|
state.isInDrag = true;
|
|||
|
state.mX = e.clientX;
|
|||
|
state.mY = e.clientY;
|
|||
|
this._container.style.position = "absolute";
|
|||
|
const { left, top } = this.getContainerPos();
|
|||
|
|
|||
|
if (this._isFirst) {
|
|||
|
|
|||
|
state.domMaxY = document.documentElement.clientHeight
|
|||
|
- this._container.offsetHeight - 1;
|
|||
|
state.domMaxX = document.documentElement.clientWidth
|
|||
|
- this._container.offsetWidth - 1;
|
|||
|
|
|||
|
this._container.style.left = left + 'px';
|
|||
|
this._container.style.top = top + 'px';
|
|||
|
|
|||
|
if (!this._style) {
|
|||
|
this._style = this._container.getAttribute("style");
|
|||
|
}
|
|||
|
|
|||
|
this._isFirst = false;
|
|||
|
}
|
|||
|
|
|||
|
state.domStartX = left;
|
|||
|
state.domStartY = top;
|
|||
|
}
|
|||
|
|
|||
|
onMouseup = (e) => {
|
|||
|
const state = this._state;
|
|||
|
|
|||
|
state.isInDrag = false;
|
|||
|
|
|||
|
const { left, top } = this.getContainerPos();
|
|||
|
state.domStartX = left;
|
|||
|
state.domStartY = top;
|
|||
|
}
|
|||
|
|
|||
|
onMousemove = throttle((e) => {
|
|||
|
const state = this._state;
|
|||
|
if (state.isInDrag) {
|
|||
|
var nowX = e.clientX,
|
|||
|
nowY = e.clientY,
|
|||
|
disX = nowX - state.mX,
|
|||
|
disY = nowY - state.mY;
|
|||
|
|
|||
|
var newDomX = state.domStartX + disX;
|
|||
|
var newDomY = state.domStartY + disY;
|
|||
|
if (this._options.inViewport) {
|
|||
|
if (newDomX < 0) {
|
|||
|
newDomX = 0;
|
|||
|
}
|
|||
|
else if (newDomX > state.domMaxX) {
|
|||
|
newDomX = state.domMaxX;
|
|||
|
}
|
|||
|
if (newDomY < 0) {
|
|||
|
newDomY = 0;
|
|||
|
}
|
|||
|
else if (newDomY > state.domMaxY) {
|
|||
|
newDomY = state.domMaxY;
|
|||
|
}
|
|||
|
}
|
|||
|
this._container.style.position = "absolute";
|
|||
|
this._container.style.margin = "0";
|
|||
|
this._container.style.paddingBottom = "0";
|
|||
|
this._container.style.left = newDomX + "px";
|
|||
|
this._container.style.top = newDomY + "px";
|
|||
|
}
|
|||
|
}, 60).bind(this)
|
|||
|
|
|||
|
onResize = throttle((e) => {
|
|||
|
const state = this._state;
|
|||
|
|
|||
|
state.domMaxY = document.documentElement.clientHeight
|
|||
|
- this._container.offsetHeight - 1;
|
|||
|
state.domMaxX = document.documentElement.clientWidth
|
|||
|
- this._container.offsetWidth - 1;
|
|||
|
state.domStartY = parseInt(this._container.style.top);
|
|||
|
state.domStartX = parseInt(this._container.style.left);
|
|||
|
if (state.domStartY > state.domMaxY) {
|
|||
|
if (state.domMaxY > 0) {
|
|||
|
this._container.style.top = state.domMaxY + "px";
|
|||
|
}
|
|||
|
}
|
|||
|
if (state.domStartX > state.domMaxX) {
|
|||
|
this._container.style.left = state.domMaxX + "px";
|
|||
|
}
|
|||
|
}, 60).bind(this)
|
|||
|
|
|||
|
bindDrag() {
|
|||
|
const triggler = this._triggler;
|
|||
|
const options = this._options;
|
|||
|
|
|||
|
triggler.addEventListener("mousedown", this.onMousedown, false);
|
|||
|
window.addEventListener("mouseup", this.onMouseup, false);
|
|||
|
document.addEventListener("mousemove", this.onMousemove);
|
|||
|
if (options.inViewport) {
|
|||
|
window.addEventListener("resize", this.onResize, false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
unbindDrag() {
|
|||
|
const triggler = this._triggler;
|
|||
|
|
|||
|
triggler.removeEventListener("mousedown", this.onMousedown, false);
|
|||
|
window.removeEventListener("mouseup", this.onMouseup, false);
|
|||
|
document.removeEventListener("mousemove", this.onMousemove);
|
|||
|
if (this._options.inViewport) {
|
|||
|
window.removeEventListener("resize", this.onResize, false);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
resetContainerStyle() {
|
|||
|
if (this._style !== null) {
|
|||
|
this._isFirst = true;
|
|||
|
this._container.setAttribute("style", this._style);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function enableDraggable(triggler: HTMLElement, container: HTMLElement, dragInViewport: boolean = true) {
|
|||
|
let dragger = eventMap.get(triggler);
|
|||
|
if (!dragger) {
|
|||
|
dragger = new Dragger(triggler, container, dragInViewport);
|
|||
|
eventMap.set(triggler, dragger);
|
|||
|
}
|
|||
|
dragger.bindDrag();
|
|||
|
}
|
|||
|
|
|||
|
function disableDraggable(triggler: HTMLElement) {
|
|||
|
const dragger = eventMap.get(triggler);
|
|||
|
if (dragger) {
|
|||
|
dragger.unbindDrag();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
function resetModalPosition(triggler: HTMLElement) {
|
|||
|
const dragger = eventMap.get(triggler);
|
|||
|
if (dragger) {
|
|||
|
dragger.resetContainerStyle();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
export { enableDraggable, disableDraggable, resetModalPosition };
|