Skip to content

Commit

Permalink
Fix #1837 filter click events on 3D mobile (#1858)
Browse files Browse the repository at this point in the history
to avoid issues when you are using cesium with multitouch.
  • Loading branch information
offtherailz authored May 19, 2017
1 parent 57a0eea commit 8f2a3ba
Showing 1 changed file with 53 additions and 10 deletions.
63 changes: 53 additions & 10 deletions web/client/components/map/cesium/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/
var Cesium = require('../../../libs/cesium');
const Rx = require('rxjs');
var React = require('react');
var ReactDOM = require('react-dom');
var ConfigUtils = require('../../../utils/ConfigUtils');
Expand Down Expand Up @@ -69,10 +70,7 @@ let CesiumMap = React.createClass({
map.imageryLayers.removeAll();
map.camera.moveEnd.addEventListener(this.updateMapInfoState);
this.hand = new Cesium.ScreenSpaceEventHandler(map.scene.canvas);
this.hand.setInputAction((movement) => {
this.onClick(map, movement);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);

this.subscribeClickEvent(map);
this.hand.setInputAction(throttle(this.onMouseMove.bind(this), 500), Cesium.ScreenSpaceEventType.MOUSE_MOVE);

map.camera.setView({
Expand All @@ -90,11 +88,7 @@ let CesiumMap = React.createClass({
if (this.props.mapOptions.navigationTools) {
this.cesiumNavigation = window.CesiumNavigation;
if (this.cesiumNavigation) {
this.cesiumNavigation.navigationInitialization(this.props.id, map, {
enableZoomControls: false,
enableDistanceLegend: false,
enableCompassOuterRing: false
});
this.cesiumNavigation.navigationInitialization(this.props.id, map);
}
}
},
Expand All @@ -108,11 +102,12 @@ let CesiumMap = React.createClass({
return false;
},
componentWillUnmount() {
this.clickStream$.complete();
this.pauserStream$.complete();
this.hand.destroy();
this.map.destroy();
},
onClick(map, movement) {

if (this.props.onClick && movement.position !== null) {
const cartesian = map.camera.pickEllipsoid(movement.position, map.scene.globe.ellipsoid);
let cartographic = ClickUtils.getMouseXYZ(map, movement) || cartesian && Cesium.Cartographic.fromCartesian(cartesian);
Expand Down Expand Up @@ -236,6 +231,54 @@ let CesiumMap = React.createClass({
this.map.camera.setView(position);
}
},
subscribeClickEvent(map) {
const samePosition = (m1, m2) => m1 && m2 && m1.x === m2.x && m1.y === m2.y;
const types = {
LEFT_UP: Cesium.ScreenSpaceEventType.LEFT_UP,
LEFT_DOWN: Cesium.ScreenSpaceEventType.LEFT_DOWN,
LEFT_CLICK: Cesium.ScreenSpaceEventType.LEFT_CLICK,
PINCH_START: Cesium.ScreenSpaceEventType.PINCH_START,
PINCH_END: Cesium.ScreenSpaceEventType.PINCH_END,
PINCH_MOVE: Cesium.ScreenSpaceEventType.PINCH_MOVE
};
const clickStream$ = new Rx.Subject();
const pauserStream$ = new Rx.Subject();
Object.keys(types).forEach((type) => this.hand.setInputAction((movement) => {
pauserStream$.next({type: types[type], movement});
clickStream$.next({type: types[type], movement});
}, types[type]));

/*
* trigger onClick only when LEFT_CLICK that follow a LEFT_DOWN at the same position.
* Every other mouse event before the LEFT_CLICK will not trigger the onClick function (happens with multitouch devices from cesium).
* If a pinch event is ended, wait to start listening left clicks. This to skip the LEFT_UP,LEFT_DOWN, LEFT_CLICK sequence that cesium triggers after a pinch end,
* that othewise can not be distinguished from a normal click event.
*/
pauserStream$
.filter( ev => ev.type === types.PINCH_END )
.switchMap( () => Rx.Observable.of(true).concat(Rx.Observable.of(false).delay(500)))
.startWith(false)
.switchMap(paused => {
// pause is realized by mapping the click stream or an infinite stream
return paused ? Rx.Observable.never() : clickStream$;
})
.filter( ev => ev.type === types.LEFT_DOWN )
.switchMap(({movement}) =>
clickStream$
.filter( ev => ev.type === types.LEFT_CLICK )
.takeUntil(
Rx.Observable.timer(500).merge(
clickStream$
.filter( ev =>
ev.type !== types.LEFT_UP && ev.type !== types.LEFT_CLICK
|| ev.type === types.LEFT_UP && !samePosition(movement && movement.position, ev.movement && ev.movement.position)
)
)
)
).subscribe(({movement}) => this.onClick(map, movement));
this.clickStream$ = clickStream$;
this.pauserStream$ = pauserStream$;
},
updateMapInfoState() {
const center = this.getCenter();
const zoom = this.getZoomFromHeight(center.height);
Expand Down

0 comments on commit 8f2a3ba

Please sign in to comment.