arcgis api for 4.x 开发笔记-在Vue 2.X项目中开发arcgis api for javascript 4.x(八)—— 自定义底图切换

前言

为什么有地图切换的需求?

  • 可视化需求:不同的底图可以以不同的样式和表达方式呈现地理信息。切换底图可以改变地图的外观和风格,使用户能够选择最适合他们需求的地图显示方式。例如,用户可能希望在街道地图和卫星图像之间进行切换,以便更好地理解和分析地理数据。
  • 上下文和背景信息:底图提供了地理环境的上下文和背景信息。在不同的应用场景中,用户可能需要不同的底图来支持他们的工作。例如,对于城市规划者来说,他们可能更关注街道和建筑物的信息,而对于环境保护机构来说,地形和土地利用可能更重要。切换底图可以提供不同的上下文信息,以便更好地理解和分析地理数据。
  • 数据可视化和分析:底图的选择可以影响地理数据的可视化效果和分析结果。不同的底图样式和颜色方案可能会突出不同的地理特征或数据模式。通过切换底图,用户可以尝试不同的可视化方案,并根据需要选择最适合的底图来突出或隐藏感兴趣的地理特征。
  • 用户偏好:用户可能有不同的地图偏好和习惯,根据他们的背景、经验和需求,他们可能更喜欢使用特定的底图。提供底图切换功能可以满足用户个性化的需求,使用户能够按照他们自己的喜好选择适合的底图。

总之,底图切换在GIS中是为了提供更好的地理信息展示和分析的灵活性和可定制性。它允许用户根据需要选择适当的底图,并根据上下文和需求更好地理解和分析地理数据。

展示

“影像”底图

“电子地图”底图

实现

BasemapGalleryWidget.js

/**
* @描述: 地图切换组件-widget-BasemapGalleryWidget
* @作者: 花姐夫JUN
* @创建时间: 2022-12-06 16:02:54
*/
<template>
    <a-popover v-bind="$attrs" v-model="isExpand" trigger="click" placement="leftBottom">
        <div slot="content" style="min-height: 155px;min-width: 160px;" v-if="activeView">
            <basemap-gallery-card :key="activeView.type" :active-view="activeView" :all-basemap-list="allBasemapList"></basemap-gallery-card>
        </div>

        <div v-show="visible"
             class="esri-component esri-home esri-widget--button esri-widget"
             role="button"
             tabindex="0"
             :aria-label="title"
             :title="title"
             @mouseover="isHover=true"
             @mouseleave="isHover=false"
             @focus="active=true"
             @blur="active=false"
             style="width: 80px;height: 80px;position: relative;right: 28px;"
             @click="handleClick()">
            <div v-if="loading" aria-hidden="true" class="esri-icon">
                <div :class="{'esri-icon-loading-indicator esri-rotating':loading}"></div>
            </div>

            <div v-else
                 aria-hidden="true"
                 class="esri-icon">
                <img :src="thumbnailUrl|imgBasePath" alt="">
            </div>
        </div>
    </a-popover>
</template>

<script lang="ts">
import { Component } from 'vue-property-decorator';
import MapView from '@c_arcgis/core/views/MapView';
import SceneView from '@c_arcgis/core/views/SceneView';
import { WidgetMixins } from '@/views/map/components/tools/widgetMixins';
import BasemapGalleryCard from '@/views/map/components/tools/BasemapGalleryWidget/BasemapGalleryCard.vue';

@Component({
    name: 'BasemapGalleryWidget',
    components: { BasemapGalleryCard },
})
export default class BasemapGalleryWidget extends WidgetMixins {
    title = '底图';

    isExpand = false;

    thumbnailUrl = '';

    activeView: MapView | SceneView = null;

    allBasemapList: Record<string, any> = {};

    // 初始化
    init(activeView, allBasemapList = undefined) {
        this.activeView = null;
        this.activeView = activeView;
        this.allBasemapList = allBasemapList;
        debugger;

        this.visible = !!(this.activeView && Object.keys(this.allBasemapList)?.length);

        const {
            thumbnailUrl,
            title,
        } = this.activeView.map.basemap;
        this.title = title;
        this.thumbnailUrl = thumbnailUrl;

        // 监听底图切换
        this.activeView.map.watch('basemap', ({
                                                  thumbnailUrl: thumbnailUrl_active,
                                                  title: title_active,
                                              }) => {
            // 是否有effect的图层,有的话清空,否则底图显示会异常
            const regionEffect_groupLayer: any = this.activeView.map.findLayerById('regionEffect_groupLayer');
            if (regionEffect_groupLayer?.opacity === 0) {
                // 为了避免异常直接移除
                this.activeView.map.remove(regionEffect_groupLayer);
                // 清空
                this.activeView.map.allLayers.forEach((layer: any) => {
                    debugger;
                    if (layer.effect === 'blur(15px) brightness(1.2) grayscale(0.6)') {
                        layer.effect = null;
                    }
                });
            }

            this.title = title_active;
            this.thumbnailUrl = thumbnailUrl_active;
        });

        return this.$el;
    }

    handleClick() {
        if (this.activeView) {
            this.isExpand = !this.isExpand;
        }
    }
}
</script>

<style scoped lang="less">
@widgetTextColor: '#8c8c8c';

.widgetLabel {
  color: @widgetTextColor !important;
  font-size: 12px;
  width: 100%;
  position: relative;
  bottom: 5px;
}

/deep/ .ant-popover-inner-content {
  padding: 5px;
}
</style>

以上BasemapGalleryWidget.js代码是为了实现地图切换组件作为地图的一个widget,从而可以使用view.ui.add(widget, position)的方式添加。并且也使用antd design的popover组件,来实现可选底图的弹出展示。

BasemapGalleryCard.js

/**
* @描述: 底图切换备选地图展示-BasemapGalleryCard
* @作者: 花姐夫JUN
* @创建时间: 2022-12-06 16:41:57
*/
<template>
    <div style="width: 200px;">
        <a-list :grid="{ gutter: 0, column: 1 }" :data-source="dataSource" :loading="loading">
            <a-list-item slot="renderItem" slot-scope="item" @click="onClick(item)">
                <div class="flex hover:bg-gray-200 cursor-default border-l-4 border-transparent" :class="{'bg-gray-200 border-blue-500':activeBasemap.id===item.id}" :title="item.title">
                    <img :src="item.thumbnailUrl" class="p-1 border-inherit border-1">
                    <div class="text-lg pl-2" style="line-height: 84px;">{{ item.title }}</div>
                </div>
            </a-list-item>
        </a-list>
    </div>
</template>

<script lang="ts">
import {
    Component, InjectReactive, Prop, Vue, Watch,
} from 'vue-property-decorator';
import BasemapGallery from '@c_arcgis/core/widgets/BasemapGallery';
import MapView from '@c_arcgis/core/views/MapView';
import SceneView from '@c_arcgis/core/views/SceneView';

@Component({ name: 'BasemapGalleryCard' })
export default class BasemapGalleryCard extends Vue {
    @Prop({
        type: Object,
        default: () => ({}),
    }) activeView: MapView | SceneView | undefined;

    @Prop({
        type: Object,
        default: () => ({}),
    }) allBasemapList: Record<string, any> | undefined;

    dataSource: Record<string, any>[] = [];

    widget;

    activeBasemap: Record<string, any> = {};

    loading = false;

    handle = null;

    init() {
        if (this.activeView && Object.keys(this.allBasemapList)?.length) {
            const { spatialReference } = this.activeView;
            this.dataSource = Object.values(this.allBasemapList)
                .filter((layer) => !!layer)
                .map((layer) => {
                    layer.spatialReference = spatialReference;
                    return layer;
                });

            this.activeBasemap = this.activeView.map.basemap;

            // 监听底图切换
            this.handle = this.activeView.map.watch('basemap', (item) => {
                this.loading = false;
                this.activeBasemap = item;
            });
        }
    }

    mounted() {
        this.init();
    }

    onClick(item) {
        if (this.activeBasemap.id !== item.id) {
            this.loading = true;
            this.activeView.map.basemap = item;
        }
    }

    destroyed() {
        this.handle.remove();
    }

    @Watch('activeView', { immediate: false })
    handleActiveViewChange(newVal, oldVal) {
        if (!_.isEqual(newVal, oldVal)) {
            this.$nextTick(() => {
                this.init();
            });
        }
    }

    @Watch('allBasemapList', { immediate: false })
    handleAllBasemapListChange(newVal, oldVal) {
        if (!_.isEqual(newVal, oldVal)) {
            this.$nextTick(() => {
                this.init();
            });
        }
    }
}
</script>

<style scoped lang="less">

</style>

BasemapGalleryCard.js代码是将传入的allBasemapList(备选底图)列表展示,并实现点击切换底图底图。

数据格式

allBasemapList(备选基础底图数据)的生成是使用这个自定义地图切换widget的关键,以下为传入自定义地图切换widget的基础底图数据生成代码块

         // 生成基础底图
            Object.entries(basemapLayersDic)
                .forEach(([basemapName, basemapInfo]: any) => {
                    let thumbnailUrl_temp = [];
                    const baseLayers = basemapInfo.map(({
                                                            layer,
                                                            thumbnailUrl,
                                                        }) => {
                        thumbnailUrl_temp = [...thumbnailUrl_temp, thumbnailUrl];
                        return layer;
                    });
                    allBasemapList[basemapName] = new Basemap({
                        baseLayers: baseLayers || [],
                        title: basemapName,
                        id: basemapName,
                        thumbnailUrl: thumbnailUrl_temp[0], // 设置地图截图
                    });
                });
        }

thumbnailUrl不是创建Basemap实例对象必须的参数,而是为了在自定义widget中实现通过thumbnailUrl展示不同底图的缩略图,更加直观的展示各种类型的底图。


参考文章:
widget添加
Basemap实例化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花姐夫Jun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值