【发布时间】:2021-05-28 23:45:54
【问题描述】:
下面的 React 组件应该允许平移 SVG。确实如此,但由于某种原因,SVG 的移动呈指数级加速,因此鼠标指针的几个像素移动会导致 SVG(或者更确切地说,SVG 视图框)的移动越来越大。例如,轻轻拖动鼠标,圆圈就会从屏幕上拉开。
这里有一个小提琴:https://jsfiddle.net/bupham/ax473r52/4/
似乎可能会发生一些 React 反馈循环,但我不确定。平移行为代码来自另一个 SO 帖子 here。
我尝试将方法调用移至容器或 SVG,但它仍然会发生。我尝试将函数传递给 setState,但仍然会发生。我尝试制作 state.viewBox 的浅拷贝而不是制作浅拷贝——仍然发生。我做错了什么?
export default class SVGContainer extends React.Component {
constructor(props) {
super(props);
this.state= {
viewBox: {x:0,y:0,w:500,h:500},
svgSize: {w: 500, h: 500},
scale: 1,
isPanning: false,
startPoint: {x:0,y:0},
endPoint: {x:0,y:0},
}
}
handleMouseDown = (e) => {
console.log('handleMouseDown e', e)
this.setState({
isPanning: true,
startPoint: {x: e.clientX, y: e.clientY},
})
}
handleMouseMove = (e) => {
this.setState((prevState, props) => {
if (prevState.isPanning) {
console.log('handleMouseMove e', e.clientX, e.clientY)
let startPoint = prevState.startPoint;
const scale = prevState.scale;
const viewBox = prevState.viewBox;
const endPoint = {x: e.clientX, y: e.clientY};
const dx = (startPoint.x - endPoint.x) / scale;
const dy = (startPoint.y - endPoint.y) / scale;
const newViewbox = {x:viewBox.x+dx, y:viewBox.y+dy, w:viewBox.w, h:viewBox.h};
console.log('the view box', newViewbox)
return {viewBox: newViewbox};
}
})
}
handleMouseUp = (e) => {
if (this.state.isPanning){
let startPoint = this.state.startPoint;
const scale = this.state.scale;
const viewBox = this.state.viewBox;
const endPoint = {x: e.clientX, y: e.clientY};
var dx = (startPoint.x - endPoint.x)/scale;
var dy = (startPoint.y - endPoint.y)/scale;
const endViewBox = {x: viewBox.x+dx, y: viewBox.y+dy, w: viewBox.w, h: viewBox.h};
console.log('viewbox at mouseup',endViewBox)
this.setState({
viewBox: endViewBox,
isPanning: false,
});
}
}
handleMouseLeave = (e) => {
this.setState({
isPanning: false,
})
}
render() {
return (
<div className="container" >
<svg width="500" height="500"
onWheel={this.handleWheelZoom}
onMouseDown={this.handleMouseDown}
onMouseMove={this.handleMouseMove}
onMouseUp={this.handleMouseUp}
onMouseLeave={this.handleMouseLeave}
viewBox={`${this.state.viewBox.x} ${this.state.viewBox.y} ${this.state.viewBox.w} ${this.state.viewBox.h}`}>
<circle cx="50" cy="50" r="50" />
</svg>
</div>
);
}
}
【问题讨论】: