HighchartsReact更改特定节点的链接半径

uqdfh47h  于 2022-11-10  发布在  Highcharts
关注(0)|答案(1)|浏览(168)

我正在使用highcharts-react-official(v.^3.1.0)来绘制组织结构图,但是我在舍入节点(一些特定节点)之间的链接时遇到了问题。
我只想更改端点角的linkRadius属性[请检查所附图像]。x1c 0d1x

const initialTree = [
 { from: 'block1', to: 'block2'},
 { from: 'block1', to: 'block3' },
 { from: 'block1', to: 'block4' },
], 

const [treeOptions, updateTreeOptions] = useState({
chart: {
  height: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 545 : 325,
  width: expandAllCards ? HTREE_WIDTH[treeType].expandAll : HTREE_WIDTH[treeType].collapsed,
  inverted: true,
  spacing: [0, 0, 0, 0],
  marginTop: -82,
  marginLeft: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 25 : undefined,
  marginRight: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 25 : undefined,
  animation: false,
},

exporting: {
  enabled: false,
},

credits: {
  enabled: false,
},

title: {
  text: null,
},

series: [
  {
    type: 'organization',
    name: 'Highsoft',
    keys: ['from', 'to'],
    borderRadius: 0,
    nodePadding: 0,
    borderWidth: 0,
    linkRadius: 0,
    minNodeLength: 106,
    nodeWidth: 188,
    linkColor: '#e8e9eb',
    data: [...initialTree],
    marker: {
      radius: 10,
    },
    levels: [
      {
        level: 0,
        color: 'none',
        linkColor: '#b3b3b3',
      },
      {
        level: 1,
        linkColor: 'transparent',
        color: 'none',
      },
      {
        level: 2,
        color: 'none',
      },
    ],
    colorByPoint: false,
    color: '#007ad0',
    events: {
      click: (
        e: ChartClickEventObject & {
          point: {
            id: string | number;
            linksFrom: string[];
            reportURL: string;
            name: string;
            incidents: number;
            dashboardId: string;
            treeType: TreeType;
            schemaName: string;
            slideOutAlias: string;
          };
          path: Array<{ id: string }>;
        },
      ) => {
        if (!e || !e.point) return;

        const clickType = (() => {
          const isCorrectClick = e.composedPath && typeof e.composedPath === 'function';

          if (!isCorrectClick) return;

          if (e.composedPath()?.some((el: Element) => el.id === `node-toggle-${e.point.id}`)) return 'toggle';
          if (e.composedPath()?.some((el: Element) => el.id === `node-incidents-${e.point.id}`))
            return 'incidents-slideout';
        })();

        if (!clickType) return;

        const {
          // eslint-disable-next-line @typescript-eslint/no-shadow
          point: { id, linksFrom, reportURL, name, treeType: currentTreeType, schemaName, slideOutAlias = '' },
        } = e;

        if (!currentTreeType) return;

        const currentFullTreeConnections = Connections[TreeTypeProps[currentTreeType].connectionsId];

        const currentInitialTree = currentFullTreeConnections.filter(
          object => object.from === TreeTypeProps[currentTreeType].rootId,
        );

        switch (clickType) {
          case 'toggle': {
            if (linksFrom.length === 0) {
              const updatedConnections = [
                ...currentInitialTree,
                ...currentFullTreeConnections.filter(connection => connection.from === id),
              ];

              const updatedTreeOptionsState = {
                ...treeOptions,
                chart: {
                  ...treeOptions.chart,
                  height: 544,
                  width: HTREE_WIDTH[currentTreeType].expanded,
                },
                series: [
                  {
                    ...treeOptions.series[0],
                    data: updatedConnections,
                    levels: [
                      ...treeOptions.series[0].levels,
                      {
                        level: 1,
                        linkColor: '#b3b3b3',
                        color: 'none',
                      },
                    ],
                  },
                ],
              };

              updateTreeOptions(updatedTreeOptionsState);
            } else {
              const updatedTreeOptionsState = {
                ...treeOptions,
                chart: {
                  ...treeOptions.chart,
                  height: 325,
                  width: HTREE_WIDTH[currentTreeType].collapsed,
                },
                series: [
                  {
                    ...treeOptions.series[0],
                    data: currentInitialTree,
                    levels: [
                      ...treeOptions.series[0].levels,
                      {
                        level: 1,
                        linkColor: 'transparent',
                        color: 'none',
                      },
                    ],
                  },
                ],
              };
              updateTreeOptions(updatedTreeOptionsState);
            }

            sendVisualizationManipulation({
              alias: slideOutAlias,
              params: {
                height:
                  linksFrom.length === 0
                    ? VisualizationManipulationChangeHeight.expand
                    : VisualizationManipulationChangeHeight.collapse,
              },
            });
            break;
          }
          case 'incidents-slideout': {
            if (reportURL === '' || !reportURL) break;

            SlideOut.open({
              targetId: reportURL,
              title: [`${name} ${SCHEMA_TYPES.get(schemaName)}`],
            });
            break;
          }
          default:
            break;
        }
      },
    },
    dataLabels: {
      padding: 0,
      borderWidth: 0,
      color: '#fff',
      nodeFormatter: function nodeFormatterFn() {
        // eslint-disable-next-line react/no-this-in-sfc
        if (!this.point) return null;

        // eslint-disable-next-line react/no-this-in-sfc
        const { options, level, id, linksFrom } = this.point;

        const currentTreeType = options.treeType as TreeType;

        if (!currentTreeType) return null;

        const isRoot = level === 0;

        const isOtherCard = id === 'OTHER';

        const { connectionsId } = TreeTypeProps[currentTreeType];

        const hasChildren = Connections[connectionsId].find(object => object.from === id);

        const isCollapsible = !isRoot && hasChildren;

        const reportURLExists = !!options.reportURL && options.reportURL !== '';

        let arrowColor;
        const isRateChangeValid = (options.rateChange && +options.rateChange !== 0) || undefined;

        if (Number(options.rateChange || 0) === 0) {
          arrowColor = ARROW_GRAY_COLOR;
        } else {
          arrowColor =
            +options.rateChange * (options.positiveValues ? -1 : 1) > 0
              ? ARROW_NEGATIVE_COLOR
              : ARROW_POSITIVE_COLOR;
        }
        const cardTree = (
          <MainTreeCard
            border={`1px solid ${isRoot ? options.rootBorderColor : options.generalBorderColor}`}
            borderLeft={`4px solid ${options.borderLeftColor}`}
            width={`${options.width}px`}
            height={`${options.height}px`}
            backgroundColor={options.bgColor}
            padding={isRoot ? '7px 9px 14px 10px' : '11px 7px 8px 10px'}>
            <TopLabel
              fontSize={`${options.fontSize}px}`}
              letterSpacing={!isRoot ? '0.25px' : 'normal'}
              // eslint-disable-next-line no-nested-ternary
              marginBottom={isRoot ? '19px' : isOtherCard ? '16px' : '17px'}
              lineHeight={isRoot ? '22px' : '18px'}
              height={`${options.labelHeight}px}`}>
              {options.name}
            </TopLabel>
            <FlexContainer
              flexDirection={isRoot ? 'row' : 'column'}
              height={isRoot ? '45px' : ''}
              justifyContent='space-between'>
              <FlexContainer
                flexDirection='column'
                justifyContent='flex-start'
                paddingLeft={isRoot ? '2px' : ''}
                marginBottom={!isRoot ? '12px' : ''}>
                <TopValueLabel
                  id={`node-incidents-${id}`}
                  fontSize={`${!isOtherCard ? options.fontSizeIncidents : 12}px`}
                  fontWeight={!isOtherCard ? '400' : '700'}
                  marginBottom={isRoot ? '0' : '5px'}
                  lineHeight={isRoot ? '31px' : '17px'}
                  letterSpacing={isOtherCard ? '0.2px' : 'normal'}
                  color={reportURLExists ? '#7740bf' : '#14113b'}
                  cursor={reportURLExists ? 'pointer' : 'auto'}
                  isLinked={reportURLExists ? 1 : 0}>
                  {!isOtherCard ? formatNumber(options.incidents, options.incidentsType) : 'View Report'}
                </TopValueLabel>

                {!isOtherCard && (
                  <TopMeasureLabel
                    marginTop={isRoot ? '0' : '-3px'}
                    lineHeight={isRoot ? '12px' : 'normal'}
                    letterSpacing={isRoot ? '0.2px' : 'normal'}>
                    {options.amountLabel}
                  </TopMeasureLabel>
                )}
              </FlexContainer>
              {!isOtherCard && (
                <FlexContainer flexDirection='row' width={isRoot ? '102px' : '82px'} justifyContent='space-between'>
                  <FlexContainer flexDirection='column'>
                    <TopSecondValueLabel
                      fontSize={!isRoot ? '20px' : '28px'}
                      lineHeight={isRoot ? '31px' : '17px'}
                      marginBottom={isRoot ? 0 : '2px'}>
                      {formatNumber(options.incidentRate, options.incidentRateType)}
                    </TopSecondValueLabel>
                    <TopMeasureLabel
                      marginTop='0'
                      letterSpacing={isRoot ? '0.2px' : 'normal'}
                      lineHeight={isRoot ? '12px' : 'normal'}>
                      {options.rateLabel}
                    </TopMeasureLabel>
                  </FlexContainer>
                  <FlexContainer justifyContent='center' alignSelf='end'>
                    <FlexContainer flexDirection='column' marginBottom='1px'>
                      {/* eslint-disable-next-line no-nested-ternary */}
                      {isRateChangeValid ? (
                        +options.rateChange > 0 ? (
                          <ICONS.ARROW_UP
                            width={11}
                            height={6}
                            marginTop='3px'
                            marginRight='2px'
                            fill={arrowColor}
                          />
                        ) : (
                          <ICONS.ARROW_DOWN
                            width={11}
                            height={6}
                            marginTop='3px'
                            marginRight='2px'
                            fill={arrowColor}
                          />
                        )
                      ) : null}
                    </FlexContainer>
                    <ChangeRateLabel color={arrowColor}>
                      {getFormattedChangeRateLabel(options.rateChange, false)}
                    </ChangeRateLabel>
                  </FlexContainer>
                </FlexContainer>
              )}
            </FlexContainer>
            {isCollapsible && hasChildren && !options.expandAllCards && (
              <ToggleLabel id={`node-toggle-${id}`} marginLeft={isRoot ? '7px' : 0}>
                {linksFrom.length === 0 ? (
                  <>
                    See More
                    <Arrow
                      rotate='rotate(45deg)'
                      position='relative'
                      borderWidth='0 2px 2px 0'
                      left='6px'
                      bottom='2px'
                    />
                  </>
                ) : (
                  <>
                    See Less
                    <Arrow
                      position='relative'
                      borderWidth='0 2px 2px 0'
                      top='2px'
                      left='1px'
                      marginLeft='5px'
                      rotate='rotate(-135deg)'
                    />
                  </>
                )}
              </ToggleLabel>
            )}
          </MainTreeCard>
        );
        return ReactDOMServer.renderToString(cardTree);
      },
    },
  },
],
tooltip: {
  enabled: false,
},

});
我试过改变linkRadius属性,但是它改变了所有的链接半径。有什么建议吗?谢谢!

ijnw1ujt

ijnw1ujt1#

首先,linkRadius选项已过时,您应该使用link.radius。然而,Highcharts API只允许为所有链接设置相同的半径。要单独设置半径,您需要修改Highcharts核心,例如通过以下插件:

(function(H) {
  H.wrap(H.seriesTypes.organization.prototype, 'translateLink', function(proceed, point) {
    if (point.from === 'CSO') {
      const linkOptions = this.options.link;
      const originalRadius = linkOptions.radius;
      // set custom radius for a specific point
      linkOptions.radius = 0;
      proceed.apply(this, Array.prototype.slice.call(arguments, 1));
      // restore the original option
      linkOptions.radius = originalRadius;
    } else {
      proceed.apply(this, Array.prototype.slice.call(arguments, 1));
    }
  });
}(Highcharts));

现场演示:https://jsfiddle.net/BlackLabel/zdxe7423/
API引用:https://api.highcharts.com/highcharts/series.organization.link.radius
文件:https://www.highcharts.com/docs/extending-highcharts/extending-highcharts

相关问题