使用javascript放大选定的svg元素

时间:2014-08-05 09:56:42

标签: javascript svg zoom

我正在开发一个需要放大,缩小和平移的应用程序。我已经使用svg。

的viewBox属性实现了所有这些功能

我当前的放大效果很好,但它会向屏幕中心缩放。我想为所选元素添加Zoom的其他功能。我知道我可以将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();

1 个答案:

答案 0 :(得分:0)

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

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

尝试在Firefox上运行。点击中心绿色圆圈缩小,红色圆圈放大。可能你会有所了解。