質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Leaflet

Leafletは、Web上で地図を作成するためのJavaScriptライブラリ。人気のあるJavaScript地図ライブラリのうちの一つでオープンソースです。軽量でインタラクティブな地図を手軽に表示することができます。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

2452閲覧

Leaflet シングルクリックとダブルクリックのイベントを区別したい

okiron9619

総合スコア5

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Leaflet

Leafletは、Web上で地図を作成するためのJavaScriptライブラリ。人気のあるJavaScript地図ライブラリのうちの一つでオープンソースです。軽量でインタラクティブな地図を手軽に表示することができます。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/11/02 05:48

編集2020/11/02 05:50

前提・実現したいこと

Leafletを用いて、マップ上にマーカーを設置し、マーカーをクリック、ダブルクリックした時に別々の処理を行いたいです。
今回の場合は、
シングルクリックイベントでは、マーカーのポップアップコメントを
ダブルクリックイベントでは、クリックした座標のアラートを表示したいと考えています。

発生している問題・エラーメッセージ

ダブルクリックの場合、シングルクリックイベント2回、ダブルクリックイベント1回が呼び出される状態です。

該当のソースコード

javascript

1let mymap = null; 2let spotListLayer = null; 3function init() { 4 mymap = L.map('mapid').setView([35.015299, 135.677990], 19); 5 L.tileLayer( 6 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { 7 attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a>', 8 maxZoom: 19, 9 minZoom: 19, 10 } 11 ).addTo(mymap); 12 mymap.createPane("pane620").style.zIndex = 620; 13} 14onEachSpotFeature = function onEachFeature(feature, layer) { 15 layer.on('click', function(e) { 16 console.log('single'); 17 var popLocation= e.latlng; 18 var popup = L.popup() 19 .setLatLng(popLocation) 20 .setContent('Hello') 21 .openOn(mymap); 22 }); 23 layer.on('dblclick', function(e) { 24 //ダブルクリック位置経緯度取得 25 const lat = e.latlng.lat; 26 const lng = e.latlng.lng; 27 //経緯度表示 28 alert('lat: ' + lat + ', lng: ' + lng); 29 }) 30} 31$(function() { 32 // 全体の初期化処理 33 init(); 34 getSpotList(912); 35}); 36function showSpotListLayer(geojson) { 37 if (spotListLayer != null) { 38 mymap.removeLayer(spotListLayer); 39 } 40 // マーカを生成する. 41 spotListLayer = L.geoJSON(geojson, { 42 onEachFeature:onEachSpotFeature, 43 pointToLayer: function( feature, latlng ) { 44 switch (feature.properties.spot.state) { 45 case 1: return L.marker( latlng, { riseOnHover: true }); 46 case 0: return L.marker( latlng, { riseOnHover: true }); 47 } 48 } 49 }).addTo(mymap); 50 // マップレイヤにspotListLayerを追加する. 51 spotListLayer.addTo(mymap); 52} 53function getSpotList(node_id) { 54 $.ajax({ 55 url: 'spot/', 56 method: 'GET', 57 data: { 58 'node_id': node_id, 59 }, 60 timeout: 10000, 61 dataType: "json", 62 }).done(function(response) { 63 let geojson = response; 64 showSpotListLayer(geojson); 65// console.log(geojson); 66 }).fail(function(response) { 67 window.alert('getSpotList() : レスポンス失敗'); 68 }); 69}

python

1views.py 2スポットの緯度経度、id0,1の状態を取得しています。 3from django.shortcuts import render 4from django.http import HttpResponse 5from django.views.generic import View 6 7from .models import Node, LinkNode, Visited, Spot, Spot_State, Spot_Mesh 8from .models import Mesh, Mesh_State, Link_Mesh 9from .view_models import SpotMapper 10 11import json 12class SpotView(View): 13 def get(self, request, *args, **kwargs): 14 """ 15 スポットリストの取得 16 """ 17 # リクエストの取得 18 visited_node_id = request.GET.get('node_id') 19 #実験 20 #クリックしたノードをstart_node_idとするLinkNodeオブジェクトの取得 21 adjacent_node_list = LinkNode.objects.filter(start_node_id= visited_node_id) 22 node_list = []#クリックしたノードに隣接するノードが訪問済みであるノードのリスト 23 remove_list = []#リンク格納用リスト 24 link_meshes = []#初期ロード以外専用 25 spot_mesh_list = []#初期ロード専用 26 link_id = 0 27 for adjacent_node in adjacent_node_list: 28 #クリックしたノードの隣接ノード取得 29 node_id = adjacent_node.end_node_id 30 #クリックしたノードの隣接ノードの内、訪問済みのノードのリストを取得 31 lists = Visited.objects.filter(node_id=node_id, state=1) 32 for list in lists: 33 node_list.append(list) 34 #開始地点やクリックしたノードが終点の場合は、省く 35 if(len(node_list) > 0): 36 #クリックしたノードがstart_node_idかつ直前のノードが訪問済みであるノードがend_node_idであるLinkNodeオブジェクトの取得 37 remove_lists = LinkNode.objects.filter(start_node_id= visited_node_id, end_node_id = node_list[0].node_id) 38 for remove in remove_lists: 39 remove_list.append(remove) 40 #link_idの取得、マイナスの場合は反転 41 link_id = remove_list[0].link_id 42 if(remove_list[0].link_id < 0): 43 link_id = remove_list[0].link_id * -1 44 print('link_id = ' + str(link_id)) 45 #初期ロードのみ、link_idは0 46 if(link_id > 0): 47 #Link_Meshオブジェクト(リンクと共有するメッシュ)の取得 48 links_meshes_lists = Link_Mesh.objects.filter(link_id = link_id) 49 for links_meshes in links_meshes_lists: 50 link_meshes.append(links_meshes) 51 print(link_meshes[-1].mesh_id) 52 spot_mesh = Spot_Mesh.objects.filter(mesh_id = link_meshes[-1].mesh_id) 53 for spot in spot_mesh: 54 spot_mesh_list.append(spot) 55 #取得したスポットidの状態を0にする 56 Spot_State(spot_id = spot_mesh_list[-1].spot_id, state = 0 ).save() 57 if(link_id == 0): 58 #初期ロードの時のみ、ノードーメッシュースポットの順でスポットの状態を変更 59 # オブジェクトの取得 60 #ノードidからメッシュidの取得 61 node_mesh = Node_Mesh.objects.filter(node_id = visited_node_id) 62 node_mesh_list = [] 63 spot_mesh_list = [] 64 for mesh in node_mesh: 65 node_mesh_list.append(mesh) 66 #メッシュidからスポットidの取得 67 spot_mesh = Spot_Mesh.objects.filter(mesh_id = node_mesh_list[-1].mesh_id) 68 for spot in spot_mesh: 69 spot_mesh_list.append(spot) 70 #取得したスポットidの状態を0にする 71 Spot_State(spot_id = spot_mesh_list[-1].spot_id, state = 0 ).save() 72 spots_list = Spot_State.objects.all() 73 # レスポンスの生成 74 features = [SpotMapper(spot).as_dict() for spot in spots_list] 75 response = { 76 'type': 'FeatureCollection', 77 'crs': { 78 'type': 'name', 79 'properties': { 80 'name': 'EPSG:4326', 81 }, 82 }, 83 'features': features, 84 } 85 response_json = json.dumps(response) 86 87 # レスポンスの返却 88 return HttpResponse(response_json, content_type='application/json') 89spot_view = SpotView.as_view()

python

1view_models.py 2class SpotMapper: 3 """スポットマッパー""" 4 5 def __init__(self, obj): 6 self.obj = obj 7 8 def as_dict(self): 9 spot = self.obj 10 #0ならtrue、それ以外はfalseに変換 11 """ 12 def str2bool(v): 13 return v.lower() in ("0") 14 """ 15 return { 16 'type': 'Feature', 17 'properties': { 18 'spot': { 19 'spot_id': spot.spot.spot_id, 20 'name': spot.spot.name, 21 'state': spot.state, 22 }, 23 }, 24 'geometry': { 25 'type': 'Point', 26 'coordinates': [spot.spot.latlng.x, spot.spot.latlng.y], 27 }, 28 }
spotsテーブル 列 | 型 | 照合順序 | Null 値を許容 | デフォルト ---------+-----------------------+----------+---------------+------------ spot_id | integer | | not null | name | character varying(50) | | not null | latlng | geometry(Point,4326) | | not null | spot_id | name | latlng ---------+----------------------------------------------------+---------------------------------------------------- 1 | Ranzan | 0101000020E61000001E53776597F5604090381A76CE814140 spots_stateテーブル 列 | 型 | 照合順序 | Null 値を許容 | デフォルト ---------+---------+----------+---------------+------------ spot_id | integer | | not null | state | integer | | | spot_id | state ---------+------- 1 | 1

試したこと

クリック数をカウントする変数を置いて(mymap.clicked = 0;のように)、onEachFeatureオプションの関数内にて、カウント数をクリックに応じて変更し、カウント数が1であればシングル、2であればダブルのクリックイベントを処理するようにしたのですが、
onEachFeatureオプションは、クリックするたびに呼び出されるのではないため、変数を上手く扱うことができませんでした。
※自分の記述方法が間違っているかもしれません。

補足情報(FW/ツールのバージョンなど)

python3.8
Leaflet1.7.1
Django3.0.8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

下記のように、onEachFeatureオプション部分を変更することで(質問の際にも、変更部分については見つけていたのですが、コードの記述方法がまずかったようです)、シングルクリック、ダブルクリックそれぞれが区別され、ダブルクリックの際に同時にシングルクリックも発火しなくなりました。

javascript

1onEachFeatureオプション部分 2onEachSpotFeature = function onEachFeature(feature, layer) { 3 mymap.clicked = 0; 4 layer.on('click', function(e) { 5 mymap.clicked = mymap.clicked + 1; 6 setTimeout(function(){ 7 if(mymap.clicked == 1){ 8 var popLocation= e.latlng; 9 var popup = L.popup() 10 .setLatLng(popLocation) 11 .setContent('Hello') 12 .openOn(mymap); 13 } 14 },300); 15 }); 16 layer.on('dblclick', function(e) { 17 mymap.clicked = 0; 18 //ダブルクリック位置経緯度取得 19 const lat = e.latlng.lat; 20 const lng = e.latlng.lng; 21 //経緯度表示 22 alert('lat: ' + lat + ', lng: ' + lng); 23 }) 24}

投稿2020/11/03 03:49

okiron9619

総合スコア5

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問