Cesium JS Feature Picking 활용하기

이번 시간에는 CesiumJS에서 glTF 형식의 3D모델을 불러온 후 마우스 이벤트를 연동하겠습니다. 먼저 결과를 확인해보세요. (여의도로 가세요.)

서비스바로가기

 

* 전체 소스코드 내용은 다음과 같습니다. 

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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<!DOCTYPE html>
<html lang='en'>
<meta charset="UTF-8">
<head>
<script src="js/Cesium-1.54/Build/Cesium/Cesium.js"></script>
<link href="js/Cesium-1.54/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
<style>
    @import url(js/Cesium-1.54/Apps/Sandcastle/templates/bucket.css);
</style>
<div id="cesiumContainer" style="width:auto; height:700px;"></div>
<script>
var extent = Cesium.Rectangle.fromDegrees(117.89628431.499028139.59738043.311528);
 
Cesium.Camera.DEFAULT_VIEW_RECTANGLE = extent;
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
 
var viewer = new Cesium.Viewer('cesiumContainer', {
     timeline : false,
     animation : false,
     selectionIndicator : false,
     navigationHelpButton : false,
     infoBox : false,
     navigationInstructionsInitiallyVisible : false   
});
 
// Gltf포맷 활용가능하게함.
var scene = viewer.scene;
var position = Cesium.Cartesian3.fromDegrees(126.93451137.5210040);
var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(position);
// fromGltf 함수를 사용하여 key : value 값으로 요소를 지정
var name = '프로그APT'
var model = viewer.scene.primitives.add(Cesium.Model.fromGltf({
    url : 'js/image/cesium.gltf',
    modelMatrix : modelMatrix,
    scale : 5000.0,
    name : name
}));
viewer.scene.primitives.add(model);
 
// nameoverlay를 위한 설정
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'= 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'black';
 
// feature select 
var selected = {
    feature : undefined,
    originalColor : new Cesium.Color()
};
 
// 모델을 select하기위한 부분
var selectedEntity = new Cesium.Entity(model);
 
// 클릭핸들러 변수선언
var clickHandler = viewer.screenSpaceEventHandler.getInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
 
if(Cesium.PostProcessStageLibrary.isSilhouetteSupported(viewer.scene)){
    // 블루, 그린 실루엣 지원
    var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
    silhouetteBlue.uniforms.length = 0.01;
    silhouetteBlue.selected = [];
    
    var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteGreen.uniforms.color = Cesium.Color.LIME;
    silhouetteGreen.uniforms.length = 0.01;
    silhouetteGreen.selected = [];
    
    viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));
    // mousemove function을 이용하여 모델을 select 후 배열에 담음
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement){
        silhouetteBlue.selected = [];
    // 모델에 마우스가 move될 시 nameoverlay 출현    
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if(!Cesium.defined(pickedFeature)){
        nameOverlay.style.display = 'none';
        return;
    }
    // nameOverlay 설정
    nameOverlay.style.display = 'block';
    nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
    nameOverlay.style.left = movement.endPosition.x +'px';
    
    nameOverlay.textContent = name;
    
    if(pickedFeature !== selected.feature){
        silhouetteBlue.selected = [model];
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
    
    // 모델을 클릭하여 알럿창을 띄우기위한 부분 / function onLeftClick
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement){
        // silhouetteGreen 변수에 담을것
        silhouetteGreen.selected = [];
        
        // 새로운 모델 선택
        var pickedFeature = viewer.scene.pick(movement.position);
        if(!Cesium.defined(model)){
            clickHandler(movement);
            return;
        }
        
        // 선택된 모델이 없으면 새로운 모델 선택 가능
         if(silhouetteGreen.selected[model] === pickedFeature){
             return;
        } 
         alert("이곳은" +name+ "입니다." +'\n'+ "높이 : "+"68.7"+"m" +'\n'+ "넓이 : "+"30.2"+"m" +'\n'+ "가구 수 : " +"1000"+ "세대");
         
        // 샌택된 모델의 기존색상 저장(파란색)
        var highlightedFeature = silhouetteBlue.selected[model];
        if(model === highlightedFeature){
            silhouetteBlue.selected = [];
        }
        
        // 새로 선택된 모델 highlight
        silhouetteGreen.selected = [model];
        
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    
}
</script>
</head>
<body>
</body>
</html>
cs

 

40 ~ 50 행 : 모델로 마우스가 이동했을 시 모델의 이름을 표출할 nameOverlay에 대한 설정입니다.

 
// nameoverlay를 위한 설정
var nameOverlay = document.createElement('div');
viewer.container.appendChild(nameOverlay);
nameOverlay.className = 'backdrop';
nameOverlay.style.display = 'none';
nameOverlay.style.position = 'absolute';
nameOverlay.style.bottom = '0';
nameOverlay.style.left = '0';
nameOverlay.style['pointer-events'= 'none';
nameOverlay.style.padding = '4px';
nameOverlay.style.backgroundColor = 'black';
cs

 

65 ~ 96행 : 블루, 그린 실루엣을 사용하기위한 변수를 선언하고 onMouseMove function을 활용하기위한 부분입니다. 

 
// 블루, 그린 실루엣 지원
    var silhouetteBlue = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteBlue.uniforms.color = Cesium.Color.BLUE;
    silhouetteBlue.uniforms.length = 0.01;
    silhouetteBlue.selected = [];
    
    var silhouetteGreen = Cesium.PostProcessStageLibrary.createEdgeDetectionStage();
    silhouetteGreen.uniforms.color = Cesium.Color.LIME;
    silhouetteGreen.uniforms.length = 0.01;
    silhouetteGreen.selected = [];
    
    viewer.scene.postProcessStages.add(Cesium.PostProcessStageLibrary.createSilhouetteStage([silhouetteBlue, silhouetteGreen]));
    // mousemove function을 이용하여 모델을 select 후 배열에 담음
    viewer.screenSpaceEventHandler.setInputAction(function onMouseMove(movement){
        silhouetteBlue.selected = [];
    // 모델에 마우스가 move될 시 nameoverlay 출현    
    var pickedFeature = viewer.scene.pick(movement.endPosition);
    if(!Cesium.defined(pickedFeature)){
        nameOverlay.style.display = 'none';
        return;
    }
    // nameOverlay 설정
    nameOverlay.style.display = 'block';
    nameOverlay.style.bottom = viewer.canvas.clientHeight - movement.endPosition.y + 'px';
    nameOverlay.style.left = movement.endPosition.x +'px';
    
    nameOverlay.textContent = name;
    
    if(pickedFeature !== selected.feature){
        silhouetteBlue.selected = [model];
    }
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
cs

* MouseMove 이벤트에 대한 설명 (Cesium Document를 통해 자세한 내용을 살펴보세요.)

마우스의 움직임으로 이벤트를 구현할 수 있습니다.

 

98 ~ 125행 : onLeftClick 함수를 사용하여 새로운 모델 선택 및 모델 실루엣 색상을 변경하기위한 부분입니다. 

 
// 모델을 클릭하여 알럿창을 띄우기위한 부분 / function onLeftClick
    viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement){
        // silhouetteGreen 변수에 담을것
        silhouetteGreen.selected = [];
        
        // 새로운 모델 선택
        var pickedFeature = viewer.scene.pick(movement.position);
        if(!Cesium.defined(model)){
            clickHandler(movement);
            return;
        }
        
        // 선택된 모델이 없으면 새로운 모델 선택 가능
         if(silhouetteGreen.selected[model] === pickedFeature){
             return;
        } 
         alert("이곳은" +name+ "입니다." +'\n'+ "높이 : "+"68.7"+"m" +'\n'+ "넓이 : "+"30.2"+"m" +'\n'+ "가구 수 : " +"1000"+ "세대");
         
        // 샌택된 모델의 기존색상 저장(파란색)
        var highlightedFeature = silhouetteBlue.selected[model];
        if(model === highlightedFeature){
            silhouetteBlue.selected = [];
        }
        
        // 새로 선택된 모델 highlight
        silhouetteGreen.selected = [model];
        
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
cs

* LeftClick 이벤트에 대한 설명 (Cesium Document를 통해 자세한 내용을 살펴보세요.)

마우스 좌클릭을 통해 선택, 드래그 등의 이벤트를 구현할 수 있습니다.

 

결과 화면을 보겠습니다. 

마우스를 모델에 올렸을 시 모델의 테두리 색상이 파란색으로 변경되고 nameoverlay가 활성화 된 것을 볼 수 있습니다.

 

 

모델을 클릭했을 시 Alert창에 모델의 이름과 임의로 지정한 값을 알립니다.

 

모델을 클릭 후 테두리 색상에 변경된것을 확인할 수 있습니다. 선택했던 모델에 재차 마우스를 올려도 nameOverlay가 활성화됩니다.

 

+ Recent posts