javascript example - HTMLElement에서 google.maps.Map 인스턴스 가져 오기




marker functions (5)

페이지에 기존지도가 있습니다. document.getElementById ()의 행을 따라 HTMLElement javascript 객체를 가져와 해당 요소를 선택할 수 있습니다. 지도가 초기화 될 때 생성 된 google.maps.Map의 인스턴스를 가져올 수 있습니까? 예 : HTMLElement 객체 또는 프로토 타입에 속성이 있습니까?


Answers

Google Maps 객체가 생성 된 DOM Element 에서 google.maps.Map 객체를 가져올 수 없습니다. google.maps.Map 은 맵을보기 위해 DOM Element 를 제어하는 ​​래퍼이며 요소에는 래퍼에 대한 참조가 없습니다.

문제가 스코프 인 경우 mapwindow 객체의 속성으로 설정하면 페이지의 모든 곳에서 액세스 할 수 있습니다. 다음 중 하나를 사용하여 'map' 를 전역으로 만들 수 있습니다.

 window.map = new google.maps.Map(..) 

또는

 map = new google.maps.Map(...) //AVOID 'var' 

Polymer 프로젝트의 Google지도 구성 요소를 사용하는 경우 다음과 같이 기존지도 Dom을 가져올 수 있습니다.

var map = document.querySelector('google-map');

일단지도가 있으면 다음과 같이지도의 현재 인스턴스에 액세스 할 수 있습니다.

var currentMapInstance = map.map;

DOM Element 에서 google.maps.Map 객체를 약간의 트릭으로 얻을 수 있습니다.

맵 오브젝트를 초기화 할 때 요소의 데이터 속성에 오브젝트를 저장해야합니다.

예:

$.fn.googleMap = function (options) {
    var _this = this;

    var settings = $.extend({}, {
        zoom: 5,
        centerLat: 0,
        centerLon: 0
    }, options);

    this.initialize = function () {
        var mapOptions = {
            zoom: settings.zoom
        };

        var map = new google.maps.Map(_this.get(0), mapOptions);
        // do anything with your map object here,
        // eg: centering map, adding markers' events

        /********************************************
         * This is the trick!
         * set map object to element's data attribute
         ********************************************/
        _this.data('map', map);

        return _this;
    };
    // ... more methods

    return this;
};

지도 요소를 정의한 후 (예 :

var mapCanvas = $('#map-canvas');
var map = mapCanvas.googleMap({
    zoom: 5,
    centerLat: 0,
    centerLong: 0
});
// ... add some pre-load initiation here, eg: add some markers
// then initialize map
map.initialize();

나중에 요소 ID를 사용하여 나중에지도 객체를 가져올 수 있습니다. 예 :

var mapCanvas = $('#map-canvas');
$('.location').on('click', function () {
    // google map takes time to load, so it's better to get
    // the data after map is rendered completely
    var map = mapCanvas.data("map");
    if (map) {
        map.panTo(new google.maps.LatLng(
            $(this).data('latitude'),
            $(this).data('longitude')
            ));
    }
});

이 방법을 사용하면 한 페이지에 다른 동작을 가진 여러 맵을 가질 수 있습니다.


지도를 초기화 할 때 인스턴스를 만듭니다.

var map = new google.maps.Map(document.getElementById("map_element"), options);

마커 넣기, 위치 변경하기 등과 같은 작업을 원할 때마다이 인스턴스를 사용합니다. HTMLElement 객체가 아닙니다. 그러나 그것은 getDiv() 메소드를 가지고 있으며,이 메소드는 여러분이 getDiv() html 요소를 제공합니다.

map.getDiv(); // in this case it returns the element with the id 'map_element'

빠른 답변 :
하위 범위는 일반적으로 부모 범위에서 프로토 타입 적으로 상속되지만 항상 그런 것은 아닙니다. 이 규칙의 한 가지 예외는 scope: { ... } 가있는 지시문입니다 scope: { ... } - 프로토 타입으로 상속하지 않는 "격리"범위를 만듭니다. 이 구문은 "재사용 가능한 구성 요소"지시문을 만들 때 종종 사용됩니다.

뉘앙스에 관해서는, 스코프 상속은 일반적으로 직선적입니다. 하위 범위에서 양방향 데이터 바인딩 (즉, 폼 요소, ng-model)이 필요하기 전까지는. Ng-repeat, ng-switch 및 ng-include는 하위 범위 내부에서 부모 범위의 기본 요소 (예 : 숫자, 문자열, 부울)에 바인딩하려고하면 사용자를 빠져 나갈 수 있습니다. 그것은 대부분의 사람들이 기대해야하는 방식으로 작동하지 않습니다. 자식 범위는 같은 이름의 부모 속성을 숨기거나 그려주는 자체 속성을 가져옵니다. 해결 방법은 다음과 같습니다.

  1. 모델에 대한 부모의 객체를 정의한 다음 하위 객체에서 해당 객체의 속성을 참조하십시오. parentObj.someProp
  2. $ parent.parentScopeProperty를 사용하십시오 (항상 가능한 것은 아니지만 가능한 경우 1보다 쉽습니다).
  3. 부모 범위에서 함수를 정의하고 자식에서 호출합니다 (항상 가능하지는 않음).

새로운 AngularJS 개발자는 새로운 ng-repeat , ng-switch , ng-view , 종료 및 ng-include 모두 인식하지 못하기 때문에 이러한 지시문이 포함될 때 문제가 자주 발생합니다. 문제의 간단한 설명은 이 예제 를 참조하십시오.

프리미티브에 대한이 문제는 항상 '최상의 방법'을 따르는 것으로 쉽게 피할 수 있습니다 . 네 - 모델에서 - 3 분 가치가 시계. Misko는 ng-switch 와의 기본적인 바인딩 문제를 보여줍니다.

가있는 '.' 모델에서 프로토 타입 상속이 작동하는지 확인합니다. 그래서, 사용

<input type="text" ng-model="someObj.prop1">

<!--rather than
<input type="text" ng-model="prop1">`
-->

긴 대답 :

JavaScript Prototypal Inheritance

또한 AngularJS 위키에 배치되었습니다. https://github.com/angular/angular.js/wiki/Understanding-Scopes

먼저 프로토 타입 상속에 대한 확실한 이해가 중요합니다. 특히 서버 측 배경에서 왔을 때 클래스 상속에 익숙하다면 더욱 그렇습니다. 먼저 검토해 보겠습니다.

parentScope에 aString, aNumber, anArray, anObject 및 aFunction 속성이 있다고 가정합니다. childScope가 parentScope에서 프로토 타입 적으로 상속받은 경우, 우리는 다음을 얻습니다 :

공간을 절약하기 위해 anArray 객체는 3 개의 개별 회색 리터럴을 가진 단일 파란색 객체가 아니라 3 개의 값이있는 단일 파란색 객체로 표시됩니다.

하위 범위에서 parentScope에 정의 된 속성에 액세스하려고하면 자바 스크립트는 먼저 하위 범위를보고 속성을 찾지 않고 상속 된 범위를보고 속성을 찾습니다. (parentScope에서 속성을 찾지 못하면 프로토 타입 체인을 루트 범위까지 계속 확장합니다.) 그래서, 이것들은 모두 사실입니다 :

childScope.aString === 'parent string'
childScope.anArray[1] === 20
childScope.anObject.property1 === 'parent prop1'
childScope.aFunction() === 'parent output'

우리가 다음과 같이한다고 가정 해보십시오.

childScope.aString = 'child string'

프로토 타입 체인은 참조되지 않으며 새 aString 속성이 childScope에 추가됩니다. 이 새 속성은 동일한 이름의 parentScope 속성을 숨기거나 음영 처리합니다. 아래에서 ng-repeat 및 ng-include를 논의 할 때 이것은 매우 중요하게됩니다.

우리가 다음과 같이한다고 가정 해보십시오.

childScope.anArray[1] = '22'
childScope.anObject.property1 = 'child prop1'

객체 (anArray 및 anObject)가 childScope에 없기 때문에 프로토 타입 체인을 참조합니다. 객체는 parentScope에서 찾을 수 있으며 속성 값은 원본 객체에서 업데이트됩니다. childScope에 추가 된 새 속성이 없습니다. 새로운 객체가 생성되지 않습니다. JavaScript 배열과 함수도 객체입니다.

우리가 다음과 같이한다고 가정 해보십시오.

childScope.anArray = [100, 555]
childScope.anObject = { name: 'Mark', country: 'USA' }

프로토 타입 체인은 참조되지 않으며 하위 범위는 동일한 이름을 가진 parentScope 객체 속성을 숨기거나 그림자 처리하는 두 개의 새 객체 속성을 가져옵니다.

테이크 아웃 :

  • childScope.propertyX를 읽고 childScope에 propertyX가 있으면 프로토 타입 체인을 참조하지 않습니다.
  • childScope.propertyX를 설정하면 프로토 타입 체인을 참조하지 않습니다.

하나의 마지막 시나리오 :

delete childScope.anArray
childScope.anArray[1] === 22  // true

먼저 childScope 속성을 삭제 한 다음 속성에 다시 액세스하려고하면 프로토 타입 체인을 참조합니다.

각도 범위 상속

경쟁자 :

  • 다음은 새 범위를 만들고 ng-repeat, ng-include, ng-controller, ng-controller, scope: true 지시문 scope: true , transclude: truetransclude: true 지시문 scope: true 프로토 타입으로 상속 transclude: true .
  • 다음은 프로토 타입을 상속받지 않는 새 범위를 만듭니다. 범위가있는 지시문 scope: { ... } . 대신 "격리"범위가 생성됩니다.

기본적으로 지시문은 새로운 범위를 만들지 않습니다. 즉, 기본값은 scope: false 입니다.

NG 포함

컨트롤러에 있다고 가정 해보십시오.

$scope.myPrimitive = 50;
$scope.myObject    = {aNumber: 11};

그리고 우리의 HTML에서 :

<script type="text/ng-template" id="/tpl1.html">
<input ng-model="myPrimitive">
</script>
<div ng-include src="'/tpl1.html'"></div>

<script type="text/ng-template" id="/tpl2.html">
<input ng-model="myObject.aNumber">
</script>
<div ng-include src="'/tpl2.html'"></div>

각 ng-include는 부모 범위에서 프로토 타입 적으로 상속되는 새 하위 범위를 생성합니다.

첫 번째 입력 텍스트 상자에 입력 (예 : "77")을 입력하면 하위 범위에서 동일한 이름의 부모 범위 속성을 숨기거나 그림자를 적용하는 새 myPrimitive 범위 속성을 가져옵니다. 이것은 아마도 당신이 원하는 / 예상하지 않습니다.

두 번째 입력란에 타이핑 (예 : "99")해도 새 하위 속성이 생성되지 않습니다. tpl2.html은 모델을 객체 속성에 바인딩하기 때문에 ngModel이 myObject 객체를 찾을 때 prototypal inheritance가 시작됩니다. 부모 객체에서 this를 찾습니다.

모델을 기본 객체에서 객체로 변경하지 않으려면 $ parent를 사용하는 첫 번째 템플릿을 다시 작성할 수 있습니다.

<input ng-model="$parent.myPrimitive">

이 입력 텍스트 상자에 타이핑 (예 : "22")을하면 ​​새 하위 속성이 생성되지 않습니다. 모델은 이제 부모 범위의 속성에 바인딩됩니다 ($ parent는 부모 범위를 참조하는 자식 범위 속성이기 때문에).

모든 범위 (원형 또는 원형)에 대해 Angular는 항상 범위 속성 $ parent, $$ childHead 및 $$ childTail을 통해 부모 - 자식 관계 (즉, 계층 구조)를 추적합니다. 나는 일반적으로 다이어그램에서 이러한 범위 속성을 표시하지 않습니다.

폼 요소가 관련되지 않은 시나리오의 경우 다른 솔루션은 부모 범위에서 프리미티브를 수정하는 함수를 정의하는 것입니다. 그런 다음 자식이 항상이 함수를 호출하는지 확인하십시오.이 함수는 프로토 타입 상속으로 인해 하위 범위에서 사용할 수 있습니다. 예를 들어,

// in the parent scope
$scope.setMyPrimitive = function(value) {
     $scope.myPrimitive = value;
}

다음은 "부모 기능"접근법을 사용하는 샘플 피들 입니다. 이 바이올린은이 답변의 일부로 작성되었습니다 ( https://.com/a/14104318/215945 .

https://.com/a/13782671/215945 및 https://github.com/angular/angular.js/issues/1267 .

ng 스위치

ng-switch 범위 상속은 ng-include와 동일하게 작동합니다. 따라서 상위 범위의 프리미티브에 양방향 데이터 바인딩이 필요하면 $ parent를 사용하거나 모델을 개체로 변경 한 다음 해당 개체의 속성에 바인딩하십시오. 이렇게하면 부모 범위 속성의 자식 범위 숨기기 / 섀도 잉이 수행되지 않습니다.

AngularJS, switch-case의 바인드 범위를 보시오 ?

반복

Ng 반복은 조금 다르게 작동합니다. 컨트롤러에 있다고 가정 해보십시오.

$scope.myArrayOfPrimitives = [ 11, 22 ];
$scope.myArrayOfObjects    = [{num: 101}, {num: 202}]

그리고 우리의 HTML에서 :

<ul><li ng-repeat="num in myArrayOfPrimitives">
       <input ng-model="num">
    </li>
<ul>
<ul><li ng-repeat="obj in myArrayOfObjects">
       <input ng-model="obj.num">
    </li>
<ul>

각 항목 / 반복에 대해 ng-repeat는 새로운 범위를 만듭니다.이 범위는 프로토 타입 적으로 상위 범위에서 상속 되지만 항목의 값은 새 하위 범위의 새 속성에 할당됩니다 . (새 속성의 이름은 루프 변수의 이름입니다.) ng-repeat의 Angular 소스 코드는 실제로 다음과 같습니다.

childScope = scope.$new();  // child scope prototypically inherits from parent scope
...
childScope[valueIdent] = value;  // creates a new childScope property

item이 프리미티브 인 경우 (myArrayOfPrimitives에서와 같이) 본질적으로 값의 복사본이 새 하위 범위 속성에 할당됩니다. 자식 범위 속성의 값을 변경하면 (즉, ng-model을 사용하므로 자식 범위 num ) 부모 범위가 참조하는 배열이 변경되지 않습니다 . 따라서 위의 첫 번째 반복에서 각 하위 범위는 myArrayOfPrimitives 배열과 독립적 인 num 속성을 가져옵니다.

이 ng-repeat는 작동하지 않습니다 (원하는대로 / 기대합니다). 텍스트 상자에 입력하면 자식 상자에서만 볼 수있는 회색 상자의 값이 변경됩니다. 우리가 원하는 것은 자식 범위 프리미티브 속성이 아니라 입력이 myArrayOfPrimitives 배열에 영향을 미치도록하는 것입니다. 이를 위해 모델을 객체의 배열로 변경해야합니다.

따라서 item이 객체이면 원본 객체에 대한 참조 (사본이 아님)가 새 하위 범위 속성에 지정됩니다. 하위 범위 속성의 값을 변경하면 (즉, ng-model을 사용하므로 obj.num ) 상위 범위가 참조하는 객체 변경됩니다. 따라서 위의 두 번째 반복에서 우리는 다음을 얻었습니다.

(회색으로 한 줄의 선을 그려서 어디로가는 지 분명히 알 수 있습니다.)

이것은 예상대로 작동합니다. 텍스트 상자에 입력하면 자식 상자와 부모 범위 모두에서 볼 수있는 회색 상자의 값이 변경됩니다.

ng-model, ng-repeat 및 입력 문제 및 https://.com/a/13782671/215945

제어 장치

ng-controller를 사용하는 중첩 컨트롤러는 ng-include 및 ng-switch와 마찬가지로 정상적인 프로토 타입 상속을 가져 오므로 동일한 기술이 적용됩니다. 그러나 "두 컨트롤러가 $ scope 상속을 통해 정보를 공유하는 것은 나쁜 형식으로 간주됩니다"- http://onehungrymind.com/angularjs-sticky-notes-pt-1-architecture/ 서비스를 사용하여 컨트롤러 대신.

컨트롤러 범위 상속을 통해 실제로 데이터를 공유하려는 경우 수행 할 작업이 하나도 없습니다. 하위 범위는 모든 부모 범위 속성에 액세스 할 수 있습니다. 참조 로드 또는 탐색시 컨트롤러로드 순서가 다릅니다.

지시문

  1. default ( scope: false ) - 지시문은 새로운 범위를 만들지 않으므로 여기에는 상속이 없습니다. 이것은 쉽지만 위험합니다. 예를 들어 지시문이 범위에서 새 속성을 만드는 것으로 생각할 수 있습니다. 예를 들어 실제로 기존 속성을 clobbering하는 경우입니다. 이것은 재사용 가능한 구성 요소로 의도 된 지시문 작성에는 적합하지 않습니다.
  2. scope: true - 지시문은 부모 범위에서 프로토 타입 적으로 상속되는 새 하위 범위를 만듭니다. 동일한 DOM 요소에있는 둘 이상의 지시문이 새 범위를 요청하면 하나의 새 하위 범위 만 만들어집니다. "정상적인"프로토 타입 상속이 있기 때문에 ng-include 및 ng-switch와 유사하므로 부모 범위 프리미티브에 대한 양방향 데이터 바인딩과 부모 범위 속성의 하위 범위 숨기기 / 섀도 잉을 조심해야합니다.
  3. scope: { ... } - 지시문은 새로운 격리 / 격리 된 범위를 만듭니다. 프로토 타입 적으로 상속받지 않습니다. 이 지시문은 실수로 부모 범위를 읽거나 수정할 수 없으므로 대개 재사용 가능한 구성 요소를 만들 때 최선의 선택입니다. 그러나 이러한 지시문은 종종 몇 가지 부모 범위 속성에 대한 액세스가 필요합니다. 객체 해시는 부모 범위와 격리 범위 사이의 양방향 바인딩 ( '='사용) 또는 단방향 바인딩 ( '@ 사용) 설정에 사용됩니다. 부모 범위 표현식에 바인딩하는 '&'도 있습니다. 따라서 이들 모두는 부모 범위에서 파생 된 로컬 범위 속성을 만듭니다. 속성은 바인딩을 설정하는 데 사용됩니다. 객체 해시에서 상위 범위 속성 이름을 참조 할 수는 없으므로 속성을 사용해야합니다. 예를 들어 격리 된 범위 인 부모 속성 parentProp <div my-directive>scope: { localProp: '@parentProp' } 에 바인딩하려는 경우에는이 옵션이 작동하지 않습니다. 지시어가 바인딩하려는 각 부모 속성을 지정하려면 특성을 사용해야합니다. <div my-directive the-Parent-Prop=parentProp> scope: { localProp: '@theParentProp' } <div my-directive the-Parent-Prop=parentProp>scope: { localProp: '@theParentProp' } .
    범위의 __proto__ 참조 객체를 분리합니다. 범위의 $ 부모 참조는 부모 범위를 참조하므로 격리되어 있고 부모 범위에서 프로토 타입을 상속받지 않지만 여전히 하위 범위입니다.
    아래 사진은
    <my-directive interpolated="{{parentProp1}}" twowayBinding="parentProp2">
    scope: { interpolatedProp: '@interpolated', twowayBindingProp: '=twowayBinding' }
    또한 지시문이 연결 함수에서이 작업을 수행한다고 가정합니다. scope.someIsolateProp = "I'm isolated"

    격리 범위에 대한 자세한 내용은 http://onehungrymind.com/angularjs-sticky-notes-pt-2-isolated-scope/ 참조하십시오.
  4. transclude: true - 지시문은 부모 범위에서 프로토 타입 적으로 상속 된 새 "중첩 된"자식 범위를 만듭니다. 중첩 된 범위와 격리 된 범위 (있는 경우)는 형제입니다. 각 범위의 $ parent 속성은 동일한 부모 범위를 참조합니다. 중첩 된 범위와 고립 된 범위가 모두 존재할 경우 범위 속성 $$ nextSibling을 분리하면 범위가 범위를 참조합니다. 나는 중첩 된 범위의 뉘앙스를 알지 못합니다.
    아래 그림에서 위와 같은 지시어를 다음과 같이 가정합니다 : transclude: true

fiddle 은 분리 및 중첩 범위를 검사하는 데 사용할 수있는 showScope() 함수를 가지고 있습니다. 바이올린의 주석에있는 지침을보십시오.

개요

범위에는 네 가지 유형이 있습니다.

  1. 일반 prototypal 범위 상속 - ng-include, ng-switch, ng-controller, scope: true 지시어 scope: true
  2. copy / assignment - ng-repeat를 사용하여 정상 원형 범위 상속. ng-repeat를 반복 할 때마다 새 하위 범위가 만들어지고 새 하위 범위는 항상 새 속성을 가져옵니다.
  3. 범위 분리 - 범위가있는 지시문 scope: {...} . 이 프로토 타입은 프로토 타입이 아니지만 '=', '@'및 '&'는 속성을 통해 부모 범위 속성에 액세스하는 메커니즘을 제공합니다.
  4. transcluded scope - transclude: truetransclude: true 지시어. 이것은 또한 일반적인 prototypal 범위 상속이지만, 그것은 또한 고립 된 범위의 형제이다.

모든 범위 (원형 또는 원형)에 대해 Angular는 항상 $ parent 및 $$ childHead 및 $$ childTail을 통해 부모 - 자식 관계 (즉, 계층 구조)를 추적합니다.

다이어그램은 github 있는 graphviz "* .dot"파일로 생성되었습니다. 팀 캐스 웰 (Tim Caswell)의 " 객체 그래프로 자바 스크립트 배우기 "는 다이어그램에서 GraphViz를 사용하는 데 영감을주었습니다.







javascript google-maps google-maps-api-3