草庐IT

yii2、百度地图、bootstrap冲突的处理过程

每天进步一点点 2023-03-28 原文

前段时间,因为工作需要,借助百度地图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加载完成后,执行调用页面的自定义代码
  5. 百度地图标注时,不能显示自定义icon

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

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

(主页面代码)
<script> // 定义全局变量给iframe生成了地图之后传回来 map=null; local=null; </script>
(iframe页面代码)

 

二、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()存在,则调用之。

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

 

五、百度地图标注时,不能显示自定义icon

这个问题在原来的版本中并不存在,而是在引入了iframe之后,我发现,标注的点,都不再显示自定义的icon图标。

说明一下:标注代码是写在iframe的父页面的。

 1 <script>
 2     function add_point(map, x, y, title1, info, type){
 3         marker=add_marker(map, x, y, type);
 4         // console.log("add_point(map, "+x+","+y+",'"+title1+"','"+info+"',"+type+");");
 5 
 6         // 创建信息窗口
 7         var opts = {
 8             width: 200,
 9             height: 100,
10             title: title1
11         };
12         var infoWindow = new BMapGL.InfoWindow(info, opts);
13         // 点标记添加点击事件
14         marker.addEventListener('click', function () {
15             map.openInfoWindow(infoWindow, new BMapGL.Point(x,y)); // 开启信息窗口
16         });
17 
18         add_label(map, x, y, title1);
19     }
20 
21     function add_marker(map, x, y, type)
22     {
23         marker_url="images/mark"+type+".png";
24         // console.log(marker_url + ' x=' + x + ' y=' + y + ', type=' + type);
25         var myIcon = new BMapGL.Icon(marker_url, new BMapGL.Size(32, 32), {
26             offset: new BMapGL.Size(10, 25), // 指定定位位置(不然图标会偏下一些)
27         });
28         console.log(myIcon);
29         if (type)
30             var marker1 = new BMapGL.Marker(new BMapGL.Point(x,y), {icon:myIcon});
31         else
32             var marker1 = new BMapGL.Marker(new BMapGL.Point(x,y));
33         // var marker1 = new BMapGL.Marker(new BMapGL.Point(x,y));
34         // 在地图上添加点标记
35         map.addOverlay(marker1);
36         return marker1;
37     }
38 
39     function add_label(map, x, y, msg)
40     {
41         var opts = {
42             position: new BMapGL.Point(x,y), // 指定文本标注所在的地理位置
43             offset: new BMapGL.Size(20, -30) // 设置文本偏移量
44         };
45         // 创建文本标注对象
46         var label = new BMapGL.Label(msg, opts);
47         // 自定义文本标注样式
48         label.setStyle({
49             color: 'blue',
50             borderRadius: '5px',
51             borderColor: '#ccc',
52             padding: '10px',
53             fontSize: '16px',
54             height: '30px',
55             lineHeight: '10px',
56             fontFamily: '微软雅黑'
57         });
58         map.addOverlay(label);
59     }
60 </script>

为什么原来的写法就可以,现在就不行呢?用笨办法逐一排除,最后发现,当在add_point()等方法放在iframe中并调用时,icon显示正常。

初步怀疑是iframe还是触碰了某种安全机制。网上找到一篇“百度地图api自定义marker图片不显示问题”,提到了是跨域的原因,但仍然没有试出解决办法。

怎么办呢?实在不甘心把自定义的标注代码写在iframe里面。。

想了一个办法:函数放在iframe里面,然后调用时,从父页面调用,像这样:

foreach ($units as $unit) 
{
   echo "document.getElementById('iframe_map').contentWindow.add_point(map, $unit->coor , '$unit->name1', '$unit->id', $unit->tagType);\n";
}

 

总结

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

 

bootstrapyii2spanstylecolor其他技术区

有关yii2、百度地图、bootstrap冲突的处理过程的更多相关文章

  1. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  2. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  3. git使用常见问题(提交代码,合并冲突) - 2

    文章目录git常用命令(简介,详细参数往下看)Git提交代码步骤gitpullgitstatusgitaddgitcommitgitpushgit代码冲突合并问题方法一:放弃本地代码方法二:合并代码常用命令以及详细参数gitadd将文件添加到仓库:gitdiff比较文件异同gitlog查看历史记录gitreset代码回滚版本库相关操作远程仓库相关操作分支相关操作创建分支查看分支:gitbranch合并分支:gitmerge删除分支:gitbranch-ddev查看分支合并图:gitlog–graph–pretty=oneline–abbrev-commit撤消某次提交git用户名密码相关配置g

  4. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  5. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  6. ruby - 如何使用 Ruby HTTP::Net 处理 404 错误? - 2

    我正在尝试解析网页,但有时会收到404错误。这是我用来获取网页的代码:result=Net::HTTP::getURI.parse(URI.escape(url))如何测试result是否为404错误代码? 最佳答案 像这样重写你的代码:uri=URI.parse(url)result=Net::HTTP.start(uri.host,uri.port){|http|http.get(uri.path)}putsresult.codeputsresult.body这将打印状态码和正文。

  7. ruby-on-rails - 使用 gmaps4rails 动态加载谷歌地图标记 - 2

    如何只加载map边界内的标记gmaps4rails?当然,在平移和/或缩放后加载新的。与此直接相关的是,如何获取map的当前边界和缩放级别? 最佳答案 我是这样做的,我只在用户完成平移或缩放后替换标记,如果您需要不同的行为,请使用不同的事件监听器:在你看来(index.html.erb):{"zoom"=>15,"auto_adjust"=>false,"detect_location"=>true,"center_on_user"=>true}},false,true)%>在View的底部添加:functiongmaps4rail

  8. ruby-on-rails - 使用 Ruby 正确处理 Stripe 错误和异常以实现一次性收费 - 2

    我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)

  9. css - Rails 4.1 和 Bootstrap 3 字形图标不工作 - 2

    我正在尝试消除使用Bootstrap3的Rails4元素中的glyphicon错误。我没有使用任何Bootstrapgem将其添加到Assets管道中。我手动将bootstrap.css和bootstrap.js添加到各自的app/assets目录下,分别添加到application.css和application.js什么的我现在在网络浏览器的控制台中看到以下内容:GEThttp://localhost:3000/fonts/glyphicons-halflings-regular.woff404(NotFound)localhost/:1GEThttp://localhost:30

  10. ruby - mixin方法名冲突时如何选择调用方法? - 2

    当你在类中包含方法名冲突的模块时,它会使用类定义的方法。有没有办法选择我想运行的?moduleBdefself.hello"helloB"endendclassAincludeBdefself.hello"helloA"endendA.hello#=>thisprints"helloA",whatifIwant"helloB"? 最佳答案 Ben,当你在Ruby中调用一个方法(比如hello)时,会发生以下情况:如果接收者的特征类有一个名为hello的方法,它将被调用。如果不是:如果接收者的类有一个名为hello的实例方法,它将被调

随机推荐