前言
最近的業務需求,要在DFP上放視差廣告,就是原本比較小的圖片,滑到一定的高度之後,會自己變大。之前的做法是準備兩個iframe,需要的時候才顯示其中一個,但是需求方不想要投放兩個DFP廣告,並要直接控制同一個iframe的內容,因此才開始找尋如何跨網域控制iframe的方法。
困難
在HTML 5之前,對於iframe的控制,只能在於同個網域,這邊 完整的表示了同網域控制iframe的方法:
1 | // 先抓iframe的ID |
這樣的話是還不錯,甚至在之前的案子中,我還利用它來播放iframe裡面的影片(當然現在已經不行了,參考鏈接),但是他不能用在DFP上。DFP廣告的素材都是自己上傳到DFP的Server,再從那邊的Server讀取,上面的方法就失效了。
方法
後來我查到在HTML 5有新的Api, Cross-document messaging,支援度也相當不錯,ie 11有支持。程式碼如下:
1 | // Main Page |
在網頁中,抓了iframe後,對iframepostMassage,在postMessage中可以傳入三個函數,前面的兩個是你要傳的訊息,以及iframe的網域,第三個是可選的參數,我還沒研究。
在iframe中,通過addEventListener中的message,會讓iframe收到訊息,,並且通過傳送過來的data來控制iframe。但沒有過濾origin的話,會使得所有其他網域的網站,能控制這個iframe。最好的方法就是,在function中加上網址過濾的判斷。
遇到的問題
在一開始執行時,會出現
1 | Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://iframeWebsite.dfp') does not match the recipient window's origin ('http://mainPageWebsite'). |
一開始我以為是http和https的問題,後來查了一下,發現是javascipt很可愛的非同步bug,就是一開始網頁就會在節點載好後,開始執行js,但是因為非同步的關係,iframe的內容還沒有生成,自然postMessage過去就找不到相應的js啦,因此我在網頁js下加上了iframe.addEventListener(‘load’, adsAction, false); 確保iframe載好後重載一次,並且也把因為重載,而造成畫面閃一下的問題處理了。
結論
看到又能用的畫面真的很開心,希望之後能想辦法解決,iframe自動播放影片的問題(好像解決了,下次有就會再分享好了)。