aboutsummaryrefslogtreecommitdiff
path: root/web/app
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2016-11-12 09:51:40 +1300
committerGitHub <noreply@github.com>2016-11-12 09:51:40 +1300
commitfe7c46a0827eff88bc54e0d175b62f762bbd3688 (patch)
treed0c5467ca2e69e2eb51699a13c57f51ce8292446 /web/app
parent11c8c039cc8c5a1948281f410bdb440d5a9f1608 (diff)
parent9b36b690301faa7b84bade074aae3e863be5495d (diff)
downloadtrackermap-web-fe7c46a0827eff88bc54e0d175b62f762bbd3688.tar.gz
trackermap-web-fe7c46a0827eff88bc54e0d175b62f762bbd3688.tar.bz2
trackermap-web-fe7c46a0827eff88bc54e0d175b62f762bbd3688.zip
Merge pull request #313 from Abyss777/device_images
Draft of device images
Diffstat (limited to 'web/app')
-rw-r--r--web/app/Application.js4
-rw-r--r--web/app/DeviceImages.js88
-rw-r--r--web/app/Style.js11
-rw-r--r--web/app/store/DeviceImages.js93
-rw-r--r--web/app/view/DeviceDialog.js16
-rw-r--r--web/app/view/DevicesController.js1
-rw-r--r--web/app/view/MapController.js96
-rw-r--r--web/app/view/ReportController.js2
8 files changed, 254 insertions, 57 deletions
diff --git a/web/app/Application.js b/web/app/Application.js
index fc6ff5e7..702a75a9 100644
--- a/web/app/Application.js
+++ b/web/app/Application.js
@@ -69,7 +69,8 @@ Ext.define('Traccar.Application', {
'ReportSummary',
'ReportTypes',
'ReportEventTypes',
- 'Statistics'
+ 'Statistics',
+ 'DeviceImages'
],
controllers: [
@@ -126,7 +127,6 @@ Ext.define('Traccar.Application', {
},
showError: function (response) {
- var data;
if (Ext.isString(response)) {
Ext.Msg.alert(Strings.errorTitle, response);
} else if (response.responseText) {
diff --git a/web/app/DeviceImages.js b/web/app/DeviceImages.js
new file mode 100644
index 00000000..fac16a57
--- /dev/null
+++ b/web/app/DeviceImages.js
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+Ext.define('Traccar.DeviceImages', {
+ singleton: true,
+
+ getImageSvg: function (color, zoom, angle, category) {
+ var i, device, svg, width, height, rotateTransform, scaleTransform, fill;
+
+ if (category) {
+ device = Ext.getStore('DeviceImages').findRecord('key', category, 0, false, false, true);
+ }
+ if (!device) {
+ device = Ext.getStore('DeviceImages').findRecord('key', 'default', 0, false, false, true);
+ }
+ svg = Ext.clone(device.get('svg'));
+
+ width = parseFloat(svg.documentElement.getAttribute('width'));
+ height = parseFloat(svg.documentElement.getAttribute('height'));
+
+ fill = device.get('fillId');
+ if (!Ext.isArray(fill)) {
+ fill = [fill];
+ }
+ for (i = 0; i < fill.length; i++) {
+ svg.getElementById(fill[i]).style.fill = color;
+ }
+
+ rotateTransform = 'rotate(' + angle + ' ' + (width / 2) + ' ' + (height / 2) + ')';
+ svg.getElementById(device.get('rotateId')).setAttribute('transform', rotateTransform);
+
+ if (zoom) {
+ width *= Traccar.Style.mapScaleSelected;
+ height *= Traccar.Style.mapScaleSelected;
+ scaleTransform = 'scale(' + Traccar.Style.mapScaleSelected + ') ';
+ } else {
+ width *= Traccar.Style.mapScaleNormal;
+ height *= Traccar.Style.mapScaleNormal;
+ scaleTransform = 'scale(' + Traccar.Style.mapScaleNormal + ') ';
+ }
+
+ if (device.get('scaleId') !== device.get('rotateId')) {
+ svg.getElementById(device.get('scaleId')).setAttribute('transform', scaleTransform);
+ } else {
+ svg.getElementById(device.get('scaleId')).setAttribute('transform', scaleTransform + ' ' + rotateTransform);
+ }
+
+ svg.documentElement.setAttribute('width', width);
+ svg.documentElement.setAttribute('height', height);
+ svg.documentElement.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
+
+ return svg;
+ },
+
+ getImageIcon: function (color, zoom, angle, category) {
+ var image, svg, width, height;
+
+ svg = this.getImageSvg(color, zoom, angle, category);
+ width = parseFloat(svg.documentElement.getAttribute('width'));
+ height = parseFloat(svg.documentElement.getAttribute('height'));
+
+ image = new ol.style.Icon({
+ imgSize: [width, height],
+ src: 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(new XMLSerializer().serializeToString(svg.documentElement))
+ });
+ image.fill = color;
+ image.zoom = zoom;
+ image.angle = angle;
+ image.category = category;
+
+ return image;
+ }
+});
diff --git a/web/app/Style.js b/web/app/Style.js
index 8db8667e..4960aefa 100644
--- a/web/app/Style.js
+++ b/web/app/Style.js
@@ -51,21 +51,18 @@ Ext.define('Traccar.Style', {
],
mapRouteWidth: 5,
- mapArrowStrokeColor: 'rgba(50, 50, 50, 1.0)',
- mapArrowStrokeWidth: 2,
-
mapTextColor: 'rgba(50, 50, 50, 1.0)',
mapTextStrokeColor: 'rgba(255, 255, 255, 1.0)',
mapTextStrokeWidth: 2,
- mapTextOffset: 10,
+ mapTextOffset: 2,
mapTextFont: 'bold 12px sans-serif',
mapColorOnline: 'rgba(77, 250, 144, 1.0)',
mapColorUnknown: 'rgba(250, 190, 77, 1.0)',
- mapColorOffline: 'rgba(255, 84, 104, 1.0)',
+ mapColorOffline: 'rgba(255, 162, 173, 1.0)',
- mapRadiusNormal: 9,
- mapRadiusSelected: 14,
+ mapScaleNormal: 1,
+ mapScaleSelected: 1.5,
mapMaxZoom: 19,
mapDelay: 500,
diff --git a/web/app/store/DeviceImages.js b/web/app/store/DeviceImages.js
new file mode 100644
index 00000000..efe8606a
--- /dev/null
+++ b/web/app/store/DeviceImages.js
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Anton Tananaev (anton@traccar.org)
+ * Copyright 2016 Andrey Kunitsyn (andrey@traccar.org)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+Ext.define('Traccar.store.DeviceImages', {
+ extend: 'Ext.data.Store',
+ fields: ['key', 'name', 'svg', 'fillId', 'rotateId', 'scaleId'],
+
+ data: [{
+ key: 'arrow',
+ name: Strings.categoryArrow,
+ svg: document.getElementById('arrowSvg').contentDocument,
+ fillId: 'arrow',
+ rotateId: 'arrow',
+ scaleId: 'arrow'
+ }, {
+ key: 'default',
+ name: Strings.categoryDefault,
+ svg: document.getElementById('defaultSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'car',
+ name: Strings.categoryCar,
+ svg: document.getElementById('carSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'bus',
+ name: Strings.categoryBus,
+ svg: document.getElementById('busSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'truck',
+ name: Strings.categoryTruck,
+ svg: document.getElementById('truckSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'ship',
+ name: Strings.categoryShip,
+ svg: document.getElementById('shipSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'plane',
+ name: Strings.categoryPlane,
+ svg: document.getElementById('planeSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'motorcycle',
+ name: Strings.categoryMotorcycle,
+ svg: document.getElementById('motorcycleSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'bicycle',
+ name: Strings.categoryBicycle,
+ svg: document.getElementById('bicycleSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }, {
+ key: 'person',
+ name: Strings.categoryPerson,
+ svg: document.getElementById('personSvg').contentDocument,
+ fillId: 'path4724',
+ rotateId: 'path4724',
+ scaleId: 'layer1'
+ }]
+});
diff --git a/web/app/view/DeviceDialog.js b/web/app/view/DeviceDialog.js
index 68740b24..d3f964ed 100644
--- a/web/app/view/DeviceDialog.js
+++ b/web/app/view/DeviceDialog.js
@@ -57,6 +57,22 @@ Ext.define('Traccar.view.DeviceDialog', {
xtype: 'textfield',
name: 'contact',
fieldLabel: Strings.deviceContact
+ }, {
+ xtype: 'combobox',
+ name: 'category',
+ fieldLabel: Strings.deviceCategory,
+ store: 'DeviceImages',
+ queryMode: 'local',
+ displayField: 'name',
+ valueField: 'key',
+ listConfig: {
+ getInnerTpl: function () {
+ return '<table><tr valign="middle" ><td><div align="center" style="width:40px;height:40px;" >' +
+ '{[new XMLSerializer().serializeToString(Traccar.DeviceImages.getImageSvg(' +
+ 'Traccar.Style.mapColorOnline, false, 0, values.key))]}</div></td>' +
+ '<td>- {name}</td></tr></table>';
+ }
+ }
}]
}
});
diff --git a/web/app/view/DevicesController.js b/web/app/view/DevicesController.js
index aa8e7886..a31ceb77 100644
--- a/web/app/view/DevicesController.js
+++ b/web/app/view/DevicesController.js
@@ -147,6 +147,7 @@ Ext.define('Traccar.view.DevicesController', {
selectDevice: function (device, center) {
this.getView().getSelectionModel().select([device], false, true);
+ this.updateButtons(this.getView().getSelectionModel());
this.getView().getView().focusRow(device);
},
diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js
index 32ea6b05..c981fabc 100644
--- a/web/app/view/MapController.js
+++ b/web/app/view/MapController.js
@@ -22,7 +22,8 @@ Ext.define('Traccar.view.MapController', {
requires: [
'Traccar.model.Position',
'Traccar.model.Device',
- 'Traccar.GeofenceConverter'
+ 'Traccar.GeofenceConverter',
+ 'Traccar.DeviceImages'
],
config: {
@@ -70,7 +71,7 @@ Ext.define('Traccar.view.MapController', {
this.lookupReference('showReportsButton').setVisible(Traccar.app.isMobile());
},
- showReports: function() {
+ showReports: function () {
Traccar.app.showReports(true);
},
@@ -85,18 +86,15 @@ Ext.define('Traccar.view.MapController', {
}
},
- changeMarkerColor: function (style, color) {
- return new ol.style.Style({
- image: new ol.style.Arrow({
- radius: style.getImage().getRadius(),
- fill: new ol.style.Fill({
- color: color
- }),
- stroke: style.getImage().getStroke(),
- rotation: style.getImage().getRotation()
- }),
+ changeMarkerColor: function (style, color, category) {
+ var newStyle = new ol.style.Style({
+ image: Traccar.DeviceImages.getImageIcon(color,
+ style.getImage().zoom,
+ style.getImage().angle,
+ category),
text: style.getText()
});
+ return newStyle;
},
updateDevice: function (store, data) {
@@ -113,7 +111,7 @@ Ext.define('Traccar.view.MapController', {
if (deviceId in this.latestMarkers) {
marker = this.latestMarkers[deviceId];
marker.setStyle(
- this.changeMarkerColor(marker.getStyle(), this.getDeviceColor(device)));
+ this.changeMarkerColor(marker.getStyle(), this.getDeviceColor(device), device.get('category')));
}
}
},
@@ -154,18 +152,20 @@ Ext.define('Traccar.view.MapController', {
if (deviceId in this.latestMarkers) {
marker = this.latestMarkers[deviceId];
marker.setGeometry(geometry);
+ marker.setStyle(this.rotateMarker(marker.getStyle(), position.get('course')));
} else {
marker = new ol.Feature(geometry);
marker.set('record', device);
- this.latestMarkers[deviceId] = marker;
- this.getView().getLatestSource().addFeature(marker);
- style = this.getLatestMarker(this.getDeviceColor(device));
+ style = this.getLatestMarker(this.getDeviceColor(device),
+ position.get('course'),
+ device.get('category'));
style.getText().setText(device.get('name'));
marker.setStyle(style);
- }
+ this.latestMarkers[deviceId] = marker;
+ this.getView().getLatestSource().addFeature(marker);
- marker.getStyle().getImage().setRotation(position.get('course') * Math.PI / 180);
+ }
if (marker === this.selectedMarker && this.followSelected()) {
this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
@@ -231,8 +231,7 @@ Ext.define('Traccar.view.MapController', {
this.reportMarkers[position.get('id')] = marker;
this.getView().getReportSource().addFeature(marker);
- style = this.getReportMarker(position.get('deviceId'));
- style.getImage().setRotation(position.get('course') * Math.PI / 180);
+ style = this.getReportMarker(position.get('deviceId'), position.get('course'));
/*style.getText().setText(
Ext.Date.format(position.get('fixTime'), Traccar.Style.dateTimeFormat24));*/
@@ -278,18 +277,10 @@ Ext.define('Traccar.view.MapController', {
});
},
- getMarkerStyle: function (radius, color) {
+ getMarkerStyle: function (zoom, color, angle, category) {
+ var image = Traccar.DeviceImages.getImageIcon(color, zoom, angle, category);
return new ol.style.Style({
- image: new ol.style.Arrow({
- radius: radius,
- fill: new ol.style.Fill({
- color: color
- }),
- stroke: new ol.style.Stroke({
- color: Traccar.Style.mapArrowStrokeColor,
- width: Traccar.Style.mapArrowStrokeWidth
- })
- }),
+ image: image,
text: new ol.style.Text({
textBaseline: 'bottom',
fill: new ol.style.Fill({
@@ -299,47 +290,58 @@ Ext.define('Traccar.view.MapController', {
color: Traccar.Style.mapTextStrokeColor,
width: Traccar.Style.mapTextStrokeWidth
}),
- offsetY: -radius / 2 - Traccar.Style.mapTextOffset,
+ offsetY: -image.getSize()[1] / 2 - Traccar.Style.mapTextOffset,
font : Traccar.Style.mapTextFont
})
});
},
- getLatestMarker: function (color) {
- return this.getMarkerStyle(
- Traccar.Style.mapRadiusNormal, color);
+ getLatestMarker: function (color, angle, category) {
+ return this.getMarkerStyle(false, color, angle, category);
},
- getReportMarker: function (deviceId) {
+ getReportMarker: function (deviceId, angle) {
var index = 0;
if (deviceId !== undefined) {
index = deviceId % Traccar.Style.mapRouteColor.length;
}
- return this.getMarkerStyle(
- Traccar.Style.mapRadiusNormal, Traccar.Style.mapRouteColor[index]);
+ return this.getMarkerStyle(false, Traccar.Style.mapRouteColor[index], angle, 'arrow');
},
- resizeMarker: function (style, radius) {
+ resizeMarker: function (style, zoom) {
+ var image, text;
+ image = Traccar.DeviceImages.getImageIcon(style.getImage().fill,
+ zoom,
+ style.getImage().angle,
+ style.getImage().category);
+ text = style.getText();
+ text.setOffsetY(-image.getSize()[1] / 2 - Traccar.Style.mapTextOffset);
return new ol.style.Style({
- image: new ol.style.Arrow({
- radius: radius,
- fill: style.getImage().getFill(),
- stroke: style.getImage().getStroke(),
- rotation: style.getImage().getRotation()
- }),
+ image: image,
+ text: text
+ });
+ },
+
+ rotateMarker: function (style, angle) {
+ var newStyle = new ol.style.Style({
+ image: Traccar.DeviceImages.getImageIcon(style.getImage().fill,
+ style.getImage().zoom,
+ angle,
+ style.getImage().category),
text: style.getText()
});
+ return newStyle;
},
selectMarker: function (marker, center) {
if (this.selectedMarker) {
this.selectedMarker.setStyle(
- this.resizeMarker(this.selectedMarker.getStyle(), Traccar.Style.mapRadiusNormal));
+ this.resizeMarker(this.selectedMarker.getStyle(), false));
}
if (marker) {
marker.setStyle(
- this.resizeMarker(marker.getStyle(), Traccar.Style.mapRadiusSelected));
+ this.resizeMarker(marker.getStyle(), true));
if (center) {
this.getView().getMapView().setCenter(marker.getGeometry().getCoordinates());
}
diff --git a/web/app/view/ReportController.js b/web/app/view/ReportController.js
index 224a2a86..a8c5f4eb 100644
--- a/web/app/view/ReportController.js
+++ b/web/app/view/ReportController.js
@@ -41,7 +41,7 @@ Ext.define('Traccar.view.ReportController', {
}
},
- hideReports: function() {
+ hideReports: function () {
Traccar.app.showReports(false);
},