我正在创建一个游戏,其中会有地图和一些svg圆(代表单位/部队),上面有一些计数。单位随鼠标的位置移动。还有一个圆圈代表范围。
我有两个需求
有两个问题
以下是代码段。我已经用评论尽可能地解释了。问题中最重要的部分是onMouseMove
中的<Board />
//helper functions
//to get the difference b/w two array.(Absoulute difference)
const getAbsDist= (arr1,arr2) => arr1.map((x,i) => Math.abs(x - arr2[i]))
//to get diagonal distance coverered from vertical and horizontal distance covered
const getDiaDist = (x,y) => Math.sqrt((x*x) + (y*y));
const clone = (obj) => JSON.parse(JSON.stringify(obj)); //to clone object
class UnitBox extends React.Component {
state = {};
render() {
const {
x, //current vertical postion
y, //current horizontal position
count,
range,
moving, //determines whether a range circle will appear or not
onMouseDown,
index,
//position from which we started moving unit
_x,
_y
} = this.props;
return (
<g className="ub">
<g
onMouseDown={() => onMouseDown(index)}
transform={"translate(" + x + ',' + y + ')'}
>
<text id="one" selectable="false">{count}</text>
<circle r="15" />
<use xlinkHref="#one" />
</g>
{moving && (
<circle r={range} cx={_x} cy={_y} className="range" />
)}
</g>
);
}
}
class Board extends React.Component {
state = {
movingUnit: -1,
unitBoxes: [
{ moving: false, count: 10, x: 200, y: 100, range: 50 }
]
};
onMouseDownUnit = unitIndex => {
const state = clone(this.state),
unit = state.unitBoxes[unitIndex];
state.movingUnit = unitIndex;
unit.moving = true;
//'_x' and '_y' are the cords from where we click mouse it repesents the initial position
[unit._x, unit._y] = [unit.x, unit.y];
this.setState(state);
};
onMouseUp = e => {
const state = clone(this.state);
const unit = state.unitBoxes[this.state.movingUnit];
state.movingUnit = -1;
if (unit) unit.moving = false;
this.setState(state);
};
onMouseMove = e => {
let { movingUnit, unitBoxes } = this.state;
if (movingUnit === -1) return;
const { clientX, clientY } = e;
const unit = unitBoxes[movingUnit];
const { x, y,_x, _y, range} = unit;
//get the difference b/w initial positon and final position and last final position and get diagonal distance from that.
let dist = getDiaDist(...getAbsDist([x, y], [_x, _y]));
//if distance covered is less than range than move the object.
if(dist < range){
unit.x = parseInt(clientX);
unit.y = parseInt(clientY);
}
this.setState({ movingUnit, unitBoxes });
};
render() {
const { unitBoxes } = this.state;
return (
<svg
height="1000px"
width="1000px"
onMouseMove={this.onMouseMove}
onMouseUp={this.onMouseUp}
style={{ backgroundColor: "orange" }}
>
{unitBoxes.map((x, i) => (
<UnitBox
onMouseDown={this.onMouseDownUnit}
{...x}
index={i}
key={i}
/>
))}
</svg>
);
}
}
ReactDOM.render(<Board/>,document.getElementById('root'))
.ub text {
text-anchor: middle;
alignment-baseline: central;
font-family: sans-serif;
font-weight: bold;
font-size: 16px;
fill: #454545;
}
.ub{
cursor: pointer;
}
.ub circle {
stroke: #707070;
fill: #cacaca;
stroke-width: 2px;
}
.ub .range{
fill:green;
fill-opacity: 0.3;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 0 :(得分:1)
您可以测量与实际位置dist
的当前距离以及移动单元的最新更新位置,但是当鼠标超出有效范围时,该位置不会更新。改用鼠标指针的当前位置:
let dist = getDiaDist(...getAbsDist([clientX, clientY], [_x, _y]));
此更改将使单位保持在其范围内,但是当鼠标移至范围之外时不会更新其位置。为此,请通过沿鼠标指针的方向将单元“夹紧”到范围来处理距离大于范围的情况:
if (dist < range) {
unit.x = clientX;
unit.y = clientY;
} else {
let xx = clientX;
let yy = clientY;
let cc = range / dist;
unit.x = _x + (xx - _x) * cc;
unit.y = _y + (yy - _y) * cc;
}