---
title: "การสร้าง Hover Effect บนแผนที่"
description: "ตัวอย่างนี้จะแสดงวิธีการสร้าง Hover Effect บน Layer ของแผนที่ Longdo Map"
canonical_url: "https://map.longdo.com/docs/v3/javascript/etc/hover-effect/"
last_updated: "2026-09-16T19:39:19.986Z"
---

# การสร้าง Hover Effect บนแผนที่

การกำหนดสไตล์ตามการ hover ช่วยให้ผู้ใช้เห็นได้ทันทีว่ากำลังชี้อยู่ที่ feature ไหน ก่อนที่จะคลิกเลือกจริง ตัวอย่างคลาสสิกคือแผนที่แบบ choropleth ที่พื้นที่จะสว่างขึ้นหรือเปลี่ยนสีเมื่อเคอร์เซอร์เลื่อนผ่าน ฟีดแบ็กทางภาพแบบนี้พบได้ทั่วไปในแดชบอร์ดและแผนที่สำหรับสำรวจข้อมูล ซึ่งการกวาดสายตาดู feature จำนวนมากอย่างรวดเร็วสำคัญกว่าการอ่านป้ายกำกับทีละอัน MapLibre ทำสิ่งนี้ได้อย่างมีประสิทธิภาพ แทนที่จะปรับสไตล์ทั้ง layer ใหม่ทุกครั้งที่เมาส์ขยับ เราแค่เก็บสถานะ `hover` เฉพาะของแต่ละ feature แล้วอ้างอิงมันโดยตรงภายใน paint expression

### การโหลดข้อมูล Feature พร้อมสร้าง ID อัตโนมัติ

ข้อมูลขอบเขตพื้นที่ของแผนที่ถูกโหลดเป็น GeoJSON source จาก Longdo Map API การกำหนด `generateId: true` จะให้ MapLibre สร้างเลข id ให้แต่ละ feature โดยอัตโนมัติ ซึ่งจำเป็นต้องใช้เป็นตัวอ้างอิงในการเรียก `setFeatureState`

```javascript
map.Renderer.addSource("states", {
  type: "geojson",
  generateId: true,
  data: `https://api.longdo.com/map/services/object?mode=geojson&id=${geocode}&dataset=${dataset}&key=${longdoApiKey}`,
});
```

### การกำหนดสไตล์ตามสถานะของ Feature

ค่า `fill-opacity` ของ layer แบบ fill เป็น expression ชนิด `case` ที่อ่านสถานะ `hover` เฉพาะของแต่ละ feature โดย feature จะแสดงผลแบบทึบเต็มที่ก็ต่อเมื่อสถานะ `hover` เป็น `true` เท่านั้น นอกเหนือจากนั้นจะแสดงผลแบบจางกว่า

```javascript
map.Renderer.addLayer({
  id: "state-fills",
  type: "fill",
  source: "states",
  layout: {},
  paint: {
    "fill-color": "#627BC1",
    "fill-opacity": [
      "case",
      ["boolean", ["feature-state", "hover"], false],
      1,
      0.5,
    ],
  },
});
```

### เปลี่ยนสี Fill แทนความโปร่งใส

การตรวจสอบ `["feature-state", "hover"]` แบบเดียวกันนี้ใช้ได้กับ paint property ใดก็ได้ ไม่ใช่แค่ `fill-opacity` เท่านั้น เพราะค่าที่ expression แบบ `case` คืนออกมาจะเป็นสีก็ได้เช่นเดียวกับตัวเลข การเปลี่ยนจากคู่ค่า "ทึบเต็มที่/จางกว่า" ไปเป็นคู่สีสองสี จะได้เอฟเฟกต์แบบ "ไฮไลต์เมื่อ hover" แทนที่จะเป็น "สว่างขึ้นเมื่อ hover":

```javascript
map.Renderer.addLayer({
  id: "state-fills",
  type: "fill",
  source: "states",
  layout: {},
  paint: {
    "fill-color": [
      "case",
      ["boolean", ["feature-state", "hover"], false],
      "#f8b400",
      "#627BC1",
    ],
    "fill-opacity": 0.6,
  },
});
```

ส่วนที่เหลือของการตั้งค่าไม่ต้องเปลี่ยนอะไรเลย ทั้ง `generateId`, `setFeatureState` และ event handler ของเมาส์ในหัวข้อถัดไปยังใช้ขับเคลื่อนได้ทั้งสองแบบ เลือก paint property (หรือจะผสมกันหลายตัว) ที่เข้ากับโทนสีของแผนที่ได้ดีที่สุด

### การอัปเดตสถานะ Feature เมื่อเกิดเหตุการณ์เมาส์

เมื่อเกิด `mousemove` feature ที่อยู่ใต้เคอร์เซอร์จะถูกตั้งสถานะ `hover` เป็น `true` โดย feature ที่ถูก hover ก่อนหน้า (เก็บไว้ในตัวแปร `hoveredStateId`) จะถูกล้างสถานะก่อนเสมอ ส่วนเมื่อเกิด `mouseleave` สถานะ `hover` ของ feature ปัจจุบันจะถูกล้างทั้งหมด

```javascript
map.Renderer.on("mousemove", "state-fills", function (e) {
  if (e.features.length > 0) {
    if (hoveredStateId) {
      map.Renderer.setFeatureState(
        { source: "states", id: hoveredStateId },
        { hover: false }
      );
    }
    hoveredStateId = e.features[0].id;
    map.Renderer.setFeatureState(
      { source: "states", id: hoveredStateId },
      { hover: true }
    );
  }
});

map.Renderer.on("mouseleave", "state-fills", function () {
  if (hoveredStateId) {
    map.Renderer.setFeatureState(
      { source: "states", id: hoveredStateId },
      { hover: false }
    );
  }
  hoveredStateId = null;
});
```

### จับคู่ Hover กับ Click-for-Detail

Hover highlight และ click-for-detail เป็นสองอย่างที่ทำงานเสริมกัน hover จะบอกผู้ใช้ว่ากำลังจะโต้ตอบกับ feature ไหน ส่วนการคลิกบน layer เดียวกันนั้นก็สามารถเปิด popup แสดงข้อมูลของ feature นั้นต่อได้ ในดีโมด้านล่างมีการเพิ่ม listener อีกตัวควบคู่ไปกับ handler ของ hover เพื่อเปิด `longdo.Popup` สำหรับ feature ที่ถูกคลิก:

```javascript
map.Renderer.on("click", "state-fills", function (e) {
  e.lngLat.lon = e.lngLat.lng;
  var popup = new longdo.Popup(e.lngLat, {
    title: e.features[0].properties.name_t,
  });
  map.Overlays.add(popup);
});
```

เนื่องจากผูกไว้กับ layer `"state-fills"` เดียวกัน การคลิกจะเกิดขึ้นก็ต่อเมื่อเคอร์เซอร์อยู่เหนือ feature เท่านั้น ซึ่งก็คือ feature เดียวกับที่เพิ่งถูก hover จึงทำให้ทั้งสองอินเทอร์แอกชันซิงค์กันได้เองโดยไม่ต้องจัดการสถานะเพิ่มเติม

- `generateId: true` : ให้ MapLibre สร้างเลข id ของ feature โดยอัตโนมัติ เพื่อใช้อ้างอิงใน `setFeatureState`
- `map.Renderer.setFeatureState({ source, id }, state)` : กำหนดสถานะเฉพาะของแต่ละ feature โดยไม่ต้องปรับสไตล์ทั้ง layer ใหม่
- `["feature-state", "hover"]` : อ่านสถานะเฉพาะของ feature นั้นๆ ได้โดยตรงภายใน paint expression
- `hoveredStateId` : เก็บ feature ที่กำลังถูก hover อยู่ เพื่อล้างสถานะก่อนจะ hover feature ใหม่

> **ดูเพิ่มเติม:** [Maplibre Documentation](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map)

<code-section src="/snippet/v3/javascript/etc/hover-effect/script.js" title="">



</code-section>
