Skip to content

Commit

Permalink
feat: add canvas zoom and panning function
Browse files Browse the repository at this point in the history
  • Loading branch information
ylzon committed Jun 12, 2024
1 parent 1b5b728 commit d261a06
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 13 deletions.
3 changes: 3 additions & 0 deletions packages/@fiagram-core/src/constant/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,6 @@ export const MovingEdgeAnchorStatusClass = 'move-edge-anchor'

export const extractNumberRegex = /[+-]?\d+(\.\d+)?/g
export const floatOrIntegerReg = /(-\d+(\.\d+)?)|(\d+(\.\d+)?)/g

export const MIN_SCALE = 0.1
export const MAX_SCALE = 10
11 changes: 10 additions & 1 deletion packages/@fiagram-core/src/utils/diagram.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _ from 'lodash'
import type { Node, Nodes, Rect } from '../../types/nodes'
import { DIRECTION, unexpandHeight, unexpandWidth } from '../constant'
import { DIRECTION, MAX_SCALE, MIN_SCALE, unexpandHeight, unexpandWidth } from '../constant'
import type { EdgeDirection, Edges } from '../../types/edges'
import type { XYCoord } from '../../types/diagram'
import { generateEdgePath } from './edge'
Expand Down Expand Up @@ -531,3 +531,12 @@ export function checkNodesByMovingNode({ node, nodes, chain }: { node: Node, nod
export function findCurrentSelectedNodes(selectedNodes: Nodes, nodes: Nodes): Nodes {
return _.map(selectedNodes, sNode => findNode(nodes, sNode.id) as Node) || []
}

/**
* 是否符合 d3.ScaleExtent 类型并满足数值范围限制
* @param extent
*/
export function isValidScaleExtent(extent: [number, number]): boolean {
const [min, max] = extent
return (min >= MIN_SCALE) && (max <= MAX_SCALE) && (min < max)
}
3 changes: 2 additions & 1 deletion packages/@fiagram-core/types/diagram.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ export interface DiagramProps {
hideDragBox?: boolean // 隐藏拖动栏
hideTools?: boolean // 隐藏工具栏
wheelZoomDisabled?: boolean // 禁止鼠标滚轮缩放
dragZoomDisabled?: boolean // 禁止鼠标拖动缩放
dragZoomDisabled?: boolean // 禁止鼠标拖动
scaleExtent?: [number, number] // 滚轮最大和最小范围: 0.1 - 10
copyNodeDisabled?: boolean // 禁止 `ctrl+c/v` 拷贝/复制节点
hideGrid?: boolean // 不显示网格
withoutCenter?: boolean // 不自动居中图形
Expand Down
2 changes: 1 addition & 1 deletion packages/@fiagram-react/src/components/canvas/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const Canvas = forwardRef<CanvasRef, CanvasProps>((props, ref) => {
store.setCanvasSize(size)
}, [size])

useSvgInfo(svgRef, auxiliaryRef)
useSvgInfo(svgRef, auxiliaryRef, props)
useCreatDrop(svgRef)
useUpdateState(props)
useImperativeHandle(ref, () => (store))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const PanelView: FC<IProps> = (props) => {
title,
dragList = [],
} = props
const { state: { height } } = useDiagramStore(state => state)
const { state: { height = 0 } } = useDiagramStore(state => state)
const maxHeight = height > 0 ? height - 120 : 'auto'

return (
Expand Down
2 changes: 1 addition & 1 deletion packages/@fiagram-react/src/hooks/useCreatDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useDiagramStore } from './useDiagramStore.ts'

export function useCreatDrop(svgRef: RefObject<SVGSVGElement>) {
const { state, setNodes } = useDiagramStore(state => state)
const { nodes, svgInfo, uniqId } = state
const { nodes = [], svgInfo, uniqId } = state
const [, drop] = useDrop({
accept: `${DRAG_DROP_KEY}-${uniqId}`,
drop: (item, monitor) => {
Expand Down
43 changes: 35 additions & 8 deletions packages/@fiagram-react/src/hooks/useSvgInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,33 @@ import * as d3 from 'd3'
import { type RefObject, useEffect } from 'react'
import type { SvgInfo } from '@fiagram/core/types/diagram'
import _ from 'lodash'
import { isValidScaleExtent } from '@fiagram/core/src/utils/diagram'
import type { CanvasProps } from '../components/canvas'
import { useDiagramStore } from './useDiagramStore'

export function useSvgInfo(svgTarget: RefObject<SVGSVGElement>, auxiliaryTarget: RefObject<SVGGElement>) {
export function useSvgInfo(svgTarget: RefObject<SVGSVGElement>, auxiliaryTarget: RefObject<SVGGElement>, props: CanvasProps) {
const { state, setSvgInfo, setState } = useDiagramStore(state => state)
const { zoomConfig, selectedNodes, selectedEdges } = state
const defaultZoomConfig = (zoomAreaEl: any) => d3
.zoom()
// .scaleExtent([1 / 5, 4])
.on('zoom', () => {
zoomAreaEl.attr('transform', (d3 as any).event.transform)
})
const { svgInfo, zoomConfig, selectedNodes, selectedEdges, marqueeNodes } = state
const { wheelZoomDisabled, dragZoomDisabled, scaleExtent } = props
const auxiliaryElement = auxiliaryTarget.current
const svgElement = svgTarget.current
const defaultZoomConfig = (zoomAreaEl: SvgInfo['svgZoomArea']) => d3
.zoom()
.scaleExtent(scaleExtent && isValidScaleExtent(scaleExtent) ? scaleExtent : [1 / 5, 4])
.on('zoom', (e) => {
zoomAreaEl.attr('transform', e.transform)
})
const setSvgTranslateScale = (svg: SvgInfo['svg'], zoom: SvgInfo['zoom']) => {
svg.call(zoom).on('dblclick.zoom', null)

if (wheelZoomDisabled) {
svg.on('wheel.zoom', null)
}

if (dragZoomDisabled) {
svg.on('mousedown.zoom', null)
}
}

// 处理svg信息
useEffect(() => {
Expand All @@ -31,6 +45,8 @@ export function useSvgInfo(svgTarget: RefObject<SVGSVGElement>, auxiliaryTarget:
marqueeSelect: marqueeWrapD3.select('.marquee-select'),
marqueeSelectCopy: marqueeWrapD3.select('.marquee-select-copy'),
}
// 配置画布的平移和缩放
setSvgTranslateScale(svgD3, newSvgInfo.zoom)
// 初始化辅助线
Array.from(auxiliaryElement?.childNodes || []).forEach((item: any) => {
const key = item?.getAttribute('data-svg-key')
Expand Down Expand Up @@ -58,10 +74,21 @@ export function useSvgInfo(svgTarget: RefObject<SVGSVGElement>, auxiliaryTarget:
if (selectedEdges && selectedEdges.length > 0) {
newState.selectedEdges = []
}
if (marqueeNodes && marqueeNodes.length > 0) {
newState.marqueeNodes = []
}
setState(newState)
}
})
}
})

// 开关变化后重新设置画布是否开启平移和缩放
useEffect(() => {
if (svgInfo?.svg) {
setSvgTranslateScale(svgInfo.svg, svgInfo.zoom)
}
}, [wheelZoomDisabled, dragZoomDisabled])

return null
}

0 comments on commit d261a06

Please sign in to comment.