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

UWP MapControl使用LocalMapTileDataSource时如何动态设置瓦片自定义透明度

解决方案

方法1:基于像素缓冲区修改的自定义透明度控制

这个方法支持灵活控制每一张瓦片的透明度,逻辑如下:

  • 保留现有瓦片坐标转QuadKey的逻辑,不要直接赋值Uri,改为先加载本地瓦片图片,对像素的Alpha通道做全局乘法后赋值给e.Request.PixelBuffer
  • 可以额外定义一个全局变量比如_tileOpacity,范围0~1,动态修改这个值之后,新加载的瓦片都会自动应用新的透明度,已经加载的瓦片可以调用tileSource.Invalidate() 刷新即可全局生效

修改后的示例代码如下:

// 全局透明度变量,可动态修改,范围0-1
private double _tileOpacity = 0.6;

private void AddLocalMapTileDataSource()
{
    MapZoomLevelRange range;
    range.Min = 8;
    range.Max = 16;
    var dataSource = new LocalMapTileDataSource();
    dataSource.UriRequested += async (s, e) =>
    {
        var deferral = e.Request.GetDeferral();
        try
        {
            var qk = TileSystem.TileXYToQuadKey(e.X, e.Y, e.ZoomLevel);
            // 加载本地瓦片文件
            var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri($"ms-appx:///Tiles/{qk}.png"));
            using (var stream = await file.OpenAsync(FileAccessMode.Read))
            {
                // 解码图片
                var decoder = await BitmapDecoder.CreateAsync(stream);
                var pixelData = await decoder.GetPixelDataAsync();
                var pixels = pixelData.DetachPixelData();

                // 遍历像素修改Alpha通道,RGBA格式下每4个字节第一个是B,第二个G,第三个R,第四个A
                for (int i = 3; i < pixels.Length; i += 4)
                {
                    pixels[i] = (byte)(pixels[i] * _tileOpacity);
                }

                // 编码回像素缓冲区赋值给请求
                using (var ms = new InMemoryRandomAccessStream())
                {
                    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, ms);
                    encoder.SetPixelData(
                        BitmapPixelFormat.Bgra8,
                        BitmapAlphaMode.Premultiplied,
                        decoder.OrientedPixelWidth,
                        decoder.OrientedPixelHeight,
                        decoder.DpiX,
                        decoder.DpiY,
                        pixels
                    );
                    await encoder.FlushAsync();
                    ms.Seek(0);
                    var reader = new DataReader(ms.GetInputStreamAt(0));
                    var bytes = new byte[ms.Size];
                    await reader.LoadAsync((uint)ms.Size);
                    reader.ReadBytes(bytes);
                    e.Request.PixelBuffer = bytes.AsBuffer();
                }
            }
        }
        catch
        {
            // 瓦片不存在时可以留空或者设置占位图
            e.Request.Uri = null;
        }
        finally
        {
            deferral.Complete();
        }
    };

    var tileSource = new MapTileSource(dataSource)
    {
        ZoomLevelRange = range
    };

    myMap.TileSources.Add(tileSource);
    tileSource.Layer = MapTileLayer.AreaOverlay;
    tileSource.IsTransparencyEnabled = true;
    tileSource.TilePixelSize = 256;
}

// 动态调整透明度的调用示例
private void UpdateTileOpacity(double newOpacity)
{
    _tileOpacity = Math.Clamp(newOpacity, 0, 1);
    // 刷新所有已加载瓦片应用新透明度
    foreach (var source in myMap.TileSources)
    {
        source.Invalidate();
    }
}

方法2:基于Composition API的全局瓦片层透明度控制

如果你只需要统一调整整个瓦片层的透明度,不需要单独控制单张瓦片,这个方法性能更好,修改完全实时,不需要刷新瓦片:

private void SetTileLayerOpacity(double opacity)
{
    // 获取MapControl的可视化层
    var visual = ElementCompositionPreview.GetElementVisual(myMap);
    var compositor = visual.Compositor;

    // 找到瓦片层的子视觉对象,AreaOverlay层对应的就是你添加的自定义瓦片
    foreach (var child in visual.Children)
    {
        if (child.Comment?.Contains("MapTileLayer_AreaOverlay") == true)
        {
            child.Opacity = (float)opacity;
            break;
        }
    }
}

注意:这个方法依赖Windows 10 1809及以上版本的SDK,适配系统版本低于该版本时建议使用方法1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 20:27:03