如何自定义react-typescript-datamaps库?

Ric*_*son 9 javascript reactjs datamaps

我目前正在 ReactJS 项目中使用react-typescript-datamaps 库,并在自定义地图上显示的国家/地区名称的字体样式和大小方面面临挑战。尽管付出了努力,我仍然无法找到合适的方法来进行必要的改变。

这是相关组件的示例:

import React, { useEffect, useState } from "react";
import { DataMapsWrapper } from "react-typescript-datamaps";
import { useDispatch, useSelector } from "react-redux";
import AttackHelper from "./AttackHelper";
import BlastHelper from "./BlastHelper";

import BubblesConfig from "./BubblesConfig";
import {  getThreatsMapData } from "../store/dataSlice";


const MapView = () => {
  const dispatch = useDispatch();
  const [index, setIndex] = useState(0);
  const [dstloc, setDstloc] = useState();
  const [srcloc, setSrcloc] = useState();
  const [arc, setArc] = useState([]);
  const [blast, setBlast] = useState([]);

  const loading = useSelector((state) => state.threatsMap.data.loading);
  const data = useSelector((state) => state.threatsMap.data.threatsMapData);

  const intervalValue = useSelector(
    (state) => state.threatsMap.state.intervalValue
  );

  const getThreatsMap = () => {
    dispatch(getThreatsMapData({  }));
  };

  useEffect(() => {
    getThreatsMap();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    const interval = setInterval(() => {
      if (loading || !data[index]) return;

      const eventData = data[index];

      const srcAttribute = eventData.Attributes.find(
        (item) => item.type === "ip-src"
      );
      const dstAttribute = eventData.Attributes.find(
        (item) => item.type === "ip-dst"
      );
      const IPv4Attribute = eventData.Attributes.find(
        (item) => item.type === "IPv4"
      );

      // Check if at least one of the attributes exists
      if (srcAttribute || dstAttribute || IPv4Attribute) {
        if (srcAttribute) {
          // setSrc([srcAttribute.value]);
          const srcLoc = srcAttribute.geo_localisation[0];
          setSrcloc({ country: srcLoc.country_name, ...srcLoc });
        }

        if (dstAttribute) {
          // setDst([dstAttribute.value]);
          const dstLoc = dstAttribute.geo_localisation[0];
          setDstloc({ country: dstLoc.country_name, ...dstLoc });
        }

        if (IPv4Attribute && IPv4Attribute.type === "IPv4") {
          // setIPv4([IPv4Attribute.value]);

          const ipv4Loc = IPv4Attribute.geo_localisation[0];
          const blast = BlastHelper({
            latitude: ipv4Loc.latitude,
            longitude: ipv4Loc.longitude,
            country: ipv4Loc.country_name || "Unknown",
            animate: true,
            highlighted: ipv4Loc.country_name || "Unknown",
          });
          setBlast([blast]);
        }

        const executeAttack = async () => {
          if (srcAttribute && dstAttribute && srcloc && dstloc) {
            const attack = AttackHelper(srcloc, dstloc);
            setArc((prevArc) => [...prevArc.slice(-3), attack]);
            setBlast([]);
          } else if (srcAttribute && srcloc) {
            const blast = BlastHelper(srcloc);
            setBlast([blast]);
          } else if (dstAttribute && dstloc) {
            const blast = BlastHelper(dstloc);
            setBlast([blast]);
          } else {
            // Handle other cases as needed
          }
        };

        executeAttack();
      }

      setIndex((prev) => (prev + 1) % data.length);
    }, intervalValue);

    return () => clearInterval(interval);
  }, [index, data, loading, intervalValue]);


  return (
    <div className={`map-container`}>
      <div className={`flex  items-center justify-between`}>
        <div>
          <DataMapsWrapper
            projection="mercator"
            responsive
            attacks={arc}
            bubbles={blast}
            geographyConfig={{
              popupOnHover: true,
              highlightOnHover: true,
              highlightFillColor: "#FC8D59", 
              highlightBorderColor: "#FC8D59", 
              borderColor: "#364d53",
              borderWidth: 0.5,
              dataType: "topojson",
              dataUrl: "/map/map.topojson",
              highlightBorderWidth: 3, 
              highlightBorderOpacity: 1, 
              highlightFillOpacity: 0.5, 
            }}
            fills={{
              defaultFill: "#101518",
              MAJOR: "#306596",
              MEDIUM: "#0fa0fa",
              MINOR: "#bada55",
            }}
            bubblesConfig={BubblesConfig}
          />
        </div>
      </div>
    </div>
  );
};

export default MapView;
Run Code Online (Sandbox Code Playgroud)

屏幕截图: 说明当前状态的屏幕截图:

在此输入图像描述

我正在寻求有关如何自定义地图上显示的国家/地区名称的字体大小和样式的指导。任何见解或代码片段将不胜感激。

Von*_*onC 4

既然你在用DataMapsWrapper,我就看一下orenef/react-typescript-datamaps src/DataMapsWrapper.tsx

\n

没有明确提及或功能允许您直接自定义国家/地区名称的字体样式和大小。

\n

对于自定义,您通常会寻找允许您传递可应用于文本元素的样式或类的属性,但根据提供的源代码,这些属性不可用。

\n

如果react-typescript-datamaps库正在为地图生成 SVG 元素,您可以使用 CSS 直接定位这些元素。
\n打开浏览器的开发人员工具并检查 SVG 以识别呈现国家/地区名称的文本元素。它们可能具有特定的类或者是特定 SVG 组(<g>元素)的子级。

\n

编写针对已识别元素的 CSS 规则。如果元素有类名,您可以直接定位该类。否则,您可能需要编写更具体的选择器,例如定位text某个父元素中的元素。

\n

您可以将这些样式添加到全局样式表中,也可以使用内联样式或样式组件将它们注入到组件中。

\n

假设文本元素有一个类名.country-name,可以应用以下CSS:

\n
.country-name {\n  font-family: \'Your desired font\', sans-serif;\n  font-size: 12px; /* Adjust as needed */\n  fill: #000; /* Text color */\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果没有类,您可能需要更通用地定位 SVG 文本元素,或者基于它们在 SVG 层次结构中的位置:

\n
svg .datamaps-subunits text {\n  font-family: \'Your desired font\', sans-serif;\n  font-size: 12px;\n  fill: #000;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果您想直接在组件中注入样式,您可能必须使用类似的库styled-components(如本文中所述),或者<style>在组件中创建一个包含自定义 CSS 的标签。

\n

例如,使用样式标签可能如下所示:

\n
const MapView = () => {\n  // ... existing component code ...\n\n  const customStyles = `\n    .country-name {\n      font-family: \'Your desired font\', sans-serif;\n      font-size: 12px;\n      fill: #000;\n    }\n  `;\n\n  return (\n    <div className={`map-container`}>\n      <style>{customStyles}</style>\n      {/* ... */}\n    </div>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

您可能必须使用!important来覆盖库设置的任何现有样式。然而,这应该是最后的手段,因为它会使未来的样式维护变得更加困难。

\n

如果您无法根据需要覆盖样式,则可能需要考虑其他方法,例如分叉库并修改它以满足您的需要,或者使用您希望的样式名称覆盖 HTML 元素。

\n
\n
\n

我尝试了你的CSS方法:.datamap { font-size: 16px !important; font-style: italic !important; }.

\n

有趣的是,斜体样式有效,但字体大小保持不变。我仔细检查了 CSS 特异性,但无法覆盖库样式设置的字体大小。

\n
\n

如果尽管有标志,字体大小没有改变!important,则可能有内联样式或更高特异性的 CSS 规则应用于文本元素。使用浏览器的开发工具检查文本元素并检查是否有font-size直接应用于该元素的内联样式。
\n内联样式将覆盖您的 CSS,除非您使用!important,但 CSS 属性可能不会覆盖直接在 SVG 元素上设置的属性。如果库使用<text>SVG 元素上的 font-size 属性设置字体大小,则 CSS 可能不会影响它。

\n

有时,如果另一个规则具有更高的特异性,仅仅使用!important是不够的。您可以通过包含更多父选择器或使用 if available 来增加选择器的特异性id:您可以在选择器链中包含更多父元素或使用 ID,它本质上比类选择器具有更高的特异性。

\n
    \n
  • 如果.datamap是 一个类 应用于具有 class 的父级中的 SVG .map-container,则选择器可以是:

    \n
    const MapView = () => {\n  // ... existing component code ...\n\n  const customStyles = `\n    .country-name {\n      font-family: \'Your desired font\', sans-serif;\n      font-size: 12px;\n      fill: #000;\n    }\n  `;\n\n  return (\n    <div className={`map-container`}>\n      <style>{customStyles}</style>\n      {/* ... */}\n    </div>\n  );\n};\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
  • 如果任何父元素上有\xe2\x80\x99s ID,则可以使用它来增加特异性,因为ID选择器比类选择器具有更高的特异性:

    \n
    .map-container .datamap text {\nfont-size: 16px !important;\n}\n
    Run Code Online (Sandbox Code Playgroud)\n
  • \n
\n

作为最后的手段,您可以使用 JavaScript 直接操作 SVG 文本元素。useEffect这可以在组件安装后运行的钩子中完成:

\n
#mapContainerID .datamap text {\nfont-size: 16px !important;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果库使用 SVG 属性来设置字体大小(例如元素font-size上的属性<text>),CSS 可能不会覆盖它。您需要使用 JavaScript 来更改这些属性。然而,这并不是对 React 最友好的方式,因为它绕过了虚拟 DOM,但如果 CSS 由于库应用样式的方式而失败,它可能是一个实用的解决方案。

\n