javascript - 使用 javascript 缩放选定的 svg 元素

标签 javascript svg zooming

我正在开发一个需要放大、缩小和平移的应用程序。我已经使用 svg 的 viewBox 属性实现了所有这些功能。

我当前的“放大”效果很好,但它会向屏幕中心放大。我想向所选元素添加放大的附加功能。我知道我可以将 viewBox 设置为所选元素的 bbox 值,但我想要顺序/平滑放大,这与我当前/默认的放大不冲突。

我怎样才能做到这一点?

这是示例代码的 jsfiddle:- http://jsfiddle.net/55G9c/

HTML 代码

<div onclick="zoomin()" style="display: block;float: left;border: 1px solid;cursor: pointer">
            ZoomIn
        </div>
        <div onclick="zoomout()" style="display: block;float: left;border: 1px solid;cursor: pointer;margin-left: 10px">
            ZoomOut
        </div>
        <svg id="mainsvg" width="600px" height="500px" viewBox="0 0 600 500">
        <g id="gnode">
        <rect id="boundry" x="0" y="0" width="599" height="499" fill="none" stroke='black'/>
        <circle id="centernode" cx="300" cy="250" r="5" fill="red" stroke="none" />
        <rect id="selected" x="450" y="100" width="50" height="50" fill="blue" stroke='none'/>
        </g>
        </svg>

Javascript 代码

var svg=document.getElementById('mainsvg');
            var gnode=document.getElementById('gnode');
            var zoomPercentage=0.25;
            var MAXIMUM_ZOOM_HEIGHT = 1400;
            var baseBox={};
            var level=0;
            var widthRatio,heightRatio;
            var clientheight = document.documentElement.clientHeight;
            var clientwidth = document.documentElement.clientWidth;

            function setup(){
                var

                baseX,
                baseY,
                baseWidth,
                baseHeight,
                percentageDifference,
                heightDifference;

                svg.setAttribute('height', clientheight);
                svg.setAttribute('width', clientwidth);

                var boundry=document.getElementById('boundry');
                boundry.setAttribute('height', clientheight-1);
                boundry.setAttribute('width', clientwidth-1);

                var centernode=document.getElementById('centernode');
                centernode.setAttribute('cy', clientheight/2);
                centernode.setAttribute('cx', clientwidth/2);

                if (svg.height.baseVal.value >= MAXIMUM_ZOOM_HEIGHT)
                    baseHeight = MAXIMUM_ZOOM_HEIGHT;
                else
                    baseHeight = Math.round(gnode.getBBox().height) + 60;

                baseY = (svg.height.baseVal.value - baseHeight) / 2;
                percentageDifference = baseHeight / svg.height.baseVal.value;
                baseWidth = percentageDifference * svg.width.baseVal.value;
                baseX = (svg.width.baseVal.value - baseWidth) / 2;


                baseBox.x = baseX;
                baseBox.y = baseY;
                baseBox.width = baseWidth;
                baseBox.height = baseHeight;
                level = 0;

                heightDifference = MAXIMUM_ZOOM_HEIGHT - baseHeight;
                zoomPercentage = (heightDifference / 10) / heightDifference;                                

                setViewBox(baseBox);
            }
            function setViewBox(viewBox) {
                svg.viewBox.baseVal.x = Math.round(viewBox.x);
                svg.viewBox.baseVal.y = Math.round(viewBox.y);
                svg.viewBox.baseVal.width = Math.round(viewBox.width);
                svg.viewBox.baseVal.height = Math.round(viewBox.height);
                setRatios();
            }
            function setRatios () {
                widthRatio = svg.viewBox.baseVal.width / svg.width.baseVal.value;
                heightRatio = svg.viewBox.baseVal.height / svg.height.baseVal.value;
            }
            function calculateViewBox(level) {

                var
                height = baseBox.height - (zoomPercentage * level * baseBox.height),
                y = baseBox.y + (baseBox.height - height) / 2,
                width = baseBox.width - (zoomPercentage * level * baseBox.width),
                x = baseBox.x + (baseBox.width - width) / 2,
                viewBox = {
                    x: x,
                    y: y,
                    width: width,
                    height: height
                }
                return viewBox;
            }

            function zoomin(){               
                level++;
                if(level>5)
                    level=5;
                 var
                                x,
                                y,
                                paperViewBox = svg.viewBox.baseVal,
                                previousViewBox = calculateViewBox(level - 1),
                                newViewBox = calculateViewBox(level);
                                //callback = this.afterZoom;

                                if (Math.round(paperViewBox.x) > Math.round(newViewBox.x))
                                        /**
                                         * is panned left
                                         */
                                        x = paperViewBox.x - (previousViewBox.width - newViewBox.width) / 2;
                                else if (Math.round(paperViewBox.x) < Math.round(previousViewBox.x) - (Math.round(newViewBox.x) - Math.round(previousViewBox.x)))
                                        /**
                                         * is panned right
                                         */
                                        x = paperViewBox.x + (previousViewBox.width - newViewBox.width) + (previousViewBox.width - newViewBox.width) / 2;
                                else
                                        x = newViewBox.x;

                                if (Math.round(paperViewBox.y) > Math.round(newViewBox.y))
                                        /**
                                         * is panned up
                                         */
                                        y = paperViewBox.y - (previousViewBox.height - newViewBox.height) / 2;
                                else if (Math.round(paperViewBox.y) < Math.round(previousViewBox.y) - (Math.round(newViewBox.y) - Math.round(previousViewBox.y)))
                                        /**
                                         * is panned down
                                         */
                                        y = paperViewBox.y + (previousViewBox.height - newViewBox.height) + (previousViewBox.height - newViewBox.height) / 2;
                                else
                                        y = newViewBox.y;


                                var data = {
                                        viewBox: {
                                                x: x,
                                                y: y,
                                                width: newViewBox.width,
                                                height: newViewBox.height
                                        }
                                }

                                SetZoomViewBox(data);
            }

            function SetZoomViewBox(data){               
                        var viewBox = data.viewBox;

                        svg.viewBox.baseVal.x = Math.round(viewBox.x);
                        svg.viewBox.baseVal.y = Math.round(viewBox.y);
                        svg.viewBox.baseVal.width = Math.round(viewBox.width);
                        svg.viewBox.baseVal.height = Math.round(viewBox.height);
                        setRatios();

            }

            function zoomout(){
                level--;
                if(level<0)
                    level=0;
                 var
                                x,
                                y,
                                paperViewBox = svg.viewBox.baseVal,
                                previousViewBox = calculateViewBox(level + 1),
                                newViewBox = calculateViewBox(level);

                                if (Math.round(paperViewBox.x) > Math.round(previousViewBox.x) + (Math.round(previousViewBox.x) - Math.round(newViewBox.x)))
                                        /**
                                         * is panned left
                                         */
                                        x = paperViewBox.x - (newViewBox.width - previousViewBox.width);
                                else if (Math.round(paperViewBox.x) < Math.round(previousViewBox.x))
                                        /**
                                         * is panned right
                                         */
                                        x = paperViewBox.x;
                                else
                                        x = newViewBox.x;

                                if (Math.round(paperViewBox.y) > Math.round(previousViewBox.y) + (Math.round(previousViewBox.y) - Math.round(newViewBox.y)))
                                        /**
                                         * is panned up
                                         */
                                        y = paperViewBox.y - (newViewBox.height - previousViewBox.height);
                                else if (Math.round(paperViewBox.y) < Math.round(previousViewBox.y))
                                        /**
                                         * is panned down
                                         */
                                        y = paperViewBox.y;
                                else
                                        y = newViewBox.y;


                                var data = {
                                        viewBox: {
                                                x: x,
                                                y: y,
                                                width: newViewBox.width,
                                                height: newViewBox.height
                                        }
                                }

                                SetZoomViewBox(data);
            }

            setup();

最佳答案

这是一个 example显示带有缩放/平移控件的 SVG 文件。

它在 SVG 根元素上设置 currentScale 和 currentTranslate 属性以执行缩放/平移。

尝试在 firefox 上运行。单击中心的绿色圆圈可缩小,单击红色圆圈可放大。您可能会有所了解。

关于javascript - 使用 javascript 缩放选定的 svg 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25135943/

相关文章:

javascript - 拓宽职能范围

javascript - 使用 if 语句和 jquery 来限制动画

javascript - 单击时如何在两个图像之间进行转换?

html - 滚动时 Opera SVG 错误

ios - uiscrollview 放大和缩小不能正常工作

c++ - 在 QScrollArea 中缩放 QWidget

javascript - 使用 JavaScript 创建 IFRAME 的最佳做法是什么?

javascript - SVG 路径在 D3 力网络图中无法正确渲染

googleapis 中的 jquery lib 导致错误 : Invalid value for property: zoom

xml - 如何在 SVG 文件中嵌入任意文本/数据?