码农-小林 2025-10-15 10:45 采纳率: 54.8%
浏览 7

使用leaflet-tilelayer-colorizr.js调用瓦片时候提示跨域

使用leaflet-tilelayer-colorizr.js调用瓦片时候提示跨域
1,leaflet-tilelayer-colorizr.js代码如下

/*
 * L.TileLayer.Colorizr is a regular tilelayer with mapped colors.

 */

 (function() {
    

    // L.TileLayer.Colorizr = 
    var Colorizr = L.TileLayer.extend({

        initialize: function (url, options) {
            options = L.extend({}, L.TileLayer.prototype.options, {
                colorize: function(pixel) {
                    return pixel;
                },
                crossOrigin: "Anonymous"
            }, options);
            L.TileLayer.prototype.initialize.call(this, url, options);
            L.setOptions(this, options);
            
            this.setColorizr(this.options.colorize);

            this.on('tileload', function(e) {
                this._colorize(e.tile);
            });
        },

        setColorizr: function(colorizrFactory) {
            if(!colorizrFactory || typeof colorizrFactory !== 'function') {
                throw 'The colorize option should be a function and return an object with at least one of "r", "g", "b", or "a" properties. Got:' + 
                    typeof colorizrFactory;
            }
            else {
                this.options.colorize = colorizrFactory;
            }

            this.redraw(true);
        },

        _createTile: function () {
            var tile = L.TileLayer.prototype._createTile.call(this);
            tile.crossOrigin = "Anonymous";
            return tile;
        },

        _colorize: function (img) {
            if (img.getAttribute('data-colorized'))
                return;

            img.crossOrigin = 'Anonymous';
            var canvas = document.createElement("canvas");
            canvas.width = img.width;
            canvas.height = img.height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);

            var imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);
            var pix = imgd.data;

            for (var i = 0, n = pix.length; i < n; i += 4) {

                // iterate through the pixels

                var pixel = this.options.colorize({r: pix[i], g: pix[i+1], b: pix[i+2], a: pix[i+3]});

                if(!!!pixel || pixel !== Object(pixel) || Object.prototype.toString.call(pixel) === '[object Array]') {
                    
                    if(i === 0) {
                        throw 'The colorize option should return an object with at least one of "r", "g", "b", or "a" properties.';
                    }

                } else {

                    if(pixel.hasOwnProperty('r') && typeof pixel.r === 'number') {
                        pix[i] = pixel.r;
                    }
                    if(pixel.hasOwnProperty('g')) {
                        pix[i+1] = pixel.g;
                    }
                    if(pixel.hasOwnProperty('b')) {
                        pix[i+2] = pixel.b;
                    }
                    if(pixel.hasOwnProperty('a')) {
                        pix[i+3] = pixel.a;
                    }
                }
                
            }

            ctx.putImageData(imgd, 0, 0);
            img.setAttribute('data-colorized', true);
            img.src = canvas.toDataURL();
        }
    });

    (function (factory, window) {

        // define an AMD module that relies on 'leaflet'
        if (typeof define === 'function' && define.amd) {
            define(['leaflet'], factory);

        // define a Common JS module that relies on 'leaflet'
        } else if (typeof exports === 'object') {
            module.exports = factory(require('leaflet'));
        }

        // attach your plugin to the global 'L' variable
        if (typeof window !== 'undefined' && window.L) {
            window.L.tileLayer.colorizr = factory(L);
        }
    }(function (L) { 
        return function(url, options) {
            return new Colorizr(url, options);
        };
    }, window));
        


 })()

2,页面调用使用如下:

  <script>
    var map = L.map('map', {
      zoominfoControl: true,
      zoomControl: false,
      //zoom: 5, 
      //center: [31.22, 121.48], 
      attributionControl: true 
    }).setView([23.3725, 116.4238], 5);
    //var map = L.map('map').setView([23.1291, 113.2644], 13);
    L.tileLayer.colorizr('gmaps/{z}/{x}/{y}.png', {

      maxZoom: 15,
 
      attribution: 'Map data &copy; GoogleMap,Support by <a href="http://rovertang.com/">RoverTang</a>'
    }).addTo(map);


     var marker = L.marker([22.7457, 113.9454]).addTo(map)
    .bindPopup("这是一个标注点")
    .openPopup();
    var marker = L.marker([35.86, 99.66]).addTo(map)
    .bindPopup("这是二个标注点")
    .openPopup();

  </script>

3,报错如下

img

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2025-10-15 10:49
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    当你使用 leaflet-tilelayer-colorizr.js 调用瓦片时遇到 跨域问题(Cross-Origin Resource Sharing, CORS),这意味着你尝试加载的瓦片图像(tile)来自一个与当前网页不同的域名、端口或协议,而服务器没有正确配置允许跨域访问。


    ✅ 问题原因分析

    1. 服务器未设置正确的 CORS 头
      瓦片服务所在的服务器没有在响应头中包含 Access-Control-Allow-Origin: * 或特定域名,导致浏览器阻止了该请求。

    2. TileLayer 的 crossOrigin 设置不正确
      虽然你在代码中设置了 crossOrigin: "Anonymous",但可能由于某些原因未生效,或者瓦片服务本身不允许匿名访问。

    3. 浏览器安全策略限制
      浏览器默认不允许从不同源加载资源,除非服务器明确允许。


    ✅ 解决方案

    1. 确保服务器支持 CORS

    这是最根本的解决方案。你需要联系瓦片服务提供者,要求他们在服务器响应头中添加以下内容:

    Access-Control-Allow-Origin: *
    

    或者指定你的域名:

    Access-Control-Allow-Origin: https://yourdomain.com
    

    如果你无法控制服务器,可以考虑使用代理服务器来绕过跨域限制。


    2. 检查 leaflet-tilelayer-colorizr.js 中的 crossOrigin 配置

    在你的代码中,已经设置了:

    options = L.extend({}, L.TileLayer.prototype.options, {
        colorize: function(pixel) {
            return pixel;
        },
        crossOrigin: "Anonymous"
    }, options);
    

    以及:

    this._createTile = function () {
        var tile = L.TileLayer.prototype._createTile.call(this);
        tile.crossOrigin = "Anonymous";
        return tile;
    };
    

    这应该已经为每个瓦片设置了 crossOrigin="Anonymous",但有时可能会被覆盖或忽略。

    建议: 在创建 TileLayer 时显式设置 crossOrigin 属性:

    L.tileLayer.colorizr('https://{s}.example.com/tiles/{z}/{x}/{y}.png', {
        crossOrigin: 'Anonymous'
    }).addTo(map);
    

    3. 使用代理服务器解决跨域问题

    如果你无法修改服务器配置,可以使用代理服务器来“中转”请求,这样客户端请求的是同一域下的代理地址,而不是原始瓦片服务地址。

    示例:使用 Nginx 作为代理

    location /proxy/ {
        proxy_pass https://tiles.example.com/;
        proxy_set_header Host tiles.example.com;
        proxy_set_header Origin "";
        add_header Access-Control-Allow-Origin "*";
    }
    

    然后在前端调用:

    L.tileLayer.colorizr('/proxy/{z}/{x}/{y}.png', {
        crossOrigin: 'Anonymous'
    }).addTo(map);
    

    4. 使用浏览器插件临时禁用 CORS(仅用于开发)

    你可以安装浏览器插件如 CORS Unblock 来临时绕过跨域限制,但这不适用于生产环境


    5. 修改 leaflet-tilelayer-colorizr.js 以增强跨域支持

    如果你确定是 leaflet-tilelayer-colorizr.js 的问题,可以在 _createTile 方法中更严格地设置 crossOrigin

    _createTile: function () {
        var tile = L.TileLayer.prototype._createTile.call(this);
        tile.crossOrigin = "Anonymous"; // 确保此行生效
        return tile;
    },
    

    如果仍然无效,可以尝试强制设置 img.crossOrigin = "Anonymous"_colorize 函数中:

    _colorize: function (img) {
        img.crossOrigin = 'Anonymous'; // 强制设置
        ...
    }
    

    ✅ 最终建议

    | 步骤 | 内容 | |------|------| | 1 | 确保瓦片服务服务器配置了正确的 CORS 响应头 | | 2 | 在创建 L.tileLayer.colorizr 时显式设置 crossOrigin: 'Anonymous' | | 3 | 如果无法控制服务器,使用代理服务器中转请求 | | 4 | 开发阶段可使用浏览器插件临时绕过 CORS 限制 | | 5 | 检查并增强 leaflet-tilelayer-colorizr.js 中的 crossOrigin 设置 |


    ✅ 示例代码(修正后的调用方式)

    <!DOCTYPE html>
    <html>
    <head>
        <title>Leaflet with Colorizr</title>
        <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
        <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
        <script src="leaflet-tilelayer-colorizr.js"></script>
    </head>
    <body>
        <div id="map" style="width: 100%; height: 100vh;"></div>
        <script>
            var map = L.map('map').setView([37.7749, -122.4194], 13);
    
            L.tileLayer.colorizr('https://{s}.example.com/tiles/{z}/{x}/{y}.png', {
                crossOrigin: 'Anonymous',
                attribution: '&copy; Example Tiles'
            }).addTo(map);
        </script>
    </body>
    </html>
    

    ✅ 总结

    • 跨域问题是由于服务器未正确设置 CORS 响应头
    • 可以通过设置 crossOrigin: 'Anonymous' 来尝试修复
    • 如果无法控制服务器,建议使用代理
    • 开发阶段可使用插件临时绕过限制

    如有更多具体错误信息(如浏览器控制台报错),请提供,我可以进一步帮你定位问题。

    评论

报告相同问题?

问题事件

  • 创建了问题 10月15日