maptalks / issues

Repo of issues for webgl layers
3 stars 0 forks source link

vt update symbol.visible性能比较差 #198

Open deyihu opened 1 year ago

deyihu commented 1 year ago

经测试发现 即使仅仅更新某个symbol.visible也会导致大面积的update

  layer.updateSymbol(i, {visible:false});

期望的效果是仅仅更新这个style item的sybmol,但是却发现其他的style item也会刷新

https://user-images.githubusercontent.com/25998927/205841058-1fc02a9b-b0f9-44ec-9ebf-e6d8da2cc8cc.mp4

视屏里仅仅是更新了绿地的style item,但是水系的也会被刷新,当style比较多时(比如有个300个style item),性能将急速下降

deyihu commented 1 year ago

应该做差异化更新,即使用户调用setStyle()也需要做差异化更新,可以用个diff库,将用户的传入的新的style和图层上的style做个diff

such as microdiff

deyihu commented 1 year ago
<!DOCTYPE html>
<html>

<head>
    <title>更新渲染插件样式</title>
    <style type="text/css">
        html,
        body {
            width: 100%;
            height: 100%;
            margin: 0px;
        }

        .container {
            background-color: #444444;
            width: 100%;
            height: 100%;
        }
    </style>
    <link rel="stylesheet" href="https://maptalks.com/api/maptalks.css" />
    <script type="text/javascript" src="https://maptalks.com/api/maptalks.min.js"></script>
    <script type="text/javascript" src="https://maptalks.com/api/maptalks-gl-layers.js"></script>
    <script type="text/javascript" src="https://maptalks.com/api/dat.gui.min.js"></script>
</head>

<body>
    <div id="map" class="container"></div>
    <script>
        const map = new maptalks.Map("map", {
            center: [-74.00912099912109, 40.71107610933129],
            zoom: 14,
        });

        const vt = new maptalks.VectorTileLayer("vt", {
            urlTemplate: "http://tile.maptalks.com/test/planet-single/{z}/{x}/{y}.mvt",
            spatialReference: "preset-vt-3857",
        });

        const style = {
            style: [
                {
                    filter: [
                        "all",
                        ["==", "$layer", "water"],
                        ["==", "$type", "Polygon"],
                    ],
                    renderPlugin: {
                        dataConfig: {
                            type: "fill",
                        },
                        type: "fill",
                    },
                    symbol: {
                        polygonFill: "#2e7e57",
                        polygonOpacity: 1,
                    },
                },
                {
                    filter: [
                        "all",
                        ["==", "$layer", "internal-road"],
                        ["==", "$type", "LineString"],
                    ],
                    renderPlugin: {
                        dataConfig: {
                            type: "line",
                        },
                        sceneConfig: {},
                        type: "line",
                    },
                    symbol: {
                        lineColor: [0.73, 0.73, 0.73, 1],
                        lineWidth: {
                            stops: [
                                [12, 1],
                                [20, 10],
                            ],
                        },
                    },
                },
            ],
        };
        vt.setStyle(style);

        const sceneConfig = {
            postProcess: {
                enable: true,
                antialias: {
                    enable: true
                }
            },
        };

        const groupLayer = new maptalks.GroupGLLayer("group", [vt], {
            sceneConfig,
        });
        groupLayer.addTo(map);

        setTimeout(() => {
            vt.updateSymbol(1, {
                visible: false
            });
        }, 5000);
    </script>
</body>

</html>
fuzhenn commented 1 year ago

设计如此,因为visible被设为false的mesh会被删除掉,这样样式里如果定义有大量visible为false的renderPlugin,但不会占用任何资源,在某些场景下还是蛮有用的。

考虑到除了设计场景下,业务系统里visible的切换并不是一个高频操作,感觉这个设计是值得的。

fuzhenn commented 1 year ago

可以考虑对每个style item对应的painter单独进行mesh重建和更新,这样在某个painter发生变化时不影响其他的painter,就不需要整体更新了。