前段时间,因为工作需要,借助百度地图api,写了一个小小的web工具,用于按关键词标注一些地点并展示出来。

解决了前期的关键点,工作完成了七七八八之后,我发现,yii2自带的bootstrap3和百度地图有点点冲突。

具体表现是,yii2自带的layout文件的第一行是 <!doctype html>,百度地图给的demo文件第一行是<html>

如果用yii2的模板,显示百度地图时会显示不正常,具体是不能把它和其它的bootstrap组件放在一起,特别是不能把地图容器放在其它div下面,不然不显示地图。

如果用百度地图的<html>做第一行,bs3的导航菜单显示就会有多余的空白出现,很难看。

(在写这篇文章时,我发现百度地图的iframe的第一行如果用yii2的,也能正常显示,以后再测试吧)

 

疫情隔离在家,正好有时间,我想好好解决一下这个问题。

我想到的方案是,在yii2的常规页面里,嵌入一个iframe,这个iframe里使用百度地图的显示代码,这样二者就不发生冲突了。

但又出现下面一些问题。

  1. 主页面如何访问iframe里的元素(主要是map变量)
  2. iframe里如何访问主页面的元素
  3. 如何判断iframe已加载完成
  4. 如何在iframe加载完成后,执行调用页面的自定义代码

一、主页面如何访问iframe里的map变量

上网查了解决方案:在显示iframe的主页面里设置全局变量,然后iframe里生成了map对象后,将之保存到这个全局变量里。

(主页面代码)
<script> // 定义全局变量给iframe生成了地图之后传回来 map=null; local=null; </script>
(iframe页面代码)
<script type="text/javascript">
    // 百度地图API功能
    var map = new BMapGL.Map("container");          
    map.centerAndZoom(new BMapGL.Point(117.16526, 35.11891), 13);
    map.enableScrollWheelZoom(true);
    var scaleCtrl = new BMapGL.ScaleControl();  // 添加比例尺控件
    map.addControl(scaleCtrl);

    var local = new BMapGL.LocalSearch(map, {
        renderOptions:{map: map}
    });
    map.addEventListener('click', function (e) {
        // jquery如何获取iframe https://www.muzhuangnet.com/show/53186/2.html
        $(window.parent.document).find('#coor').val(e.latlng.lng + ',' + e.latlng.lat);
        // alert('点击位置经纬度:' + e.latlng.lng + ',' + e.latlng.lat);
    });

    //把自己的变量传回父窗口的全局变量
    parent.map=map; 
    parent.local=local;
</script>

 

二、iframe里如何访问主页面的元素

有时候,我在iframe里的地图上点击后,需要更新主页面上的元素(填充点击位置的坐标值)。这里还用到了jquery,具体方法是:

    map.addEventListener('click', function (e) {
        // jquery如何获取iframe https://www.muzhuangnet.com/show/53186/2.html
        $(window.parent.document).find('#coor').val(e.latlng.lng + ',' + e.latlng.lat);
        // alert('点击位置经纬度:' + e.latlng.lng + ',' + e.latlng.lat);
    });

 

三、如何判断iframe已加载完成

主页面上要执行的一些操作,需要在iframe已加载完成,map对象创建成功之后才可以继续执行,不然会出错。

上网查了一下,这里 给出了解决方案。用在我的代码里是这样:

<script>
    // iframe子页面与父页面元素的访问以及js变量的访问 https://www.cnblogs.com/Capricorn-HCL/articles/4216302.html
    $(document).ready(function(){
        if (can_load_iframe()) load_iframe();
    });

    function can_load_iframe()
    {
        var url = window.location.search;
        action4=url.substr(3,4);
        
        return action4=='site';
    }

    function load_iframe()
    {
        var iframe = document.createElement("iframe");
        iframe.src = "<?=Url::to(['site/map-frame', 'type'=>0])?>";
        
        if (iframe.attachEvent){
            iframe.attachEvent("onload", function(){
                console.log("Local iframe is now loaded1.");
            });
        } else {
            iframe.onload = function(){
                frame_onload()
            };
        }
        
        document.getElementById('container').appendChild(iframe);
        h=window.innerHeight - document.getElementById('w0').height - document.getElementById('footer').height;
        h=h-$("[id^='w2-']").height();
        iframe.width='100%';
        iframe.height=h;
        iframe.id='iframe_map';
    }

    function frame_onload() {。。。}
</script>

 

四、如何在iframe加载完成后,执行调用页面的自定义代码

前面实现的是通用的layout,显示地图的地方都会调用它,但是每一个页面的脚本动作各有不同,比如有的页面需要在一开始时标注出若干个地图上的点。

如果在调用者页面上直接使用onload,还是会面临前面的iframe是否已经加载完成的问题,所以我给各页面里增加了一个函数 my_init(),然后在主layout模板中,在iframe的onload事件中,加一个判断,如果函数my_init()存在,则调用之。

这样就解决了不同页面的定制化需求的问题。

 

总结

以上的方案,由页面的主模板生成并插入iframe,在iframe中把生成的map等对象保存到主模板的全局变量中,在主模板中监听iframe的onload事件,然后执行调用者页面的my_init()函数。该方案可解决现有问题,但中间各种同步、异步,耦合度较高,互相调用的时序问题、变量问题等复杂度直线上升,不是一个理想的解决方案。此处先记录下来,不管怎么说,也是一些经验了。等待更好的方案的出现。

 

原文地址:http://www.cnblogs.com/anjo/p/16847328.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性