add opacity slider (bootstrap-slider) for route track and markers
This commit is contained in:
parent
0b22a75d18
commit
d30684b6c8
6 changed files with 143 additions and 4 deletions
|
|
@ -97,3 +97,5 @@ Copyright (c) 2011-2014 Twitter, Inc; [MIT License](https://github.com/twbs/boot
|
||||||
Copyright 2005, 2014 jQuery Foundation and other contributors; [MIT License](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
|
Copyright 2005, 2014 jQuery Foundation and other contributors; [MIT License](https://github.com/jquery/jquery/blob/master/LICENSE.txt)
|
||||||
* [DataTables](https://github.com/DataTables/DataTables)
|
* [DataTables](https://github.com/DataTables/DataTables)
|
||||||
Copyright (C) 2008-2014, SpryMedia Ltd.; [MIT License](http://www.datatables.net/license/mit)
|
Copyright (C) 2008-2014, SpryMedia Ltd.; [MIT License](http://www.datatables.net/license/mit)
|
||||||
|
* [bootstrap-slider](https://github.com/seiyria/bootstrap-slider)
|
||||||
|
Copyright (c) 2015 Kyle Kemp, Rohit Kalkur, and contributors; [MIT License](https://github.com/seiyria/bootstrap-slider/blob/master/LICENSE.md)
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
"Leaflet.Elevation": "MrMufflon/Leaflet.Elevation#master",
|
"Leaflet.Elevation": "MrMufflon/Leaflet.Elevation#master",
|
||||||
"leaflet-control-geocoder": "~1.1.0",
|
"leaflet-control-geocoder": "~1.1.0",
|
||||||
"L.EasyButton": "*",
|
"L.EasyButton": "*",
|
||||||
"bootbox": "~4.4.0"
|
"bootbox": "~4.4.0",
|
||||||
|
"seiyria-bootstrap-slider": "~4.8.1"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"leaflet": {
|
"leaflet": {
|
||||||
|
|
|
||||||
|
|
@ -264,3 +264,51 @@ table.dataTable.display tbody tr.odd:hover,
|
||||||
table.dataTable.display tbody tr.even:hover {
|
table.dataTable.display tbody tr.even:hover {
|
||||||
background-color: rgba(255,255,0,0.2);
|
background-color: rgba(255,255,0,0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* opacity slider control (seiyria-bootstrap-slider)
|
||||||
|
*/
|
||||||
|
|
||||||
|
.control-slider {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider.slider-vertical {
|
||||||
|
height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* invert track and selection styles to get partial gradient for "selection" */
|
||||||
|
.slider.slider-vertical .slider-track {
|
||||||
|
width: 8px;
|
||||||
|
margin-left: -4px;
|
||||||
|
background-image: linear-gradient(to right, #f0f0f0 0%, #e9e9e9 100%);
|
||||||
|
box-shadow: inset -1px -0px 1px rgba(55, 55, 55, 0.3), inset 1px 0px 1px rgba(230, 230, 230, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-slider:hover .slider-track,
|
||||||
|
.control-slider:active .slider-track {
|
||||||
|
background-image: linear-gradient(to bottom, magenta 0%, white 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-selection {
|
||||||
|
background-color: #C6C6C6;
|
||||||
|
background-image: none;
|
||||||
|
box-shadow: inset 1px 1px 3px rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider.slider-vertical .slider-tick,
|
||||||
|
.slider.slider-vertical .slider-handle {
|
||||||
|
margin-left: -6px;
|
||||||
|
cursor: ns-resize;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
/* bootstrap .btn-default */
|
||||||
|
background-image: linear-gradient(to bottom,#fff 0,#e0e0e0 100%);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
box-shadow: inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);
|
||||||
|
border: 1px solid #adadad;
|
||||||
|
}
|
||||||
|
|
|
||||||
52
js/control/OpacitySlider.js
Normal file
52
js/control/OpacitySlider.js
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
BR.OpacitySlider = L.Control.extend({
|
||||||
|
options: {
|
||||||
|
position: 'topleft',
|
||||||
|
callback: function(opacity) {}
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
var container = L.DomUtil.create('div', 'leaflet-bar control-slider'),
|
||||||
|
input = $('<input id="slider" type="text"/>'),
|
||||||
|
item = localStorage.opacitySliderValue,
|
||||||
|
value = item ? parseInt(item) : 100;
|
||||||
|
|
||||||
|
var stopClickAfterSlide = function(evt) {
|
||||||
|
L.DomEvent.stop(evt);
|
||||||
|
removeStopClickListeners();
|
||||||
|
};
|
||||||
|
var removeStopClickListeners = function() {
|
||||||
|
document.removeEventListener('click', stopClickAfterSlide, true);
|
||||||
|
document.removeEventListener('mousedown', removeStopClickListeners, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
$(container).html(input);
|
||||||
|
$(container).attr('title', 'Set transparency of route track and markers');
|
||||||
|
|
||||||
|
input.slider({
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 1,
|
||||||
|
value: value,
|
||||||
|
orientation: 'vertical',
|
||||||
|
reversed : true,
|
||||||
|
selection: 'before', // inverted, serves as track style, see css
|
||||||
|
tooltip: 'hide'
|
||||||
|
}).on('slide slideStop', { self: this }, function (evt) {
|
||||||
|
evt.data.self.options.callback(evt.value / 100);
|
||||||
|
}).on('slideStop', function (evt) {
|
||||||
|
localStorage.opacitySliderValue = evt.value;
|
||||||
|
|
||||||
|
// When dragging outside slider and over map, click event after mouseup
|
||||||
|
// adds marker when active on Chromium. So disable click (not needed)
|
||||||
|
// once after sliding.
|
||||||
|
document.addEventListener('click', stopClickAfterSlide, true);
|
||||||
|
// Firefox does not fire click event in this case, so make sure stop listener
|
||||||
|
// is always removed on next mousedown.
|
||||||
|
document.addEventListener('mousedown', removeStopClickListeners, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.options.callback(value / 100);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -217,6 +217,7 @@
|
||||||
trackCasing: {
|
trackCasing: {
|
||||||
weight: 8,
|
weight: 8,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
|
// assumed to be same as track, see setOpacity
|
||||||
opacity: 1
|
opacity: 1
|
||||||
},
|
},
|
||||||
nodata: {
|
nodata: {
|
||||||
|
|
@ -276,6 +277,9 @@
|
||||||
|
|
||||||
nogos.addTo(map);
|
nogos.addTo(map);
|
||||||
routing.addTo(map);
|
routing.addTo(map);
|
||||||
|
map.addControl(new BR.OpacitySlider({
|
||||||
|
callback: L.bind(routing.setOpacity, routing)
|
||||||
|
}));
|
||||||
|
|
||||||
// initial option settings (after controls are added and initialized with onAdd, before permalink)
|
// initial option settings (after controls are added and initialized with onAdd, before permalink)
|
||||||
router.setOptions(nogos.getOptions());
|
router.setOptions(nogos.getOptions());
|
||||||
|
|
@ -293,7 +297,7 @@
|
||||||
profile: profile
|
profile: profile
|
||||||
}).addTo(map);
|
}).addTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
initMap();
|
initMap();
|
||||||
initApp();
|
initApp();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
BR.Routing = L.Routing.extend({
|
BR.Routing = L.Routing.extend({
|
||||||
options: {
|
options: {
|
||||||
|
position: 'topright',
|
||||||
icons: {
|
icons: {
|
||||||
/* not implemented yet
|
/* not implemented yet
|
||||||
start: new L.Icon.Default({iconUrl: 'bower_components/leaflet-gpx/pin-icon-start.png'}),
|
start: new L.Icon.Default({iconUrl: 'bower_components/leaflet-gpx/pin-icon-start.png'}),
|
||||||
end: new L.Icon.Default(),
|
end: new L.Icon.Default(),
|
||||||
normal: new L.Icon.Default()
|
normal: new L.Icon.Default()
|
||||||
*/
|
*/
|
||||||
draw: false
|
draw: false,
|
||||||
|
opacity: 1
|
||||||
},
|
},
|
||||||
snapping: null,
|
snapping: null,
|
||||||
zIndexOffset: -2000
|
zIndexOffset: -2000
|
||||||
|
|
@ -20,6 +22,8 @@ BR.Routing = L.Routing.extend({
|
||||||
this._segments.on('layeradd', this._addSegmentCasing, this);
|
this._segments.on('layeradd', this._addSegmentCasing, this);
|
||||||
this._segments.on('layerremove', this._removeSegmentCasing, this);
|
this._segments.on('layerremove', this._removeSegmentCasing, this);
|
||||||
|
|
||||||
|
this._waypoints.on('layeradd', this._setMarkerOpacity, this);
|
||||||
|
|
||||||
// turn line mouse marker off while over waypoint marker
|
// turn line mouse marker off while over waypoint marker
|
||||||
this.on('waypoint:mouseover', function(e) {
|
this.on('waypoint:mouseover', function(e) {
|
||||||
// L.Routing.Edit._segmentOnMouseout without firing 'segment:mouseout' (enables draw)
|
// L.Routing.Edit._segmentOnMouseout without firing 'segment:mouseout' (enables draw)
|
||||||
|
|
@ -102,6 +106,33 @@ BR.Routing = L.Routing.extend({
|
||||||
this._segmentsCasing.removeLayer(e.layer._casing);
|
this._segmentsCasing.removeLayer(e.layer._casing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
,setOpacity: function(opacity) {
|
||||||
|
// Due to the second Polyline layer for casing, the combined opacity is less
|
||||||
|
// transparent than with a single layer and the slider is non-linear. The
|
||||||
|
// inverted formula is used to get the same result as with a single layer.
|
||||||
|
// SVG simple alpha compositing: Ca' = 1 - (1 - Ea) * (1 - Ca)
|
||||||
|
// http://www.w3.org/TR/SVG11/masking.html#SimpleAlphaBlending
|
||||||
|
var sourceOpacity = 1 - Math.sqrt(1 - opacity);
|
||||||
|
|
||||||
|
this.options.styles.track.opacity = sourceOpacity;
|
||||||
|
this.options.styles.trackCasing.opacity = sourceOpacity;
|
||||||
|
this.options.icons.opacity = opacity;
|
||||||
|
|
||||||
|
this._segments.setStyle({
|
||||||
|
opacity: sourceOpacity
|
||||||
|
});
|
||||||
|
this._segmentsCasing.setStyle({
|
||||||
|
opacity: sourceOpacity
|
||||||
|
});
|
||||||
|
this._waypoints.eachLayer(function(marker) {
|
||||||
|
marker.setOpacity(opacity);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
,_setMarkerOpacity: function(e) {
|
||||||
|
e.layer.setOpacity(this.options.icons.opacity);
|
||||||
|
}
|
||||||
|
|
||||||
,_removeMarkerEvents: function(marker) {
|
,_removeMarkerEvents: function(marker) {
|
||||||
marker.off('mouseover', this._fireWaypointEvent, this);
|
marker.off('mouseover', this._fireWaypointEvent, this);
|
||||||
marker.off('mouseout' , this._fireWaypointEvent, this);
|
marker.off('mouseout' , this._fireWaypointEvent, this);
|
||||||
|
|
@ -186,7 +217,8 @@ BR.Routing = L.Routing.extend({
|
||||||
// animate dashed trailer as loading indicator
|
// animate dashed trailer as loading indicator
|
||||||
if (m1 && m2) {
|
if (m1 && m2) {
|
||||||
loadingTrailer = new L.Polyline([m1.getLatLng(), m2.getLatLng()], {
|
loadingTrailer = new L.Polyline([m1.getLatLng(), m2.getLatLng()], {
|
||||||
opacity: 0.6,
|
color: this.options.styles.track.color,
|
||||||
|
opacity: this.options.styles.trailer.opacity,
|
||||||
dashArray: [10, 10],
|
dashArray: [10, 10],
|
||||||
className: 'loading-trailer'
|
className: 'loading-trailer'
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue