drag and drop, как 'отпустить' блок
Я разбираюсь как сделать drag and drop.
Я хочу при клике мышкой на блок, чтобы блок переносился туда, где мышка, когда мышь отпущена, чтобы блок переставал двигаться к мышке.
Я столкнулся с тем, что не понимаю, почему я не могу отпустить блок.
class BlockInGame {
constructor(src = 'move__block', styles) {
this.globalSelectors();
this.node = document.createElement('div');
this.node.classList.add(src);
this.addStyles(styles);
this.addInBody();
this.listeners(); // добавление слушателей
}
listeners() {
this.node.ondragstart = () => {
return false;
}
this.node.addEventListener('mousedown', (e) => {
const localMouseupFunc = (e) => {
document.removeEventListener('mousemove', this.onMouseMove.bind(this));
this.node.removeEventListener('mouseup', localMouseupFunc);
}
document.addEventListener('mousemove', this.onMouseMove.bind(this));
this.node.addEventListener('mouseup', localMouseupFunc);
});
}
globalSelectors() {
if (!this.globalSelectors.body) {
this.globalSelectors.body = document.querySelector('body');
}
if (!this.globalSelectors.game) {
this.globalSelectors.game = this.globalSelectors.body.querySelector('.game');
}
}
addStyles(styles) {
for (let key in styles) {
this.node.style[key] = styles[key];
}
}
addInBody() {
this.globalSelectors.game.append(this.node);
}
move(pageX, pageY) {
this.node.style.left = pageX - this.node.offsetWidth / 2 + 'px';
this.node.style.top = pageY - this.node.offsetHeight / 2 + 'px';
}
onMouseMove(event) {
this.move(event.pageX, event.pageY);
}
}
const block = new BlockInGame(undefined, {
backgroundColor: 'red',
width: '80px',
height: '80px'
});
*,
*::before,
*::after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
}
body {
overflow: hidden;
}
img {
max-width: 100%;
display: block;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.container {
max-width: 900px;
margin: 0 auto;
}
section {
background-color: #00cbff;
min-height: 100vh;
}
.game {
padding: 20px;
position: relative;
}
.move__block {
-webkit-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
cursor: pointer;
position: absolute;
left: 0;
top: 0;
}
<section class="game">
</section>
Ответы (1 шт):
Автор решения: Михаил Камахин
→ Ссылка
Надо было в слушатель передавать просто функцию, а не новую функцию, так как метод .bind возвращает новую функцию
Было:
const localMouseupFunc = (e) => {
document.removeEventListener('mousemove', this.onMouseMove.bind(this));
this.node.removeEventListener('mouseup', localMouseupFunc);
}
document.addEventListener('mousemove', this.onMouseMove.bind(this));
this.node.addEventListener('mouseup', localMouseupFunc);
Стало:
const localMouseupFunc = (e) => {
document.removeEventListener('mousemove', onMouseMoveBind);
this.node.removeEventListener('mouseup', localMouseupFunc);
}
const onMouseMoveBind = this.onMouseMove.bind(this);
document.addEventListener('mousemove', onMouseMoveBind);
this.node.addEventListener('mouseup', localMouseupFunc);
class BlockInGame {
constructor(src = 'move__block', styles) {
this.globalSelectors();
this.node = document.createElement('div');
this.node.classList.add(src);
this.addStyles(styles);
this.addInBody();
this.listeners();
}
listeners() {
this.node.ondragstart = function() {
return false;
}
this.node.addEventListener('mousedown', (e) => {
const localMouseupFunc = (e) => {
document.removeEventListener('mousemove', onMouseMoveBind);
this.node.removeEventListener('mouseup', localMouseupFunc);
}
const onMouseMoveBind = this.onMouseMove.bind(this);
document.addEventListener('mousemove', onMouseMoveBind);
this.node.addEventListener('mouseup', localMouseupFunc);
});
}
globalSelectors() {
if (!this.globalSelectors.body) {
this.globalSelectors.body = document.querySelector('body');
}
if (!this.globalSelectors.game) {
this.globalSelectors.game = this.globalSelectors.body.querySelector('.game');
}
}
addStyles(styles) {
for (let key in styles) {
this.node.style[key] = styles[key];
}
}
addInBody() {
this.globalSelectors.game.append(this.node);
}
move(pageX, pageY) {
this.node.style.left = pageX - this.node.offsetWidth / 2 + 'px';
this.node.style.top = pageY - this.node.offsetHeight / 2 + 'px';
}
onMouseMove(event) {
this.move(event.pageX, event.pageY);
}
}
const block = new BlockInGame(undefined, {
backgroundColor: 'red',
width: '80px',
height: '80px'
});
@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap');
*,
*::before,
*::after {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
}
body {
overflow: hidden;
}
img {
max-width: 100%;
display: block;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.container {
max-width: 900px;
margin: 0 auto;
}
section {
background-color: #00cbff;
min-height: 100vh;
}
.game {
padding: 20px;
position: relative;
}
.move__block {
-webkit-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.75);
cursor: pointer;
position: absolute;
left: 0;
top: 0;
}
<section class="game">
</section>