Добавьте класс к определенным элементам с помощью чистого JavaScript - PullRequest
0 голосов
/ 17 декабря 2018

Я оцениваю цветное изображение SVG.Функция оценивает цвета заливки, установленные пользователем, по списку правильных ответов, просматривая их с помощью метода querySelectorAll и преобразуя (для сравнения их значений) в массивы.Только пути с классом setColor могут быть окрашены.

Вопрос: Как добавить класс wrongColor ТОЛЬКО к элементам пути, которые имеют неправильный цвет заливки?

<!--Hypothetical SVG that must be colored correctly.-->
    <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
        <path id="aSVG" class="setColor" d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="green" />
        <path id="bSVG" class="setColor" d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="red" />
        <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="white" />
        <path id="cSVG" class="setColor" d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="lightblue" />
        <path id="dSVG" class="setColor" d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="lightblue" />
        <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="white" />
        <path id="eSVG" class="setColor" d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="lightblue" />
        <path id="fSVG" class="setColor" d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="lightblue" />
        <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="white" />
    </svg>


    <!--Correct answers list. Not visible in user-->
    <ol class="answersList">
        <li class="t1">red</li>
        <li class="t1">green</li>
        <li class="t1">lightblue</li>
        <li class="t1">lightblue</li>
        <li class="t1">lightblue</li>
        <li class="t1">lightblue</li>
    </ol>

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

@ Amethystx87 Ваш код добавляет класс wrongColor к всем путям с классом setColor.Вы можете увидеть это ниже в фрагменте кода.Свойство map создаст ошибку «document.querySelectorAll (...). Map не является функцией», поскольку querySelectorAll возвращает Node List (как в массиве), поэтому вам нужно преобразовать Node List в массив, а затемметоды массива могут быть использованы.

У меня тоже была та же проблема, и я решил ее, как в приведенном ниже коде JavaScript с комментариями «проверить ответы пользователей», «проверить список правильных ответов».В комментарии «Решение Amethystx87» - это способ, которым я заставил ваш код работать, но еще не полностью.

@ DacreDenny Я не мог использовать ваше решение, возможно, по моей вине.Я надеюсь, что фрагмент кода ниже может дать вам четкое представление о проблеме.В фрагменте вы увидите, что неправильные ответы (я специально сделал ошибку) - это первые два (зеленый, красный), но правильные (красный, зеленый) такие же, как в списке ответов.

/*~~~~~~~~check button~~~~~~~~~~~*/

document.querySelector(".check").addEventListener('click', checkSvgAnswers);

function checkSvgAnswers() {


  /*~~~check users answers~~~*/

  var selectedFillColor = document.querySelectorAll(".setColor");
  var selectedFillColorArray = [];
  for (var i = 0; i < selectedFillColor.length; i++) {
    var selectedColors = selectedFillColor[i].getAttribute('fill').toUpperCase();
    selectedFillColorArray.push(selectedColors);
  }

  console.log(selectedFillColorArray);

  /*~~~check correct answers list~~~~~~~~~~~*/

  var correctAnswers = document.querySelectorAll("li.t1");
  var correctAnswersArray = [];
  for (var i = 0; i < correctAnswers.length; i++) {
    var answerList = correctAnswers[i].innerText.toUpperCase();
    correctAnswersArray.push(answerList);
  }

  console.log(correctAnswersArray);

  /*~~~~compare answers helper function~~~~~~~~~~*/
  var isEqual = function(value, other) {

    // Get the value type
    var type = Object.prototype.toString.call(value);

    // If the two objects are not the same type, return false
    if (type !== Object.prototype.toString.call(other)) {
      return false;
    }

    // If items are not an object or array, return false
    if (['[object Array]', '[object Object]'].indexOf(type) < 0) {
      return false;
    }
    // Compare the length of the length of the two items
    var valueLen = type === '[object Array]' ? value.length : Object.keys(value).length;
    var otherLen = type === '[object Array]' ? other.length : Object.keys(other).length;
    if (valueLen !== otherLen) {
      return false;
    }
    // Compare two items
    var compare = function(item1, item2) {

      // Get the object type
      var itemType = Object.prototype.toString.call(item1);

      // If an object or array, compare recursively
      if (['[object Array]', '[object Object]'].indexOf(itemType) >= 0) {
        if (!isEqual(item1, item2)) {
          return false;
        }
      }

      // Otherwise, do a simple comparison
      else {

        // If the two items are not the same type, return false
        if (itemType !== Object.prototype.toString.call(item2)) {
          return false;
        }
        // Else if it's a function, convert to a string and compare
        // Otherwise, just compare
        if (itemType === '[object Function]') {

          if (item1.toString() !== item2.toString()) {

            return false;
          }
        } else if (item1 !== item2) {

          return false;
        }

      }
    };
    // Compare properties
    if (type === '[object Array]') {
      for (var i = 0; i < valueLen; i++) {
        if (compare(value[i], other[i]) === false) {

          return false;
        }
      }
    } else {
      for (var key in value) {
        if (value.hasOwnProperty(key)) {
          if (compare(value[key], other[key]) === false) {

            return false;
          }
        }
      }
    }

    // If nothing failed, return true
    return true;

  };

  /*~~~~~~~~compare colors~~~~~~~~~~~*/
  if (isEqual(selectedFillColorArray, correctAnswersArray)) {
    document.querySelector(".coloringResult").innerHTML = "<span style='color:#00B119;'>&#x2714;</span>";
  } else if (!isEqual(selectedFillColorArray, correctAnswersArray)) {
    document.querySelector(".coloringResult").innerHTML = "<span style='color:#D40D0D;'>&#10007;</span>";
  }
  console.log(isEqual(selectedFillColorArray, correctAnswersArray));

  /*~~~~~~~~Amethystx87 solution*/
  document.querySelectorAll('.setColor').forEach((element) => {
    if (!correctAnswersArray.includes(element.fill)) {
      element.classList.add('wrongColor');
    }
  });
};
<!--Hypothetical color palette. User can drag and drop colors ONLY to svg paths with the class="setColor" to change the default "fill" color values-->
<div class="colorPalette">
  <p>green</p>
  <p>red</p>
  <p>lightblue</p>
</div>

<!--Hypothetical SVG that must be colored correctly.-->
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">

        <path id="aSVG" class="setColor" d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="green" />
        <path id="bSVG" class="setColor" d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="red" />
        <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="white" />
        <path id="cSVG" class="setColor" d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="lightblue" />
        <path id="dSVG" class="setColor" d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="lightblue" />
        <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="white" />
        <path id="eSVG" class="setColor" d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="lightblue" />
        <path id="fSVG" class="setColor" d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="lightblue" />
        <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="white" />

    </svg>

<!--Appears on check button click showing tick for correct, x for wrong.-->
<p class="coloringResult">&nbsp;</p>

<!--control buttons-->
<!--Check button: compares the users colors placed on the svg, with the correct colors from the answers list. Score container appears and shows user score-->
<button class='check' type='button'>Check</button>

<!--Try again button: keep the correct answers, the wrong answers return to the original "fill" color and the score is changed keeping only the correct colors score-->
<button class='try-again' type='button'>Try again</button>

<!--Reset button: reset exersice to original state. All svg paths to default "fill" color. Score resets to 0 and disappears from screen -->
<button class='clear-answers' type='button'>Reset</button>

<!--Correct answers list. Not visible in user-->
<ol class="answersList">
  <li class="t1">red</li>
  <li class="t1">green</li>
  <li class="t1">lightblue</li>
  <li class="t1">lightblue</li>
  <li class="t1">lightblue</li>
  <li class="t1">lightblue</li>
</ol>

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Вы можете запрашивать элементы SVG и обновлять список классов элемента SVG так же, как и любой другой элемент в DOM.

Так, например, вы можете запросить все элементы SVG с помощью fill значение атрибута "неправильного цвета заливки" white, выполнив это:

const wrongFillColor = "white";

document.querySelectorAll(`svg [fill="${wrongFillColor}"]`)

Затем можно выполнить итерацию результирующего набора узлов и добавить классы к соответствующим элементам, например:

const wrongFillColor = "white";

document.querySelectorAll(`svg [fill="${wrongFillColor}"]`).forEach(function(element) {
  element.classList.add("wrongColor")
})
.wrongColor {
  fill: yellow;
}
<!--Hypothetical SVG that must be colored correctly.-->
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
        <path id="aSVG" class="setColor" d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="green" />
        <path id="bSVG" class="setColor" d="M70 10 C 70 20, 120 20, 120 10" stroke="black" fill="red" />
        <path d="M130 10 C 120 20, 180 20, 170 10" stroke="black" fill="white" />
        <path id="cSVG" class="setColor" d="M10 60 C 20 80, 40 80, 50 60" stroke="black" fill="lightblue" />
        <path id="dSVG" class="setColor" d="M70 60 C 70 80, 110 80, 110 60" stroke="black" fill="lightblue" />
        <path d="M130 60 C 120 80, 180 80, 170 60" stroke="black" fill="white" />
        <path id="eSVG" class="setColor" d="M10 110 C 20 140, 40 140, 50 110" stroke="black" fill="lightblue" />
        <path id="fSVG" class="setColor" d="M70 110 C 70 140, 110 140, 110 110" stroke="black" fill="lightblue" />
        <path d="M130 110 C 120 140, 180 140, 170 110" stroke="black" fill="white" />
    </svg>
0 голосов
/ 17 декабря 2018

как то так

// Get all the correct colors and map them to an array
const correctColors = document.querySelectorAll('.t1')
  .map(element => return element.textContent);
// Loop through all with class setColor and add wrongColor to the element's classList
document.querySelectorAll('.setColor').forEach((element) => {
    if (!correctColors.includes(element.fill)) {
        element.classList.add('wrongColor');
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...