Add support for right-down arrows
This commit is contained in:
+126
-38
@@ -13,7 +13,39 @@
|
||||
}
|
||||
|
||||
@function calcArrowHeight($length) {
|
||||
@return 2px + ($row-offset * $length) + ($icon-size * ($length - 1))
|
||||
@return 2px + ($row-offset * $length) + ($icon-size * ($length - 1));
|
||||
}
|
||||
|
||||
@mixin arrow-left {
|
||||
background-image: url('../images/arrows/left.png');
|
||||
background-position: center left;
|
||||
|
||||
&.arrow--active {
|
||||
background-image: url('../images/arrows/left-active.png');
|
||||
}
|
||||
|
||||
// Cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: -3px + calcLeftOffset($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin arrow-right {
|
||||
background-image: url('../images/arrows/right.png');
|
||||
background-position: center right;
|
||||
|
||||
&.arrow--active {
|
||||
background-image: url('../images/arrows/right-active.png');
|
||||
}
|
||||
|
||||
// Cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: 3px + calcRightOffset($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.arrow {
|
||||
@@ -40,35 +72,11 @@
|
||||
}
|
||||
|
||||
&--right {
|
||||
background-image: url('../images/arrows/right.png');
|
||||
background-position: center right;
|
||||
|
||||
&.arrow--active {
|
||||
background-image: url('../images/arrows/right-active.png');
|
||||
}
|
||||
|
||||
// Cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: 3px + calcRightOffset($i);
|
||||
}
|
||||
}
|
||||
@include arrow-right()
|
||||
}
|
||||
|
||||
&--left {
|
||||
background-image: url('../images/arrows/left.png');
|
||||
background-position: center left;
|
||||
|
||||
&.arrow--active {
|
||||
background-image: url('../images/arrows/left-active.png');
|
||||
}
|
||||
|
||||
// Cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: -3px + calcLeftOffset($i);
|
||||
}
|
||||
}
|
||||
@include arrow-left()
|
||||
}
|
||||
|
||||
&--down {
|
||||
@@ -83,7 +91,7 @@
|
||||
// Rows
|
||||
@for $i from 0 through 6 {
|
||||
&[data-row="#{$i}"] {
|
||||
top: 40px + baseRowTopOffset($i);
|
||||
top: $icon-size + baseRowTopOffset($i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,23 +110,103 @@
|
||||
}
|
||||
}
|
||||
|
||||
&--right-down {
|
||||
// Horizontal
|
||||
::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: $arrow-width;
|
||||
background-image: url('../images/arrows/rightdown.png');
|
||||
background-position: center right;
|
||||
&--right-down,
|
||||
&--left-down {
|
||||
// Position based on row
|
||||
@for $i from 0 through 6 {
|
||||
&[data-row="#{$i}"] {
|
||||
top: 12px + baseRowTopOffset($i);
|
||||
|
||||
&:after {
|
||||
top: $arrow-width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical
|
||||
::after {
|
||||
// Width
|
||||
@for $i from 0 through 3 {
|
||||
&[data-width="#{$i}"] {
|
||||
width: 2px + ($icon-size * $i);
|
||||
}
|
||||
}
|
||||
|
||||
// Height
|
||||
@for $i from 0 through 3 {
|
||||
&[data-height="#{$i}"] {
|
||||
height: 8px + ($row-offset + ($icon-size * .5)) * $i;
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: $arrow-width;
|
||||
}
|
||||
|
||||
// Arrow down
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: $arrow-width;
|
||||
top: $arrow-width;
|
||||
right: 0;
|
||||
bottom: -3px;
|
||||
background-image: url('../images/arrows/down.png');
|
||||
background-position: center bottom;
|
||||
}
|
||||
}
|
||||
|
||||
&--right-down {
|
||||
// Positioning based on cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: 2px + calcRightOffset($i);
|
||||
}
|
||||
}
|
||||
|
||||
&.arrow--active {
|
||||
&:before { background-image: url('../images/arrows/rightdown-active.png'); }
|
||||
&:after { background-image: url('../images/arrows/down-active.png'); }
|
||||
}
|
||||
|
||||
// Arrow to the right
|
||||
&:before {
|
||||
background-image: url('../images/arrows/rightdown.png');
|
||||
background-position: center right;
|
||||
}
|
||||
|
||||
// Arrow down
|
||||
&:after {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--left-down {
|
||||
// Positioning based on cols
|
||||
@for $i from 0 through 3 {
|
||||
&[data-col="#{$i}"] {
|
||||
left: -2px + calcLeftOffset($i);
|
||||
}
|
||||
}
|
||||
|
||||
&.arrow--active {
|
||||
&:before { background-image: url('../images/arrows/leftdown-active.png'); }
|
||||
&:after { background-image: url('../images/arrows/down-active.png'); }
|
||||
}
|
||||
|
||||
// Arrow to the left
|
||||
&:before {
|
||||
background-image: url('../images/arrows/leftdown.png');
|
||||
background-position: center left;
|
||||
}
|
||||
|
||||
// Arrow down
|
||||
&:after {
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-10
@@ -8,23 +8,40 @@ interface Props {
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
export const Arrow: FC<Props> = ({ from, to, active = false }) => {
|
||||
const length = to.row === from.row
|
||||
? Math.abs(to.col - from.col)
|
||||
: to.row - from.row
|
||||
const getDirection = (from: TalentData, to: TalentData): string => {
|
||||
if (to.row > from.row && to.col === from.col) {
|
||||
return 'down'
|
||||
} else if (to.row === from.row && to.col > from.col) {
|
||||
return 'right'
|
||||
} else if (to.row === from.row && to.col < from.col) {
|
||||
return 'left'
|
||||
} else if (to.row > from.row && to.col === from.col + 1) {
|
||||
return 'right-down'
|
||||
} else if (to.row > from.row && to.col === from.col - 1) {
|
||||
return 'left-down'
|
||||
}
|
||||
throw new Error(`Could not determine direction from (row ${from.row}, col ${from.col}) to (row ${to.row}, col ${to.col})`)
|
||||
}
|
||||
|
||||
export const Arrow: FC<Props> = ({ from, to, active = false }) => {
|
||||
const props = {
|
||||
'data-col': from.col,
|
||||
'data-row': from.row,
|
||||
'data-length': length,
|
||||
}
|
||||
|
||||
const className = classNames('arrow', {
|
||||
const height = to.row - from.row
|
||||
const width = Math.abs(to.col - from.col)
|
||||
|
||||
const dir = getDirection(from, to)
|
||||
if (dir === 'right-down' || dir === 'left-down') {
|
||||
props['data-height'] = height
|
||||
props['data-width'] = width
|
||||
} else {
|
||||
props['data-length'] = to.row === from.row ? width : height
|
||||
}
|
||||
|
||||
const className = classNames('arrow', `arrow--${dir}`, {
|
||||
'arrow--active': active,
|
||||
'arrow--down': to.row > from.row,
|
||||
'arrow--right': to.row === from.row && to.col > from.col,
|
||||
'arrow--left': to.row === from.row && to.col < from.col,
|
||||
'arrow--right-down': to.row === from.row + 1 && to.col === from.col + 1
|
||||
})
|
||||
|
||||
return <div className={className} {...props} />
|
||||
|
||||
@@ -38,10 +38,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
&--loading {
|
||||
.icon__bg {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__bg {
|
||||
position: absolute;
|
||||
background-size: cover;
|
||||
border-radius: 5px;
|
||||
opacity: 1;
|
||||
transition: all 100ms ease-out;
|
||||
}
|
||||
|
||||
&__frame {
|
||||
|
||||
+15
-11
@@ -1,4 +1,4 @@
|
||||
import React, { FC } from 'react'
|
||||
import React, { FC, useState, useEffect } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import './Icon.scss'
|
||||
|
||||
@@ -9,21 +9,25 @@ interface Props {
|
||||
}
|
||||
|
||||
export const Icon: FC<Props> = ({ name, size = 'medium', golden = false, children }) => {
|
||||
const className = classNames(
|
||||
'icon',
|
||||
`icon--${size}`, {
|
||||
'icon--golden': golden
|
||||
}
|
||||
)
|
||||
const [hasLoadedImage, setHasLoadedImage] = useState(false)
|
||||
|
||||
const bgSize = size === 'medium' ? 'large' : 'medium'
|
||||
const bgStyle = {
|
||||
backgroundImage: `url(https://wow.zamimg.com/images/wow/icons/${bgSize}/${name}.jpg)`
|
||||
}
|
||||
const url = `https://wow.zamimg.com/images/wow/icons/${bgSize}/${name}.jpg`
|
||||
|
||||
useEffect(() => {
|
||||
const img = new Image()
|
||||
img.onload = () => setHasLoadedImage(true)
|
||||
img.src = url
|
||||
}, [])
|
||||
|
||||
const className = classNames('icon', `icon--${size}`, {
|
||||
'icon--golden': golden,
|
||||
'icon--loading': !hasLoadedImage
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="icon__bg" style={bgStyle} />
|
||||
<div className="icon__bg" style={{ backgroundImage: `url(${url})` }} />
|
||||
<div className="icon__frame" />
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -14,6 +14,7 @@ interface Props {
|
||||
|
||||
export const TalentTree: React.FC<Props> = ({ specId, knownTalents, availablePoints, onTalentPress }) => {
|
||||
const talents = Object.values(talentsBySpec[specId])
|
||||
const bgImg = require(`../images/specs/${specId}.jpg`)
|
||||
|
||||
const handleClick = useCallback(
|
||||
(talentId) => onTalentPress(specId, talentId, 1),
|
||||
@@ -24,12 +25,8 @@ export const TalentTree: React.FC<Props> = ({ specId, knownTalents, availablePoi
|
||||
[specId, onTalentPress]
|
||||
)
|
||||
|
||||
const bodyStyle = {
|
||||
backgroundImage: `url(${require(`../images/specs/${specId}.jpg`)})`
|
||||
}
|
||||
|
||||
const arrows = talents
|
||||
.filter((talent) => talent.requires.length > 0)
|
||||
.filter((talent) => talent.requires.length)
|
||||
.map((talent) => {
|
||||
return <Arrow
|
||||
key={talent.id}
|
||||
@@ -45,7 +42,7 @@ export const TalentTree: React.FC<Props> = ({ specId, knownTalents, availablePoi
|
||||
<h3>{specNames[specId]} ({getPointsInSpec(specId, knownTalents)})</h3>
|
||||
</div>
|
||||
|
||||
<div className="tree__body" style={bodyStyle}>
|
||||
<div className="tree__body" style={{ backgroundImage: `url(${bgImg})` }}>
|
||||
{talents.map((talent) =>
|
||||
<TalentSlot
|
||||
key={talent.id}
|
||||
|
||||
Reference in New Issue
Block a user