high tech resizing svg action

This commit is contained in:
ntr 2019-06-03 17:18:47 +10:00
parent 3bd72cff8f
commit 9bb251724f
3 changed files with 76 additions and 58 deletions

View File

@ -78,9 +78,7 @@ module.exports = {
// enforce that class methods use "this" // enforce that class methods use "this"
// https://eslint.org/docs/rules/class-methods-use-this // https://eslint.org/docs/rules/class-methods-use-this
'class-methods-use-this': ['error', { 'class-methods-use-this': 0,
exceptMethods: [],
}],
// require return statements to either always or never specify values // require return statements to either always or never specify values
'consistent-return': 'error', 'consistent-return': 'error',

View File

@ -81,7 +81,7 @@
} }
.game .targeting-arrows { .game .targeting-arrows {
stroke-width: 5px; stroke-width: 2px;
} }
.game-construct .targeting { .game-construct .targeting {
@ -429,8 +429,4 @@
.game .effects { .game .effects {
font-size: 100%; font-size: 100%;
} }
}
.game .targeting-arrows {
stroke-width: 1em;
}
}

View File

@ -1,6 +1,9 @@
const preact = require('preact'); const preact = require('preact');
const { Component } = require('preact');
const { connect } = require('preact-redux'); const { connect } = require('preact-redux');
const throttle = require('lodash/throttle');
const addState = connect( const addState = connect(
({ game, account, resolution }) => ({ game, account, resolution }) ({ game, account, resolution }) => ({ game, account, resolution })
); );
@ -13,43 +16,72 @@ const TC_MAP = [
TARGET_COLOURS.GREEN, TARGET_COLOURS.GREEN,
]; ];
function TargetSvg(args) { class TargetSvg extends Component {
const { game, account, resolution } = args; constructor() {
super();
this.state = { width: 3000, height: 1000 };
const playerTeam = game.players.find(t => t.id === account.id); this.onResize = throttle(() => {
const otherTeam = game.players.find(t => t.id !== account.id); console.warn('resize')
const svg = document.getElementById('targeting');
const { width, height } = svg.getBoundingClientRect();
this.setState({ width, height });
}, 500);
}
const playerTeamIds = playerTeam.constructs.map(c => c.id); render(props, state) {
const outgoing = game.stack.filter(stack => playerTeamIds.includes(stack.source_construct_id)); const { game, account, resolution } = props;
const { width, height } = state;
const WIDTH = 3000; const playerTeam = game.players.find(t => t.id === account.id);
const HEIGHT = 1000; const otherTeam = game.players.find(t => t.id !== account.id);
function getPath(cast) { const playerTeamIds = playerTeam.constructs.map(c => c.id);
const source = playerTeam.constructs.findIndex(c => c.id === cast.source_construct_id); const outgoing = game.stack.filter(stack => playerTeamIds.includes(stack.source_construct_id));
const defensive = playerTeamIds.includes(cast.target_construct_id);
const target = defensive
? playerTeam.constructs.findIndex(c => c.id === cast.target_construct_id)
: otherTeam.constructs.findIndex(c => c.id === cast.target_construct_id);
const stroke = TC_MAP[source]; function getPath(cast) {
const source = playerTeam.constructs.findIndex(c => c.id === cast.source_construct_id);
const defensive = playerTeamIds.includes(cast.target_construct_id);
const target = defensive
? playerTeam.constructs.findIndex(c => c.id === cast.target_construct_id)
: otherTeam.constructs.findIndex(c => c.id === cast.target_construct_id);
const sourceY = HEIGHT; const stroke = TC_MAP[source];
const sourceX = (source * WIDTH / 3) + WIDTH / 6;
const targetX = (target * WIDTH / 3) + WIDTH / 6 + (defensive ? WIDTH / 24 : 0); const sourceY = height;
const targetY = defensive ? HEIGHT : 0; const sourceX = (source * width / 3) + width / 6;
const curveEnd = HEIGHT * 0.25; const targetX = (target * width / 3) + width / 6 + (defensive ? width / 24 : 0);
const curveStart = HEIGHT * 0.75; const targetY = defensive ? height : 0;
const curveEnd = height * 0.25;
const curveStart = height * 0.75;
if (defensive) {
const path = `
M${sourceX},${sourceY}
L${sourceX},${height * 0.75}
L${targetX},${height * 0.75}
L${targetX},${targetY}
L${targetX - (width * 0.005)},${height * 0.875}
M${targetX},${targetY}
L${targetX + (width * 0.005)},${height * 0.875}
`;
return <path
style={ { stroke} }
d={path}
/>;
}
if (defensive) {
const path = ` const path = `
M${sourceX},${sourceY} M${sourceX},${sourceY}
L${sourceX},${HEIGHT * 0.75} L${sourceX},${curveStart}
L${targetX},${HEIGHT * 0.75} C${sourceX},${curveEnd} ${targetX},${curveStart} ${targetX},${curveEnd}
L${targetX},${targetY} L${targetX},${targetY}
L${targetX - (WIDTH * 0.005)},${HEIGHT * 0.875} L${targetX - (width * 0.005)},${height * 0.125}
M${targetX},${targetY} M${targetX},${targetY}
L${targetX + (WIDTH * 0.005)},${HEIGHT * 0.875} L${targetX + (width * 0.005)},${height * 0.125}
`; `;
return <path return <path
@ -58,33 +90,25 @@ function TargetSvg(args) {
/>; />;
} }
const path = ` const arrows = resolution
M${sourceX},${sourceY} ? null
L${sourceX},${curveStart} : outgoing.map(getPath);
C${sourceX},${curveEnd} ${targetX},${curveStart} ${targetX},${curveEnd}
L${targetX},${targetY} return (
L${targetX - (WIDTH * 0.005)},${HEIGHT * 0.125} <svg id="targeting" viewBox={`0 0 ${width} ${height}`} preserveAspectRatio="none" className="targeting-arrows">
M${targetX},${targetY} {arrows}
L${targetX + (WIDTH * 0.005)},${HEIGHT * 0.125} </svg>
);
`;
return <path
style={ { stroke} }
d={path}
/>;
} }
const arrows = resolution componentDidMount() {
? null window.addEventListener('resize', this.onResize);
: outgoing.map(getPath); this.onResize();
}
return ( componentWillUnmount() {
<svg viewBox={`0 0 ${WIDTH} ${HEIGHT}`} preserveAspectRatio="none" className="targeting-arrows"> window.removeEventListener('resize', this.onResize);
{arrows} }
</svg>
);
} }
module.exports = addState(TargetSvg); module.exports = addState(TargetSvg);