Не могу вызвать события мыши на SVG в Angular 7 - PullRequest
1 голос
/ 14 июня 2019

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

Однако никакие события мыши не работают. Я могу изменить атрибуты SVG в TypeScript (например, изменить область просмотра SVG для панорамирования и масштабирования или выделения метки красным, когда происходит событие), но я не могу инициировать какие-либо события щелчка, прокрутки, наведения и т. Д. Внутри самого SVG .

Пока я пробовал:

  • Добавление атрибутов угловых событий в SVG, которые, очевидно, не являются допустимыми XML, поэтому браузер не может проанализировать его для рендеринга, и;
  • Нахождение элемента по его идентификатору (что я могу) и затем присоединение к нему анонимной onclick функции - но он никогда не срабатывает

SVG включен через тег object.

<!--map.component.html-->
<object id="svg-object" #svgObject type="image/svg+xml" data="../../../assets/img/map_large.svg"></object>

В моем компоненте после загрузки SVG я делаю следующее, но ничего не происходит. Он даже не входит в функцию.

// map.component.ts
this.svgDocument = this.svgObject.nativeElement.contentDocument.documentElement;
let el = this.svgDocument.getElementById("zoomToThis");
// this never gets triggered
el.addEventListener("click", function(event)
    {
        event.currentTarget.style.opacity = "1";
    }
);

Это, однако, работает просто отлично. Итак, ясно, что доступ к элементам документа не проблема.

// map.component.ts
this.svgDocument = this.svgObject.nativeElement.contentDocument.documentElement;
let el = this.svgDocument.getElementById("zoomToThis");
el.style.opacity = "1";

Как я могу это исправить? Я играю над идеей разорвать все это и использовать ванильный JavaScript в iFrame, но мне сказали, что ведущий отказывается это делать. Учитывая большой размер карты, мы также отказываемся от нее.

Ответы [ 2 ]

1 голос
/ 15 июня 2019

Я ломал голову над этим даже в нерабочее время и нашел что-то, что работает. Кажется грязным, но работает.

Сначала я получаю окно контента тега объекта, а не документ контента .

// map.component.ts
let cw = this.svgObject.nativeElement.contentWindow;

Окно контента работает аналогично iFrame. Чтобы события щелчка работали внутри SVG, я могу добавить функцию в окно содержимого.

// map.component.ts
cw.nameOfMyFunction = (event) => { /* do something */ }

Затем, внутри самого SVG, я могу добавить обработчики кликов к элементам (либо путем редактирования XML напрямую, либо в программном обеспечении, таком как Inkskape).

<!--map_large.svg-->
<rect onclick="nameOfMyFunction(event)" />

Я щелкаю прямоугольник, и функция срабатывает, как и ожидалось.

0 голосов
/ 14 июня 2019

Вы можете использовать HostListener с функцией, которая проверяет, имеет ли событие click элемент SVG:

// map.component.ts
@ViewChild('svgObject')    svgEl:    ElementRef;
@HostListener('click', ['$event.target'])
clickEvent(target: any) {
    if (target === svgEl.nativeElement) {
        svgEl.nativeElement.style.opacity = '1';
    }
}

Редактировать: еще один способ - добавить событие onClick к элементу:

<!--map.component.html-->
<object id="svg-object" #svgObject (click)=changeOpacity() type="image/svg+xml"data="../../../assets/img/map_large.svg"></object>

// map.component.ts
changeOpacity() {
    this.svgDocument = this.svgObject.nativeElement.contentDocument.documentElement;
    let el = this.svgDocument.getElementById("zoomToThis");
    el.style.opacity = "1";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...