mirror of
https://github.com/valitydev/redash.git
synced 2024-11-06 17:15:17 +00:00
Custom Map Markers (#3840)
This commit is contained in:
parent
d617f57f7d
commit
99bf6d122c
@ -1,8 +1,19 @@
|
||||
@import '../assets/less/inc/variables';
|
||||
|
||||
color-box {
|
||||
vertical-align: text-bottom;
|
||||
display: inline;
|
||||
|
||||
span {
|
||||
width: 12px !important;
|
||||
height: 12px !important;
|
||||
display: inline-block !important;
|
||||
margin-right: 5px;
|
||||
vertical-align: middle;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
}
|
||||
& ~ span {
|
||||
vertical-align: bottom;
|
||||
color: @input-color;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import 'leaflet.markercluster';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.css';
|
||||
import 'leaflet.markercluster/dist/MarkerCluster.Default.css';
|
||||
import 'beautifymarker';
|
||||
import 'beautifymarker/leaflet-beautify-marker-icon.css';
|
||||
import markerIcon from 'leaflet/dist/images/marker-icon.png';
|
||||
import markerIconRetina from 'leaflet/dist/images/marker-icon-2x.png';
|
||||
import markerShadow from 'leaflet/dist/images/marker-shadow.png';
|
||||
@ -12,6 +14,7 @@ import 'leaflet-fullscreen';
|
||||
import 'leaflet-fullscreen/dist/leaflet.fullscreen.css';
|
||||
import { angular2react } from 'angular2react';
|
||||
import { registerVisualization } from '@/visualizations';
|
||||
import ColorPalette from '@/visualizations/ColorPalette';
|
||||
|
||||
import template from './map.html';
|
||||
import editorTemplate from './map-editor.html';
|
||||
@ -76,9 +79,28 @@ const MAP_TILES = [
|
||||
},
|
||||
];
|
||||
|
||||
const iconAnchors = {
|
||||
marker: [14, 32],
|
||||
circle: [10, 10],
|
||||
rectangle: [11, 11],
|
||||
'circle-dot': [1, 2],
|
||||
'rectangle-dot': [1, 2],
|
||||
doughnut: [8, 8],
|
||||
};
|
||||
|
||||
const popupAnchors = {
|
||||
rectangle: [0, -3],
|
||||
circle: [1, -3],
|
||||
};
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
classify: 'none',
|
||||
clusterMarkers: true,
|
||||
iconShape: 'marker',
|
||||
iconFont: 'circle',
|
||||
foregroundColor: '#ffffff',
|
||||
backgroundColor: '#356AFF',
|
||||
borderColor: '#356AFF',
|
||||
};
|
||||
|
||||
function heatpoint(lat, lon, color) {
|
||||
@ -92,6 +114,7 @@ function heatpoint(lat, lon, color) {
|
||||
}
|
||||
|
||||
const createMarker = (lat, lon) => L.marker([lat, lon]);
|
||||
const createIconMarker = (lat, lon, icn) => L.marker([lat, lon], { icon: icn });
|
||||
|
||||
function createDescription(latCol, lonCol, row) {
|
||||
const lat = row[latCol];
|
||||
@ -229,7 +252,22 @@ const MapRenderer = {
|
||||
const groupColor = this.options.groups[name].color;
|
||||
marker = heatpoint(lat, lon, groupColor);
|
||||
} else {
|
||||
marker = createMarker(lat, lon);
|
||||
if (this.options.customizeMarkers) {
|
||||
const icon = L.BeautifyIcon.icon({
|
||||
iconShape: this.options.iconShape,
|
||||
icon: this.options.iconFont,
|
||||
iconSize: this.options.iconShape === 'rectangle' ? [22, 22] : false,
|
||||
iconAnchor: iconAnchors[this.options.iconShape],
|
||||
popupAnchor: popupAnchors[this.options.iconShape],
|
||||
prefix: 'fa',
|
||||
textColor: this.options.foregroundColor,
|
||||
backgroundColor: this.options.backgroundColor,
|
||||
borderColor: this.options.borderColor,
|
||||
});
|
||||
marker = createIconMarker(lat, lon, icon);
|
||||
} else {
|
||||
marker = createMarker(lat, lon);
|
||||
}
|
||||
}
|
||||
|
||||
marker.bindPopup(createDescription(latCol, lonCol, row));
|
||||
@ -308,6 +346,20 @@ const MapEditor = {
|
||||
|
||||
this.mapTiles = MAP_TILES;
|
||||
|
||||
this.iconShapes = {
|
||||
marker: 'Marker + Icon',
|
||||
doughnut: 'Circle',
|
||||
'circle-dot': 'Circle Dot',
|
||||
circle: 'Circle + Icon',
|
||||
'rectangle-dot': 'Square Dot',
|
||||
rectangle: 'Square + Icon',
|
||||
};
|
||||
|
||||
this.colors = {
|
||||
White: '#ffffff',
|
||||
...ColorPalette,
|
||||
};
|
||||
|
||||
$scope.$watch('$ctrl.data.columns', () => {
|
||||
this.columns = this.data.columns;
|
||||
this.columnNames = _.map(this.columns, c => c.name);
|
||||
|
@ -2,7 +2,7 @@
|
||||
<ul class="tab-nav">
|
||||
<li ng-class="{active: $ctrl.currentTab == 'general'}"><a ng-click="$ctrl.setCurrentTab('general')">General</a></li>
|
||||
<li ng-class="{active: $ctrl.currentTab == 'groups'}"><a ng-click="$ctrl.setCurrentTab('groups')">Groups</a></li>
|
||||
<li ng-class="{active: $ctrl.currentTab == 'map'}"><a ng-click="$ctrl.setCurrentTab('map')">Map Settings</a></li>
|
||||
<li ng-class="{active: $ctrl.currentTab == 'style'}"><a ng-click="$ctrl.setCurrentTab('style')">Style</a></li>
|
||||
</ul>
|
||||
|
||||
<div ng-show="$ctrl.currentTab == 'general'" class="m-t-10 m-b-10">
|
||||
@ -57,7 +57,9 @@
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div ng-show="$ctrl.currentTab == 'map'" class="m-t-10 m-b-10">
|
||||
<div ng-show="$ctrl.currentTab == 'style'" class="m-t-10 m-b-10">
|
||||
<h4>Tile</h4>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="$ctrl.options.clusterMarkers">
|
||||
@ -70,6 +72,95 @@
|
||||
<select ng-options="tile.url as tile.name for tile in $ctrl.mapTiles"
|
||||
ng-model="$ctrl.options.mapTileUrl" class="form-control"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4>Marker</h4>
|
||||
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="$ctrl.options.customizeMarkers">
|
||||
<i class="input-helper"></i>Override default style
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label>Shape</label>
|
||||
<ui-select ng-model="$ctrl.options.iconShape"
|
||||
ng-disabled="!$ctrl.options.customizeMarkers">
|
||||
<ui-select-match>{{$select.selected.value}}</ui-select-match>
|
||||
<ui-select-choices repeat="shapes.key as (key, shapes) in $ctrl.iconShapes">
|
||||
{{shapes.value}}
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label>Icon Font
|
||||
<span class="m-1-5" uib-popover-html="'Enter an icon name from<br/><a href="https://fontawesome.com/v4.7.0/icons/" target="_blank">Font-Awesome 4.7.</a><br/>(e.g. check, times-circle, flag)<br/>Leave blank to remove.'"
|
||||
popover-trigger="'click outsideClick'">
|
||||
<i class="fa fa-question-circle"></i>
|
||||
</span>
|
||||
</label>
|
||||
<input ng-model="$ctrl.options.iconFont" type="text" class="form-control"
|
||||
ng-disabled="!$ctrl.options.customizeMarkers"></select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Foreground Color</label>
|
||||
<ui-select ng-model="$ctrl.options.foregroundColor"
|
||||
ng-disabled="!$ctrl.options.customizeMarkers">
|
||||
<ui-select-match>
|
||||
<color-box color="$select.selected.value"></color-box>
|
||||
<span ng-bind-html="$select.selected.key | capitalize"></span>
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="color.value as (key, color) in $ctrl.colors">
|
||||
<color-box color="color.value"></color-box>
|
||||
<span ng-bind-html="color.key | capitalize | highlight: $select.search"></span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Background Color</label>
|
||||
<ui-select ng-model="$ctrl.options.backgroundColor"
|
||||
ng-disabled="!$ctrl.options.customizeMarkers">
|
||||
<ui-select-match>
|
||||
<color-box color="$select.selected.value"></color-box>
|
||||
<span ng-bind-html="$select.selected.key | capitalize"></span>
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="color.value as (key, color) in $ctrl.colors">
|
||||
<color-box color="color.value"></color-box>
|
||||
<span ng-bind-html="color.key | capitalize | highlight: $select.search"></span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Border Color</label>
|
||||
<ui-select ng-model="$ctrl.options.borderColor"
|
||||
ng-disabled="!$ctrl.options.customizeMarkers">
|
||||
<ui-select-match>
|
||||
<color-box color="$select.selected.value"></color-box>
|
||||
<span ng-bind-html="$select.selected.key | capitalize"></span>
|
||||
</ui-select-match>
|
||||
<ui-select-choices repeat="color.value as (key, color) in $ctrl.colors">
|
||||
<color-box color="color.value"></color-box>
|
||||
<span ng-bind-html="color.key | capitalize | highlight: $select.search"></span>
|
||||
</ui-select-choices>
|
||||
</ui-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -49,6 +49,7 @@
|
||||
"angular-vs-repeat": "^1.1.7",
|
||||
"angular2react": "^3.0.2",
|
||||
"antd": "^3.12.3",
|
||||
"beautifymarker": "^1.0.7",
|
||||
"bootstrap": "^3.3.7",
|
||||
"brace": "^0.11.0",
|
||||
"chroma-js": "^1.3.6",
|
||||
|
Loading…
Reference in New Issue
Block a user