Как сверстать веб-компонент для управления камерой?
На работе была поставлена задача создать виджет для интерактивной карты. Движок карты позволяет вывести на страницу произвольный html, но только в строковом виде: целевая версия транспиляции ниже es2015 и применение shadow-dom для произвольных элементов невозможно.
И так, возникают следующие вопросы по реализации:
- Как декомпозировать подобный код? Тут определенно нужен JavaScript, не писать же его в тегах...
- Как вытащить коллбек из произвольного html кода в Angular или любой другой фреймворк, использующий WebPack для сборки?
- Не учился в 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));
Однако, угол между векторами нельзя применить для создания ползунка поворота: не хватит точности из-за мантиссы. Для вытягивания угла я применил следующий метод:


