자바 스 크 립 트 대상 실전 패키지 드래그 대상
15938 단어 대상 을 향 하 다끌다포장 하 다
여러분 이 더 많은 방식 을 이해 하고 비교 할 수 있 도록 저 는 세 가지 다른 방식 으로 끌 어 당 길 것 입 니 다.
1.DOM 요 소 를 어떻게 움 직 입 니까?
우 리 는 항상 요소 의 top,left,translate 를 통 해 그 위치 가 달라 집 니 다.다음 예 에서 단 추 를 한 번 누 를 때마다 해당 요 소 는 5px 를 이동 합 니 다.모두 클릭 하여 볼 수 있 습 니 다.
원 소 를 움 직 이 는 작은 예 를 보 려 면 누 르 십시오.
하나의 요소 top/left 값 을 수정 하면 페이지 를 다시 그 릴 수 있 지만 translate 는 할 수 없 기 때문에 성능 최적화 로 판단 하여 저 희 는 translate 속성 을 우선 사용 할 것 입 니 다.
2.현재 브 라 우 저 에서 지원 하 는 transform 호 환 쓰기 방법 을 어떻게 가 져 옵 니까?
transform 은 css 3 의 속성 입 니 다.우리 가 그것 을 사용 할 때 호환성 문제 에 직면 해 야 합 니 다.서로 다른 버 전의 브 라 우 저의 호 환 쓰기 방법 은 크게 다음 과 같은 몇 가지 가 있 습 니 다.
['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform']
따라서 현재 브 라 우 저 환경 이 지원 하 는 transform 속성 이 어떤 것 인지 판단 해 야 합 니 다.방법 은 다음 과 같 습 니 다.
// transform
function getTransform() {
var transform = '',
divStyle = document.createElement('div').style,
// ,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
i = 0,
len = transformArr.length;
for(; i < len; i++) {
if(transformArr[i] in divStyle) {
// ,
return transform = transformArr[i];
}
}
// ,
return transform;
}
이 방법 은 브 라 우 저가 지원 하 는 transform 속성 을 가 져 오 는 데 사 용 됩 니 다.빈 문자열 로 되 돌아 오 면 현재 브 라 우 저 는 transform 을 지원 하지 않 습 니 다.이 럴 때 우 리 는 left,top 값 을 사용 하여 요소 의 위 치 를 바 꿔 야 합 니 다.지원 하면 transform 의 값 을 바 꿉 니 다.3.요소 의 초기 위 치 를 어떻게 가 져 옵 니까?
우 리 는 먼저 목표 요소 의 초기 위 치 를 가 져 와 야 하기 때문에 요소 스타일 을 가 져 오 는 기능 함수 가 필요 합 니 다.
그러나 IE 브 라 우 저 에서 요소 스타일 을 가 져 오 는 것 은 다른 브 라 우 저 와 다 르 기 때문에 호환성 있 는 쓰기 가 필요 합 니 다.
function getStyle(elem, property) {
// ie currentStyle , getComputedStyle
return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elem, false)[property] : elem.currentStyle[property];
}
이 방법 이 있 으 면 목표 요소 의 초기 위 치 를 얻 는 방법 을 쓰기 시작 할 수 있다.
function getTargetPos(elem) {
var pos = {x: 0, y: 0};
var transform = getTransform();
if(transform) {
var transformValue = getStyle(elem, transform);
if(transformValue == 'none') {
elem.style[transform] = 'translate(0, 0)';
return pos;
} else {
var temp = transformValue.match(/-?\d+/g);
return pos = {
x: parseInt(temp[4].trim()),
y: parseInt(temp[5].trim())
}
}
} else {
if(getStyle(elem, 'position') == 'static') {
elem.style.position = 'relative';
return pos;
} else {
var x = parseInt(getStyle(elem, 'left') ? getStyle(elem, 'left') : 0);
var y = parseInt(getStyle(elem, 'top') ? getStyle(elem, 'top') : 0);
return pos = {
x: x,
y: y
}
}
}
}
끌 어 당 기 는 과정 에서 우 리 는 목표 요소 의 새로운 위 치 를 끊임없이 설정 해 야 이동 할 수 있 기 때문에 목표 요소 의 위 치 를 설정 하 는 방법 이 필요 합 니 다.
// pos = { x: 200, y: 100 }
function setTargetPos(elem, pos) {
var transform = getTransform();
if(transform) {
elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)';
} else {
elem.style.left = pos.x + 'px';
elem.style.top = pos.y + 'px';
}
return elem;
}
5.우 리 는 어떤 사건 을 사용 해 야 합 니까?pc 의 브 라 우 저 에서 mousedown,mousemove,mouseup 세 가지 사건 을 결합 하면 끌 어 당 기 는 데 도움 이 됩 니 다.
마우스 다운 을 눌 렀 을 때 발동
우리 가 요 소 를 이 이벤트 에 연결 할 때 하나의 이벤트 대상 은 매개 변수 로 리 셋 함수 에 전 달 됩 니 다.이벤트 대상 을 통 해 우 리 는 현재 마우스 의 정확 한 위 치 를 얻 을 수 있 습 니 다.마우스 위치 정 보 는 드래그 를 실현 하 는 관건 입 니 다.
사건 대상 은 매우 중요 합 니 다.그 중에서 매우 많은 유용 한 정 보 를 포함 하고 있 습 니 다.여 기 는 제 가 확장 하지 않 겠 습 니 다.여러분 은 함수 에서 사건 대상 을 인쇄 하여 그 중의 구체 적 인 속성 을 볼 수 있 습 니 다.이 방법 은 사건 대상 의 중요 한 속성 을 기억 하지 못 하 는 어린이 신발 에 매우 유용 합 니 다.
6.끌 어 당 기 는 원리
이벤트 가 실 행 될 때,우 리 는 이벤트 대상 을 통 해 마우스 의 정확 한 위 치 를 얻 을 수 있 습 니 다.이것 은 드래그 를 실현 하 는 관건 이다.마우스 가(mousedown 트리거)를 눌 렀 을 때 우 리 는 마우스 의 초기 위치 와 목표 요소 의 초기 위 치 를 기억 해 야 한다.우리 의 목 표 는 마우스 가 이동 할 때 목표 요소 도 따라 이동 하 는 것 이다.상식 적 으로 우 리 는 다음 과 같은 관 계 를 얻 을 수 있다.
이동 한 마우스 위치-마우스 초기 위치=이동 한 대상 요소 위치-대상 요소 의 초기 위치
마우스 위치의 차 이 를 dis 로 표시 하면 대상 요소 의 위 치 는 다음 과 같 습 니 다.
이동 후 대상 요소 의 위치=dis+대상 요소 의 초기 위치
이벤트 대상 을 통 해 우 리 는 마우스 의 현재 위 치 를 정확하게 알 수 있 기 때문에 마우스 가 드래그(mousemove)할 때 마우스 가 이동 하 는 차 이 를 끊임없이 계산 하여 목표 요소 의 현재 위 치 를 구 할 수 있 습 니 다.이 과정 은 드래그 를 실현 했다.
마우스 가 풀 리 고 끌 기 를 끝 낼 때 우 리 는 마무리 작업 을 처리 해 야 한다.자세 한 내용 은 코드 참조.
7.저 는 또 사고 지도 보조 코드 를 추천 하 러 왔 습 니 다.
항상 새로운 친구 들 이 달 려 와 서 나 에 게 논리 적 사고력 이 강하 지 않 으 면 코드 를 써 서 전단 지 를 만 들 수 있 느 냐 고 묻는다.나의 답 은:네.사유 도 를 빌려 논리의 단점 을 쉽게 보완 할 수 있 기 때문이다.그리고 자신의 머 릿 속 에 있 는 뇌 보 논리 보다 훨씬 뚜렷 하고 실수 하기 쉽다.
위의 여섯 번 째 점 에서 저 는 원 리 를 소 개 했 기 때문에 어떻게 하 는 것 이 그리 어렵 지 않 습 니 다.구체 적 인 절 차 는 아래 의 사고 지도 에서 명확 하 게 제 시 했 습 니 다.우 리 는 이 절차 에 따라 코드 를 쓰 면 됩 니 다.해 보 세 요.아주 쉬 울 것 입 니 다.
사고 지도 로 끌 어 당 기 는 과정 에서 우리 가 해 야 할 일 을 분명하게 표현 하 다.
8.코드 구현
준비 작업
//
var oElem = document.getElementById('target');
// 2 x,y
var startX = 0;
var startY = 0;
// 2 x,y
var sourceX = 0;
var sourceY = 0;
기능 함수이전에 이미 코드 를 붙 였 기 때문에,다시 반복 하지 않 는 다.
// transform
function getTransform() {}
//
function getStyle(elem, property) {}
//
function getTargetPos(elem) {}
//
function setTargetPos(elem, potions) {}
part 3、세 이벤트 의 리 셋 함수 설명이 세 가지 방법 은 바로 끌 어 당 기 는 핵심 을 실현 하 는 것 이다.나 는 위의 사고 지도 중의 절차 에 따라 우리 의 코드 를 엄 격 히 완성 할 것 이다.
// mousedown ,event
function start(event) {
//
startX = event.pageX;
startY = event.pageY;
//
var pos = getTargetPos(oElem);
sourceX = pos.x;
sourceY = pos.y;
//
document.addEventListener('mousemove', move, false);
document.addEventListener('mouseup', end, false);
}
function move(event) {
//
var currentX = event.pageX;
var currentY = event.pageY;
//
var distanceX = currentX - startX;
var distanceY = currentY - startY;
//
setTargetPos(oElem, {
x: (sourceX + distanceX).toFixed(),
y: (sourceY + distanceY).toFixed()
})
}
function end(event) {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', end);
// do other things
}
OK,간단하게 끌 어 당 겨 서 이렇게 즐겁게 이 루어 졌 습 니 다.아래 링크 를 클릭 하면 온라인 으로 이 예 의 demo 를 볼 수 있 습 니 다.원생 js 로 드래그
9.패키지 드래그 대상
우 리 는 위 에서 이 루어 진 드래그 를 드래그 대상 으로 봉 했다.끌 어 당 기 는 인 스 턴 스 를 설명 하면 들 어 오 는 목표 요 소 는 자동 으로 끌 어 당 길 수 있 는 기능 을 갖 추 는 것 이 목표 입 니 다.
실제 개발 에서 한 대상 을 우 리 는 항상 하나의 js 파일 에 단독으로 놓는다.이 js 파일 은 하나의 모듈 로 서 각종 모듈 의 방식 을 이용 하여 조직 하여 사용 할 것 이다.물론 여기 에는 복잡 한 모듈 의 상호작용 이 없다.왜냐하면 이 예 때문에 우 리 는 하나의 모듈 만 있 으 면 된다.
변수 오염 을 피하 기 위해 서 우 리 는 모듈 을 함수 자체 실행 방식 으로 모 의 한 블록 급 역할 영역 에 배치 해 야 합 니 다.
(function() {
...
})();
일반적인 모듈 조직 에서 우 리 는 단지 많은 js 파일 을 하나의 js 파일 로 압축 했 을 뿐 이 므 로 이곳 의 첫 번 째 분 호 는 이전 모듈 의 끝 에 분 호 를 사용 하지 않 아 오 류 를 보고 하 는 것 을 방지 하기 위해 서 이다.없어 서 는 안 된다.물론 require 나 ES6 모듈 등 을 통 해 이런 상황 은 일어나 지 않 는 다.우 리 는 한 대상 을 봉인 할 때,우 리 는 속성 과 방법 을 구조 함수 나 원형 에 놓 을 수 있 고,실행 함 수 를 증가 한 후에,우 리 는 속성 과 방법 을 모듈 의 내부 작용 역 과 방지 할 수 있다 는 것 을 안다.이것 은 폐쇄 적 인 지식 이다.
그렇다면 우리 가 직면 한 도전 은 속성 과 방법의 위 치 를 어떻게 합 리 적 으로 처리 하 느 냐 에 있다.
물론 모든 대상 의 상황 이 다 르 기 때문에 일률적으로 논 할 수 없다.우 리 는 이 세 가지 위치의 특성 을 분명하게 알 아야 가장 적합 한 결정 을 내 릴 수 있다.
4.567917.구조 함수 에서 속성 과 방법 은 현재 인 스 턴 스 를 단독으로 가지 고 현재 인 스 턴 스 에 만 접근 할 수 있 으 며 하나의 인 스 턴 스 를 설명 할 때마다 그 방법 은 다시 만 들 수 있 습 니 다4.567917.원형 에서 속성 과 방법 은 모든 인 스 턴 스 가 공동으로 가지 고 있 으 며 모든 인 스 턴 스 에 접근 할 수 있 습 니 다.새로운 성명 인 스 턴 스 는 생 성 방법 을 반복 하지 않 습 니 다4.567917.모듈 역할 영역 에서 속성 과 방법 은 인 스 턴 스 에 접근 할 수 없 지만 내부 방법 에 접근 할 수 있 습 니 다.새로운 성명 의 인 스 턴 스 는 같은 방법 을 반복 하지 않 습 니 다방법 에 대한 판단 은 비교적 간단 하 다.
구조 함수 에서 의 방법 은 항상 새로운 인 스 턴 스 를 설명 할 때 중복 되 기 때문에 우리 가 설명 하 는 방법 은 구조 함수 에 나타 나 지 않도록 합 니 다.
만약 당신 의 방법 에 구조 함수 의 변 수 를 사용 하거나 공개 하려 면 원형 에 넣 어야 합 니 다.
방법 이 외부 에 접근 하지 않 고 개인 적 으로 필요 하 다 면 모듈 역할 영역 에 두 세 요.
속성 이 어떤 위치 에 놓 여 있 는 지 에 대해 정확 한 판단 을 하기 어 려 울 때 가 있 기 때문에 저 는 정확 한 정 의 를 내 려 어떤 속성 이 반드시 어떤 위치 에 놓 여야 하 는 지 알려 드 리 기 어렵 습 니 다.이것 은 실제 개발 에서 끊임없이 경험 을 정리 해 야 합 니 다.그러나 전반적 으로 이 세 위치의 특성 을 결합 해 가장 적절 한 판단 을 내 려 야 한다.
만약 에 속성 값 이 인 스 턴 스 에 의 해 단독으로 만 가 질 수 있다 면,예 를 들 어 person 대상 의 name 은 특정한 person 인 스 턴 스 에 속 할 수 있 습 니 다.예 를 들 어 여기 서 끌 어 당 기 는 대상 에서 특정한 요소 의 초기 위치 도 이 요소 의 현재 위치 일 뿐 입 니 다.이 속성 은 구조 함수 에 적합 합 니 다.
만약 에 하나의 속성 이 내부 방법 으로 만 접근 할 수 있다 면 이 속성 은 모듈 역할 영역 에 넣 기 에 적합 합 니 다.
대상 을 향 한 위의 몇 가지 생각 에 대해 나 는 이 글 이 가장 진지 하 게 생각 할 만 한 정수 라 고 생각한다.포장 할 때 생각 을 잘 하지 못 하면 예상 치 못 한 bug 를 많이 만 날 수 있 으 므 로 개발 경험 과 결합 하여 생각 을 많이 하고 자신의 관점 을 정리 하 는 것 을 권장 합 니 다.
이런 생각 에 따라 여러분 스스로 포장 을 시도 해 보 세 요.그리고 나 서 나의 생각 과 비교 해서 우리 의 생각 이 어떤 차이 가 있 는 지 보 자.다음 사례 의 주석 에서 나 는 자신의 생각 을 표현 했다.
봉 인 된 데모 보기 클릭
js 소스 코드
(function() {
// ,
var transform = getTransform();
function Drag(selector) {
// ,
this.elem = typeof selector == 'Object' ? selector : document.getElementById(selector);
this.startX = 0;
this.startY = 0;
this.sourceX = 0;
this.sourceY = 0;
this.init();
}
//
Drag.prototype = {
constructor: Drag,
init: function() {
//
this.setDrag();
},
// , , getName
getStyle: function(property) {
return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(this.elem, false)[property] : this.elem.currentStyle[property];
},
// ,
getPosition: function() {
var pos = {x: 0, y: 0};
if(transform) {
var transformValue = this.getStyle(transform);
if(transformValue == 'none') {
this.elem.style[transform] = 'translate(0, 0)';
} else {
var temp = transformValue.match(/-?\d+/g);
pos = {
x: parseInt(temp[4].trim()),
y: parseInt(temp[5].trim())
}
}
} else {
if(this.getStyle('position') == 'static') {
this.elem.style.position = 'relative';
} else {
pos = {
x: parseInt(this.getStyle('left') ? this.getStyle('left') : 0),
y: parseInt(this.getStyle('top') ? this.getStyle('top') : 0)
}
}
}
return pos;
},
//
setPostion: function(pos) {
if(transform) {
this.elem.style[transform] = 'translate('+ pos.x +'px, '+ pos.y +'px)';
} else {
this.elem.style.left = pos.x + 'px';
this.elem.style.top = pos.y + 'px';
}
},
//
setDrag: function() {
var self = this;
this.elem.addEventListener('mousedown', start, false);
function start(event) {
self.startX = event.pageX;
self.startY = event.pageY;
var pos = self.getPosition();
self.sourceX = pos.x;
self.sourceY = pos.y;
document.addEventListener('mousemove', move, false);
document.addEventListener('mouseup', end, false);
}
function move(event) {
var currentX = event.pageX;
var currentY = event.pageY;
var distanceX = currentX - self.startX;
var distanceY = currentY - self.startY;
self.setPostion({
x: (self.sourceX + distanceX).toFixed(),
y: (self.sourceY + distanceY).toFixed()
})
}
function end(event) {
document.removeEventListener('mousemove', move);
document.removeEventListener('mouseup', end);
// do other things
}
}
}
// , transform
function getTransform() {
var transform = '',
divStyle = document.createElement('div').style,
transformArr = ['transform', 'webkitTransform', 'MozTransform', 'msTransform', 'OTransform'],
i = 0,
len = transformArr.length;
for(; i < len; i++) {
if(transformArr[i] in divStyle) {
return transform = transformArr[i];
}
}
return transform;
}
//
window.Drag = Drag;
})();
// : 2
new Drag('target');
new Drag('target2');
이렇게 끌 어 당 기 는 대상 은 포장 이 끝났다.제 가 제공 한 사고방식 에 따라 구성 요 소 를 많이 포장 해 보 시 는 것 을 권장 합 니 다.예 를 들 어 탄창 하 나 를 봉 하고 순환 윤 파 를 봉 하 는 등 이다.많이 연습 하면 상 대 를 향 한 것 은 더 이상 문제 가 아니다.이런 사고방식 은 미래 에 언제든지 사용 할 수 있다.
이상 은 자바 스 크 립 트 가 대상 을 대상 으로 실전 패키지 드래그 대상 에 대한 상세 한 내용 입 니 다.JS 가 대상 을 대상 으로 어떻게 패키지 드래그 대상 을 실현 하 는 지 에 대한 자 료 는 우리 의 다른 관련 글 에 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JS 에서 대상 을 마주 하 는 프로 그래 밍유형 적 으로 특정한 기능 을 실현 하면 모든 인 스 턴 스 가 이 기능 을 갖 출 수 있 습 니 다.만약 우리 가 방법 을 다 썼 다 면 우 리 는 원래 코드 를 바 꾸 지 않 고 새로운 기능 을 추가 할 수 있다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.