처음에 일반적인 방법으로 아래의 코드와 같이 작성하였는데 ajax통신 success에서 console.log(i);로 찍어문 for문의 i 값이 0,1,2,3 순이 아니라 마지막 값만 찍혔다....

 

원인은...

ajax는 비동기 방식이라 for문 하고 같이 작동하는것이 아니라는 것이다. for문 따로, ajax 따로....

즉, ajax의 url에서 데이터를 받아 올 동안 for문은  이미 다 돌고 있다는 거였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for(var i = 0; i < addressArr.length; i++){
        $.ajax({
            type:'GET',
            url: /* user url*/,
            dataType : "jsonp",
            async:false,
            success:function(result){
                 console.log(i);
             },
             error: function(xhr,status,error){
                console.log(xhr+status+error);
             } 
        });
}
 
 

해결 방법...

stackoverflow에서 찾았다.

아래와 같이 사용 하면 된다고 한다.

1
2
3
4
5
6
7
for (var i .....) {
  (function (i) {
    async(function() {
      use(i);
    });
  })(i);
}
 

위의 방법대로 적용한 결과는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for(var i = 0; i < addressArr.length; i++){
    (function(i) {
            $.ajax({
                type:'GET',
                url: /* user url*/,
                dataType : "jsonp",
                async:false,
                success:function(result){
                     console.log(i);
                 },
                 error: function(xhr,status,error){
                    console.log(xhr+status+error);
                 } 
            });
    })(i);
}
 
 

잘 돌아 간다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
function updateLog($userType$userID){
    
    $base_dir = $_SERVER['DOCUMENT_ROOT'];              //웹서버 설치 경로
    $date = date("Ymd");                                // 현재 날짜 구하는 함수
    $is_dir = $base_dir.'/signUpLog/'.$date.'/';        // 저장 경로가 존재하는지 판별
    if(!is_dir($is_dir)){       // 디렉토리가 존재하지 않는다면 새로 생성 0777은 권한 설정
        mkdir($is_dir0777);
    }
    $fileName = "0".$userType.$userType.".txt";         // 생성할 파일 이름과 확장자
   
    $text = "USERTYPE : ".$userType." | "."UID : ".$userID;         // 생성할 파일에 들어갈 텍스트
    $logFile = fopen($is_dir."/".$fileName,"a");                // 생성한 파일 열기
    if(fwrite($logFile$text."\r\n")){                         // 생성한 파일에 텍스트 입력하기
        fclose($logFile);                                       // 닫기
        return true;
    }else{
        return false;
    }
}
?>
 
 

1. 생성할 파일을 저장 할 경로가 있는지 판별한다. (경로가 존재하지 않는다면 경로 생성);

   is_dir() 함수는 경로 판별 함수이다.

 

2. 생성할 파일의 이름과 확장자 지정 (phpdptj '.' 기호는 문자열 붙이는 기능);

  $파일 이름 변수 = "당신이 원하는 파일이름".".txt";

 

3. fopen( 열고자 하는 파일 경로, "a");

4. fwrite( 입력하고자하는 파일, 들어갈 내용 );  // 입력하고자하는 파일은 반드시 fopen()함수로 열어주어야 한다.

5. fclose( 닫고자하는 파일); 

1. 지도 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    // 지도 중심 좌표 (강남역)
    var olCenter = ol.proj.fromLonLat([127.027583,37.497928]);
 
    // 지도 기본 타일 설정
    var olLayer = new ol.layer.Tile({
        source: new ol.source.XYZ({
        url: 'http://api.vworld.kr/req/wmts/1.0.0/'+key+'/Base/{z}/{y}/{x}.png'                 // key는 브이월드 인증키이다.
        })
    });
 
    // 지도 기본 뷰 설정
    var olView = new ol.View({
        center: olCenter,
        zoom: 15,
        minZoom : 6,
        maxZoom : 19,
    });
 
    // 팝업 옵션 설정
    var overlay = new ol.Overlay({
        element: container,
        autoPan: true,
        autoPanAnimation: {
        duration: 250
        }
    });
 
    // 지도 생성
    var olMap = new ol.Map({
        layers: [olLayer],
        overlays: [overlay],
        target: 'vMap',                     // html에 존재하는 div영역의 id 이름
        view: olView,
        moveTolerance: 5
    });
 
 

2. 지도 클릭(클릭한 곳 좌표 구하기)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    // 지도 클릭 이벤트
    olMap.on('singleclick'function(event) {
 
        // 마우스 커서 아래의 좌표값 구하기
        var coordinate = event.coordinate;
        lon = coordinate[0];
        lat = coordinate[1];
 
        if (olMap.hasFeatureAtPixel(event.pixel) === true) {                                        // 마커를 클릭할 경우
            overlay.setPosition([lon,lat]);                                     // 해당 좌표로 팝업 이동
        }else{
            
            if(checkRoadView){                                                                      // checkRoadView가 true라면 로드뷰 실행 fales라면 마커 생성
                var tansform = ol.proj.transform([lon,lat], 'EPSG:3857''EPSG:4326')               // 브이월드 좌표계에서 다음 지도 좌표계로 변환 EPSG:3857=>EPSG:4326
                location.href="https://map.kakao.com/link/roadview/"+tansform[1]+","+tansform[0];   // 로드뷰 불러오기
            }else{
                FindAddress(lon, lat);                                                              // FindAddress 위경도 변수 넘기고 실행
            }
        }
    });
 
 

3. 마커 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    // 마커,팝업 생성 함수
    function addMarker(lon, lat){                // 파라미터로 위도,경도
        // 마커 feature 설정
        var feature = new ol.Feature({
            geometry: new ol.geom.Point([lon,lat])
        });
 
        // 마커 스타일 설정
        var style = new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [0.520],
                anchorXUnits: 'fraction',
                anchorYUnits: 'pixels',
                src: 'http://map.vworld.kr/images/ol3/marker_blue.png'
            }),
        });
        
        // feature에 스타일 설정
        feature.setStyle(style);
 
        // 마커 레이어에 들어갈 소스 생성
        var source = new ol.source.Vector({
            features: [feature]
        });
 
        // 마커 레이어 생성
        var layer = new ol.layer.Vector({
            source: source,
            name'MARKER'
        });
 
        // layer의 ZIndex 설정(다른 레이어들 보다 더 앞에 보여주는 기능)
        layer.setZIndex(6);
 
        // 지도에 마커 추가
        olMap.addLayer(layer);
 
        //------------------------------------------팝업-------------------------------------------//
        overlay.setPosition([lon,lat]);
    }
 
 

구현한 기능

1. 브이월드 지도API 로 지도 생성(버전 : 2D 지도 API 2.0)

2. 지도 위에서 마우스 클릭시 해당 좌표 반환 및 마커 클릭 이벤트 처리

3. 좌표를 주소로 변환(지오코딩)

4. 상권 지도(layer) 및 다음 로드뷰 페이지 연결(브이월드 좌표계에서 다음 지도 좌표계로 변환)

5. 브이월드 검색 API 활용(버전 : 검색 API 2.0)

6. 주소 검색 타입(지번,도로명)에 따라 마커의 팝업창에 다르게 표시

[html]

1
<script type="text/javascript" src="http://map.vworld.kr/js/vworldMapInit.js.do?version=2.0&apiKey=[인증키]"></script>
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class='title'>
    <p>상권 지도</p>
</div>
    <article class="at_1">
        <div class="search_div">
            <span>
                <select class='search_type'>
                    <option value="road">도로명</option>
                    <option value="parcel" selected>지번</option>
                </select>
            </span>
                <span><input type="text" id="search" placeholder="찾고자하는 것을 입력하세요."></span>
                <span><button class="search_btn">검색</button>
        </div>
        <div class="map_wrap">
            <div id='vMap'></div>
            <div class="custom_typecontrol radius_border">
                <span id="btnRoadmap" class="selected_btn active">지도</span>
                <span id="btnSkyview" class="selected_btn">로드뷰</span>
                <span id="btnCommercial" class="selected_btn">상권</span>
            </div>
        </div>
</article>
 
 

 

[자바스크립트 - 사용할 변수 및 맵 생성]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    var vmap;                                                                           // 기본 지도를 받을 변수
    var markerLayer;                                                                    // 마커 레이어를 받을 변수
    var x,y;                                                                            // 클릭한 위경도를 받을 변수
    var checkRoadView = false;
    var key = "";                                   // 브이월드 인증키
    var titleName;                                                                      // 마커에 표시될 검색방법 타이틀
 
    vw.ol3.CameraPosition.center = [14134490.6769418594516889.004840847];             // 기본 지도 시작 중심 좌표 지정(서울역)
    vw.ol3.CameraPosition.zoom = 15;                                                    // 시작 Zoom 레벨
 
    vw.ol3.MapOptions = {                                                               // 기본지도의 옵션
        basemapType: vw.ol3.BasemapType.GRAPHIC
    , controlDensity: vw.ol3.DensityType.EMPTY
    , interactionDensity: vw.ol3.DensityType.BASIC
    , controlsAutoArrange: true
    , homePosition: vw.ol3.CameraPosition
    , initPosition: vw.ol3.CameraPosition
    }; 
        
    vmap = new vw.ol3.Map("vMap",  vw.ol3.MapOptions);                                  // 기본 지도 생성  
 

 

[자바스크립트 - 지도 클릭 이벤트]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 지도 클릭 이벤트
    vmap.on('click'function(event) {
        
        var feature = vmap.forEachFeatureAtPixel(event.pixel, function (feature,layer) {// 클릭한 좌표를 첫번째 인자로 주어 해당 위치에 있는 feature를 구하고 두번쨰 인자(함수)로 넘겨준다.
            if(layer != null && layer.className == 'vw.ol3.layer.Marker'){              // 해당 좌표에 마커 레이어가 있다면
                return feature;
            }else{
                return false;
            }
        });
        
        if (!feature) {
            var coord = vmap.getCoordinateFromPixel(event.pixel);                       // 마우스 커서 아래의 좌표값 구하기
            x = coord[0];
            y = coord[1];
            if(checkRoadView){                                                          // 로드뷰 실행
                var tansform = ol.proj.transform([x,y], 'EPSG:3857''EPSG:4326')       // 브이월드 좌표계에서 다음 지도 좌표계로 변환 EPSG:3857=>EPSG:4326
                location.href="https://map.kakao.com/link/roadview/"+tansform[1]+","+tansform[0];   // 로드뷰 불러오기
            }else{
                addMarker(x, y);                                                        // addMarker함수에 위경도 변수 넘기고 실행
            }
        }
    });
 
 

 

[자바스크립트 - 마커 생성 및 좌표를 주소로 변환]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 머커 생성 및 좌표를 지번 주소로 변환
    function addMarker(lon ,lat) {
        vmap.removeLayer(markerLayer);                                          // 기존의 마커가 있다면 제거
        markerLayer = new vw.ol3.layer.Marker(vmap);                            // 마커 객체 상성
 
        var typeName = $('.search_type option:selected').val();                 // 선택한 검색 종류 값
 
        if(typeName == "road"){titleName = "도로명 주소";}
        else if(typeName == "parcel"){titleName = "지번 주소";}
 
        //  (비동기)좌표를 주소로 변환하는 api, 도로명주소 검색의 경우 건물의 geometry 기반으로 도로명 주소값을 가지고 오기 때문에 
        //  건물 외의 것을 클릭하면 값이 없을 수 있습니다. 
        //  브이월드 지도서비스에서 행정 주제도중 도로명주소건물 주제도에 해당 좌표값이 들어와야만 도로명 주소값을 리턴 받을 수 있습니다.
        $.ajax({ 
            type: 'GET',
            url: 'http://api.vworld.kr/req/address?',
            dataType : "jsonp",                                                 // CORS 문제로 인해 브이월드에선 jsonp를 사용한다고 함
            data: {
                service: "address",
                version: "2.0",
                request: "getaddress",
                format: "json",                                                 // 결과 포멧으로 xml 또는 json 타입으로 받아볼 수 있다.
                key: key,                                                       // 브이월드 인증키
                type: typeName,                                                 // 검색 타입으로 '도로명:road' 또는 '지번:parcel' 또는 '둘다:both' 중 선택
                crs: "epsg:3857",                                               // 브이월드 기본 좌표계
                point: lon+","+lat,                                             // 좌표
                zipcode: true,                                                  // 우편번호 여부
                simple: false                                                   // 간략 결과 여부
            },
            success: function(json_data){
                if(json_data.response.status == "NOT_FOUND"){
                    text = "검색 결과가 없습니다.";
                }else{
                    text = json_data.response.result[0].text;                   // 받아온 json데이터에서 주소를 추출
                }
                
                vw.ol3.markerOption = {                                         // 마커 옵션 설정
                    x : lon,
                    y : lat,
                    epsg : "EPSG:3857",
                    title : titleName,
                    contents : text,
                    iconUrl : 'http://map.vworld.kr/images/ol3/marker_blue.png'
                };
                markerLayer.addMarker(vw.ol3.markerOption);                     // 마커 옵션을 마커에 적용
                vmap.addLayer(markerLayer);                                     // 마커를 vmap에 등록
            },
            error: function(xtr,status,error){
                alert(xtr +" : "+status+" : "+error);
            }
        });
    };
 
 

 

[자바스크립트  - 검색]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 지도 검색
    $('.search_btn').on('click',function(){
 
        vmap.removeLayer(markerLayer);                              // 기존의 마커 제거
        markerLayer = new vw.ol3.layer.Marker(vmap);                // 마커 객체 상성
 
        var contents_data;
        var typeName = $('.search_type option:selected').val();     // 선택한 검색 종류 값
        
        $.ajax({
            type: "get",
            url: "http://api.vworld.kr/req/search",
            data : {
                page: 1,
                type: 'address',                                    // 주소 검색방법
                category: typeName,                                 // 도로명 : road, 지번 : parcel
                request: 'search',
                apiKey: key,                                        // 브이월드 지도 인증기
                domain: '본인의 map을 보여주는 도메인 ex) http://111.111.111.111/map.html',
                crs : 'EPSG:3857',                                  // 브이월드 좌표계
                query : $('#search').val()                          // 사용자가 입력한 text
            },
            dataType: 'jsonp',
            async: false,
            success: function(data) {
                if(data.response.status =="NOT_FOUND"){
                    alert("검색결과가 없습니다.");
                }else{
                    for(var o in data.response.result.items){ 
                        if(o==0){
                            move(data.response.result.items[o].point.x*1,data.response.result.items[o].point.y*1);
                            if(typeName == "road"){
                                titleName = "도로명 주소";
                                contents_data = data.response.result.items[o].address.road;
                            }
                            else if(typeName == "parcel"){
                                titleName = "지번 주소";
                                contents_data = data.response.result.items[o].address.parcel;
                            }
                        }
 
                        vw.ol3.markerOption = {                                         // 마커 옵션 설정
                            x : data.response.result.items[o].point.x,
                            y : data.response.result.items[o].point.y,
                            epsg : "EPSG:3857",
                            title : titleName,
                            contents : contents_data,
                            iconUrl : 'http://map.vworld.kr/images/ol3/marker_blue.png'
                        };
 
                        markerLayer.addMarker(vw.ol3.markerOption);                  // 마커 옵션을 마커에 적용
                    }
                }
            },
            complete:function(){
                vmap.addLayer(markerLayer)                                   // 마커를 vmap에 등록
            },
            error: function(xhr, status, error) {
                console.log(xhr, status, error);
            }
        });
        var move = function(x,y){
            vmap.getView().setCenter([ x, y ]); // 지도 이동
            vmap.getView().setZoom(15);         // 줌레벨 설정
        }
    });
 
 

 

[자바스크립트 - WMS(상권 지도)]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 상권 Layer
    function Commercial(){
        var wms_title = '상권지역';
        var wms_val = 'lt_c_dgmainbiz';                     // 상권지도에 해당하는 코드
        
        vmap.removeLayer(vmap.getLayerByName("wms_theme"))  // 기존결과 삭제
 
        var layer_tile = new ol.layer.Tile({
            title: wms_title,
            id: wms_val,
            name"wms_theme",                              // vmap 올린 레이어를 삭제하거나 수정,변경할때 접근할 name 속성
            projection: "EPSG:3857",                        // 좌표계 설정 (기본값)
            extent: vmap.getView().getProjection().getExtent(), //[-20037508.34, -20037508.34, 20037508.34, 20037508.34]
            maxZoom: 18,
            minZoom: 10,
            tilePixelRatio: 1,
            tileSize: [512512],
            source: new ol.source.TileWMS({
                url: "http://api.vworld.kr/req/wms?",
                params: {
                    LAYERS: wms_val,
                    STYLES: wms_val,
                    CRS: "EPSG:3857",
                    apikey: key,
                    DOMAIN:"http://192.168.0.2:80",
                    title: wms_title,
                    FORMAT: "image/png",
                    domain: "http://192.168.0.2",
                    WIDTH:512,
                    HEIGHT:512,
                    EXCEPTIONS: "text/xml",
                    //bgcolor: '0xFF00FF'               // 안먹힘...분홍색
                }
            })
        });
        layer_tile.setZIndex(5);
        vmap.addLayer(layer_tile);
    };
 
 
기본 지도
상권 지도
선택박스[지번]일때, 마우스로 지도를 클릭하면 지번 표시
선택박스[도로명]일때, 마우스로 지도를 클릭하면 도로명 표시

* 도로명주소 검색의 경우 건물의 geometry 기반으로 도로명 주소값을 가지고 오기 때문에 마우스로 건물 외의 것을 클릭하면 값이 없을 수 있습니다.

로드뷰 버튼을 누르고 원하는 곳의 근처 도로를 클릭한다. 

클릭한 곳의 좌표를 다음 지도 좌표계로 변환한뒤 다음 로드뷰api로 보낸다.

다음 로드뷰 페이지가 열리고 해당 좌표의 로드뷰를 보여준다.
지번 검색
도로명 검색

[자바스크립트]

var index = 0부터

파일첨부 버튼이 동적으로 생성될때마다 index++

 

파일 첨부 버튼을 동적으로 생성하고자 한다면 아래의 링크로....

https://mygameprogamming.tistory.com/66?category=711768

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 파일 전송
    $('.jeompo_register_btn').on('click',function(e){
        var formData = new FormData();
        
        var i;
        for( i = 0 ; i < index ; i++ ){
            var name = "file_" + i;
            formData.append( name , $("#image_plus_" + i)[0].files[0]);
        }
        
        formData.append("idx", index);
 
        e.preventDefault();
        $.ajax({
            type: 'POST',
            url: 'http://ip주소/pass_register.php',
            data: formData,
            contentType: false,
            processData: false,
            success : function(result){
                alert(result);
            },
            error : function (xtr,status,error){
                alert(xtr + ":" + status + ":" + error);
            }
        });
    });
 

[php]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?php
    include "../connectDB.php";
    
    $index = $_POST['idx'];
    $fileArr = array();
    $image_dir = $_SERVER['DOCUMENT_ROOT'];     //웹서버 설치 경로
    $check = true;
    for($i = 0 ; $i < $index ;$i++){
        $fileArr[$i= $_FILES["file_$i"]['name'];                                                               //파일 이름
        $tmp_name = $_FILES["file_$i"]['tmp_name'];                                                              //파일 임시저장 경로
        $fileArr[$i= preg_replace("/[ #\&\+\%@=\/\\\:;,\'\"\^`~\|\!\?\*$#<>()\[\]\{\}]/i"""$fileArr[$i]); //특수문자제거
        $fileArr[$i= iconv("utf-8""euc-kr"$fileArr[$i]);                                                   //한글 인코딩
        $save_dir = $image_dir.'/image_box/'.$fileArr[$i];                                                       //실제 저장 경로
        if(!move_uploaded_file($tmp_name,$save_dir)){
            $check = false;
            break;
        }
    }
    if($check){
        echo "success";
    }else{
        echo "fail";
    }
 
    mysqli_close($db);
?>
 
 

비동기 방식인 ajax를 통해 php의 db에 있는 데이터를 불러와 html에 뿌려주는 작업을 하는도중

ajax의 결과로 나온 html 요소가 정상 작동하지 않았다.

 

그 이유는 처음에 html 화면이 출력할때는 각각의 요소에 이벤트가 바인딩되었지만 

ajax로 새로 생겨난 html은 이벤트 바인딩이 안 되었던것....

 

[script - ajax]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 점포 전체 검색
  function search_store(){
    $.ajax({
      type : 'POST',
      url : 'http://192.168.0.2:80/cube2/pass/search',
      data : {
        value:"1"
      },
      success : function(result){
        $('ul').html(result);
      },
      error : function(xtr,status,error){
        alert(xtr +":"+status+":"+error);
      }
    });
  }
 

[script - 이벤트 바인딩]

1
2
3
4
$(document).on("click"'.at_l ul li'function(event) {
    var target = $(this);
    location.href ="ip주소?idx="+target.attr('id');
}); 
 

[html/php]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<article class="at_2">
    <ul>
    <?php
        while($row=$result->fetch_array(MYSQLI_ASSOC)){
            if(strlen($row["pTitle"])>15){ 
            $title=str_replace($row["pTitle"],mb_substr($row["pTitle"],0,8,"UTF8")."...",$row["pTitle"]); //title이 8을 넘어서면 ...표시
            }
            $NO = $row['idx'];
            echo "
                <li id=".$NO.">
                    <img src = '/cube/image_store/".$row['pImage']."' />
                    <h3><span>[등록날짜]</span><span class='date'>&nbsp;2018.03.30&nbsp;</span><span class='seller'>".$row['pSeller']."</span></h3>
                    <p>".$row['pTitle']."<p> 
                </li>
                ";
        }   
    ?>
    </ul>
</article>
 
 

 

+ Recent posts