如何在 Mapbox IControl 中使用 Vue 组件

问题描述 投票:0回答:2

我想在 MapBox 控件中使用 Vue,而不是玩旧的 DOM API。

vue.js mapbox-gl-js
2个回答
0
投票
<template>
  <span :id="id" class="mapboxgl-ctrl mapboxgl-ctrl-group">
    <button type="button">
      <FitFeaturesIcon class="mapboxgl-ctrl-icon" aria-hidden="true" />
    </button>
  </span>
</template>

<script>
import FitFeaturesIcon from './FitFeaturesIcon'

const id = 'FitFeaturesControl'

export default {
  components: { FitFeaturesIcon },
  data: () => ({
    id
  })
}

export class CFitFeaturesControl {
  onAdd(map) {
    this._map = map
    this._container = document.getElementById(id)
    return this._container
  }
}
</script>


0
投票

我尝试做同样的事情——在 MapBox 控件中使用 Vue 组件。我很难找到其他解决方案,所以我最终想出了自己的办法。这远非完美,我相信有更好的解决方案。

我创建了一个临时的 Vue 实例,用于呈现组件,在我的例子中是一个图标 (https://oh-vue-icons.js.org)。然后返回生成的 DOM 元素并由 MapBox 使用。我的解决方案基于this codepen.

import { createApp, h } from "vue";
import mapboxgl from "mapbox-gl";
import { OhVueIcon } from "oh-vue-icons";
import "@/icons";

export class MapboxGLButtonControl implements mapboxgl.IControl {
    icon: string;
    className = "";
    title = "";
    eventHandler = (e: MouseEvent) => {};
    activeToggle = false;

    map: mapboxgl.Map | undefined = undefined;
    container: HTMLDivElement | undefined = undefined;
    btn: HTMLButtonElement | undefined = undefined;

    constructor(
        icon: string,
        {
            className = "",
            title = "",
            eventHandler = (e: MouseEvent) => {},
            activeToggle = false,
        }
    ) {
        this.icon = icon;
        this.className = className;
        this.title = title;
        this.eventHandler = eventHandler;
        this.activeToggle = activeToggle;
    }

    onAdd(map: mapboxgl.Map) {
        this.map = map;

        const { title, icon, className, eventHandler, activeToggle } = this;

        this.container = document.createElement("div");
        this.container.className = "mapboxgl-ctrl-group mapboxgl-ctrl";

        const tempApp = createApp({
            render() {
                this.btn = h(
                    "button",
                    {
                        class: "mapbox-gl-draw_ctrl-draw-btn" + " " + className,
                        type: "button",
                        title: title,
                        onClick: (e: MouseEvent) => {
                            if (activeToggle && e.target) {
                                this.btn.el?.classList.toggle("btn-active");
                            }

                            eventHandler(e);
                        },
                    },
                    h(OhVueIcon, {
                        name: icon,
                    })
                );

                return this.btn;
            },
        });
        const mountedApp = tempApp.mount(this.container);
        return this.container;
    }

    onRemove() {
        if (this.container && this.container.parentNode) {
            this.container.parentNode.removeChild(this.container);
        }

        this.map = undefined;
        this.container = undefined;
        this.btn = undefined;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.