mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-18 12:59:31 +00:00
71 lines
2.4 KiB
JavaScript
71 lines
2.4 KiB
JavaScript
import { createSelector } from 'reselect';
|
|
|
|
import { NODE_BASE_SIZE } from '../constants/styles';
|
|
import { zoomCacheKey } from '../utils/topology-utils';
|
|
|
|
// TODO: Make all the selectors below pure (so that they only depend on the global state).
|
|
|
|
const viewportWidthSelector = createSelector(
|
|
[
|
|
state => state.width,
|
|
(_, props) => props.margins,
|
|
],
|
|
(width, margins) => width - margins.left - margins.right
|
|
);
|
|
const viewportHeightSelector = createSelector(
|
|
[
|
|
state => state.height,
|
|
(_, props) => props.margins,
|
|
],
|
|
(height, margins) => height - margins.top
|
|
);
|
|
|
|
// Compute the default zoom settings for the given graph layout.
|
|
const defaultZoomSelector = createSelector(
|
|
[
|
|
state => state.layoutNodes,
|
|
(_, props) => props.margins,
|
|
viewportWidthSelector,
|
|
viewportHeightSelector,
|
|
],
|
|
(layoutNodes, margins, width, height) => {
|
|
if (layoutNodes.size === 0) {
|
|
return {};
|
|
}
|
|
|
|
const xMin = layoutNodes.minBy(n => n.get('x')).get('x');
|
|
const xMax = layoutNodes.maxBy(n => n.get('x')).get('x');
|
|
const yMin = layoutNodes.minBy(n => n.get('y')).get('y');
|
|
const yMax = layoutNodes.maxBy(n => n.get('y')).get('y');
|
|
|
|
const xFactor = width / (xMax - xMin);
|
|
const yFactor = height / (yMax - yMin);
|
|
|
|
// Maximal allowed zoom will always be such that a node covers 1/5 of the viewport.
|
|
const maxZoomScale = Math.min(width, height) / NODE_BASE_SIZE / 5;
|
|
|
|
// Initial zoom is such that the graph covers 90% of either the viewport,
|
|
// or one half of maximal zoom constraint, whichever is smaller.
|
|
const zoomScale = Math.min(xFactor, yFactor, maxZoomScale / 2) * 0.9;
|
|
|
|
// Finally, we always allow zooming out exactly 5x compared to the initial zoom.
|
|
const minZoomScale = zoomScale / 5;
|
|
|
|
// This translation puts the graph in the center of the viewport, respecting the margins.
|
|
const panTranslateX = ((width - ((xMax + xMin) * zoomScale)) / 2) + margins.left;
|
|
const panTranslateY = ((height - ((yMax + yMin) * zoomScale)) / 2) + margins.top;
|
|
|
|
return { zoomScale, minZoomScale, maxZoomScale, panTranslateX, panTranslateY };
|
|
}
|
|
);
|
|
|
|
// Use the cache to get the last zoom state for the selected topology,
|
|
// otherwise use the default zoom options computed from the graph layout.
|
|
export const topologyZoomState = createSelector(
|
|
[
|
|
(state, props) => state.zoomCache[zoomCacheKey(props)],
|
|
defaultZoomSelector,
|
|
],
|
|
(cachedZoomState, defaultZoomState) => cachedZoomState || defaultZoomState
|
|
);
|