Функция с высокой производительностью, которая добавляет прослушиватель событий на каждый полигон в очень большой SVG

#javascript #html #css #performance #svg

Вопрос:

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

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

Вот код:

 function hexagonHover() {
    for (i = 0; i < poly.length; i  ) {
        poly[i].addEventListener('mouseover', function (event) {
            for (i = 0; i < poly.length; i  ) {

                var pos = poly[i].getBoundingClientRect();

                let _x = Math.round(pos.left   pos.width / 2);
                let _y = Math.round(pos.top   pos.height / 2);
                
                var mouseX = Math.round(event.clientX);
                var mouseY = Math.round(event.clientY);

                var a = _x - mouseX;
                var b = _y - mouseY;

                var dist = Math.round(Math.sqrt(a * a   b * b));

                if (dist <= 30) {

                    let v = mapRange(dist, 0, 30, 1.2, 0.2);

                    poly[i].style.webkitTransform = poly[i].style.transform =
                        "scale("   v   ")";
                    poly[i].style.webkitTransform = poly[i].style.transformOrigin =
                        "center";
                    poly[i].style.webkitTransform = poly[i].style.transformBox = "fill-box";
                    poly[i].style.transition = "transform ease 1s";
                } else {
                    poly[i].style.webkitTransform = poly[i].style.transform = "scale(1.0)";
                }
            }
        });
    }
}
 

Вот кодовый код, который демонстрирует эффект, хотя и в гораздо меньшем масштабе

Комментарии:

1. 1. Не выполняйте вычисления при каждом наведении; выполняйте все вычисления заранее и назначайте результат каждой полилинии. 2. Не преобразуйте полилинию, добавьте дополнительную полилинию, которую вы размещаете (h)поверх полилинии, чтобы лежащая в ее основе полилиния не вызывала никаких переплавов DOM

2. @Danny’365CSI ‘ Энгельман Каков был бы наилучший способ присвоения результатов расстояния каждой полилинии? Будет ли работать создание массива со всеми результатами в том же порядке, что и массив полилиний, или я могу использовать атрибуты данных?

3. @Danny’365CSI ‘ Энгельман Я создал новую функцию, но я только что добавил список событий в документ вместо добавления по одному в каждый шестиугольник, потому что мне все еще нужно было событие, чтобы получить текущее положение мыши. И я сохраняю результаты dist в массиве. Сработает ли это? И каков был бы лучший способ скопировать полилинию поверх существующей в js? Овации

4. Лучшего способа не существует, вы программист и делаете то, что считаете лучшим. Судя по вашему описанию, вы на правильном пути. Основная предпосылка состоит в том, чтобы сделать как можно больше расчетов заранее. Это должно привести вас к серьезному улучшению. Если этого недостаточно, вы используете JavaScript для размещения дополнительного многоугольника в Z-слое высоты на экране.