February 28, 2019
별점 평가 컴포넌트에 가면 데모버전 확인 가능합니다.
위 두가지 목적을 가지고 제작된 컴포넌트 입니다.
시간적 제한을 가지고 제작되어서, 코드내 잡음 주의!
yarn create react-app star-rate
# project tree
- public
- favicon.ico
- index.html
- src
- images
- reset.svg
- star-empty.svg
- star-full.svg
- star-half.svg
- App.js
- StarRate.js
- StarRate.css
- index.css
- index.js
- .gitignore
- README.md
- package.json
- yarn.lock
.star__rate{
background: url('./images/star-empty.svg');
width: 32px;
height: 31px;
background-size: 100%;
display: inline-block;
vertical-align: -7px;
margin:0 2px;
cursor: pointer;
}
.star__rate.is-selected{
background: url('./images/star-full.svg');
width: 32px;
height: 31px;
background-size: 100%;
display: inline-block;
vertical-align: -7px;
margin:0 2px;
cursor: pointer;
}
.star__rate.is-half-selected{
background: url('./images/star-half.svg');
width: 32px;
height: 31px;
background-size: 100%;
display: inline-block;
vertical-align: -7px;
margin:0 2px;
cursor: pointer;
cacheRating < rating 우선순위를 가진다.
_resetRating(e) {
if (e.type === "mouseleave" || e.type === "onTouchEnd") {
this.props.onChange(this.props.cacheIdx, this.props.cacheRating);
} else if (e.type === "click") {
this.props.onChange(0, 0);
}
}
_makeStars() {
let stars = [];
for (let i = 0; i < 5; i++) {
let starClass = "star__rate";
if (this.props.rating !== 0) {
if (i <= this.props.idx) {
if (this.props.idx === i && this.props.rating % 2 !== 0) {
starClass += " is-half-selected";
} else {
starClass += " is-selected";
}
}
} else if (this.props.cacheRating !== 0) {
if (i <= this.props.cacheIdx) {
if (this.props.cacheIdx === i && this.props.cacheRating % 2 !== 0) {
starClass += " is-half-selected";
} else {
starClass += " is-selected";
}
}
}
stars.push(
<label
key={i}
className={starClass}
onClick={() => {
this.props.onChange(this.props.idx, this.props.rating);
}}
onMouseOver={e => {
this.props._mouseOver(e, i);
}}
onMouseMove={e => {
this.props._mouseOver(e, i);
}}
onMouseLeave={e => {
this._resetRating(e);
}}
onTouchMove={e => {
this.props._mouseOver(e, i);
}}
onTouchStart={e => {
this.props._mouseOver(e, i);
}}
onTouchEnd={e => {
this._resetRating(e);
}}
/>
);
}
return stars;
}
render() {
return (
<div className="starRate__wrap">
{this._makeStars()}
<div className="reset__btn">
<img src={Reset} alt="reset" onClick={(e)=>{this._resetRating(e)}} />
</div>
</div>
);
}
state = {
idx: 0,
rating: 0,
cacheIdx: 0,
cacheRating: 0
};
_mouseOver = (e, i) => {
e.persist();
let offsetX = e.nativeEvent.offsetX;
let clientX = e.target.clientWidth;
if (offsetX > clientX / 2) {
let value = 2;
this.setState({
idx: i,
rating: value
});
} else {
let value = 1;
this.setState({
idx: i,
rating: value
});
}
};
handleChange = (i, v) => {
this.setState({
idx: 0,
rating: 0,
cacheIdx: i,
cacheRating: v
});
};
render() {
return (
<StarRate
_mouseOver={this._mouseOver}
onChange={this.handleChange}
idx={this.state.idx}
rating={this.state.rating}
cacheIdx={this.state.cacheIdx}
cacheRating={this.state.cacheRating}
/>
);
}