자바 스 크 립 트 대상 실전 패키지 드래그 대상

개술
여러분 이 더 많은 방식 을 이해 하고 비교 할 수 있 도록 저 는 세 가지 다른 방식 으로 끌 어 당 길 것 입 니 다.
  • 포장 하지 않 은 대상 이 직접 실현 된다
  • 원생 JavaScript 를 이용 하여 끌 어 당 기 는 대상 을 봉인 합 니 다
  • jQuery 확장 을 통 해 드래그 대상 을 실현 합 니 다
  • 끌 어 당 기 는 실현 과정 은 매우 많은 실 용적 인 작은 지식 과 관련 될 수 있 기 때문에 제 지식 축적 을 공 고 히 하고 여러분 들 이 더 많은 지식 을 배 울 수 있 도록 저 는 가능 한 한 상세 하 게 세부 사항 을 공유 할 것 입 니 다.여러분 들 이 열심히 읽 은 후에 반드시 무언 가 를 배 울 수 있 을 것 이 라 고 믿 습 니 다.
    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 세 가지 사건 을 결합 하면 끌 어 당 기 는 데 도움 이 됩 니 다.
    마우스 다운 을 눌 렀 을 때 발동
  • 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 가 대상 을 대상 으로 어떻게 패키지 드래그 대상 을 실현 하 는 지 에 대한 자 료 는 우리 의 다른 관련 글 에 주목 하 세 요!

    좋은 웹페이지 즐겨찾기