Почему при вызове метода класса для одного блока он применяться одновременн и для других?

При нажатии на фигуру срабатывает метод класса move() и в зависимости от нажатых кнопок она перемещается, если после перемещений первой фигуры начать перемещать вторую фигуру то они начинают двигаться вместе.

Как сделать чтобы они не двигались вместе, подскажите пожалуйста.

введите сюда описание изображения

class Figure {
  constructor(type, name, styles) {
    this.type = type;
    this.name = name;
    this.styles = styles;
  }

  createFigure() {
    
    this.element = document.createElement('div');
    this.element.classList.add('el', `${this.type}`);
    this.element.style = `${this.css(this.styles)}`;
    this.element.dataset.name = this.name;

    this.element.addEventListener('click', () => this.move());

    let content = document.querySelector('#content');
    content.append(this.element);

  }

  move() {
    
    let y = 0;
    let x = 0;
    window.addEventListener('keydown', (event) => {
      event.preventDefault();
      
      const keyCode = event.code;
      
      switch (keyCode) {
        case 'ArrowDown':
          y++;
          this.element.style.top = y + 'px';
          break;
        case 'ArrowUp':
          y--;
          this.element.style.top = y + 'px';
          break;
        case 'ArrowLeft':
          x--;
          this.element.style.left = x + 'px';
          break;
        case 'ArrowRight':
          x++;
          this.element.style.left = x + 'px';
          break;
      }
    });
  }

  css(styles = {}) {
    if (typeof styles === 'string') return styles;
    return Object.keys(styles).map(key => `${key}: ${styles[key]}`).join(';');
  }

}

let a = new Figure('circle', 'Круг', {
    width: '100px',
    height: '100px',
    'border-radius': '50px',
    background: 'lightblue'
  }
);

let b = new Figure('square', 'Квадрат', {
    width: '100px',
    height: '100px',
    background: '#cccccc'
  }
);

a.createFigure();
b.createFigure();
    #content {
        position: relative;
    }
    
    .el {
        position: relative;
    }
<div id="app">
    <div id="content"></div>
    <div id="panel"></div>
  </div>


Ответы (1 шт):

Автор решения: Zhihar

Уф, пришлось ваш код перелопатить, чтобы он стал работоспособным тут :)

одновременно у вас объекты двигаются по причине, что когда вы нажимаете на объект и вызывается метод move внутри этого метода вы вешаете новое событие

window.addEventListener('keydown', (event) => {

таким образом у вас не происходит переключение с одного объекта на другой - типа что событие работает только для одного объекта

происходит следующее:

  1. если нажать на стрелку вправо, то ни один объект не двигается

  2. если нажать на круг, то будет добавлено событие на нажатие кнопки для круга

  3. если нажать на стрелку вправо, то будет двигаться круг, а квадрат двигаться не будет

  4. если нажать на квадрат, то будет добавлено событие на нажатие кнопки для квадрата (но останется и событие на нажатие кнопки для круга)

  5. если нажать стрелку вправо, то будут двигаться и круг и квадрат, потому что для каждого будет вызван соответствующий код

Например можно сделать так:

я добавил глобальную переменную target (дадада, глобальное - это не хорошо, но для демонстрации сойдет)

let target = '';

и когда вызывается метод move присваиваю target тип того объекта чей метод вызван:

target = this.type;

а уже внутри события нажатия кнопки отслеживаю а соответствует ли target типу объекта:

if (target != this.type)
    return;

в результате всегда двигается только 1 объект

let target = '';

class Figure {
  constructor(type, name, styles) {
    this.type = type;
    this.name = name;
    this.styles = styles;
  }

  createFigure() {
    
    this.element = document.createElement('div');
    this.element.classList.add('el', `${this.type}`);
    this.element.style = `${this.css(this.styles)}`;
    this.element.dataset.name = this.name;

    this.element.addEventListener('click', () => this.move());

    let content = document.querySelector('#content');
    content.append(this.element);

  }

  move() {
    
    target = this.type;
    
    let y = 0;
    let x = 0;

    window.addEventListener('keydown', (event) => {
      
      if (target != this.type)
        return;
      
      const keyCode = event.code;
      
      switch (keyCode) {
        case 'ArrowDown':
          y++;
          this.element.style.top = y + 'px';
          break;
        case 'ArrowUp':
          y--;
          this.element.style.top = y + 'px';
          break;
        case 'ArrowLeft':
          x--;
          this.element.style.left = x + 'px';
          break;
        case 'ArrowRight':
          x++;
          this.element.style.left = x + 'px';
          break;
      }
    });
  }

  css(styles = {}) {
    if (typeof styles === 'string') return styles;
    return Object.keys(styles).map(key => `${key}: ${styles[key]}`).join(';');
  }

}

let a = new Figure('circle', 'Круг', {
    width: '100px',
    height: '100px',
    'border-radius': '50px',
    background: 'lightblue'
  }
);

let b = new Figure('square', 'Квадрат', {
    width: '100px',
    height: '100px',
    background: '#cccccc'
  }
);

a.createFigure();
b.createFigure();
    #content {
        position: relative;
    }
    
    .el {
        position: relative;
    }
  <div id="app">
    <div id="content"></div>
    <div id="panel"></div>
  </div>

→ Ссылка