JS - Удалить все объекты одного типа - PullRequest
0 голосов
/ 07 мая 2020

Привет, я кодирую холст-игру как школьный проект, и я создал конструктор для объекта «кнопка», например:

// button object constructor

function button(xL, xR, yT, yB) {
    this.xLeft = xL;
    this.xRight = xR;
    this.yTop = yT;
    this.yBottom = yB;
    this.width = xR - xL;
    this.height = yB - yT;
    this.drawMe = function() {
        neonWariorPlayArea.context.strokeStyle = "blue";
        neonWariorPlayArea.context.beginPath();
        neonWariorPlayArea.context.rect(this.xLeft, this.yTop, this.width, this.height);
        neonWariorPlayArea.context.stroke();
    }
}

button.prototype.clicked = function() {
    if (this.xLeft <= mouseX && mouseX <= this.xRight && this.yTop <= mouseY && mouseY <= this.yBottom) {
        return true;

    }
}

Теперь я столкнулся с проблемой, которую я не знаю. Не знаю, как подойти и вот как удалить каждую уже созданную кнопку? Мне это нужно, потому что, когда я меняю экран (например, из главного меню на создателя персонажа), кнопки все еще присутствуют и доступны для нажатия. Я пытался создать какой-то массив, в котором я бы удерживал все объекты кнопок, а затем l oop через этот массив, удаляя каждый элемент массива.

var buttons = new Array();

playBtn = new button(500, 650, 50, 100);
tutorialBtn = new button(500, 760, 110, 160);
scoreBtn = new button(500, 670, 180, 230);

buttons.push(playBtn, tutorialBtn, scoreBtn);

function deleteBtns() {
    buttons.forEach(iterate);
}

function iterate(item, index) {
    console.log(index);
    delete buttons[index];
}

Теперь я дошел до того момента, когда у меня закончились идеи, и мой гугл-фу недостаточно силен. Спасибо за помощь или совет.

Ответы [ 3 ]

0 голосов
/ 07 мая 2020

Элемент canvas сам по себе представляет собой просто растровое изображение и не предоставляет информацию ни о каких нарисованных объектах. [sr c https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API]

Вы не можете «выбрать», а затем удалить объект с холста. Вместо этого используйте метод clearRect, чтобы очистить прямоугольную angular область от холста.

проверить stackblitz для рабочего образца https://stackblitz.com/edit/js-j81gxm?file=index.js

Я добавил два дополнительные свойства для вашего класса кнопок

  1. strokeWidth - ширина штриха всегда добавляется к размерам вашего прямоугольника. например: если ширина вашего прямоугольника и обводка равны 1 пикселю, то эффективная ширина прямоугольника становится 1 + 100 + 1 = 102 пикселя. Вы можете использовать свойство strokeWidth, чтобы установить переменную strokeWidth и использовать ее в качестве ссылки для функции remove

  2. Активная кнопка - чтобы отслеживать, активна ли кнопка для области щелчка

В класс button добавлен метод remove Этот метод удалит прямоугольную область angular и пометит кнопку как неактивную

deleteBtns функция отфильтрует кнопки массив при вызове метода удаления для отдельной кнопки.

const canvas = document.getElementById('app');

var neonWariorPlayArea = canvas.getContext("2d");
function button(xL, xR, yT, yB) {
    this.xLeft = xL;
    this.xRight = xR;
    this.yTop = yT;
    this.yBottom = yB;
    this.width = xR - xL;
    this.height = yB - yT;
    this.active = true;
    this.strokeWidth = 1;
    this.drawMe = function() {
        neonWariorPlayArea.strokeStyle = "green";
        neonWariorPlayArea.beginPath();
        neonWariorPlayArea.rect(this.xLeft, this.yTop, this.width, this.height);
        neonWariorPlayArea.stroke();
    }
}

button.prototype.clicked = function() {

    if (this.xLeft <= mouseX && mouseX <= this.xRight && this.yTop <= mouseY && mouseY <= this.yBottom && this.active ) {
        return true;

    }
}

button.prototype.remove = function() {
    this.active = false;
    neonWariorPlayArea.clearRect ( this.xLeft-this.strokeWidth, this.yTop-this.strokeWidth, this.width+this.strokeWidth*2, this.height+this.strokeWidth*2 );
}


var buttons = new Array();

const playBtn = new button(0, 50, 0, 50);
const tutorialBtn = new button(50, 100, 50, 100);
const scoreBtn = new button(100, 100, 50, 50);
playBtn.drawMe ();
tutorialBtn.drawMe ();
scoreBtn.drawMe ();
buttons.push(playBtn, tutorialBtn, scoreBtn);

function deleteBtns() {
    buttons = buttons.filter ( btn => {
      btn.remove ();
      return false;
    })
}
deleteBtns ();
0 голосов
/ 07 мая 2020

Вот как бы я это сделал:

<canvas id=canvas width=350 height=180></canvas>
<script>
    function object(x, y, c) {
        this.x = x;
        this.y = y;
        this.color = c
        this.draw = function () {
            context.fillStyle = this.color;
            context.beginPath();
            context.arc(this.x, this.y, 10, 0, 2 * Math.PI, false)
            context.fill();
        }
    }

    var canvas = document.getElementById('canvas')
    var context = canvas.getContext('2d')
    var img = new Image;
    img.onload = draw;
    img.src = "http://i.stack.imgur.com/UFBxY.png";
    var objects = []
    objects.push(new object(200, 100, "blue"));
    objects.push(new object(250, 90, "cyan"));

    function draw() {
        context.clearRect(0, 0, canvas.width, canvas.height)
        context.drawImage(img, 0, 0);
        objects.forEach(o => o.draw());
    }

    canvas.onclick = function (e) {
        objects.push(new object(Math.random()*200, Math.random()*100, "red"));
        if (objects.length > 5)
            objects = objects.filter(o => o.color != "red");
        draw()
    }
</script>

Сосредоточьте внимание на function draw()
Это вызывается при загрузке изображения, а также при каждом щелчке по холсту.

На каждом рисовании мы стираем весь холст и рисуем его снова, это может показаться слишком большим, но в современных браузерах это происходит так быстро, что вы не видите никаких мерцаний.

Я создал массив objects = [] и при щелчке я добавляю новый объект в случайном месте, при четвертом щелчке я удаляю все красные, и новые будут добавляться при последующих щелчках.


Было предложено просто очистите секцию rect angular с холста, но это вызовет проблемы, как вы можете видеть, я также рисую фоновое изображение, если я очищу раздел, он также может очистить фон, не лучшее поведение, и я уверен, что ваши формы станет более сложным.

Ключ состоит в том, чтобы очистить весь ваш холст и снова нарисовать все.

Имея это в виду, все, что вам нужно сделать в событии, которое запускает ваше удаление, всего l oop над массивом и удалите ненужные.

0 голосов
/ 07 мая 2020

Вы можете .filter button удалить ненужную кнопку и переназначить ее массиву.

Удаление всего, что вы можете сделать, назначив blank array: buttons = []

Чтобы получить уникальную кнопку, вы можете создать уникальную функцию.

function unique(buttons) {
  let set = new Set();
  let filtedBtns = [];
  buttons.forEach((btn) => {
    if (!set.has(btn.toString())) {
      filtedBtns.push(btn);
      set.add(btn.toString());
    }
  });
  return filtedBtns;
}

var buttons = new Array();
function button(x, y, a, b) {
  this.x = x;
  this.y = y;
  this.a = a;
  this.b = b;
  this.toString = () => {
    return `${x}::${y}::${a}::${b}`;
  };
}

playBtn = new button(500, 650, 50, 100);
tutorialBtn = new button(500, 760, 110, 160);
duplicateBtn = new button(500, 760, 110, 160);
scoreBtn = new button(500, 670, 180, 230);

buttons.push(playBtn, tutorialBtn, duplicateBtn, scoreBtn);
function unique() {
  let set = new Set();
  let filtedBtns = [];
  buttons.forEach((btn) => {
    if (!set.has(btn.toString())) {
      filtedBtns.push(btn);
      set.add(btn.toString());
    }
  });
  return filtedBtns;
}

function deleteBtns(index) {
  buttons = buttons.filter((_, i) => i !== index);
}
function deleteAll() {
  buttons = [];
}
console.log(buttons);
deleteBtns(1);
buttons = unique(buttons)
console.log(buttons);

deleteBtns(1);
console.log(buttons);
deleteAll();
console.log(buttons);

Подход на основе классов:

class Button {
  constructor(x, y, a, b) {
    this.x = x;
    this.y = y;
    this.a = a;
    this.b = b;
  }
  toHash() {
    return `${this.x}::${this.y}::${this.a}::${this.b}`;
  }
}

class Buttons {
  constructor(...btns) {
    this.buttons = btns;
  }
  unique() {
    let set = new Set();
    let filtedBtns = [];
    this.buttons.forEach((btn) => {
      if (!set.has(btn.toHash())) {
        filtedBtns.push(btn);
        set.add(btn.toHash());
      }
    });
    this.buttons = filtedBtns;
  }
  deleteBtns(index) {
    this.buttons = this.buttons.filter((_, i) => i !== index);
  }
  deleteAll() {
    this.buttons = [];
  }
}
let playBtn = new Button(500, 650, 50, 100);
let tutorialBtn = new Button(500, 760, 110, 160);
let duplicateBtn = new Button(500, 760, 110, 160);
let scoreBtn = new Button(500, 670, 180, 230);
const btns = new Buttons(playBtn, tutorialBtn, duplicateBtn, scoreBtn);

console.log(btns.buttons);

btns.unique(); // update unique
console.log(btns.buttons);

btns.deleteBtns(1); // delete by index

console.log(btns.buttons);

btns.deleteAll(); // delete all
console.log(btns.buttons);
...