component.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /**
  2. * Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
  3. * SPDX-License-Identifier: MIT
  4. */
  5. import React, { CSSProperties, useEffect, useRef, useState } from 'react';
  6. import { usePlaygroundContainer } from '@flowgram.ai/core';
  7. import { MinimapInactiveStyle } from './type';
  8. import { FlowMinimapService } from './service';
  9. import { MinimapDefaultInactiveStyle } from './constant';
  10. interface MinimapProps {
  11. service?: FlowMinimapService;
  12. panelStyles?: CSSProperties;
  13. containerStyles?: CSSProperties;
  14. inactiveStyle?: Partial<MinimapInactiveStyle>;
  15. }
  16. export const MinimapRender: React.FC<MinimapProps> = (props) => {
  17. const { panelStyles = {}, containerStyles = {}, inactiveStyle: customInactiveStyle = {} } = props;
  18. const inactiveStyle = {
  19. ...MinimapDefaultInactiveStyle,
  20. ...customInactiveStyle,
  21. };
  22. const playgroundContainer = usePlaygroundContainer();
  23. const service = props.service || playgroundContainer?.get(FlowMinimapService);
  24. const panelRef = useRef<HTMLDivElement>(null);
  25. const [activated, setActivated] = useState<boolean>(false);
  26. useEffect(() => {
  27. const canvasContainer: HTMLDivElement | null = panelRef.current;
  28. if (canvasContainer && service.canvas) {
  29. canvasContainer.appendChild(service.canvas);
  30. }
  31. const disposer = service.onActive((activate: boolean) => {
  32. setActivated(activate);
  33. });
  34. service.setVisible(true);
  35. service.render();
  36. return () => {
  37. disposer.dispose();
  38. service.setVisible(false);
  39. };
  40. }, [service]);
  41. // 计算缩放比例和透明度
  42. const scale: number = activated ? 1 : inactiveStyle.scale;
  43. const opacity: number = activated ? 1 : inactiveStyle.opacity;
  44. // 计算偏移量
  45. const translateX: number = activated ? 0 : inactiveStyle.translateX; // 向右偏移的像素
  46. const translateY: number = activated ? 0 : inactiveStyle.translateY; // 向下偏移的像素
  47. return (
  48. <div
  49. className="minimap-container"
  50. style={{
  51. position: 'fixed',
  52. right: 30,
  53. bottom: 70,
  54. transition: 'all 0.3s ease', // 添加过渡效果
  55. transform: `scale(${scale}) translate(${translateX}px, ${translateY}px)`,
  56. opacity: opacity,
  57. transformOrigin: 'bottom right', // 设置变换的原点
  58. ...containerStyles,
  59. }}
  60. >
  61. <div
  62. className="minimap-panel"
  63. style={{
  64. display: 'flex',
  65. width: '100%',
  66. height: '100%',
  67. borderRadius: '10px',
  68. backgroundColor: 'rgba(255, 255, 255, 1)',
  69. border: '0.572px solid rgba(6, 7, 9, 0.10)',
  70. overflow: 'hidden',
  71. boxShadow:
  72. '0px 2.289px 6.867px 0px rgba(0, 0, 0, 0.08), 0px 4.578px 13.733px 0px rgba(0, 0, 0, 0.04)',
  73. boxSizing: 'border-box',
  74. padding: 8,
  75. ...panelStyles,
  76. }}
  77. data-flow-editor-selectable="false"
  78. ref={panelRef}
  79. onMouseEnter={() => {
  80. service.setActivate(true);
  81. }}
  82. onMouseLeave={() => {
  83. service.setActivate(false);
  84. }}
  85. onTouchStartCapture={() => {
  86. service.setActivate(true);
  87. }}
  88. onTouchEndCapture={() => {
  89. service.setActivate(false);
  90. }}
  91. ></div>
  92. </div>
  93. );
  94. };