2014-03-27 122 views
2

我正在開發一個小型教育工具,爲此我想將陰影添加到SVG路徑。爲了構建我的圖形,我使用了D3.js.這通常是可愛的,但具體的形狀我遇到了問題,特別是對於具有水平和/或垂直線的小形狀。如何防止使用D3的小形狀的前衛陰影

爲了說明這一點,我做了一個JSFiddle example三個三角形。綠色三角形上的陰影看起來很漂亮,橙色三角形上的陰影仍然正常,但紅色三角形上的陰影看起來非常難看。

陰影使用this code作爲示例中創建:

var defs = svg.append("defs").attr("height","160%"); 
var filter = defs.append("filter").attr("id", "schaduw"); 
filter.append("feGaussianBlur").attr("in", "SourceAlpha") 
     .attr("stdDeviation", 5).attr("result", "blur"); 
filter.append("feOffset").attr("in", "blur") 
     .attr("dx", 3) 
     .attr("dy", 3) 
     .attr("result", "offsetBlur"); 
var feMerge = filter.append("feMerge"); 
feMerge.append("feMergeNode").attr("in", "offsetBlur"); 
feMerge.append("feMergeNode").attr("in", "SourceGraphic"); 

如在的jsfiddle碼中可以看出,形狀之間的唯一有意義的區別是它們的大小。我怎樣才能防止小的形狀有醜陋的陰影?

任何幫助非常感謝! =)

回答

0

您引用的陰影質量由您使用的高斯模糊的標準偏差控制。在這裏使用絕對值意味着無論您使用過濾器的元素的大小如何,陰影都是「分散」的。對於較小的形狀,這有你看到的效果。

有兩種方法可以解決這個問題。快速簡便的方法是降低標準偏差,使其即使對於最小的形狀也很好看。我已經通過設置.attr("stdDeviation", 1)在您的示例here中完成了此操作。

另一種選擇是針對不同的形狀尺寸有不同的標準偏差,因爲我用哈克的方式完成了here。這會更困難,因爲它需要您計算形狀的大小,確定合適的標準偏差,並可能創建適當的過濾器(如果不存在)。此外,陰影看起來不太一致。

1

您的陰影正在被基礎SVG濾鏡的濾鏡區域裁剪。默認過濾器效果顯示在過濾形狀周圍的10%溢出區域中。您在較小形狀上的陰影太大,並且溢出該區域。這是造成邊緣。你需要添加一個明確的過濾區域並使其更大。這將擴大過濾區周圍形狀的20%區域:

var filter = defs.append("filter").attr("id", "schaduw") .attr("width", 1.4) 
    .attr("height",1.4) .attr("x",-0.2) .attr("y",-0.2); 

如果你想有一個影子是成正比的過濾元素,你並不需要計算的任何大小。 SVG具有通過在objectBoundingBox單位中定義單位來進行相對大小調整的內置功能。這裏您應該使用objectBoundingBox單位作爲您的過濾器基元單位,而不是userSpaceUnits(「常規」視框單位)的(默認)默認值。您需要重申模糊的stdDeviation,還有的偏移量在%'的原始元素箱的偏移S以小數表示:

var filter = defs.append("filter").attr("id", "schaduw") .attr("width", 1.4) 
    .attr("height",1.4) .attr("x",-0.2) .attr("y",-0.2)  
    .attr("primitiveUnits","objectBoundingBox"); 
filter.append("feGaussianBlur").attr("in", "SourceAlpha") 
       .attr("stdDeviation", .02).attr("result", "blur"); 
filter.append("feOffset").attr("in", "blur") 
       .attr("dx", .01) 
       .attr("dy", .01) 
       .attr("result", "offsetBlur"); 
var feMerge = filter.append("feMerge"); 
feMerge.append("feMergeNode").attr("in", "offsetBlur"); 
feMerge.append("feMergeNode").attr("in", "SourceGraphic"); 

現在,你會發現,這個看起來有點奇怪 - 因爲只要你想讓所有的形狀看起來像是在同一個平面上,你的陰影大小應該在整個形狀上保持一致,不管它們有多大或多小。

相關問題