使用SVG是相对直接的--直到你想混合DOM和矢量交互。
在这一系列的SVG文章中,我们已经看了什么是SVG,为什么你应该考虑它们,以及你如何将它们嵌入你的网页中。我们还看了基本的绘图元素和更复杂的路径是如何工作的。
SVG有自己的坐标系统,在viewBox 属性中定义。比如说。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
这就设置了一个宽度为800单位,高度为600单位,从0,0 。这些单位是用于绘图的任意测量,也可以使用单位的零头。如果你把这个SVG定位在一个800 by600 像素的区域内,每个SVG单位应该直接映射到一个屏幕像素。
然而,矢量图像可以被缩放到任何尺寸--尤其是在响应式设计中。你的SVG可以被缩小到400 by300 ,甚至在10 by1000 的空间里被拉伸到无法辨认。如果你想根据光标的位置来放置更多的元素,那么向这个SVG添加更多的元素就会变得更加困难。
注意:请参阅Sara Soueidan的viewport、viewBox和reserveAspectRatio一文,以了解更多关于SVG坐标的信息。
避免坐标翻译
你也许可以完全避免坐标系之间的转换。
嵌入HTML页面的SVG(而不是图像或CSS背景)成为DOM的一部分,可以用与其他元素类似的方式进行操作。例如,以一个带有单个圆的基本SVG为例。
<svg id="mysvg" xmlns="https://www.w3.org/2000/svg" viewBox="0 0 800 600" preserveAspectRatio="xMidYMid meet">
<circle id="mycircle" cx="400" cy="300" r="50" />
<svg>
你可以对其应用CSS效果。
circle {
stroke-width: 5;
stroke: #f00;
fill: #ff0;
}
circle:hover {
stroke: #090;
fill: #fff;
}
你还可以附加事件处理程序来修改属性。
const mycircle = document.getElementById('mycircle');
mycircle.addEventListener('click', (e) => {
console.log('circle clicked - enlarging');
mycircle.setAttribute('r', 60);
});
下面的例子在SVG图像中添加了三十个随机的圆,在CSS中应用了悬停效果,并使用JavaScript在点击圆时将半径增加十个单位。
参见CodePen上SitePoint(@SitePoint)的Pen
SVG交互。
SVG到DOM的坐标转换
可能有必要在一个SVG元素上面叠加一个DOM元素--例如,在世界地图上显示的活动国家的菜单或信息框。假设SVG被嵌入到HTML中,元素就成为DOM的一部分,所以getBoundingClientRect()方法可以用来提取位置和尺寸。(打开上面的例子中的控制台,可以看到点击的圆在半径增加后的新属性。)
Element.getBoundingClientRect() 在所有的浏览器中都支持,并返回一个 对象,该对象具有以下像素尺寸的属性。DOMrect
.x和 :元素左边的x坐标,相对于视口原点。.left.right: 元素右边的x坐标,相对于视口原点的坐标.y.top:元素顶部相对于视口原点的y坐标。.bottom:元素底部相对于视口原点的y坐标。.width:该元素的宽度(在IE8及以下版本不支持,但与.right减去.left相同)。.height元素的高度(IE8及以下版本不支持,但与.bottom减去.top相同)。
所有的坐标都是相对于浏览器视口的,因此会随着页面的滚动而改变。页面上的绝对位置可以通过将window.scrollX 加到.left 和window.scrollY 加到.top 来计算。
SVG有自己的坐标系统。它是通过viewbox 属性定义的,例如,viewbox="0 0 800 600" ,它设置了一个宽度为800单位,高度为600单位的坐标系,从(0,0)开始。如果你将这个SVG定位在一个800×600像素的区域内,每个SVG单元直接映射到一个屏幕像素。
然而,矢量图像的魅力在于它们可以被缩放到任何尺寸。你的SVG可以在400×300的空间里被缩放,甚至可以在100×1200的空间里被拉伸到无法辨认。如果你不知道该把它们放在哪里,向SVG中添加更多的元素就变得很困难。
(SVG的坐标系统可能很混乱--Sara Soueidan的viewport、viewBox和preserveAspectRatio文章描述了这些选项。)
简单分离的SVG协同效应
你也许可以完全避免坐标系之间的转换。
嵌入到页面中的SVG(而不是图像或CSS背景)成为DOM的一部分,可以用类似于其他元素的方式进行操作。例如,给定一个带有单个圆的基本SVG。
[code language="html"]
<svg id="mysvg" xmlns="www.w3.org/2000/svg" viewBox="0 0 800 600″ preserveAspectRatio="xMidYMid meet">
<圆圈id="mycircle".circle id="mycircle" cx="400″ cy="300″ r="50″ />
[/code]
我们可以应用CSS效果。
[code language="css"]
circle {
strok-width: 5;
stroke:#f00;
fill:#ff0;
}
circle:hover {
stroke:#090;
fill:#fff;
}
[/code]
并附加事件处理程序来修改其属性。
[code language="javascript"]
var mycircle = document.getElementById('mycircle');
mycircle.addEventListener('click', function(e) {
console.log('circle clicked - enlarging');
mycircle.setAttributeNS(null, 'r', 60);
}, false);
[/code]
下面的例子在一个SVG图片上添加了三十个随机的圆圈,在CSS中应用了一个悬停效果,并使用JavaScript在点击圆圈时将半径增加十个单位。
参见CodePen上SitePoint(@SitePoint)的PenSVG交互。
SVG到DOM的坐标转换
如果我们想在一个SVG项目上叠加一个DOM元素,例如地图上的菜单或信息框,该怎么办?同样,由于我们的HTML嵌入的SVG元素构成了DOM的一部分,我们可以使用神话般的getBoundingClientRect()方法在一次调用中返回所有尺寸。打开上面的例子中的控制台,可以看到点击的圆在半径增加后的新属性。
Element.getBoundingClientRect() 所有的浏览器都支持该方法,并返回一个DOMrect对象,该对象具有以下像素尺寸的属性。
.x和 - X坐标,相对于视口原点,元素的左侧.left.right- X坐标,相对于视口原点,元素的右侧.y和 - 相对于视口原点的Y坐标,元素的顶面.top.bottom- 元素底部相对于视口原点的y坐标.width- 元素的宽度(在IE8及以下版本中不支持,但与 减去 )相同.right.left.height- 元素的高度(在IE8及以下版本中不支持,但与 减去 相同).bottom.top
继续阅读:如何从DOM翻译成SVG坐标,再返回到SitePoint上。