【问题标题】:React-Leaflet same marker in multiple LayersReact-Leaflet 多个图层中的相同标记
【发布时间】:2021-04-14 12:16:08
【问题描述】:

如何在 react-leaflet 的多个图层中添加相同的标记?

例如:

我有一个应用程序来搜索带有反应传单的餐厅,每个标记都是不同的餐厅。我想要一个LayerControl 来按类型和评级(1..5 星)过滤它们。

我可以使用LayerControl.Overlay 按类型(例如自助餐)进行过滤,但我也想按评级进行过滤。如果我有一家餐厅 type='buffet' 和 rating=4,我该怎么做才能仅在检查自助餐类型和 4 星评级时显示标记。

这是我的current code,仅按类型过滤。

我正在使用 react-leaflet v3。

【问题讨论】:

  • 到目前为止你尝试过什么?你有我们可以玩的样本数据集吗?我的建议是不要将相同的标记添加到多个图层,因为它会在同一个点上渲染许多标记,这会浪费 CPU,并且会夸大标记阴影(如果您正在使用一个)。最好创建一个自定义图层控件,在单个数据集上应用过滤器并仅呈现传递过滤器参数的标记。如果您创建示例代码框或代码挂起,我们可以帮助您更好地实现这一目标。
  • 感谢您的回答!我在问题中添加了我的current code 示例。我不能为同一家餐厅设置多个标记,因为我只想在选中两个过滤器(类型和评级)时显示它。

标签: javascript reactjs leaflet react-leaflet


【解决方案1】:

您用于创建各种图层组来管理过滤器的方法并不是最好的方法。我采取了另一种方法。

使用所需的过滤器创建一个状态对象

在您的应用中,创建一个包含潜在过滤器的状态变量。我们将其设置为最初包含所有选项:

const restaurantTypes = ["Family Style", "Buffet", "Fast Food", "Cafe"];
const ratings = [1, 2, 3, 4, 5];

function App() {
  const [filters, setFilters] = useState({
    restaurantTypes,
    ratings
  });
  ...
}

自定义过滤器组件

我选择创建一个自定义组件,它基本上与传单层控件完全相同的 html 标记,但没有任何功能。您可以在此答案末尾查看沙箱,但它所做的只是管理我们刚刚定义的 filters 状态变量。以下是一个简短的摘要:

const FilterControl = ({ filters, setFilters }) => {
  return (
    <div>
      <h3>Type</h3>
      {restaurantTypes.map((type) => (
        <label>
          <input
            type="checkbox"
            checked={filters.restaurantTypes.includes(type)}
            onClick={(e) => {
              if (filters.restaurantTypes.includes(type)) {
                setFilters((prevFilters) => ({
                  ...prevFilters,
                  restaurantTypes: prevFilters.restaurantTypes.filter(
                    (f) => f !== type
                  )
                }));
              } else {
                setFilters((prevFilters) => ({
                  ...prevFilters,
                  restaurantTypes: [...prevFilters.restaurantTypes, type]
                }));
              }
            }}
          />
          <span>{type}/span>
        </label>
      ))}
      <h3>Rating</h3>
      {ratings.map((rating) => (
        // same as above but for ratings
      ))}
    </div>
  );
};

所以现在您的FilterControl 可以巧妙地管理filters 的状态。

根据过滤器过滤标记

现在您所要做的就是映射您的restaurants 数据集,并且只渲染typerating 在当前filters 中的标记:

function App() {
  const [filters, setFilters] = useState({
    restaurantTypes,
    ratings
  });
  return (
    <MapContainer ... >
      <TileLayer ... />
      <FilterControl filters={filters} setFilters={setFilters} />
      {restaurants.map((restaurant) => {
        if (
          filters.restaurantTypes.includes(restaurant.type) &&
          filters.ratings.includes(restaurant.rating)
        ) {
          return <Marker position={restaurant.coordinates} />
        }
        return null;
      })}
    </MapContainer>
  );
}

Working codesandbox

【讨论】:

    猜你喜欢
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    相关资源
    最近更新 更多