---
description: https://github.com/catc/displace
---

# Sử dụng thư viện displace để làm menu kéo thả (ok):)))

{% file src="https://2494213435-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYjAG13rAPdbArSfRyB%2F-Lx5HZO1EgRqnVzMxmYV%2F-Lx5HcsRe5yXS_f8DGQd%2Fdisplace-master.zip?alt=media&token=a9402936-246b-427f-9fd2-2f5bfefdd13c" %}

![](https://2494213435-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYjAG13rAPdbArSfRyB%2F-Lx5GNZHVqqhVzvnETjx%2F-Lx5HWJ4vntXdC0icZ2K%2Fdisplace%201.png?alt=media\&token=cbc5a306-0fcb-4d87-89ac-1be91f32cdba)

Bước  1: Tải thư v iện displace.js

```javascript
! function(t, e) {
    "object" == typeof exports && "object" == typeof module ? module.exports = e() : "function" == typeof define && define.amd ? define([], e) : "object" == typeof exports ? exports.displacejs = e() : t.displacejs = e()
}(this, function() {
    return function(t) {
        function e(n) {
            if (o[n]) return o[n].exports;
            var s = o[n] = {
                exports: {},
                id: n,
                loaded: !1
            };
            return t[n].call(s.exports, s, s.exports, e), s.loaded = !0, s.exports
        }
        var o = {};
        return e.m = t, e.c = o, e.p = "", e(0)
    }([function(t, e, o) {
        "use strict";

        function n(t) {
            return t && t.__esModule ? t : {
                default: t
            }
        }
        var s = o(1),
            i = n(s);
        t.exports = i.default
    }, function(t, e, o) {
        "use strict";

        function n(t, e) {
            if (!(t instanceof e)) throw new TypeError("Cannot call a class as a function")
        }

        function s() {
            var t = this,
                e = this.el,
                o = this.opts || c,
                n = {};
            if (e.style.position = "absolute", this.handle = o.handle || e, o.constrain) {
                for (var s = o.relativeTo || e.parentNode, a = e, h = 0, v = 0; a !== s;) a = a.parentNode, (0, i.isRelative)(a) && (h -= a.offsetLeft, v -= a.offsetTop), a === s && (h += a.offsetLeft, v += a.offsetTop);
                var l = h + s.offsetWidth - e.offsetWidth,
                    f = v + s.offsetHeight - e.offsetHeight;
                n.xClamp = (0, i.generateClamp)(h, l), n.yClamp = (0, i.generateClamp)(v, f)
            }
            this.opts = o, this.data = n, this.events = {
                mousedown: u.mousedown.bind(this),
                mouseup: u.mouseup.bind(this),
                touchstart: u.touchstart.bind(this),
                touchstop: u.touchstop.bind(this),
                scrollFix: function(e) {
                    t.isDragging && e.preventDefault()
                }
            }, this.handleMove = r(this.opts.customMove), this.handle.addEventListener("mousedown", this.events.mousedown, !1), this.handle.addEventListener("touchstart", this.events.touchstart, !1), document.addEventListener("touchmove", this.events.scrollFix, {
                passive: !1
            })
        }
        Object.defineProperty(e, "__esModule", {
            value: !0
        });
        var i = o(2),
            u = o(3),
            r = (0, i.generateMoveFn)(),
            c = {
                constrain: !1,
                relativeTo: null,
                handle: null,
                highlightInputs: !1,
                onMouseDown: null,
                onMouseMove: null,
                onMouseUp: null,
                onTouchStart: null,
                onTouchMove: null,
                onTouchStop: null,
                customMove: null
            },
            a = function() {
                function t(e, o) {
                    if (n(this, t), !e) throw Error("Must include moveable element");
                    this.el = e, this.opts = o, s.call(this)
                }
                return t.prototype.reinit = function() {
                    this.destroy(), s.call(this)
                }, t.prototype.destroy = function() {
                    var t = this.events;
                    this.handle.removeEventListener("mousedown", t.mousedown, !1), document.removeEventListener("mousemove", t.mousemove, !1), document.removeEventListener("mouseup", t.mouseup, !1), this.handle.removeEventListener("touchstart", t.touchstart, !1), document.removeEventListener("touchmove", t.touchmove, !1), document.removeEventListener("touchstop", t.touchstop, !1), document.removeEventListener("touchmove", this.events.scrollFix, {
                        passive: !1
                    })
                }, t
            }();
        e.default = function(t, e) {
            return new a(t, e)
        }
    }, function(t, e) {
        "use strict";

        function o(t, e) {
            return function(o) {
                return Math.min(Math.max(o, t), e)
            }
        }

        function n(t) {
            return "relative" === window.getComputedStyle(t).position
        }

        function s() {
            return window.requestAnimationFrame ? function(t) {
                var e = t || i;
                return function(t, o, n) {
                    window.requestAnimationFrame(function() {
                        e(t, o, n)
                    })
                }
            } : function(t) {
                return function(e, o, n) {
                    var s = t || i;
                    s(e, o, n)
                }
            }
        }

        function i(t, e, o) {
            t.style.left = e + "px", t.style.top = o + "px"
        }
        Object.defineProperty(e, "__esModule", {
            value: !0
        }), e.generateClamp = o, e.isRelative = n, e.generateMoveFn = s
    }, function(t, e) {
        "use strict";

        function o(t) {
            var e = this.opts;
            if (e.highlightInputs) {
                var o = t.target.tagName.toLowerCase();
                if ("input" === o || "textarea" === o) return
            }
            if (0 === t.button) {
                var s = this.el,
                    i = this.events;
                "function" == typeof e.onMouseDown && e.onMouseDown(s, t);
                var u = t.clientX - s.offsetLeft,
                    r = t.clientY - s.offsetTop;
                i.mousemove = n.bind(this, u, r), document.addEventListener("mousemove", i.mousemove, !1), document.addEventListener("mouseup", i.mouseup, !1)
            }
        }

        function n(t, e, o) {
            var n = this.el,
                s = this.opts,
                i = this.data;
            "function" == typeof s.onMouseMove && s.onMouseMove(n, o);
            var u = o.clientX - t,
                r = o.clientY - e;
            return s.constrain && (u = i.xClamp(u), r = i.yClamp(r)), this.handleMove(n, u, r), o.preventDefault(), !1
        }

        function s(t) {
            var e = this.el,
                o = this.opts,
                n = this.events;
            "function" == typeof o.onMouseUp && o.onMouseUp(e, t), document.removeEventListener("mouseup", n.mouseup, !1), document.removeEventListener("mousemove", n.mousemove, !1)
        }

        function i(t) {
            var e = this.opts;
            if (e.highlightInputs) {
                var o = t.target.tagName.toLowerCase();
                if ("input" === o || "textarea" === o) return
            }
            var n = this.el,
                s = this.events;
            "function" == typeof e.onTouchStart && e.onTouchStart(n, t);
            var i = t.targetTouches[0],
                r = i.clientX - n.offsetLeft,
                c = i.clientY - n.offsetTop;
            s.touchmove = u.bind(this, r, c), this.isDragging = !0, document.addEventListener("touchmove", s.touchmove, !1), document.addEventListener("touchend", s.touchstop, !1), document.addEventListener("touchcancel", s.touchstop, !1)
        }

        function u(t, e, o) {
            var n = this.el,
                s = this.opts,
                i = this.data;
            "function" == typeof s.onTouchMove && s.onTouchMove(n, o);
            var u = o.targetTouches[0],
                r = u.clientX - t,
                c = u.clientY - e;
            return s.constrain && (r = i.xClamp(r), c = i.yClamp(c)), this.handleMove(n, r, c), o.preventDefault(), !1
        }

        function r(t) {
            this.isDragging = !1;
            var e = this.el,
                o = this.opts,
                n = this.events;
            "function" == typeof o.onTouchStop && o.onTouchStop(e, t), document.removeEventListener("touchmove", n.touchmove, !1), document.removeEventListener("touchend", n.touchstop, !1), document.removeEventListener("touchcancel", n.touchstop, !1)
        }
        Object.defineProperty(e, "__esModule", {
            value: !0
        }), e.mousedown = o, e.mousemove = n, e.mouseup = s, e.touchstart = i, e.touchmove = u, e.touchstop = r
    }])
});
```

Link: [https://github.com/catc/displace](https://github.com/catc/displace)&#x20;

Bước 2 : Sử dụng mẫu

```markup
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>displace.js</title>
		<link rel="stylesheet" href="./style.css">
		<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
	</head>
	<body>
		<span class="moveable"><span class="moveable__msg">Drag me</span></span>	
		<script src="./displace.min.js"></script>
		<script>
			const displace = window.displacejs;
			jQuery(document).ready(function($) {
				const el = document.querySelector('.moveable');
				displace(el);
			});
		</script>
	</body>
</html>
```
