Draggable Elements 요소 드래그 기능 구현 코드

물론 우 리 는 js 라 이브 러 리 의 소스 코드 를 연구 할 수 있 고 스스로 바퀴 를 발명 해 볼 수 있 습 니 다.그 과정 은 매우 재 미 있 습 니 다.다음 페이지 요소 의 드래그 기능 을 실현 하 겠 습 니 다.지금부터 시작 하 겠 습 니 다.맨 위 에 있 는 방법 부터 drag object 를 초기 화 하 는 데 사 용 됩 니 다.방법 에 대한 설명 은 다음 과 같 습 니 다 function DragObject(cfg)여기 cfg 는 하나의 대상 으로 들 어 갑 니 다.Extjs 설정 속성
 
var dragObj = new DragObject({
el: 'exampleB',
attachEl: 'exampleBHandle',
lowerBound: new Position(0, 0), //position , x,y
upperBound: new Position(500, 500),
startCallback: ..., //
moveCallback: ..., //
endCallback: ..., //
attachLater: ... //
});
설정 매개 변수 에서 el 은 구체 적 인 요소 의 id 일 수도 있 고 dom 대상 attach El 이 바로 예 중의 handle 요소 일 수도 있 습 니 다.끌 어 당 겨 서 요 소 를 끌 어 당 깁 니 다.lowerBound 와 upperBound 는 끌 어 당 기 는 범 위 를 제한 하 는 데 사 용 됩 니 다.모두 Position 대상 입 니 다.이 대상 의 패 키 징 과 역할 에 대해 우 리 는 다음 과 같이 분석 할 것 입 니 다.급 하지 않 습 니 다.)들 어 오지 않 으 면 끌 어 당 기 는 범 위 는 제한 이 없습니다.startCallback,moveCallback,endCallback 은 모두 리 셋 함수 입 니 다.attachLater 는 true 또는 false 입 니 다.아래 의 분석 을 잘 모 르 면,나 는 당신 이 곧 알 게 될 것 이 라 고 생각 합 니 다.다음은 Position 을 쓰 겠 습 니 다.코드 는 다음 과 같 습 니 다.
 
function Position(x, y) {
this.X = x;
thix.Y = y;
}
Position.prototype = {
constructor: Position,
add : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X += val.X;
newPos.Y += val.Y;
}
return newPos;
},
subtract : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X -= val.X;
newPos.Y -= val.Y;
}
return newPos;
},
min : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X = this.X > val.X ? val.X : this.X;
newPos.Y = this.Y > val.Y ? val.Y : this.Y;
return newPos;
}
return newPos;
},
max : function(val) {
var newPos = new Position(this.X, this.Y);
if (val) {
newPos.X = this.X < val.X ? val.X : this.X;
newPos.Y = this.Y < val.Y ? val.Y : this.Y;
return newPos;
}
return newPos;
},
bound : function(lower, upper) {
var newPos = this.max(lower);
return newPos.min(upper);
},
check : function() {
var newPos = new Position(this.X, this.Y);
if (isNaN(newPos.X))
newPos.X = 0;
if (isNaN(newPos.Y))
newPos.Y = 0;
return newPos;
},
apply : function(el) {
if(typeof el == 'string')
el = document.getElementById(el);
if(!el) return;
el.style.left = this.X + 'px';
el.style.top = this.Y + 'px';
}
};
하나의 좌표 점 의 간단 한 패 키 징 은 두 개의 값 을 저장 합 니 다.x,y 좌표.우 리 는 add 와 substract 방법 으로 다른 좌표 점 과+연산 과-연산 을 하여 계 산 된 새로운 좌표 점 을 되 돌려 줄 수 있 습 니 다.min 과 max 함 수 는 말 그대로 다른 좌표 점 과 비교 할 수 있 습 니 다.그리고 그 중에서 비교적 작고 큰 값 을 가 르 칩 니 다.bound 방법 은 한 정 된 범위 내 에 있 는 좌표 점 을 되 돌려 줍 니 다.check 방법 은 속성 x,y 의 값 은 숫자 형식 을 확보 하 는 데 사 용 됩 니 다.그렇지 않 으 면 0 을 설정 합 니 다.마지막 으로 apply 방법 은 속성 x,y 를 요소 style.left 와 top 에 작용 하 는 것 입 니 다.이 어 저 는 남 은 대부분의 코드 를 꺼 내 서 다시 한 번 보 겠 습 니 다.
 
function DragObject(cfg) {
var el = cfg.el,
attachEl = cfg.attachEl,
lowerBound = cfg.lowerBound,
upperBound = cfg.upperBound,
startCallback = cfg.startCallback,
moveCallback = cfg.moveCallback,
endCallback = cfg.endCallback,
attachLater = cfg.attachLater;
if(typeof el == 'string')
el = document.getElementById(el);
if(!el) return;
if(lowerBound != undefined && upperBound != undefined) {
var tempPos = lowerBound.min(upperBound);
upperBound = lowerBound.max(upperBound);
lowerBound = tempPos;
}
var cursorStartPos,
elementStartPos,
dragging = false,
listening = false,
disposed = false;
function dragStart(eventObj) {
if(dragging || !listening || disposed) return;
dragging = true;
if(startCallback)
startCallback(eventObj, el);
cursorStartPos = absoluteCursorPosition(eventObj);
elementStartPos = new Position(parseInt(getStyle(el, 'left')), parseInt(getStyle(el, 'top')));
elementStartPos = elementStartPos.check();
hookEvent(document, 'mousemove', dragGo);
hookEvent(document, 'mouseup', dragStopHook);
return cancelEvent(eventObj);
}
function dragGo(e) {
if(!dragging || disposed) return;
var newPos = absoluteCursorPosition(e);
newPos = newPos.add(elementStartPos)
.subtract(cursorStartPos)
.bound(lowerBound, upperBound);
newPos.apply(el);
if(moveCallback)
moveCallback(newPos, el);
return cancelEvent(e);
}
function dragStopHook(e) {
dragStop();
return cancelEvent(e);
}
function dragStop() {
if(!dragging || disposed) return;
unhookEvent(document, 'mousemove', dragGo);
unhookEvent(document, 'mouseup', dragStopHook);
cursorStartPos = null;
elementStartPos = null;
if(endCallback)
endCallback(el);
dragging = false;
}
this.startListening = function() {
if(listening || disposed) return;
listening = true;
hookEvent(attachEl, 'mousedown', dragStart);
};
this.stopListening = function(stopCurrentDragging) {
if(!listening || disposed)
return;
unhookEvent(attachEl, 'mousedown', dragStart);
listening = false;
if(stopCurrentDragging && dragging)
dragStop();
};
this.dispose = function() {
if(disposed) return;
this.stopListening(true);
el = null;
attachEl = null;
lowerBound = null;
upperBound = null;
startCallback = null;
moveCallback = null;
endCallback = null;
disposed = true;
};
this.isDragging = function() {
return dragging;
};
this.isListening = function() {
return listening;
};
this.isDisposed = function() {
return disposed;
};
if(typeof attachEl == 'string')
attachEl = document.getElementById(attachEl);
// , Dom , el
if(!attachEl) attachEl = el;
if(!attachLater)
this.startListening();
}
그 중에서 방법 을 제시 하지 않 았 습 니 다.아래 를 분석 하 는 과정 에서 일일이.........................................................................attach El 이 설정 되 어 있 지 않 거나 해당 요 소 를 찾 지 못 하면 엘 로 대체 합 니 다.드래그 에 사용 할 변 수 를 동시에 설정 하 였 습 니 다.cursor StartPos 는 마 우 스 를 누 르 고 드래그 를 시작 할 때 마우스 의 좌표 점 을 저장 하 는 데 사 용 됩 니 다.element StartPos 는 요소 가 드래그 를 시작 할 때의 시작 점 을 저장 하 는 데 사 용 됩 니 다.dragging,listening,disposed 는 일부 상태 변수 입 니 다.listening:drag object 가 드래그 시작 사건 을 감청 하고 있 는 지 여부 입 니 다.dragging:요소 가 끌 리 고 있 는 지 여부 입 니 다.disposed:drag object 가 정리 되 어 더 이상 끌 릴 수 없습니다.코드 의 마지막 에 attachLater 가 true 가 아니라면 startListening 을 호출 하 는 것 을 보 았 습 니 다.이것 은 public 방법 으로 drag object 에 정의 되 어 있 습 니 다.그것 의 실현
 
this.startListening = function() {
if(listening || disposed) return;
listening = true;
hookEvent(attachEl, 'mousedown', dragStart);
};
앞의 두 줄 은 판단 을 하 는 것 입 니 다.끌 어 당 기 는 사건 을 감청 하거나 정리 하기 시 작 했 으 면 아무것도 하지 않 고 바로 return 합 니 다.그렇지 않 으 면 listening 상 태 를 true 로 설정 하여 감청 을 시작 했다 는 뜻 입 니 다.dragstart 함 수 를 attachEl 의 mousedown 사건 에 연결 합 니 다.여 기 는 hookEvent 함 수 를 만 났 습 니 다.그 모습 을 살 펴 보 겠 습 니 다.
 
function hookEvent(el, eventName, callback) {
if(typeof el == 'string')
el = document.getElementById(el);
if(!el) return;
if(el.addEventListener)
el.addEventListener(eventName, callback, false);
else if (el.attachEvent)
el.attachEvent('on' + eventName, callback);
}
사실 아무것도 아 닙 니 다.바로 요소 사건 의 감청 에 대해 브 라 우 저 를 뛰 어 넘 는 패 키 징 을 했 습 니 다.똑 같은 unhookEvent 방법 은 다음 과 같 습 니 다
 
function unhookEvent(el, eventName, callback) {
if(typeof el == 'string')
el = document.getElementById(el);
if(!el) return;
if(el.removeEventListener)
el.removeEventListener(eventName, callback, false);
else if(el.detachEvent)
el.detachEvent('on' + eventName, callback);
}
.이어서 dragstart 함수 의 실현 을 살 펴 보 겠 습 니 다.이것 은 drag object 의 개인 함수
 
function dragStart(eventObj) {
if(dragging || !listening || disposed) return;
dragging = true;
if(startCallback)
startCallback(eventObj, el);
cursorStartPos = absoluteCursorPosition(eventObj);
elementStartPos = new Position(parseInt(getStyle(el, 'left')), parseInt(getStyle(el, 'top')));
elementStartPos = elementStartPos.check();
hookEvent(document, 'mousemove', dragGo);
hookEvent(document, 'mouseup', dragStopHook);
return cancelEvent(eventObj);
}
attachEl 이 가리 키 는 dom 대상 이 mousedown 사건 을 포착 한 후에 이 함 수 를 호출 합 니 다.우선 drag object 가 끌 기 에 적합 한 상태 에 있 는 지 확인 합 니 다.끌 기 가 진행 되 고 있 거나 끌 기 사건 을 감청 하지 않 았 거나'뒷 일'을 처리 하지 않 았 다 면 아무것도 하지 않 습 니 다.만약 모든 ok,dragging 상 태 를 true 로 설정 하고"시 작 했 습 니 다".startCallback 이 정의 되면 mousedown event 와 el 을 매개 변수 로 호출 합 니 다.이 어 마우스 의 절대 위 치 를 찾 아 cursor StartPos 에 저장 합 니 다.그리고 드래그 요소 의 현재 top,left,Position 대상 으로 봉인 하여 element StartPos 에 저장 합 니 다.보험 은 element StartPos 의 속성 이 합 법 적 인지 확인 합 니 다.두 개의 hookEvent 호출 을 보십시오.하 나 는 mousemove 이벤트 입 니 다.dragging 을 하고 있 음 을 표시 합 니 다.dragging 함 수 를 호출 합 니 다.하 나 는 mouseup 이벤트 입 니 다.드래그 의 끝 을 의미 합 니 다.dragstop Hook 함 수 를 호출 합 니 다.왜 이벤트 가 document 에 연결 되 어 있 는 지 물 어 볼 수 있 습 니 다.끌 어 당 기 는 요소 가 아 닙 니 다.예 를 들 어 우리 가 있 는 엘 이나 attachel.이 벤트 를 요소 에 직접 연결 하 는 것 을 고려 하면 브 라 우 저의 지연 시간 이 효과 에 영향 을 줄 수 있 기 때문에 이 벤트 를 document 에 직접 연결 합 니 다.이해 하지 못 하면 영향 도 크 지 않 을 수 있 습 니 다.P..마지막 말 에서 cancelEvent(eventObj)
 
function cancelEvent(e) {
e = e ? e : window.event;
if(e.stopPropagation)
e.stopPropagation();
if(e.preventDefault)
e.preventDefault();
e.cancelBubble = true;
e.returnValue = false;
return false;
}
를 보면 거품 을 멈 추 는 데 사 용 됩 니 다.기본 이 벤트 를 막 는 것 은 보안 고려 로 이해 할 수 있 습 니 다...dragstart 에서 소개 할 방법 이 있 습 니 다.먼저 absoluteCursor Position 을 살 펴 보고 getStyle
 
function absoluteCursorPosition(e) {
e = e ? e : window.event;
var x = e.clientX + (document.documentElement || document.body).scrollLeft;
var y = e.clientY + (document.documentElement || document.body).scrollTop;
return new Position(x, y);
}
을 보 세 요.이 방법 은 브 라 우 저 에서 마우스 의 절대 위 치 를 얻 는 데 만 사 용 됩 니 다.스크롤 바 를 고려 하면 됩 니 다
 
function getStyle(el, property) {
if(typeof el == 'string')
el = document.getElementById(el);
if(!el || !property) return;
var value = el.style[property];
if(!value) {
if(document.defaultView && document.defaultView.getComputedStyle) {
var css = document.defaultView.getComputedStyle(el, null);
value = css ? css.getPropertyValue(property) : null;
} else if (el.currentStyle) {
value = el.currentStyle[property];
}
}
return value == 'auto' ? '' : value;
}
getStyle 방법 은 요소 의 css 속성 값 을 얻 는 데 사 용 됩 니 다.이렇게 하면 당신 의 스타일 이 내 연 형식 으로 쓰 이 든 css 에 정의 되 든 우 리 는 정확 한 값 을 얻 을 수 있 습 니 다.물론 우 리 는 요소 의 top,left 속성 만 얻 으 면 됩 니 다.아래 에서 끌 어 당 기 는 작업 을 진정 으로 처리 하 는 방법 drag go
 
function dragGo(e) {
if(!dragging || disposed) return;
var newPos = absoluteCursorPosition(e);
newPos = newPos.add(elementStartPos)
.subtract(cursorStartPos)
.bound(lowerBound, upperBound);
newPos.apply(el);
if(moveCallback)
moveCallback(newPos, el);
return cancelEvent(e);
}
방법 은 복잡 하지 않 습 니 다.그의 방법 처럼 우 리 는 먼저 상태 가 어떤 지 살 펴 보 겠 습 니 다.끌 어 당 기거 나 정리 되 지 않 았 다 면.그러면 아무것도 하지 않 습 니 다.만약 모든 것 이 순조롭다 면,우 리 는 마우스 의 현재 위치,요소 의 초기 위치,마우스 의 초기 위치,그리고 제한 범위(upper Bound,lower Bound 를 설정 하면)를 이용 하여 결과 점 을 계산 합 니 다.apply 방법 을 통 해 계 산 된 좌 표를 요소 style.top 과 style.left 에 부여 하여 드래그 요 소 를 그 위 치 를 확인 합 니 다.moveCallback 을 설정 하면,그러면 마지막 으로 cancelEvent 를 호출 합 니 다................................................................................cursor StartPos 와 element StartPos 의 값 을 풀 어 주 고 한 번 끌 기 가 끝 났 습 니 다.endCallback 이 설정 되 어 있 으 면 호출 하고 마지막 으로 dragging 상 태 를 false 로 설정 합 니 다.마지막 으로 사용 할 Public 방법
 
function dragStopHook(e) {
dragStop();
return cancelEvent(e);
}
function dragStop() {
if(!dragging || disposed) return;
unhookEvent(document, 'mousemove', dragGo);
unhookEvent(document, 'mouseup', dragStopHook);
cursorStartPos = null;
elementStartPos = null;
if(endCallback)
endCallback(el);
dragging = false;
}
stopListening 은 감청 끌 기 mousedown 사건 을 제거 하고 감청 상태 listening 을 false 로 설정 합 니 다.여기에 매개 변수 stopCurrentDragging 이 이름 을 알 수 있 습 니 다.dispose 방법 은 처리 작업 에 사 용 됩 니 다.drag object 가 끌 리 지 않 으 려 면 dispose 를 호출 하면 됩 니 다.아래 의 세 가지 작은 방법 인 isDragging,isListening,isDisposed 는 한 번 보면 알 수 있 습 니 다.마지막 으로 소스 의 드 롭 다운 링크다운로드에 원 우 를 환영 하 는 메 시 지 를 남 겨 주 고 교 류 를 합 니 다!

좋은 웹페이지 즐겨찾기