React.js & Node.js open source developer
📦 NPM
:eyes: A React component that adds pan and zoom features to SVG
Home Page: https://chrvadala.github.io/react-svg-pan-zoom/
License: MIT License
Is it possible to load an external SVG file?
Hi,
thanks for this great library, as it provide just enough functionalities for me. One issue I am facing is, with the tool being selected (pan / zoom), it still interact with the child elements. I cannot reproduce it in the example, as I changed the rect to
<rect
x="400"
y="40"
width="100"
height="200"
fill="#4286f4"
stroke="#f4f142"
onClick={this.onClick}
/>
and the onClick
only triggers if tool is not set.
I have exactly same code which ReactSVGPanZoom
wraps my components, but it allow interaction with tool being set. But, if I set a breakpoint at features/interactions.js
,
event.preventDefault();
return nextValue;
then it hits the breakpoint, and never triggers child component click handler (expected behavior).
if I remove the bk point at features/interactions.js
, it calls child click handler!!!
so, kinda timing like issue. From your experience, can you suggest why I see this behavior.
Else, I may move to controlled component and disable interaction explicitly if tool selected.
thanks again,
bsr
Just thought these might be nice to have. In our implementation, we would like to know when a user clicks the toolbar so that we can show some messaging or tooltip popup.
So maybe we could add:
onClick
, onMouseEnter
, onMouseLeave
, onMouseOver
?
the rect that is under the rendered SVG has a wrong size
https://github.com/chrvadala/react-svg-pan-zoom/blob/master/src/viewer.js#L229-L230
Hey there! Thank you for this incredibly useful component, its been a huge help for a project I'm working on. I encountered a problem, though - When the primary component's props are set below, the pinch gesture works (on a macbook air's trackpad) as it does by default (zooming the whole page) instead of zooming just the SVG (on OSX, in updated chrome):
<ReactSVGPanZoom
detectWheel={false}
detectPinchGesture={true} />
This feels somewhat counter-intuitive at a minimum, but also makes it so that if you want pinch-to-zoom, you have to enable scroll-to-zoom, which doesn't work for the UX on my project. I'm currently investigating this issue, and if I can figure it out, I'll put up a PR, but wanted to see if anybody else had an answer/if anybody else encountered this bug.
hi, i am using matrix transformation to rotate svg - calculate custom a,b,c,d,e,f from original to rotate and setValue it to Viewer.
When it's rotated, and you try to pan, the svg jumps to center, because of autoPanIfNeeded method, and you cant move outside of viewbox on some sides.
thats how i rotate matrix:
const multiply = (A, B) => ({
a: A.a*B.a+A.c*B.b,
b: A.b*B.a+A.d*B.b,
c: A.a*B.c+A.c*B.d,
d: A.b*B.c+A.d*B.d,
e: A.a*B.e+A.c*B.f+A.e,
f: A.b*B.e+A.d*B.f+A.f,
});
const getRotationMatrix = (degree) => ({
a: Math.round(Math.cos(degree)),
b: Math.round(Math.sin(degree)),
c: -Math.round(Math.sin(degree)),
d: Math.round(Math.cos(degree)),
e: 0,
f: 0,
});
const getTranslationMatrix = (x, y) =>
({ a: 1, b: 0, c: 0, d: 1, e: x, f: y });
/**
* Rotates the given SVG by transforming it's matrix
* @param {number} rads - radians to rotate the SVG by
* @param {object} SVG - object containing:
* a, b, c, d, e, f attributes describing the SVG transform matrix
* SVGWidth, SVGHeight - size of the SVG
* @returns the given SVG object with adjusted matrix attributes. (rotated SVG)
*/
export const rotate = (rads, SVG) => {
let m = {a: SVG.a, b: SVG.b, c: SVG.c, d: SVG.d, e: SVG.e, f: SVG.f};
m = multiply(m, getTranslationMatrix(SVG.SVGWidth/2, SVG.SVGHeight/2));
m = multiply(m, getRotationMatrix(rads));
m = multiply(m, getTranslationMatrix(-SVG.SVGWidth/2, -SVG.SVGHeight/2));
return Object.assign({}, SVG, m);
};
In my opinion it would be nice if there were possibility to disable autoPanIfNeeded by props.
Is there a better possibility to rotate svg ?
If you are focused on an input element outside of SVG, and there is a blur event listener on that input. Clicking the SVG does not fire the blur event handler on the input and does not lose focus.
event.preventDefault()
on mousedown events seems to interfere with this.
src/features/interactions.js: 48
- in function onMouseDown
Everything seems to work as expected when I remove the preventDefault().
Is there a specific reason to call event.preventDefault() on all the mouse events?
I got the following code:
<ReactSVGPanZoom
width={1010}
height={660}
toolbarPosition="right"
miniaturePosition="none"
className="world-map"
background="#81d6ff"
>
{worldMap}
</ReactSVGPanZoom>
where worldMap
is an SVG with a viewbox of 0 0 1010 660
and tons of paths.
On load I get the following warning:
warning.js?6327:35 Warning: Failed prop type: SVG should have props `width` and `height`
in t (created by Home)
in Home (created by Connect(Home))
in Connect(Home) (created by Route)
in Route (created by Router)
in div (created by Layout)
in div (created by Layout)
in Layout (created by Connect(Layout))
in Connect(Layout) (created by Router)
in Router (created by BrowserRouter)
in BrowserRouter (created by Router)
in Router (created by App)
in Provider (created by App)
in App
Which is fine as it's just a warning and has no repercutions over behavior. After the map SVG loads, I zoom using the scroll wheel and things work perfectly fine. However if I click the toolbar button to reset the zoom to the original value, I get the following error.
Error: <g> attribute transform: Expected number, "matrix(NaN,NaN,NaN,NaN,…".
which seems to be coming from DOMPropertyOperations.js?cedd:141
At this point, zooming in or out stops working, no matter if I want to do it with the toolbar or the scroll wheel.
The bug can be reproduced at https://mmellado.github.io/visitedcountries/ (FB login required, sorry about that), however, the full code can be found in http://github.com/mmellado/visitedcountries
Is this a legitimate bug or am I not using the component properly?
Thanks!
Hey, I am trying to run example with my SVG and get this errors
Warning: If(...): No
rendermethod found on the returned component instance: you may have forgotten to define
render, returned null/false from a stateless component, or tried to render an element whose type is a function that isn't a React component.
ReactCompositeComponent.js:587 Uncaught TypeError: inst.render is not a function at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:587) at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:607) at ReactCompositeComponentWrapper.wrapper [as _renderValidatedComponent] (ReactPerf.js:66) at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:220) at ReactCompositeComponentWrapper.wrapper [as mountComponent] (ReactPerf.js:66) at Object.mountComponent (ReactReconciler.js:37) at ReactDOMComponent.mountChildren (ReactMultiChild.js:241) at ReactDOMComponent._createContentMarkup (ReactDOMComponent.js:591) at ReactDOMComponent.mountComponent (ReactDOMComponent.js:479) at Object.mountComponent (ReactReconciler.js:37)
Hi,
I'm trying to display a diagram with a lot of elements, which shall be interacted with. The problem is that the group, in which the my original Diagram gets wrapped in has the style="pointer-events: none;"
So there is no mouse interaction with elements within that group.
Example:
const style = { pointerEvents: "all" };
<ReactSVGPanZoom ref={ref => this.elRefs.panZoomRoot = ref} width={this.props.width} height={this.props.height}
toolbarPosition="none"
className="diagram-pane-pan-zoom-root"
tool="pan"
style={style}
>
Renders as:
<div style="position: relative; width: 712px; height: 832px;">
<svg width="712" height="832" style="cursor: -webkit-grab; pointer-events: all;">
<rect fill="#616264" x="0" y="0" width="712" height="832" style="pointer-events: none;"></rect>
<g transform="matrix(0.4772809502278394, 0, 0, 0.4772809502278394, -1037.1809629679985, 64.83617277676811)" style="pointer-events: none;">
<rect fill="#fff" x="0" y="0" width="10434" height="2451"></rect>
...
As you can see the group itself has a style="pointer-events: none;"
. So there is no mouse interaction with anything inside that group.
It would be great if there was a way to control the styles, not only of the surrounding svg-element, but also of the inner elements created by the component.
regards,
toolchild
When I want to define custom Miniature component based on existent Miniature from the tool, I can`t import it, but Toolbar I can.
I have made a fork when diff is only export this Component like a Toolbar. Can you accept a pull request? #54
My react app is receiving svg as response from an API call and it is currently rendered using below syntax
<span dangerouslySetInnerHTML={{__html: this.state.data.image}} />
I want to add pan-zoom features but not sure how to do it with this library. Could you please allow passing image data as props to this component or suggest any workarounds.
-thnx
Let's assume that we don't want to use the zoom tool, but we wanted to click a button and have it zoom in. Obviously this can be done because we control value and pass it to viewer. But how should it be done?
Can anyone help with this, when I try to integrate AutoSizer, it doesn't work. and shows:
Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in. Check the render method of
StadiumMap
.
And here is the code snippet in StadiumMap.js file (almost the same as the examplel
import { ReactSVGPanZoom, AutoSizer } from 'react-svg-pan-zoom';
...
render () {
return (
<AutoSizer>
{({width, height}) => width === 0 || height === 0 ? null : (
<ReactSVGPanZoom
width={512} height={384}
className="svg-pan-zoom-wrapper"
style={{ outline: "1px solid black" }}
ref={Viewer => this.Viewer = Viewer}
>
<svg ...> ... </svg>
</ReactSVGPanZoom>
)}
</AutoSizer>
)}
export default connect(mapStateToProps, { setCurSection })(StadiumMap);
Outside the componet StadiumMap, it is wrapped by
<div className="row"><div className="col-md-7"><StadiumMap /></div></div>
I tends to make rectangle svg which the width is large than the height。However , i found that when using the default settings, I got a miniature which has a width less than height.
I check the code in lib/ui-miniature/miniature.js and found :
var SVGWidth = value.SVGWidth,
SVGHeight = value.SVGHeight,
viewerWidth = value.viewerWidth,
viewerHeight = value.viewerHeight;
var ratio = SVGWidth / SVGHeight;
var miniatureHeight = miniatureWidth * ratio;
It seems you may mis calculate the ratio? I think it should be
ratio = SVGHeight/SVGWidth.
May be i have make a mistake of this code.
Hello! I am trying to put the tool on auto (as a fixed tool setting), but it throws me this warning:
Failed prop type: Invalid prop
tool
of valueauto
supplied toReactSVGPanZoom
, expected one of ["none","pan","zoom-in","zoom-out"].
Should I be calling up
tool={"auto"}
differently?
Is there a way to change the miniature mask color (not the miniature background). Currently the mask is not clearly visible with an SVG with black background.
Hi:
I've met this case when the viewer is square and a portait svg such as 500px * 800px, I invoke fitToViewer
but only got its width fitted. Could I fit entire svg inside the viewer? Thanks.
Is there any way to customize the toolbar or remove it completely?
It seems svg element will be replaced with a new one, all properties are gone. Is there a way to set a property on our own, like set a viewBox.
Would be nice to have some sort of callback to hook in to for zoom and pan events.
For example, when I pan my <svg>
"paper", I want to move an html
based menu that lies outside of the <svg>
"paper" as I pan the <svg>
paper. Currently, I have no way of knowing when the pan is occurring and when it completes.
I propose adding: onZoom
and onPan
as props for the ReactSVGPanZoom
component and passing back the scaleFactor and translateX/translateY properties respectively.
Happy to put up a PR that handles this.
Add a map, displayed in a corner, that show the full svg image
I don't seem to be able to prevent a zoom when I double click. Is there a way to disable it. Setting the onDoubleClick prop is not working for me. Thanks.
Would be nice to add a prop to the ReactSVGPanZoom
component that allows you to set the min/max scaleFactor.
Happy to put up a PR that handles this.
When using the component .zoom or .zoomOnViewerCenter, is there a way to ensure that the resulting scaling is consistent?
For example if you were you call zoomOnViewerCenter(0.9) followed by zoomOnViewerCenter(1.1), then call both methods again, you will continually move the zoom range window "outward".
Attached a screenshot of an example console output from the above test.
The second number represents the value returned from component.getValue().a
The typings file for this project defines background
prop as type React.CSSProperties
. It should be string
.
Apologies for raising the issue here and not in the DefinitelyTyped project but i'm not sure who maintains the typings file or how to contribute there
Related to #22
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.