Страница 1 из 1

Cобытие click

Добавлено: 18 дек 2018, 21:54
Неуловимый_Джо
Всем привет. Ни как не могу понять как используя событие click в ArcGIS API for JavaScript 4.10, по клику выводить информацию о точке? Если же пользователь кликнет не по точке ничего выводиться не должно. На данный момент, я создал слой, добавил туда точки. Пробовал делать как в этом примере:
https://developers.arcgis.com/javascrip ... tro-popup/, только без использования локатора адресов, так как его использовать не планирую. Других примеров с событием click к сожалению не нашёл.

Код: Выделить всё

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
    <script src="https://js.arcgis.com/4.10/"></script>

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        require([
            "esri/Map",
            "esri/layers/GraphicsLayer",
            "esri/views/MapView",
            "esri/Graphic",
            "esri/tasks/Locator",
        ], function (
            Map, FeatureLayer, MapView, Graphic, Locator
        ) {
            var locatorTask = new Locator({
            url: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
            });
            var map = new Map({
                basemap: "hybrid"
            });

            var view = new MapView({
                center: [-80, 35],
                container: "viewDiv",
                map: map,
                zoom: 3
            });

            /*************************
             * Create a point graphic
             *************************/
            var multipoint = {
                type: "multipoint",
                points: {{ResponseData}},
            };
            // Create a symbol for drawing the point
            var markerSymbol = {
                type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
                color: [111, 119, 40],
                outline: { // autocasts as new SimpleLineSymbol()
                    color: [1, 255, 255],
                    width: 1
                }
            };
            var template = {
                title: "{{Descr}}"
            };
            // Create a graphic and add the geometry and symbol to it
            var pointGraphic = new Graphic({
                geometry: multipoint,
                symbol: markerSymbol,
            });
            // var pointLayer = new GraphicsLayer({graphics: pointGraphic})
            // Add the graphics to the view's graphics layer
            // view.graphics.addMany([pointGraphic]);

            //добавляем слой
            var pointLayer = new FeatureLayer();
            pointLayer.graphics.add(pointGraphic);
            pointLayer.add(pointGraphic);
            pointLayer.popup.autoOpenEnabled = true;
            pointLayer.popup.popupEnabled = true;
            pointLayer.on("click", function(event) {
                var lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
                var lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

                pointLayer.popup.open({
                    // Set the popup's title to the coordinates of the location
                    title: "Reverse geocode: [" + lon + ", " + lat + "]",
                    location: event.mapPoint // Set the location of the popup to the clicked location
                });
            }
            map.add(pointLayer);
        });
    </script>
</head>
<body>
<h1>Станции и обсерватории</h1>
<div id="viewDiv"></div>
</body>
</html>

Re: Cобытие click

Добавлено: 19 дек 2018, 09:58
novia
вариантов не особо много.
1. запрос identify task к mapservice с координатами клика
2. query task к конкретному слою по пересечению с координатами клика
3. отображение при нажатии на объект из слоя feature layer/graphic layer, которые "уже на клиенте"

Re: Cобытие click

Добавлено: 19 дек 2018, 10:26
Неуловимый_Джо
novia писал(а):
19 дек 2018, 09:58
3. отображение при нажатии на объект из слоя feature layer/graphic layer, которые "уже на клиенте"
Хотелось бы реализовать данный вариант, но не представляю как это возможно сделать?

Re: Cобытие click

Добавлено: 19 дек 2018, 11:11
novia
нужно на объектах типа Graphic слушать клики мыши

Re: Cобытие click

Добавлено: 19 дек 2018, 11:34
Неуловимый_Джо
Попробовал слушать клики на слое Graphic, ничего не получается, точки вовсе перестали отображаться.

Код: Выделить всё

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
    <script src="https://js.arcgis.com/4.10/"></script>

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        require([
            "esri/Map",
            "esri/layers/GraphicsLayer",
            "esri/views/MapView",
            "esri/Graphic",
            "esri/tasks/Locator",
        ], function (
            Map, GraphicsLayer, MapView, Graphic, Locator
        ) {
            var locatorTask = new Locator({
            url: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
            });
            var map = new Map({
                basemap: "hybrid"
            });

            var view = new MapView({
                center: [-80, 35],
                container: "viewDiv",
                map: map,
                zoom: 3
            });
            /*************************
             * Create a point graphic
             *************************/
            var multipoint = {
                type: "multipoint",
                points: {{ResponseData}},
            };
            // Create a symbol for drawing the point
            var markerSymbol = {
                type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
                color: [111, 119, 40],
                outline: { // autocasts as new SimpleLineSymbol()
                    color: [1, 255, 255],
                    width: 1
                }
            };
            var template = {
                title: "{{Descr}}"
            };
            // Create a graphic and add the geometry and symbol to it
            var pointGraphic = new Graphic({
                geometry: multipoint,
                symbol: markerSymbol,
            });
            //добавляем слой
            var pointLayer = new GraphicsLayer();
            pointLayer.add(pointGraphic);
            pointLayer.popup.autoOpenEnabled = false;
            pointLayer.on("click", function(event) {

                // Get the coordinates of the click on the view
                var lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
                var lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

                pointLayer.popup.open({
                // Set the popup's title to the coordinates of the location
                    title: "Reverse geocode: [" + lon + ", " + lat + "]",
                    location: event.mapPoint // Set the location of the popup to the clicked location
                });
             });
            map.add(pointLayer);
        });
    </script>
</head>
<body>
<h1>Станции и обсерватории</h1>
<div id="viewDiv"></div>
</body>
</html>

Re: Cобытие click

Добавлено: 20 дек 2018, 10:01
novia
как минимум тут ошибка
points: {{ResponseData}},
и лишняя запятая и непонятно, что такое ResponseData

и, если мне не изменяет память, в примерах на сайтах esri on("click",) вешали не на слой, а на объект (на каждый) типа Graphic

Re: Cобытие click

Добавлено: 20 дек 2018, 14:31
Неуловимый_Джо
Для начала, уточню что я работаю в фреймворке Django. {{ResponseData}} это массив координат точек вида ResponseData= [[-122.63, 45.51], [-122.56, 45.51], [-122.56, 45.55]]. Этот массив передается с view.py в station_list.html, то есть в js скрипт. Ниже представленный код работает, то есть я создаю слой, добавляю в него точки, в результате у меня отображается карта на которой, отображаются точки. Но у меня не получается никак прописать событие, которое при клике на точку выводит её координаты.
view.py:

Код: Выделить всё

from django.shortcuts import render
from django.views.generic import TemplateView
from .models import Station

def get_point(): #Формируем массив с координатами точек
    pointlat = Station.objects.values_list("latitude", flat=True) #Получаем широту точки выполняя запрос к БД
    pointlong = Station.objects.values_list("longitude", flat=True) #Получаем долготу точки выполняя запрос к БД
    points = [] # массив который будет содержать внутри себя координаты точек
    i = 0
    while i < len(pointlat):
        points.append([float(pointlong[i]), float(pointlat[i])])
        i += 1
    return (points)
    # return (point)

class List(TemplateView):
    template_name = 'station_list.html'

    def get(self, request):
        all_stations = Station.objects.all()
        ResponseData = get_point()  #Получаем массив с координатами точек
        ctx = {
           'ResponseData': ResponseData #Передаем все что необходимо отправить в ctx
        }
        return render(request, self.template_name, ctx)
station_list.html

Код: Выделить всё

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
    <script src="https://js.arcgis.com/4.10/"></script>
    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        require([
            "esri/Map",
            "esri/layers/GraphicsLayer",
            "esri/views/MapView",
            "esri/Graphic"
        ], function (
            Map, GraphicsLayer, MapView, Graphic
        ) {
            var view = new MapView({
                center: [-80, 35],
                container: "viewDiv",
                map: map,
                zoom: 3
            });
            /*************************
             * Create a point graphic
             *************************/
            var multipoint = {
                type: "multipoint",
                points: {{ResponseData}},
            };
            // Create a symbol for drawing the point
            var markerSymbol = {
                type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
                color: [111, 119, 40],
                outline: { // autocasts as new SimpleLineSymbol()
                    color: [1, 255, 255],
                    width: 1
                }
            };
            var template = {
                title: "{{Descr}}"
            };
            // Create a graphic and add the geometry and symbol to it
            var pointGraphic = new Graphic({
                geometry: multipoint,
                symbol: markerSymbol
            });
            //добавляем слой
            var pointLayer = new GraphicsLayer();
            pointLayer.add(pointGraphic);
            map.add(pointLayer);
        });
    </script>
</head>
<body>
<h1>Станции и обсерватории</h1>
<div id="viewDiv"></div>
</body>
</html>

Re: Cобытие click

Добавлено: 20 дек 2018, 14:46
Неуловимый_Джо
Вот я не понимаю как вешать событие на объект типа Graphic, и сделать так чтобы при клике выводились правильные координаты точек. Нашел только пример https://developers.arcgis.com/javascrip ... tro-popup/, попробовал сделать, так, чтобы при клике выводились координаты точек. Проблема в том что если сделать, как в примере с локатором адресов, то координаты клика выводятся, если даже клик совершен не на точке. Послушав совет novia, я попытался повесить событие on("click") на объект типа Graphic. Но в результате точки вовсе перестали отображаться. Ниже представлены результат в виде рисунка и измененный код station_list.html

Код: Выделить всё

!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
    <script src="https://js.arcgis.com/4.10/"></script>

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <script>
        require([
            "esri/Map",
            "esri/layers/GraphicsLayer",
            "esri/views/MapView",
            "esri/Graphic",
            "esri/tasks/Locator",
        ], function (
            Map, GraphicsLayer, MapView, Graphic, Locator
        ) {
            var locatorTask = new Locator({
            url: "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer"
            });
            var map = new Map({
                basemap: "hybrid"
            });

            var view = new MapView({
                center: [-80, 35],
                container: "viewDiv",
                map: map,
                zoom: 3
            });
            /*************************
             * Create a point graphic
             *************************/
            var multipoint = {
                type: "multipoint",
                points: {{ResponseData}},
            };
            // Create a symbol for drawing the point
            var markerSymbol = {
                type: "simple-marker", // autocasts as new SimpleMarkerSymbol()
                color: [111, 119, 40],
                outline: { // autocasts as new SimpleLineSymbol()
                    color: [1, 255, 255],
                    width: 1
                }
            };
            var template = {
                title: "{{Descr}}"
            };
            // Create a graphic and add the geometry and symbol to it
            var pointGraphic = new Graphic({
                geometry: multipoint,
                symbol: markerSymbol
            });
            //добавляем слой
            var pointLayer = new GraphicsLayer();
            pointGraphic.popup.autoOpenEnabled = false;
            pointGraphic.on("click", function(event) {

                // Get the coordinates of the click on the view
                var lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
                var lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

                pointGraphic.popup.open({
                // Set the popup's title to the coordinates of the location
                    title: "Reverse geocode: [" + lon + ", " + lat + "]",
                    location: event.mapPoint // Set the location of the popup to the clicked location
                });
             });
            pointLayer.add(pointGraphic);
            map.add(pointLayer);
        });
    </script>
</head>
<body>
<h1>Станции и обсерватории</h1>
<div id="viewDiv"></div>
</body>
</html>

Re: Cобытие click

Добавлено: 20 дек 2018, 17:47
novia
а если вешать событие on на Graphic после добавления точки к слою, а не до?

Re: Cобытие click

Добавлено: 20 дек 2018, 20:58
Неуловимый_Джо
Повесил событие on на Graphic после добавления точки к слою, все равно таже проблема

Код: Выделить всё

var pointLayer = new GraphicsLayer();
            pointLayer.add(pointGraphic);
            pointGraphic.popup.autoOpenEnabled = false;
            pointGraphic.on("click", function(event) {

                // Get the coordinates of the click on the view
                var lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
                var lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

                pointGraphic.popup.open({
                // Set the popup's title to the coordinates of the location
                    title: "Reverse geocode: [" + lon + ", " + lat + "]",
                    location: event.mapPoint // Set the location of the popup to the clicked location
                });
            });
            map.add(pointLayer);

Re: Cобытие click

Добавлено: 21 дек 2018, 07:27
novia
раньше, в примерах для flex api такое событие вешали на graphic в отработчике события самого слоя <onGraphicAdd> (точное название уже не вспомню). то есть в момент, когда графика "уже на карте"
но перед тем как гуглить то, что написано выше, попробуйте еще и слой сам на карту добавлять перед тем, как добавляется графика.

Re: Cобытие click

Добавлено: 21 дек 2018, 09:24
Неуловимый_Джо
Точки снова отобразились, но при щелчке событие не срабатывает. К сожалению для меня flex api не подходит, реализовать надо именно в arcgis js api

Код: Выделить всё

 var pointLayer = new GraphicsLayer();
            map.add(pointLayer);
            pointLayer.add(pointGraphic);
            pointGraphic.popup.autoOpenEnabled = false;
            pointGraphic.on("click", function(event) {

                // Get the coordinates of the click on the view
                var lat = Math.round(event.mapPoint.latitude * 1000) / 1000;
                var lon = Math.round(event.mapPoint.longitude * 1000) / 1000;

                pointGraphic.popup.open({
                // Set the popup's title to the coordinates of the location
                    title: "Reverse geocode: [" + lon + ", " + lat + "]",
                    location: event.mapPoint // Set the location of the popup to the clicked location
                });
            });

Re: Cобытие click

Добавлено: 21 дек 2018, 12:35
Неуловимый_Джо
Получилось, сделать следующим образом:

Код: Выделить всё

view.on("click", function (event) {
                var screenPoint = {
                    x: event.x,
                    y: event.y
                };

                // Search for graphics at the clicked location
                view.hitTest(screenPoint).then(function (response) {
                    if (response.results.length) {
                        var graphic = response.results.filter(function (result) {
                            // check if the graphic belongs to the layer of interest
                            return result.graphic.layer === pointLayer;
                        })[0].graphic;
                        // do something with the result graphic
                        view.popup.open({
                            // Set the popup's title to the coordinates of the location
                            title: "Reverse geocode: [",
                            location: event.mapPoint
                        });
                    }
                });
            });
Теперь только при клике на точку выводится окошко. Спасибо вам большое novia, только благодаря нашей дискуссии, я во всем разобрался!

Re: Cобытие click

Добавлено: 21 дек 2018, 15:14
novia
Неуловимый_Джо писал(а):
21 дек 2018, 09:24
К сожалению для меня flex api не подходит, реализовать надо именно в arcgis js api
это я сразу понял. но в те далекие времена, когда flex api был актуален, рекомендуемый подход был как я описывал выше. сейчас я лишь предлагал одно из направлений поиска. при этом похожих примеров в актуальной версии js api уже не нахожу.

а нахожу следующее:
посмотрел текущие примеры реализации всплывающих окон и пришел к выводу, что отработку кликов по графике взял на себя API. разработчикам предлагают сконцентрироваться не на обработке кликов, а на визуализации контента. что, в принципе, не так плохо.
по этой ссылке пройдите шаги начиная со второго, чтобы создать шаблон окна
https://developers.arcgis.com/javascrip ... index.html
и потом назначьте его как шаблон окна popupTemplate для Graphic. инфоокно при клике на графике должно отобразиться "само" при наличии шаблона.
The default behavior on a Graphic is to show the view's Popup after a click on the Graphic. A PopupTemplate is required for this default behavior.
отсюда - https://developers.arcgis.com/javascrip ... plate.html
pointGraphic.popup.autoOpenEnabled = false;
а для чего вы такое писали? если возьметесь делать что написал выше, эту строку скорее всего нужно будет убрать


з.ы. в справке API теперь рекомендуют создавать для "своей" графики FeatureLayer. Он будет похож на слой графики, но с дополнительными плюшками.

и так как у FeatureLayer схема атрибутов одинаковая для всех объектов слоя, то и popupTemplate нужно будет задать 1 раз для всего слоя целиком. У слоя графики атрибуты у объектов могут быть любыми, поэтому шаблон инфоокна задается на уровне объекта.