mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 02:50:02 -03:30
Move zoom methods into a hook.
This commit is contained in:
parent
ef5cd66494
commit
039c038cd7
@ -1,5 +1,4 @@
|
||||
import React, { useEffect, useCallback, useState } from 'react';
|
||||
import * as d3 from 'd3';
|
||||
import { t } from '@lingui/macro';
|
||||
import { PageSection, Card, CardBody } from '@patternfly/react-core';
|
||||
import ContentError from 'components/ContentError';
|
||||
@ -7,6 +6,8 @@ import useRequest from 'hooks/useRequest';
|
||||
import { MeshAPI } from 'api';
|
||||
import Header from './Header';
|
||||
import MeshGraph from './MeshGraph';
|
||||
import useZoom from './utils/useZoom';
|
||||
import { CHILDSELECTOR, PARENTSELECTOR } from './constants';
|
||||
|
||||
function TopologyView() {
|
||||
const [showLegend, setShowLegend] = useState(true);
|
||||
@ -27,52 +28,11 @@ function TopologyView() {
|
||||
useEffect(() => {
|
||||
fetchMeshVisualizer();
|
||||
}, [fetchMeshVisualizer]);
|
||||
const { zoom, zoomFit, zoomIn, zoomOut, resetZoom } = useZoom(
|
||||
PARENTSELECTOR,
|
||||
CHILDSELECTOR
|
||||
);
|
||||
|
||||
const zoom = d3.zoom().on('zoom', ({ transform }) => {
|
||||
d3.select('.mesh').attr('transform', transform);
|
||||
});
|
||||
const zoomIn = () => {
|
||||
d3.select('.mesh-svg').transition().call(zoom.scaleBy, 2);
|
||||
};
|
||||
const zoomOut = () => {
|
||||
d3.select('.mesh-svg').transition().call(zoom.scaleBy, 0.5);
|
||||
};
|
||||
const resetZoom = () => {
|
||||
const parent = d3.select('.mesh').node().parentElement;
|
||||
const width = parent.clientWidth;
|
||||
const height = parent.clientHeight;
|
||||
d3.select('.mesh-svg')
|
||||
.transition()
|
||||
.duration(750)
|
||||
.call(
|
||||
zoom.transform,
|
||||
d3.zoomIdentity,
|
||||
d3
|
||||
.zoomTransform(d3.select('.mesh-svg').node())
|
||||
.invert([width / 2, height / 2])
|
||||
);
|
||||
};
|
||||
|
||||
const zoomFit = () => {
|
||||
const bounds = d3.select('.mesh').node().getBBox();
|
||||
const parent = d3.select('.mesh').node().parentElement;
|
||||
const fullWidth = parent.clientWidth;
|
||||
const fullHeight = parent.clientHeight;
|
||||
const { width, height } = bounds;
|
||||
const midX = bounds.x + width / 2;
|
||||
const midY = bounds.y + height / 2;
|
||||
if (width === 0 || height === 0) return; // nothing to fit
|
||||
const scale = 0.8 / Math.max(width / fullWidth, height / fullHeight);
|
||||
const translate = [
|
||||
fullWidth / 2 - scale * midX,
|
||||
fullHeight / 2 - scale * midY,
|
||||
];
|
||||
const [x, y] = translate;
|
||||
d3.select('.mesh-svg')
|
||||
.transition()
|
||||
.duration(750)
|
||||
.call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(scale));
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Header
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export const SELECTOR = '#chart';
|
||||
export const PARENTSELECTOR = '.mesh-svg';
|
||||
export const CHILDSELECTOR = '.mesh';
|
||||
export const MESH_FORCE_LAYOUT = {
|
||||
defaultCollisionFactor: 80,
|
||||
defaultForceStrength: -100,
|
||||
|
||||
74
awx/ui/src/screens/TopologyView/utils/useZoom.js
Normal file
74
awx/ui/src/screens/TopologyView/utils/useZoom.js
Normal file
@ -0,0 +1,74 @@
|
||||
import * as d3 from 'd3';
|
||||
import { getWidth, getHeight } from './helpers';
|
||||
|
||||
/**
|
||||
* useZoom provides a collection of zoom behaviors/functions for D3 graphs
|
||||
* Params: string value of parent and child classnames
|
||||
* The following hierarchy should be followed:
|
||||
* <div id="chart">
|
||||
* <svg><-- parent -->
|
||||
* <g><-- child -->
|
||||
* </svg>
|
||||
* </div>
|
||||
* Returns: {
|
||||
* zoom: d3 zoom behavior/object/function to apply on selected elements
|
||||
* zoomIn: function that zooms in
|
||||
* zoomOut: function that zooms out
|
||||
* zoomFit: function that scales child element to fit within parent element
|
||||
* resetZoom: function resets the zoom level to its initial value
|
||||
* }
|
||||
*/
|
||||
|
||||
export default function useZoom(parentSelector, childSelector) {
|
||||
const zoom = d3.zoom().on('zoom', ({ transform }) => {
|
||||
d3.select(childSelector).attr('transform', transform);
|
||||
});
|
||||
const zoomIn = () => {
|
||||
d3.select(parentSelector).transition().call(zoom.scaleBy, 2);
|
||||
};
|
||||
const zoomOut = () => {
|
||||
d3.select(parentSelector).transition().call(zoom.scaleBy, 0.5);
|
||||
};
|
||||
const resetZoom = () => {
|
||||
const parent = d3.select(parentSelector).node();
|
||||
const width = parent.clientWidth;
|
||||
const height = parent.clientHeight;
|
||||
d3.select(parentSelector)
|
||||
.transition()
|
||||
.duration(750)
|
||||
.call(
|
||||
zoom.transform,
|
||||
d3.zoomIdentity,
|
||||
d3
|
||||
.zoomTransform(d3.select(parentSelector).node())
|
||||
.invert([width / 2, height / 2])
|
||||
);
|
||||
};
|
||||
const zoomFit = () => {
|
||||
const bounds = d3.select(childSelector).node().getBBox();
|
||||
const fullWidth = getWidth(parentSelector);
|
||||
const fullHeight = getHeight(parentSelector);
|
||||
const { width, height } = bounds;
|
||||
const midX = bounds.x + width / 2;
|
||||
const midY = bounds.y + height / 2;
|
||||
if (width === 0 || height === 0) return; // nothing to fit
|
||||
const scale = 0.8 / Math.max(width / fullWidth, height / fullHeight);
|
||||
const translate = [
|
||||
fullWidth / 2 - scale * midX,
|
||||
fullHeight / 2 - scale * midY,
|
||||
];
|
||||
const [x, y] = translate;
|
||||
d3.select(parentSelector)
|
||||
.transition()
|
||||
.duration(750)
|
||||
.call(zoom.transform, d3.zoomIdentity.translate(x, y).scale(scale));
|
||||
};
|
||||
|
||||
return {
|
||||
zoom,
|
||||
zoomIn,
|
||||
zoomOut,
|
||||
zoomFit,
|
||||
resetZoom,
|
||||
};
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user