aboutsummaryrefslogtreecommitdiff
path: root/web/app
diff options
context:
space:
mode:
Diffstat (limited to 'web/app')
-rw-r--r--web/app/Application.js3
-rw-r--r--web/app/DeviceImages.js74
-rw-r--r--web/app/Style.js6
-rw-r--r--web/app/store/DeviceImages.js69
-rw-r--r--web/app/view/MapController.js88
5 files changed, 189 insertions, 51 deletions
diff --git a/web/app/Application.js b/web/app/Application.js
index fc6ff5e..a92d148 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: [
diff --git a/web/app/DeviceImages.js b/web/app/DeviceImages.js
new file mode 100644
index 0000000..ade88bd
--- /dev/null
+++ b/web/app/DeviceImages.js
@@ -0,0 +1,74 @@
+/*
+ * 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,
+
+ getImageIcon: function(color, zoom, angle, category) {
+ var image, device, svg, width, height, rotateTransform, scaleTransform, transform;
+ // Get right image or fallback to default arrow
+ if (category) {
+ device = Ext.getStore('DeviceImages').findRecord('key', category);
+ }
+ if (device === undefined || device === null) {
+ device = Ext.getStore('DeviceImages').findRecord('key', 'default');
+ }
+
+ // Duplicate svg object to not brake origin
+ svg = Ext.clone(device.get('svg'));
+
+ // Get original dimensions
+ width = parseFloat(svg.documentElement.getAttribute('width'));
+ height = parseFloat(svg.documentElement.getAttribute('height'));
+ // Colorize
+ svg.getElementById(device.get('fillId')).style.fill = color;
+ // Prepare rotate transformation
+ rotateTransform = 'rotate(' + angle + ' ' + (width / 2) + ' ' + (height / 2) + ')';
+
+ // Adjust size and prepare scale transformation
+ width *= device.get('scale');
+ height *= device.get('scale');
+ if (zoom) {
+ width *= Traccar.Style.mapScaleSelected;
+ height *= Traccar.Style.mapScaleSelected;
+ scaleTransform = 'scale(' + device.get('scale') * Traccar.Style.mapScaleSelected + ') ';
+ } else {
+ scaleTransform = 'scale(' + device.get('scale') + ') ';
+ }
+
+ //Apply both transformation in right order
+ transform = scaleTransform + ' ' + rotateTransform;
+ svg.getElementById(device.get('rotateId')).setAttribute('transform', transform);
+
+ // Set dimension attributes
+ svg.documentElement.setAttribute('width', width);
+ svg.documentElement.setAttribute('height', height);
+ svg.documentElement.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
+
+ image = new ol.style.Icon({
+ imgSize: [width, height], // Workaround for IE
+ 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;
+ }
+}); \ No newline at end of file
diff --git a/web/app/Style.js b/web/app/Style.js
index b4201bb..2353a21 100644
--- a/web/app/Style.js
+++ b/web/app/Style.js
@@ -49,9 +49,6 @@ 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,
@@ -62,8 +59,7 @@ Ext.define('Traccar.Style', {
mapColorUnknown: 'rgba(250, 190, 77, 1.0)',
mapColorOffline: 'rgba(255, 84, 104, 1.0)',
- mapRadiusNormal: 9,
- mapRadiusSelected: 14,
+ 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 0000000..968f90c
--- /dev/null
+++ b/web/app/store/DeviceImages.js
@@ -0,0 +1,69 @@
+/*
+ * 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', 'url', 'svg', 'fillId', 'rotateId', 'scale'],
+
+ data: [{
+ key: 'default',
+ name: Strings.categoryDefault,
+ svg: (new DOMParser())
+ .parseFromString('<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="26" height="26">'
+ + '<polygon id="arrow" points="13,4 19,22 13,19 7,22" '
+ + 'style="fill:#008000;stroke:#000000;stroke-width:2px;" transform="" /></svg>', "image/svg+xml"),
+ rotateId: 'arrow',
+ fillId: 'arrow',
+ scale: 1
+ }, {
+ key: 'car',
+ name: Strings.categoryCar,
+ url: 'images/car.svg',
+ fillId: 'path4149',
+ rotateId: 'g4207',
+ scale: 0.06,
+ }, {
+ key: 'bus',
+ name: Strings.categoryBus,
+ url: 'images/bus.svg',
+ fillId: 'path4713',
+ rotateId: 'layer2',
+ scale: 0.12,
+ }, {
+ key: 'truck',
+ name: Strings.categoryTruck,
+ url: 'images/truck.svg',
+ fillId: 'path4718',
+ rotateId: 'layer2',
+ scale: 0.1,
+ }],
+
+ constructor: function() {
+ this.callParent(arguments);
+ this.config.data.forEach(function (device) {
+ if (device.url) {
+ Ext.Ajax.request({
+ url: device.url,
+ scope: device,
+ success: function (response) {
+ this.svg = (new DOMParser()).parseFromString(response.responseText, "image/svg+xml");
+ }
+ });
+ }
+ });
+ }
+}); \ No newline at end of file
diff --git a/web/app/view/MapController.js b/web/app/view/MapController.js
index 32ea6b0..7875e94 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: {
@@ -86,17 +87,14 @@ 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()
- }),
+ var newStyle = new ol.style.Style({
+ image: Traccar.DeviceImages.getImageIcon(color,
+ style.getImage().zoom,
+ style.getImage().angle,
+ style.getImage().category),
text: style.getText()
});
+ return newStyle;
},
updateDevice: function (store, data) {
@@ -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,9 @@ Ext.define('Traccar.view.MapController', {
});
},
- getMarkerStyle: function (radius, color) {
+ getMarkerStyle: function (zoom, color, 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: Traccar.DeviceImages.getImageIcon(color, zoom, angle, category),
text: new ol.style.Text({
textBaseline: 'bottom',
fill: new ol.style.Fill({
@@ -299,47 +289,55 @@ Ext.define('Traccar.view.MapController', {
color: Traccar.Style.mapTextStrokeColor,
width: Traccar.Style.mapTextStrokeWidth
}),
- offsetY: -radius / 2 - Traccar.Style.mapTextOffset,
+ offsetY: -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);
},
- resizeMarker: function (style, radius) {
- return new ol.style.Style({
- image: new ol.style.Arrow({
- radius: radius,
- fill: style.getImage().getFill(),
- stroke: style.getImage().getStroke(),
- rotation: style.getImage().getRotation()
- }),
+ resizeMarker: function (style, zoom) {
+ var newStyle = new ol.style.Style({
+ image: Traccar.DeviceImages.getImageIcon(style.getImage().fill,
+ zoom,
+ style.getImage().angle,
+ style.getImage().category),
+ text: style.getText()
+ });
+ return newStyle;
+ },
+
+ 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());
}