blob: cebe8c74b3d5b10319d39d33528d53ac9505764d [file] [log] [blame]
/*
* Copyright 2015-present Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
ONOS GUI -- SVG -- Zoom Service
*/
(function () {
'use strict';
// configuration
var defaultSettings = {
zoomMin: 0.05,
zoomMax: 10,
zoomEnabled: function (ev) { return true; },
zoomCallback: function () {}
};
// injected references to services
var $log;
angular.module('onosSvg')
.factory('ZoomService', ['$log',
function (_$log_) {
$log = _$log_;
/*
NOTE: opts is an object:
{
svg: svg, D3 selection of <svg> element
zoomLayer: zoomLayer, D3 selection of <g> element
zoomEnabled: function (ev) { ... },
zoomCallback: function () { ... }
}
where:
* svg and zoomLayer should be D3 selections of DOM elements.
* zoomLayer <g> is a child of <svg> element.
* zoomEnabled is an optional predicate based on D3 event.
* default is always enabled.
* zoomCallback is an optional callback invoked each time we pan/zoom.
* default is do nothing.
Optionally, zoomMin and zoomMax also can be defined.
These default to 0.25 and 10 respectively.
*/
function createZoomer(opts) {
var cz = 'ZoomService.createZoomer(): ',
d3s = ' (D3 selection) property defined',
settings = angular.extend({}, defaultSettings, opts),
zoom = d3.behavior.zoom()
.translate([0, 0])
.scale(1)
.scaleExtent([settings.zoomMin, settings.zoomMax])
.on('zoom', zoomed),
fail = false,
zoomer;
if (!settings.svg) {
$log.error(cz + 'No "svg" (svg tag)' + d3s);
fail = true;
}
if (!settings.zoomLayer) {
$log.error(cz + 'No "zoomLayer" (g tag)' + d3s);
fail = true;
}
if (fail) {
return null;
}
// zoom events from mouse gestures...
function zoomed() {
var ev = d3.event.sourceEvent;
if (settings.zoomEnabled(ev)) {
adjustZoomLayer(d3.event.translate, d3.event.scale);
}
}
function adjustZoomLayer(translate, scale, transition) {
settings.zoomLayer.transition()
.duration(transition || 0)
.attr("transform",
'translate(' + translate + ')scale(' + scale + ')');
settings.zoomCallback(translate, scale);
}
zoomer = {
panZoom: function (translate, scale, transition) {
zoom.translate(translate).scale(scale);
adjustZoomLayer(translate, scale, transition);
},
reset: function () {
zoomer.panZoom([0,0], 1);
},
translate: function () {
return zoom.translate();
},
scale: function () {
return zoom.scale();
},
scaleExtent: function () {
return zoom.scaleExtent();
}
};
// apply the zoom behavior to the SVG element
settings.svg && settings.svg.call(zoom);
// Remove zoom on double click (prevents a
// false zoom navigating regions)
settings.svg.on("dblclick.zoom", null);
return zoomer;
}
return {
createZoomer: createZoomer
};
}]);
}());