Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add rotation function #370

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ svgPanZoom('#demo-tiger', {
, onZoom: function(){}
, beforePan: function(){}
, onPan: function(){}
, beforeRotate: function(){}
, onRotate: function(){}
, onUpdatedCTM: function(){}
, customEventsHandler: {}
, eventsListenerElement: null
Expand All @@ -135,6 +137,8 @@ If any arguments are specified, they must have the following value types:
* 'onZoom' must be a callback function to be called when zoom changes.
* 'beforePan' must be a callback function to be called before pan changes.
* 'onPan' must be a callback function to be called when pan changes.
* 'beforeRotate' must be a callback function to be called before rotation changes.
* 'onRotate' must be a callback function to be called when rotation changes.
* 'customEventsHandler' must be an object with `init` and `destroy` arguments as functions.
* 'eventsListenerElement' must be an SVGElement or null.

Expand Down Expand Up @@ -338,8 +342,12 @@ When you call `svgPanZoom` method it returns an object with following methods:
* zoomOut
* setOnUpdatedCTM
* getZoom
* rotate
* rotateRelative
* getRotate
* resetZoom
* resetPan
* resetRotate
* reset
* fit
* contain
Expand Down Expand Up @@ -380,7 +388,21 @@ panZoomTiger.zoomAtPoint(2, {x: 50, y: 50})
// Zoom by 130% at given point
panZoomTiger.zoomAtPointBy(1.3, {x: 50, y: 50})
```
To programmatically rotate, you can use the rotate method to specify your desired angle (in degrees) value:

```js
// Get instance
var panZoomTiger = svgPanZoom('#demo-tiger');

// Rotate 45 °
panZoomTiger.rotate(45)

// If rotation is 45 ° then the resulting angle will be 90°
panZoomTiger.rotateRelative(45)

// Reset rotation back to angle 0
panZoomTiger.resetRotate();
```
> Zoom is relative to initial SVG internal zoom level. If your SVG was fit at the beginning (option `fit: true`) and thus zoomed in or out to fit available space - initial scale will be 1 anyway.

Or you can use the zoomIn or zoomOut methods:
Expand Down Expand Up @@ -455,6 +477,7 @@ If you need more data about SVG you can call `getSizes`. It will return an objec
* `height`
* `x` - x offset
* `y` - y offset
* `rotate` - rotation angle in degrees

Destroy SvgPanZoom instance:

Expand Down
5 changes: 4 additions & 1 deletion demo/simple-animation.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ <h1>Demo for svg-pan-zoom: In-line SVG</h1>

intervalID = setInterval(function(){
if (animationStep++ < animationSteps) {
panZoomInstance.panBy({x: stepX, y: stepY})
panZoomInstance.panBy({x: stepX, y: stepY});
panZoomInstance.rotate(panZoomInstance.getRotate()+5);

} else {
// Cancel interval
clearInterval(intervalID)
Expand All @@ -63,6 +65,7 @@ <h1>Demo for svg-pan-zoom: In-line SVG</h1>
button.addEventListener("click", function() {
// Pan by any values from -80 to 80
customPanBy({x: Math.round(Math.random() * 160 - 80), y: Math.round(Math.random() * 160 - 80)})

});
};
</script>
Expand Down
120 changes: 113 additions & 7 deletions dist/svg-pan-zoom.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,8 @@ ShadowViewport.prototype.init = function(viewport, options) {
this.options = options;

// State cache
this.originalState = { zoom: 1, x: 0, y: 0 };
this.activeState = { zoom: 1, x: 0, y: 0 };
this.originalState = { zoom: 1, x: 0, y: 0, rotate:0 };
this.activeState = { zoom: 1, x: 0, y: 0, rotate:0 };

this.updateCTMCached = Utils.proxy(this.updateCTM, this);

Expand Down Expand Up @@ -410,6 +410,37 @@ ShadowViewport.prototype.computeRelativeZoom = function(scale) {
ShadowViewport.prototype.getPan = function() {
return { x: this.activeState.x, y: this.activeState.y };
};
/**
* Get rotate
*
* @return {Float} angle
*/
ShadowViewport.prototype.getRotate = function() {
return this.activeState.rotate
}

/**
* Get rotate transformation
*
* @return {Object} angle and point of rotation
*/
ShadowViewport.prototype.getRotateTransform = function() {
return {
angle: this.getRotate(),
x: this.getViewBox().width / 2,
y: this.getViewBox().height / 2
}
}

/**
* Set rotate
*
* @param {Float} angle
*/
ShadowViewport.prototype.rotate = function(angle) {
this.activeState.rotate = angle;
this.updateCTMOnNextFrame()
}

/**
* Return cached viewport CTM value that can be safely modified
Expand Down Expand Up @@ -554,7 +585,7 @@ ShadowViewport.prototype.updateCTM = function() {
var ctm = this.getCTM();

// Updates SVG element
SvgUtils.setCTM(this.viewport, ctm, this.defs);
SvgUtils.setCTM(this.viewport, ctm, this.defs, this.getRotateTransform());

// Free the lock
this.pendingUpdate = false;
Expand Down Expand Up @@ -619,6 +650,8 @@ var optionsDefaults = {
onZoom: null,
beforePan: null,
onPan: null,
beforeRotate: null,
onRotate:null,
customEventsHandler: null,
eventsListenerElement: null,
onUpdatedCTM: null
Expand Down Expand Up @@ -680,6 +713,16 @@ SvgPanZoom.prototype.init = function(svg, options) {
return that.options.onPan(point);
}
},
beforeRotate: function(point) {
if (that.viewport && that.options.beforeRotate) {
return that.options.beforeRotate(point);
}
},
onRotate: function(point) {
if (that.viewport && that.options.onRotate) {
return that.options.onRotate(point);
}
},
onUpdatedCTM: function(ctm) {
if (that.viewport && that.options.onUpdatedCTM) {
return that.options.onUpdatedCTM(ctm);
Expand All @@ -694,6 +737,8 @@ SvgPanZoom.prototype.init = function(svg, options) {
publicInstance.setOnZoom(this.options.onZoom);
publicInstance.setBeforePan(this.options.beforePan);
publicInstance.setOnPan(this.options.onPan);
publicInstance.setBeforeRotate(this.options.beforeRotate);
publicInstance.setOnRotate(this.options.onRotate);
publicInstance.setOnUpdatedCTM(this.options.onUpdatedCTM);

if (this.options.controlIconsEnabled) {
Expand Down Expand Up @@ -975,6 +1020,32 @@ SvgPanZoom.prototype.publicZoomAtPoint = function(scale, point, absolute) {

this.zoomAtPoint(scale, point, absolute);
};
/**
* Rotate
*
* @param {Float} angle
*/
SvgPanZoom.prototype.rotate = function(angle) {
this.viewport.rotate(angle)
}

/**
* Rotate relative
*
* @param {Float} relative angle
*/
SvgPanZoom.prototype.rotateRelative = function(angle) {
this.rotate(this.getRotate() + angle)
}

/**
* Get rotate for public usage
*
* @return {Float} rotate
*/
SvgPanZoom.prototype.getRotate = function() {
return this.viewport.getRotate()
}

/**
* Get zoom scale
Expand Down Expand Up @@ -1019,13 +1090,19 @@ SvgPanZoom.prototype.resetZoom = function() {
SvgPanZoom.prototype.resetPan = function() {
this.pan(this.viewport.getOriginalState());
};

/**
* Set rotate to initial state
*/
SvgPanZoom.prototype.resetRotate = function() {
this.rotate(this.viewport.getOriginalState().rotate);
}
/**
* Set pan and zoom to initial state
*/
SvgPanZoom.prototype.reset = function() {
this.resetZoom();
this.resetPan();
this.resetRotate();
};

/**
Expand Down Expand Up @@ -1262,6 +1339,8 @@ SvgPanZoom.prototype.destroy = function() {
this.onZoom = null;
this.beforePan = null;
this.onPan = null;
this.beforeRotate = null;
this.onRotate = null;
this.onUpdatedCTM = null;

// Destroy custom event handlers
Expand Down Expand Up @@ -1356,6 +1435,17 @@ SvgPanZoom.prototype.getPublicInstance = function() {
fn === null ? null : Utils.proxy(fn, that.publicInstance);
return that.pi;
},
// Rotate event
setBeforeRotate: function(fn) {
that.options.beforeRotate =
fn === null ? null : Utils.proxy(fn, that.publicInstance);
return that.pi;
},
setOnRotate: function(fn) {
that.options.onRotate =
fn === null ? null : Utils.proxy(fn, that.publicInstance);
return that.pi;
},
// Zoom and Control Icons
enableZoom: function() {
that.options.zoomEnabled = true;
Expand Down Expand Up @@ -1460,7 +1550,16 @@ SvgPanZoom.prototype.getPublicInstance = function() {
},
getZoom: function() {
return that.getRelativeZoom();
},
},
rotate: function(angle) {
that.rotate(angle); return that.pi
},
rotateRelative: function(angle) {
that.rotateRelative(angle); return that.pi
},
getRotate: function() {
return that.getRotate()
},
// CTM update
setOnUpdatedCTM: function(fn) {
that.options.onUpdatedCTM =
Expand All @@ -1476,6 +1575,9 @@ SvgPanZoom.prototype.getPublicInstance = function() {
that.resetPan();
return that.pi;
},
resetRotate: function() {
that.resetPan(); return that.pi
},
reset: function() {
that.reset();
return that.pi;
Expand Down Expand Up @@ -1507,7 +1609,8 @@ SvgPanZoom.prototype.getPublicInstance = function() {
width: that.width,
height: that.height,
realZoom: that.getZoom(),
viewBox: that.viewport.getViewBox()
viewBox: that.viewport.getViewBox(),
rotate: that.getRotate()
};
},
// Destroy
Expand Down Expand Up @@ -1714,7 +1817,7 @@ module.exports = {
* @param {SVGMatrix} matrix CTM
* @param {SVGElement} defs
*/
setCTM: function(element, matrix, defs) {
setCTM: function(element, matrix, defs, rotate) {
var that = this,
s =
"matrix(" +
Expand All @@ -1730,6 +1833,9 @@ module.exports = {
"," +
matrix.f +
")";
if(rotate != 0){
s += ' rotate(' + rotate.angle + ',' + rotate.x + ',' + rotate.y + ')';
}

element.setAttributeNS(null, "transform", s);
if ("transform" in element.style) {
Expand Down
2 changes: 1 addition & 1 deletion dist/svg-pan-zoom.min.js

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"keywords": [
"svg",
"pan",
"zoom"
"zoom",
"rotate"
],
"devDependencies": {
"browserify": "^16.5.0",
Expand Down
37 changes: 34 additions & 3 deletions src/shadow-viewport.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ ShadowViewport.prototype.init = function(viewport, options) {
this.options = options;

// State cache
this.originalState = { zoom: 1, x: 0, y: 0 };
this.activeState = { zoom: 1, x: 0, y: 0 };
this.originalState = { zoom: 1, x: 0, y: 0, rotate:0 };
this.activeState = { zoom: 1, x: 0, y: 0, rotate:0 };

this.updateCTMCached = Utils.proxy(this.updateCTM, this);

Expand Down Expand Up @@ -206,6 +206,37 @@ ShadowViewport.prototype.computeRelativeZoom = function(scale) {
ShadowViewport.prototype.getPan = function() {
return { x: this.activeState.x, y: this.activeState.y };
};
/**
* Get rotate
*
* @return {Float} angle
*/
ShadowViewport.prototype.getRotate = function() {
return this.activeState.rotate
}

/**
* Get rotate transformation
*
* @return {Object} angle and point of rotation
*/
ShadowViewport.prototype.getRotateTransform = function() {
return {
angle: this.getRotate(),
x: this.getViewBox().width / 2,
y: this.getViewBox().height / 2
}
}

/**
* Set rotate
*
* @param {Float} angle
*/
ShadowViewport.prototype.rotate = function(angle) {
this.activeState.rotate = angle;
this.updateCTMOnNextFrame()
}

/**
* Return cached viewport CTM value that can be safely modified
Expand Down Expand Up @@ -350,7 +381,7 @@ ShadowViewport.prototype.updateCTM = function() {
var ctm = this.getCTM();

// Updates SVG element
SvgUtils.setCTM(this.viewport, ctm, this.defs);
SvgUtils.setCTM(this.viewport, ctm, this.defs, this.getRotateTransform());

// Free the lock
this.pendingUpdate = false;
Expand Down
Loading