1.1.0 • Published 1 year ago
ray-pan-zoom v1.1.0
ray-pan-zoom
install
npm i --save ray-pan-zoom
usage
- PanAndZoom
- panZoomConnect
- zoomConnect
PanAndZoom
- basic
import PanAndZoom from 'ray-pan-zoom';
class BasicDemo extends React.PureComponent {
public render() {
return (
<PanAndZoom>
<img src={require('./../images/dog1.png')} alt="" />
</PanAndZoom>
);
}
}
- complex demo
import PanAndZoom from 'ray-pan-zoom';
import Actions from './Actions';
import { generateNormal } from './datas';
import Inner from './Inner';
class PanAndZoomDemo extends Component {
render() {
const datas = generateNormal();
return (
<PanAndZoom style={{ background: '#c8c8ff' }}>
{
datas.map(d => <Inner {...d} key={d.key} />)
}
</PanAndZoom>
);
}
}
- Inner.js
import { itemStyle } from './../style';
const Inner = ({ label, color }) => {
return (
<div style={{ ...itemStyle, background: color }}>
{label}
</div>
);
};
Inner.propTypes = {
label: PropTypes.string,
color: PropTypes.string
};
- datas.js
import { randomColor } from './../utils';
export const generateNormal = () => {
const pans = [];
const len = Math.floor(Math.random() * 10) + 1;
for (let i = 0; i < len; i++) {
pans.push({
key: `normal-${i}`,
label: `pan&zoom# ${i}`,
color: randomColor()
});
}
return pans;
};
panZoomConnect
- basic
import { panZoomConnect } from 'ray-pan-zoom';
class BasicDemo extends Component {
render() {
const { x, y, scale, width, height, ...other } = this.props;
return (
<div style={{width, height, overflow: 'hidden', border: '1px solid black'}}>
<img
style={{transform: `scale(${scale}, ${scale}) translate(${(0.5 - x) * width}px, ${(0.5 - y) * height}px`}}
width={width}
height={height}
{...other}
/>
</div>
);
}
}
const PanZoomCompoment = panAndZoomHoc(BasicDemo);
class App extends Component {
render() {
return (
<PanZoomCompoment
renderOnChange={true}
passOnProps={true}
src={require('./../images/dog0.png')}
width={400}
height={200}
/>
);
}
}
- controlled
import { panZoomConnect } from 'ray-pan-zoom';
const PanZoomDiv = panZoomConnect('div');
class App extends React.Component {
state = {
x: 0.5,
y: 0.5,
scale: 1
};
handlePanAndZoom(x, y, scale) {
this.setState({x, y, scale});
}
handlePanMove(x, y) {
this.setState({x, y});
}
render() {
const {x, y, scale} = this.state;
return (
<PanZoomDiv
x={x}
y={y}
scale={scale}
scaleFactor={Math.sqrt(2)}
minScale={1}
maxScale={2 ** 18}
onPanAndZoom={(x, y, scale) => this.handlePanAndZoom(x, y, scale)} style={{width: 250, height: 250, border: '1px solid black', position: 'relative'}}
onPanMove={(x, y) => this.handlePanMove(x, y)}
>
<div style={{position: 'absolute', top: `${y * 100}%`, left: `${x * 100}%`, width: 1, height: 1, backgroundColor: 'black'}}/>
</PanZoomDiv>
);
}
}
zoomConnect
- basic
import { zoomConnect } from 'ray-pan-zoom';
import { DemoContent } from 'ray-page-container';
import Actions from './Actions';
class PrePanZoom extends Component {
render() {
const { referencePoint, zoom, width, height, ...other } = this.props;
return (
<div style={{ width, height, overflow: 'hidden', border: '1px solid black' }}>
<img
style={{
transformOrigin: referencePoint,
transform: `scale(${zoom}`
}}
width={width}
height={height}
alt=""
{...other}
/>
</div>
);
}
}
const ZoomCompoment = zoomConnect(PrePanZoom);
class BasicDemo extends Component {
render() {
return (
<DemoContent
title={`缩放 props 设置`}
actions={<Actions />}
>
<ZoomCompoment
passOnProps
src={require('./../images/dog3.png')}
width={400}
height={200}
/>
</DemoContent>
);
}
}
export default BasicDemo;
- controlled
import { zoomConnect } from 'ray-pan-zoom';
import { DemoContent } from 'ray-page-container';
import Actions from './Actions';
const ZoomDiv = zoomConnect('div');
class ControlledDemo extends Component {
state = {
zoom: 1
};
onZoom = (zoom, e) => {
this.setState({ zoom });
}
render() {
const { x, y, zoom } = this.state;
return (
<DemoContent
title={`缩放 props 设置`}
actions={<Actions />}
>
<ZoomDiv
zoom={zoom}
min={0.5}
step={0.1}
max={2}
onZoom={this.onZoom}
style={{ width: 500, height: 500, boxSizing: 'border-box', border: '1px solid black', position: 'relative' }}
>
<div style={{ position: 'absolute', width: 50 * zoom, height: 50 * zoom, backgroundColor: 'black' }} />
{/* Axes */}
<div style={{ position: 'absolute', width: 1, height: 500, backgroundColor: 'red', transform: 'translateX(250px)' }} />
<div style={{ position: 'absolute', width: 500, height: 1, backgroundColor: 'red', transform: 'translateY(250px)' }} />
</ZoomDiv>
</DemoContent>
);
}
}
export default ControlledDemo;
- actions.js
import { ActionItem } from 'ray-page-container';
import { toNumber } from './../utils';
const zoomConfig = {
max: 3,
min: 0.1,
step: 0.1
};
const options = ['top', 'right', 'bottom', 'left', 'center', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'];
class Actions extends Component {
state = {
zoom: 1,
enableWheel: false,
origin: 'center'
};
zoom = (type) => {
let { zoom } = this.state;
zoom = toNumber(zoom);
switch (type) {
case 'zoomIn':
if (zoom < zoomConfig.max){
zoom += zoomConfig.step;
}
break;
case 'zoomOut':
if (zoom > zoomConfig.min){
zoom -= zoomConfig.step;
}
break;
default:
break;
}
this.setState({
zoom
});
this.props.onPropsChange({
type: 'zoom',
value: zoom
});
}
zooming = (e) => {
let zoom = e.target.value;
zoom = toNumber(zoom);
this.setState({
zoom
});
this.props.onPropsChange({
type: 'zoom',
value: zoom
});
}
toggleEnableWheel = (e) => {
const checked = e.target.checked;
this.setState({
enableWheel: checked
});
this.props.onPropsChange({
type: 'enableWheel',
value: checked
});
}
originChange = (e) => {
const value = e.target.value;
this.setState({
origin: value
});
this.props.onPropsChange({
type: 'referencePoint',
value
});
}
render() {
const { zoom, enableWheel, origin } = this.state;
return (
<div className="pan-zoom-action">
<ActionItem label="缩放(0.1~3)">
<input
type="range"
value={zoom}
min={zoomConfig.min}
max={zoomConfig.max}
step={zoomConfig.step}
onChange={this.zooming}
/>
</ActionItem>
<ActionItem label="缩放">
<div>
<div className="action-btn" onClick={() => this.zoom('zoomIn')}>+</div>
<div className="action-btn" onClick={() => this.zoom('zoomOut')}>-</div>
</div>
</ActionItem>
<ActionItem label="是否启用Wheel">
<input
type="checkbox"
checked={enableWheel}
onChange={this.toggleEnableWheel}
/>
</ActionItem>
<ActionItem label="origin 位置">
<select value={origin} onChange={this.originChange}>
{
options.map(o => <option key={o} value={o}>{o}</option>)
}
</select>
</ActionItem>
</div>
);
}
}
Actions.propTypes = {
onPropsChange: PropTypes.func
};
export default Actions;
props
PanAndZoom Props
params | type | default | description |
---|---|---|---|
width | number or string | - | container width. |
height | number or string | - | container height. |
className | string | - | container class name. |
zoom | number | 1 | zoom level. |
pandx | number | 0 | Provide the initial x co-ordinate to pan the underlying element to be. |
pandy | number | 0 | Provide the initial y co-ordinate to pan the underlying element to be. |
enableZoom | boolean | true | enabled zoom |
enablePan | boolean | true | enabled pan |
onPan | function: (dx, dy) => {} | () => {} | pan callback handle. |
For more information on what dx
and dy
mean please refer here
(tx == dx and ty == dy)
.
panZoomConnect props
params | type | default | description |
---|---|---|---|
x | number | 0.5 | initial x-coordinate that represents the horizontal center of the viewport |
y | number | 0.5 | initial y-coordinate that represents the vertical center of the viewport. |
scale | number | 1 | initial scale of the viewport. |
scaleFactor | number | √2 | when zooming in or out, use this factor to multiply the scale by. |
minScale | number | Number.EPSILON | minimal allowed value for the scale. |
maxScale | number | Number.POSITIVE_INFINITY | maximal allowed value for the scale. |
renderOnChange | boolean | false | if true , when panning or zooming, it will force a re-render of the component. |
passOnProps | boolean | false | if true , will pass on the x , y , and scale props to the wrapped component. If renderOnChange is also set to true this will cause the props (with updated values) to be passed on every time a pan or zoom event occurs. |
ignorePanOutside | boolean | false | if true , when the mouse exits the element the panning will stop. When the mouse re-enters the element, and the mouse button is still down, then panning will resume. |
onPanStart | function: (event) => {} | - | invoked when the component starts to pan. Receives the following arguments: event (MouseEvent): original event which triggered the panning to start. |
onPanMove | function: (x: number, y: number, event: MouseEvent) => {} | - | invoked when the component pans in the x or y direction. Receives the following arguments: x (number): new x-coordinate.y (number): new y-coordinate.event (MouseEvent): original event which triggered the panning movement. |
onPanEnd | function: (x: number, y: number, event: MouseEvent) => {} | - | invoked when the component stop panning. Receives the following arguments: x (number): new x-coordinate. y (number): new y-coordinate. event (MouseEvent): original event which triggered the panning to stop. |
onZoom | function | - | currently not used, reserved for future use. |
onPanAndZoom | function: (x: number, y: number, scale: number, event: MouseEvent) => {} | - | invoked when the component pans and zooms (for example when the mouse wheel is used). Receives the following arguments: x (number): new x-coordinate. y (number): new y-coordinate. scale (number): new scale value. event (MouseEvent): original event which triggered the pan/zoom event. |
zoomConnect Props
params | type | default | description |
---|---|---|---|
style | object | - | container style |
onZoom | function | - | currently not used, reserved for future use. |
step | number | 0.1 | zoom step. |
zoom | number | 1 | zoom value. |
min | number | Number.EPSILON | zoom min. |
max | number | Number.MAX_SAFE_INTEGER | zoom max. |
enableWheel | boolean | false | enable mouseWheel. |
passOnProps | boolean | false | if true , will pass on the reference , zoom props to the wrapped component. |
referencePoint | string | center | reference point. use transformOrigin , 'top', 'right', 'bottom', 'left', 'center', 'topLeft', 'topRight', 'bottomLeft', 'bottomRight' or other transformOrigin value |
Lecense
MIT
changelog
v1.1.0
去除低版本 react 相关方法,支持 react@16.x
所有版本