Нажмите 2 элемента одновременно? - PullRequest
3 голосов
/ 02 марта 2020

У меня есть сценарий, в котором пользователь может выбрать 1 элемент или 2 элемента , чтобы щелкнуть
Если пользователь выбрал 2 элемента , он может выбрать 2 элементы в один клик, но только к соседнему элементу
Пример:
Если пользователь щелкнет контейнер Elem 1, контейнер ниже будет активен или нажмет
Элем 1 и Элем 2
Если пользователь щелкнет на контейнере Elem 3, контейнер, указанный ниже, будет активен или нажмет
Элем 2 и Элем 3

Более того, если пользователь нажал на Elem 2 , это будет зависеть от ближайшей области, где пользователь щелкнул ( ось Y ), если он будет сотрудничать с Elem 1 или Elem 3

Но НЕ Элемент с 1 по 3, потому что между ними (Элемент 2) есть промежуток и, как я уже упоминал, только соседний контейнер.

Я использую ReactJS

enter image description here

<div class="myClass">
  Elem 1
</div>

<div class="myClass">
  Elem 2
</div>

<div class="myClass">
  Elem 3
</div>

Ответы [ 4 ]

3 голосов
/ 02 марта 2020

Редактировать 1

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

Смотрите обновленную React Песочницу с кодом здесь


App.jsx

import React, { useState } from "react";
import "./styles.css";

const ElementsList = () => {
  // 1. List of Items, they could be anything
  const items = ["Elem 1", "Elem 2", "Elem 3", "Element 4", "Element 5"];

  // 2. Track the selected items in state
  const [selectedItems, setSelectedItems] = useState([]);

  const handleClick = (e, index) => {
    // 7. Extract the click position and element height from the event target.
    const nextItems = getNextSelections({
      currentIndex: index,
      totalItems: items.length,
      elementHeight: e.currentTarget.getBoundingClientRect().height,
      distanceFromTop: e.clientY - e.currentTarget.getBoundingClientRect().top
    });

    // 4. Do whatever you want with the selected items :), then update state
    setSelectedItems(nextItems);
  };

  return (
    <div className="List">
      {items.map((value, index) => (
        <div
          key={value}
          className={`myClass ${
            // 5. Conditionally set selected class if index is present in selected Items array
            selectedItems.includes(index) ? "selected" : ""
          }`}
          // 6. Capture the click event and the index of the selected item
          onClick={e => handleClick(e, index)}
        >
          {value}
        </div>
      ))}
    </div>
  );
};

export default function App() {
  return (
    <div className="App">
      <h1>2 Items Selector</h1>
      <ElementsList />
    </div>
  );
}

Помощник getNextSelections


// Helper to get Select items based on mouse position
const getNextSelections = ({
  currentIndex, // Index of the clicked Item
  totalItems, // Total number of items in the list
  elementHeight, // Height of the bounding rectangle of the element
  distanceFromTop // Distance of Mouse click postion from top of boudning rectangle of the element
}) => {
  // A. Return first and second item if first item is clicked, exit early
  if (currentIndex <= 0) return [0, 1];

  // B. Return last and second last if last item is clicked and exit early
  if (currentIndex === totalItems - 1) return [currentIndex - 1, currentIndex];

  // C. If clicked in top half of the element, return previous and current item
  if (distanceFromTop < elementHeight / 2) {
    console.log("Cicked Next to the Top of Element");
    return [currentIndex - 1, currentIndex];
  }

  // D. Otherwise return current and next item indicies
  return [currentIndex, currentIndex + 1];
};

Стили. css

.App {
  font-family: sans-serif;
  text-align: center;
}

.List {
  width: 80%;
  margin: 0 auto;
  text-align: center;
}

.myClass {
  padding: 1rem;
  border: solid 4px black;
  border-bottom: none;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.myClass.selected {
  background: rgb(236, 174, 174);
  transition: background 1s;
}
.myClass:last-child {
  border: solid 4px black;
}


Я добавил помощника для условной проверки позиции щелчка в верхней части ограничения выбранного элемента. прямоугольник. Следуйте этим допущениям.

  1. Если щелкнуть первый элемент, просто выберите первый и второй элементы. [A]
  2. Выберите последний и второй последний элемент, если щелкнуть последний элемент , [B]
  3. Для элементов в середине списка выберите предыдущий элемент в качестве второго выбора, если щелчок происходит в верхней половине ограничительного прямоугольника выбранного элемента [C], в противном случае выберите предыдущий элемент. [D]

Код Песочница: выбор нескольких элементов с помощью мыши. Близость

Изменить 2

В своих комментариях вы говорите список содержит строки и столбцы :( Вы можете расширить помощник для учета горизонтальной близости, используя getBoundingClientRect().left and width, и использовать тот же подход, чтобы выбрать индекс элементов на стороне, ближайшей к щелчку.

Редактировать 3

Удален подход, при котором следующий выбранный элемент не зависит от положения щелчка мыши, но код можно найти в этой Редакции 1 этого поста здесь и в Codesandbox «Несколько элементов выбираются без близости мыши»

1 голос
/ 02 марта 2020

Я создал решение для этого, используя javascript только

В этом подходе я использовал Event Bubbling Concept тоже. Вы можете проверить это в https://jsfiddle.net/harshapache/dhqnrvwx/


Важные методы DOM (javascript):

  • проверьте, что у вашего div есть класс (например, активный) event.target.classList.contains ("active");
  • Следующий родной элемент event.target.nextElementSibling
  • Предыдущий элемент родного брата event.target.previousElementSibling
  • Добавить класс event.target .classList.add ("active");
  • Удалить класс event.target.classList.remove ("active");

HTML

  <div id="myClassWrapper">
     <div class="myClass">Elem 1</div>
     <div class="myClass">Elem 2</div>
     <div class="myClass">Elem 3</div>
  </div>

JS

    var selectedElements = 0;
    var myClassWrapper = document.getElementById('myClassWrapper');
        myClassWrapper.addEventListener("click", function(event){
    var isMyClassClicked = event.target.classList.contains("myClass");


    if(isMyClassClicked){
      var isActive = event.target.classList.contains("active");
      if(isActive){
       //Do Unselect
       event.target.classList.remove("active");
       selectedElements--;
      }
      else{
        //Do Select
        //1.Check selectedElemnts not equal to 2
        if(selectedElements == 2) alert('You already selected two elements');
         if(selectedElements == 1){
         //check neighbour has active or not
         var isNextElemActive = event.target.nextElementSibling ? event.target.nextElementSibling.classList.contains("active") : false;
         var isPrevElemActive = event.target.previousElementSibling ? event.target.previousElementSibling.classList.contains("active") : false;
         if(isNextElemActive || isPrevElemActive){
           event.target.classList.add("active");
           selectedElements++;
         }else{
           alert("you can't select it");
         }
        }
        if(selectedElements == 0){
          event.target.classList.add("active");
          selectedElements++;
        }
       }
     }
   });
0 голосов
/ 02 марта 2020

Я прочитал ваш вопрос, поэтому у вас есть 3 элемента, и все, что вам нужно, это если вы нажмете на вышеуказанную часть элемента, и над и под ним будет выделен тот же элемент. То же самое касается нижней части, если вы нижняя часть элемент выше и ниже одного будет выделен для этой функции, я протестировал jQuery код

<script>
$(document).ready(function(){
  $(".oneEbottom").on("click", function(event){
    $(event.delegateTarget).css("background-color", "red");
    $(".twoE").css("background-color", "red");
    $(".oneE").css("background-color", "red");
    $(".threeE").css("background-color", "white");
  });

  $(".twoEabove").on("click", function(event){
    $(event.delegateTarget).css("background-color", "red");
    $(".oneE").css("background-color", "red");
    $(".twoE").css("background-color", "red");
    $(".threeE").css("background-color", "white");
  });

  $(".twoEbottom").on("click", function(event){
    $(event.delegateTarget).css("background-color", "red");
    $(".threeE").css("background-color", "red");
    $(".twoE").css("background-color", "red");
    $(".oneE").css("background-color", "white");
  });

  $(".threeEabove").on("click", function(event){
    $(event.delegateTarget).css("background-color", "red");
    $(".threeE").css("background-color", "red");
    $(".twoE").css("background-color", "red");
     (".oneE").css("background-color", "white");
  });
});
</script>

, вы можете использовать этот простой скрипт для этой функциональности, но вы должны связать файл jQuery в вы помечаете

<head>

<style>
.a {
    border: 1px solid #000;
}

</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

</head>
<body>






<div class="oneE a" >
<div class="oneEinner">Element 1</div>
<div class="oneEbottom s"><small>to highlight Element 1 & 2</small></div>
</div>

<div class="twoE a">
    <div class="twoEabove s"><small>to highlight Element 1 & 2</small></div>
    <div class="twoEinner">Element 2</div>
    <div class="twoEbottom s"><small>to highlight Element 2 & 3</small></div>
</div>

<div class="threeE a">
<div class="threeEabove s"><small>to highlight Element 2 & 3</small></div>
<div class="threeEinner">Element 3</div>
</div>

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

0 голосов
/ 02 марта 2020

Вы можете использовать метод jQuery's .next(), чтобы найти следующее деление.

$(".myClass").on("click", function() {
    $('.myClass').css("background","none");
    $(this).css("background", "red");
    $(this).next(".myClass").css("background", "red");
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="myClass">
  Elem 1
</div>

<div class="myClass">
  Elem 2
</div>

<div class="myClass">
  Elem 3
</div>
...