Last active
May 16, 2018 05:59
-
-
Save whatwewant/c785a6cdc1b01d8f430e896568cd9128 to your computer and use it in GitHub Desktop.
enable element move anywhere on browser
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function isSupportPassive() { | |
let isSupport = false; | |
try { | |
const opts = Object.defineProperty({}, 'passive', { | |
get() { | |
isSupport = true; | |
}, | |
}); | |
window.addEventListener('test', null, opts); | |
} catch (e) { | |
// | |
} | |
return isSupport; | |
} | |
const passiveOptions = isSupportPassive() ? { | |
passive: true, | |
capture: false, | |
} : false; | |
function setStyle($node, name, value) { | |
$node.style[name] = typeof value === 'number' ? `${value}px` : value; // eslint-disable-line | |
} | |
function $(selector) { | |
return typeof selector === 'string' ? document.querySelector(selector) : selector; | |
} | |
export default class Movable { | |
/** | |
* Constructor | |
* params: | |
* handlerSelector: handler document node selector. | |
* containerSelector: container document node selector. | |
* boundable: support have boundary, default false. | |
*/ | |
constructor(options = {}) { | |
const { | |
handlerSelector = '.handler', | |
containerSelector = '.container', | |
boundable = false, | |
} = options; | |
this.$handler = $(handlerSelector); | |
this.$container = $(containerSelector); | |
this.state = { | |
boundable, | |
movable: false, | |
currentX: 0, | |
currentY: 0, | |
top: 0, | |
left: 0, | |
maxLeft: 0, | |
maxTop: 0, | |
}; | |
this.listen(); | |
} | |
/** | |
* style memebers: handler + container | |
* 1 make container position absolute | |
* 2 make handler cursor as move | |
*/ | |
styledMembers() { | |
// @1 make container absolute | |
setStyle(this.$container, 'position', 'absolute'); | |
// @2 make handler cusor move | |
setStyle(this.$handler, 'cursor', 'move'); | |
} | |
listen() { | |
this.styledMembers(); | |
// @1 mouse down on handler | |
this.$handler.addEventListener('mousedown', this.onMouseDown, passiveOptions); | |
// @2 mouse up on document | |
document.addEventListener('mouseup', this.onMouseUp, passiveOptions); | |
// @3 mouse move on documnent | |
document.addEventListener('mousemove', this.onMouseMove, passiveOptions); | |
} | |
onMouseDown = (event) => { | |
const { | |
top, | |
left, | |
width, | |
height, | |
} = this.$container.getBoundingClientRect(); | |
this.state.top = top; | |
this.state.left = left; | |
this.state.width = width; | |
this.state.height = height; | |
this.state.maxLeft = window.innerWidth - width; | |
this.state.maxTop = window.innerHeight - height; | |
this.state.currentX = event.clientX; | |
this.state.currentY = event.clientY; | |
this.state.movable = true; | |
}; | |
onMouseUp = () => { | |
this.state.movable = false; | |
}; | |
onMouseMove = (event) => { | |
if (!this.state.movable) return false; | |
const deltaX = event.clientX - this.state.currentX; | |
const deltaY = event.clientY - this.state.currentY; | |
let left = this.state.left + deltaX; | |
let top = this.state.top + deltaY; | |
if (this.state.boundable) { | |
if (left < 0) { | |
left = 0; | |
} else if (left > this.state.maxLeft) { | |
left = this.state.maxLeft; | |
} | |
if (top < 0) { | |
top = 0; | |
} else if (top > this.state.maxTop) { | |
top = this.state.maxTop; | |
} | |
} | |
setStyle(this.$container, 'top', top); | |
setStyle(this.$container, 'left', left); | |
}; | |
} | |
// test | |
new Movable('.handler', '.container', true); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment