You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Svelte应用中使用双范围滑块过滤地图上的城市

苏格兰地图Svelte应用城市人口筛选问题修复

问题描述

开发了一个展示苏格兰地图的Svelte应用,地图上标注多个城市。计划通过双范围滑块根据人口数量筛选显示的城市,已添加RangeSlider组件及事件处理器,控制台能正确打印滑块取值,但使用数组filter方法过滤城市数据时未生效。

问题根源

  1. Array.filter()方法不会修改原数组,而是返回新的过滤后数组,当前代码仅调用filter却未将结果赋值给用于渲染的变量。
  2. 模板中始终遍历原始的cities数组,未关联过滤后的结果,导致滑块变化无法触发视图更新。

修复方案

1. 定义响应式过滤变量

在脚本中添加响应式变量filteredCities,初始化为原始城市数据:

import { cities } from "./cities";
// 新增:存储过滤后的城市列表
let filteredCities = [...cities];
let maxPopSize = 598830;
let newValues = [0, maxPopSize];

2. 优化过滤逻辑(两种方式可选)

方式一:使用响应式声明自动触发过滤

利用Svelte的$:响应式特性,当newValues变化时自动重新过滤:

// 响应式过滤:当滑块值变化时自动更新filteredCities
$: filteredCities = cities.filter(d => 
  d.population >= newValues[0] && d.population <= newValues[1]
);

function handleOnChange(event){
  newValues = event.detail.values;
}

方式二:在事件处理器中直接赋值

function handleOnChange(event){
  newValues = event.detail.values;
  // 将filter结果赋值给filteredCities
  filteredCities = cities.filter(d => 
    d.population >= newValues[0] && d.population <= newValues[1]
  );
}

3. 修改模板渲染逻辑

将遍历的数组从cities改为filteredCities:

{#each filteredCities as city}
  <circle
    class="city"
    cx={$currentProj([city.lon, city.lat])[0]}
    cy={$currentProj([city.lon, city.lat])[1]}
    r=5
    fill=#000 />
{/each}

修改后的完整App.svelte脚本部分

<script>
  import { geoAlbers, geoPath, geoProjection } from "d3-geo";
  import { geoAlbersUk } from "d3-composite-projections";
  import { scaleLinear, scaleSqrt } from "d3-scale";
  import { extent } from "d3-array";
  import { onMount } from "svelte";
  import { feature } from "topojson";
  import { tweened } from "svelte/motion";
  import { interpolate } from "d3-interpolate";
  import Feature from "./Feature.svelte";
  import { cities } from "./cities";
  import RangeSlider from "svelte-range-slider-pips";

  let data = [];
  let colorScale = () => {};
  const width = "960";
  const height = "500";
  const projectionAlbers = geoAlbers()
    .rotate([4.4, 0.8])
    .center([0, 55.4])
    .parallels([50, 60])
    .scale(3800)
    .translate([width / 2, (1.8 * height) / 2]);

  const projectionAlbersUk = geoAlbersUk()
    .translate([width / 2, (1.85 * height) / 2])
    .scale(5200);

  const currentProj = tweened(projectionAlbers, {
    duration: 1000
  });

  $: path = geoPath().projection($currentProj);

  const opacity = tweened(0, {
    duration: 1000
  });

  onMount(async function() {
    const response = await fetch(
      "https://gist.githubusercontent.com/rveciana/27272a581e975835aaa321ddf816d726/raw/c40062a328843322208b8e98c2104dc8f6ad5301/uk-counties.json"
    );
    const json = await response.json();
    const topoData = feature(json, json.objects.UK);
    const land = {
      ...topoData,
      features: topoData.features.filter(
        d => d.properties.NAME_1 === "Scotland"
      )
    };

    const namesExtent = extent(land.features, d => d.properties.NAME_2.length);

    data = land.features;
  });

  let maxPopSize = 598830;
  let newValues = [0, maxPopSize];
  // 初始化过滤后的城市列表
  let filteredCities = [...cities];

  // 响应式过滤逻辑
  $: filteredCities = cities.filter(d => 
    d.population >= newValues[0] && d.population <= newValues[1]
  );

  function handleOnChange(event){
    newValues = event.detail.values;
  }
</script>

内容的提问来源于stack exchange,提问作者sprucegoose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 02:24:53