我希望能够创建一个 SVG,它在背景中有一个(正常)图像,在某个地方有一个不同的较小图像,它的 4 个“边缘”移动以创建一个非矩形形状。类似于扭曲图像以创建透视图。
在 SVG 中可以吗?如果不是,是否有可能在 CSS 中以一种在页面的非固定元素中可见的方式?
我发现了一些 CSS 透视图,但它使用了 X、Y、Z,当我真的只需要在预定义的非平行边“盒子”中调整(扭曲)图像时。
最佳答案
从理论上讲,有一种方法可以使用 SVG 1.1 创建您需要的失真类型。它依赖于 <feDisplacementMap>
filter element .
如果您想探索它,我在下面提供了示例代码。但是,除了好奇之外,我不会推荐它。根据我的测试,该代码目前仅在 Chrome(以及可能相关的浏览器)中给出了预期的结果。 Internet Explorer 会扭曲图像,但略有不同。实际上,我让它在 I.E. 中使用略有不同的代码,但在 Chrome 中却没有。 Firefox 不支持使用 <feImage>
过滤元素以从 SVG 导入片段,因此测试用例失败;如果您将 map 渐变创建为单独的图像文件,它应该可以工作。渲染质量也很差,因为您使用像素操作扭曲了图像。
linearGradient {
color-interpolation:linearRGB;
}
<svg height="400px" width="400px">
<defs>
<linearGradient id="red-grad" x2="0" y2="100%">
<stop offset="0" stop-color="#F00" />
<stop offset="1" stop-color="#000" />
</linearGradient>
<linearGradient id="mask-grad" x2="100%" y2="0">
<stop offset="0" stop-opacity="0" stop-color="white" />
<stop offset="1" stop-opacity="1" stop-color="white" />
</linearGradient>
<mask id="mask">
<rect fill="url(#mask-grad)"
height="100%" width="100%"/>
</mask>
<rect id="red-rect" fill="url(#red-grad)" mask="url(#mask)"
height="100%" width="100%"/>
<filter id="perspective" primitiveUnits="objectBoundingBox"
x="-50%" y="-50%" width="200%" height="200%">
<feImage xlink:href="#red-rect" result="red" />
<feFlood flood-color="black" result="black" />
<feComposite operator="over" in="red" in2="black"
result="map"/>
<feDisplacementMap in="SourceGraphic" in2="map"
yChannelSelector="R"
xChannelSelector="G"
scale="1.1" />
</filter>
</defs>
<g style="opacity:0.5">
<image id="pic" height="100%" width="100%" xlink:href="http://upload.wikimedia.org/wikipedia/commons/thumb/2/24/Iglesia_de_Santiago_Tlatelolco%2C_M%C3%A9xico_D.F.%2C_M%C3%A9xico%2C_2013-10-16%2C_DD_38.JPG/320px-Iglesia_de_Santiago_Tlatelolco%2C_M%C3%A9xico_D.F.%2C_M%C3%A9xico%2C_2013-10-16%2C_DD_38.JPG"
/>
</g>
<g transform="scale(0.7 0.5)skewY(4)">
<use y="25%" xlink:href="#pic" filter="url(#perspective)" />
</g>
</svg>
<p>Image by <a href="http://commons.wikimedia.org/wiki/File:Iglesia_de_Santiago_Tlatelolco,_M%C3%A9xico_D.F.,_M%C3%A9xico,_2013-10-16,_DD_38.JPG">Diego Dielso, via Wikimedia Commons.</a></p>
相反,正如 Robert Longson 在评论中建议的那样,最好的方法是使用 3D transforms来营造透视效果。大多数浏览器(最新版本)现在支持对 HTML 图像进行 3D 转换,尽管您需要使用 -webkit- 前缀复制声明。
如果您在 CSS 代码中声明,许多浏览器(IE 除外)也将支持 SVG 元素的 3D 转换。然而,transform-origin
SVG 不支持属性;最好保留默认值(SVG 坐标系原点,与 SVG1.1 变换相同),并使用其他变换来获得您想要的效果。
片段的解释,对于那些好奇的人:
两个渐变、 mask 、矩形和前三个滤镜元素都只是创建二维黑色到红色渐变(右上角为红色,左侧和底部为黑色。这就是 IE 的问题所在——不同元素的大小不正确,所以大部分图像最终都是黑色的。我必须将
color-interpolation
属性设置为linearRGB
,以便红色 channel 的值平滑增加基于数值,而不是进行 Gamma 校正。如上所述,您可以将 map 渐变创建为单独的图像文件,并将其导入到具有单个<feImage>
元素的滤镜中,然后 Firefox 也支持该效果.feDisplacementMap
过滤器元素获取in
中的每个像素图形,并根据in2
中对应像素的颜色值进行移动图形(黑色和红色渐变)。 y 位移设置为使用贴图的红色值,而 x 位移使用绿色值(对于整个红黑渐变将为零)。第一个图像元素是半透明背景。
此图像随后被复制到
<use>
中元素,并应用过滤器。一组额外的变换用于缩放图像并调整整体倾斜(倾斜),以便透视失真看起来相当居中。
关于css - 如何将 SVG(或 CSS)中的图像转换为非平行四边形形状?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27108793/