如何解决在嵌套的 SVG 中使用视图框实现缩放
我的任务是在基于 SVG 的自定义图表中实现缩放。在我有一个 <svg>
元素之前。我研究了使用 transform
或 viewBox
方法并决定使用 viewBox
方法。由于我必须支持仅在 x 轴上缩放,图表内容将根据 zoomFactor
和需要 preserveAspectRatio="none"
被压缩。这对于我使用 foreignObjects
的图表标签来说并不好看。它们也变得混乱,不再可读。我没有找到关于如何将 viewBox
仅应用于实际图表内容而不是比例/标签的任何解决方案。
我想出了将图表拆分为 3 个嵌套 svg 的解决方案。结构如下:
<svg> // Container SVG
<svg>...</svg> // XAxis
<svg>...</svg> // YAxis
<svg>...</svg> // ChartContent
</svg>
viewBox
将仅应用于 ChartContent svg 并且具有实际比例的 svgs 保持不变,如果需要,只需在不同位置使用不同标签重新渲染。期望的结果类似于此示例:https://jsfiddle.net/19h83ker/1/
假设我有一个图表要显示,例如 4000 像素宽和 200 像素高,y 轴是 40 像素宽和 200 像素高,x 轴是 40 像素高和 4000 像素宽,我通常应该如何设置视口?如果我在 ContainerSVG 和 ChartContent SVG 上设置 width="100%"
和 height="100%"
,我没有可用的滚动条。如果我在 ContainerSVG 上设置 width="4040"
并在 ChartContent SVG 上设置 width="4000"
,我有一个滚动条,但是在缩小 100% 时应用 viewBox
只会将我的 svg 的宽度和右侧减半50% 留空。我真的不明白我的结构中宽度/高度的组合是什么,我应该去。或者我在一般情况下犯了一个错误?有没有更好的方法来实现预期的结果?我已经在这上面花了 2 天的时间,除了这 3 个嵌套的 svgs 之外,真的没有看到任何其他选项。在一天结束时,应该可以在 4000 像素宽的示例 SVG 图表中进行平移/缩放。
解决方法
您提到的建议涉及设置宽度和高度,然后使用默认浏览器行为进行滚动和缩放。相反,您需要拦截适当的事件并修改 viewBox 属性。
下面的代码演示了鼠标滚轮事件的缩放。平移应该更简单(只有 viewBox 的第一和第二部分需要更改),但实现取决于您要使用的 UI 控件。
svg = document.getElementById("s")
var vb = [0,300,200]
svg.setAttribute("viewBox",vb) // vb gets converted to the string "0,40"
function zoom(wheelEvent){
let k=1.005**wheelEvent.deltaY
let ctm = svg.children[0].getScreenCTM()//If the svg is empty,this won't work
// position of the mouse in svg coords
let mx = (wheelEvent.clientX-ctm.e)/ctm.a
let my = (wheelEvent.clientY-ctm.f)/ctm.d
// To center the zoom on the mouse,we need:
// (mx - initialX)/initialWidth == (mx - finalX)/finalWidth
// finalX = mx - (mx - initalX)*(finalWidth/initialWidth)
vb[0] = mx-(mx-vb[0])*k
vb[1] = my-(my-vb[1])*k
vb[2] *= k
vb[3] *= k
svg.setAttribute("viewBox",vb)
wheelEvent.preventDefault() // prevent the page from scrolling
}
svg.addEventListener("wheel",zoom)
html,body,svg{
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#s{
width: 100%;
height: 100%;
background-color: red;
}
<svg id="outer" viewBox="0 0 200 100" preserveAspectRatio="xMinYMin">
<rect x="0" y="0" width="20" height="200" />
<rect x="0" y="0" width="100%" height="20" />
<svg id="s" x="20" y="20" width="180" height="180" viewBox="0,200">
<rect x="-1000" y="-1000" width="2000" height="2000" fill="lightgray"/>
<text font-size="60" x="10" y="60" fill="blue"> hello </text>
</svg>
</svg>
如果您只想缩放 x 轴,则需要为 'preserveAspectRatio' 属性设置不同的值(以及删除更改 vb[1] 和 vb[3] 的代码)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。