Add support for right-down arrows

This commit is contained in:
Melvin Valster
2019-07-24 13:25:57 +02:00
parent d5121960a1
commit 94a0a97fbf
6 changed files with 180 additions and 66 deletions
+126 -38
View File
@@ -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
View File
@@ -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} />
+8
View File
@@ -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
View File
@@ -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>
+3 -6
View File
@@ -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}