只是工作筆記,想想之後一定會忘記這件事情,所以就記錄一下。大抵上就好像是,明知道 transform
搭配 position: fixed
會有雷,然後我還是傻傻的踩下去一樣。
關於上面提及的雷,可以參考 這裡,並不是每一種瀏覽器都會這樣,不過就是 Chrome/Firefox 會爆炸就是了。
這種時候要讚揚一下 IE11,他在搭配使用的時候,
fixed
還是fixed
,並不會因為transform
而有所改變。只是說,有沒有改變到底是不是要依照 w3c 說的那樣,這個留給後人繼續發掘了(喂
SVG
向量圖形正夯,為了一些相容性的問題,所以坊間建議使用的 <img>
來包 SVG 圖檔,在某些行動裝置上的瀏覽器會中邪(對,就是 Safari
一般 SVG 要使用 #target
會事先利用 style
把 Group 給藏起來,
<def>
<style><![CDATA[
.flag { display: none; }
.flag:target { display: block; }
]]></style>
</def>
類似這樣,如果使用 #target
來指定想顯示什麼圖層的話,在 Safari 上面會出包。當你的 SVG 有好幾個圖層隱藏,然後在同一個畫面畫出來,例如,
<img src="flag.svg#tw">
<img src="flag.svg#jp">
<img src="flag.svg#us">
然後你的 <img>
會在畫面上亂跳,有興趣的可以使用 Safari 試試看這件事情。基本上在其他的瀏覽器都沒問題,偏偏 Safari/Mobile Safari 都會,著實令人頭痛。
Object Tag
坊間的解法是,使用 <object>
來包 SVG,以達到相容性最大值的效果,
<object data="flag.svg#tw" type="image/svg+xml" width="100%" height="100%"></object>
這樣打包的話,當你使用 :target
屬性,就不會有什麼問題了,所有瀏覽器也能正常顯示。
Object Tag with AngularJS
然而,問題來了,如果有使用 AngularJS 的話,<object>
包起來的 SVG 就無法吃到 ng 的相關動作,舉例來說,
<button ng-click="clickme()">
<object data="flag.svg#tw" type="image/svg+xml" width="100%" height="100%"></object>
</button>
基本上,上面的 ng-click
是無效的。原因在於,<object>
會把 SVG 讀入 DOM 裡面(當作是 Shadow DOM 來繪製,理所當然,既然是 Shadow DOM,如果 AngularJS 還碰得到的話,那就是奇蹟了(或許以後的 ng 可以摸到 Shadow DOM 也不一定?
利用 Directive 來 $compile
解法也是有的,利用 directive 把 SVG 讀取進來,然後 $compile
當中需要的元素即可,舉例來說,
angular.module('SVGMapApp')
.directive('SvgMap', ['$compile', function($compile) {
return {
restrict: 'A',
scope: {
language: '=bhSvgMap'
},
templateUrl: '/images/icon_locale_flag.svg',
link: function($scope, $element, $attrs) {
var element = angular.element('#'+$scope.language);
$compile(element)($scope);
}
};
}]);
然後我們的 SVG 可能長這樣,
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg viewBox="0 0 640 480" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g id="zh-tw" ng-if="language === 'zh-tw'>
...
</g>
<g id="en-us" ng-if="language === 'en-us'>
...
</g>
</svg>
最後我們在 HTML 當中就這樣寫就好,
<div svg-map="'zh-tw'"></div>
這個時候,他畫出正常的 SVG,而這時候你也可以使用 ng,不管是外層還是內層。例如,我在 svgMap
加入一個程序讓 ng-click
來吃,然後在 SVG 當中加入 ng-click
,
<g id="zh-tw" ng-if="language === 'zh-tw' ng-click="showMe()">
...
</g>
link: function($scope, $element, $attrs) {
$scope.showMe = function() {
console.log($scope.language);
};
var element = angular.element('#'+$scope.language);
$compile(element)($scope);
}
執行結果如圖,
小結
說好之後要改 ReactJS 的吧?
SVG 這種狀況,雖然我不知道這到底算不算是雷,不過,依照目前使用 <object>
的結果看來,如果真的都是 Shadow DOM 的話,我想 ReactJS 應該也有屬於 ReactJS 的解法,畢竟,要另外寫東西去碰到 Shadow DOM 還是相當麻煩的一件事情。