Как сверстать веб-компонент для управления камерой?

На работе была поставлена задача создать виджет для интерактивной карты. Движок карты позволяет вывести на страницу произвольный html, но только в строковом виде: целевая версия транспиляции ниже es2015 и применение shadow-dom для произвольных элементов невозможно.

Макет

И так, возникают следующие вопросы по реализации:

  1. Как декомпозировать подобный код? Тут определенно нужен JavaScript, не писать же его в тегах...
  2. Как вытащить коллбек из произвольного html кода в Angular или любой другой фреймворк, использующий WebPack для сборки?
  3. Не учился в 9 классе, помогите с математекой (шутка)!

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

Автор решения: Трипольский Пётр

По пунктам.

1. Создание собственных веб-компонентов на legacy javascript избегая современный синтаксический сахар.

Можно избежать наследования от HTMLElement es2015 синтаксисом, применив для создания инстанции элемента Reflect. Код при этом будет примерно следующий:

let callback = null;

function SomeComponent() {
    const div = Reflect.construct(HTMLElement, [], SomeComponent);
    div.innerText = 'omg';
    div.onclick = () => callback();
    return div;
}

SomeComponent.prototype = Object.create(HTMLElement.prototype);
customElements.define('some-component', SomeComponent);

export function setCallback(c) {
    callback = c;
}

/**
 * Использование:
 *
 *  - Создание компонента (только из JavaScript после загрузки)
 *
 *      document.body.innerHTML = '<some-component></some-component>'
 *
 *  - Переброс коллбека (подойдет метод готовности представления
 *    жизненного цикла любого фреймворка)
 *
 *      ngOnInit() {
 *        setCallback(() => console.log(123);
 *      }
 */

2. Переброс коллбека и декомпозиция

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

3. Математика

Для создания подвижных слайдеров мы рассматриваем мышь и ползунки как точки. Далее, из трех точек можно получить два вектора и, применив формулу угол между векторами из первой картинки в Google, найти косинус угла. Далее, умножив его на гипотенузу, найти нужный катет.

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

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

const { abs, sqrt, pow, round, PI, atan } = Math;
const angle = ([x1,y1], [x2, y2], [x3, y3]) => {
  const A = { x: x2 - x1, y: y2 - y1 };
  const B = { x: x3 - x2, y: y3 - y2 };
  const angleCos = abs((A.x * B.x) + (A.y * B.y)) / 
                   (sqrt(pow(A.x, 2) + pow(A.y, 2)) * sqrt(pow(B.x, 2) + pow(B.y, 2)));
  return angleCos;
}
const length = ([x1,y1], [x2, y2], [x3, y3]) => {
  const angleCos = angle([x1,y1], [x2, y2], [x3, y3]);
  const hypotenuse = distance(x3, y3, x2, y2);
  const sign = distance(x2, y2, x1, y1) > distance(x3, y3, x1, y1) ? -1 : 1;
  return round(sign * angleCos * hypotenuse);
};
const distance = (a1, a2, b1, b2) => sqrt(pow(b2 - a2, 2) + pow(b1 - a1, 2));

Однако, угол между векторами нельзя применить для создания ползунка поворота: не хватит точности из-за мантиссы. Для вытягивания угла я применил следующий метод:

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

→ Ссылка