1

i am working on an application which require Zoom In, Zoom out and Panning. I have achieved all these functionality using viewBox property of svg.

My current Zoom In works fine but it zoom toward the center of screen. I want to add additional functionality of Zoom in toward a selected element. I know i can set viewBox to the selected element bbox values, but i want sequential/smooth zoom in which does not conflict with my current/default zoom in.

how i can achieve this?

here is jsfiddle for the sample code:- http://jsfiddle.net/55G9c/

HTML Code

<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 Code

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 Answer 1

1

Here's an example that shows an SVG file with a zoom/pan control.

It sets the currentScale and currentTranslate attributes on the SVG root element to perform zooming/panning.

try running on firefox. click the center green circle to zoom out and red circle to zoom in. Probably you'll get some idea.

7
  • thanks for your reply, but thats not what i am looking for, i already achieved zoom pan using vieBox, kindly read question above
    – RashFlash
    Commented Aug 18, 2014 at 10:13
  • 1
    I tried... you don't have to minus vote my answer. :(
    – xxbinxx
    Commented Aug 18, 2014 at 10:56
  • @xK0nB1n I did -1 because it is obvious that you didn't even read the title of the question, let alone the text of the question which does already has a solution for the task you try to solve with your question.
    – tobltobs
    Commented Feb 3, 2017 at 8:36
  • @tobltobs I'll try again :) I posted the zoom in and zoom out functionality to give him some idea. I guess you wanted me to post a exact answer.
    – xxbinxx
    Commented Nov 20, 2017 at 5:55
  • 1
    Something is wrong with your sample @xxbinxx get lots of console errors Commented Jul 21, 2020 at 23:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.