美文网首页
在react中用canvas做一个电影院选座功能

在react中用canvas做一个电影院选座功能

作者: 终身成长人格 | 来源:发表于2019-10-08 16:30 被阅读0次

    又到了每日分享了。这次分享的是:在react中用canvas做一个电影院选座功能。
    前言:项目采用create-react-app脚手架,就是做了一个效果所以只有一个页面但是也用了react-router-dom路由把details作为path=’/'首页了。

    效果图: 20191008150425.jpg
    一、App.js
    import React from 'react';
    import {BrowserRouter,Route} from 'react-router-dom'
    import Details from './routes/Details'
    function App() {
      return (
        <div className="App">
          <BrowserRouter>
            <Route path='/' component={Details}></Route>
          </BrowserRouter>
        </div>
      );
    }
     
    export default App;
    

    这是入口文件的代码内容
    二、Details.jsx

    import React,{Component} from 'react';
    import './Details.css';
    import Footer from './Footer';
    import SeatSelector from './SeatSelector'
    class Details extends Component {
        
          state = {
                selectSeat:[]
          }
          addSeat = (seat)=>{
                this.setState(prevState=>({
                      selectSeat:[...prevState.selectSeat,seat]
                }))
          }
          removeSeat = (id)=>{
                this.setState({
                    selectSeat:this.state.selectSeat.filter(seat=>seat.id !== id)
                })
          }
        render() {
            const {selectSeat} = this.state;
            return (
                <div>
                    <header>
                        <div className='header-container'>
                            <h2>决战时刻</h2>
                            <h3>今天 09-21 15:40~18:00 (国语 2D)</h3>
                        </div>
                    </header>
                    <div className='seat'>
                        <SeatSelector selected={selectSeat} onAdd={this.addSeat} onRemove={this.removeSeat}/>
                    </div>
                    <Footer data={selectSeat} onRemove={this.removeSeat}/>
                </div>
            );
        }
    }
    
    export default Details;
    

    这是效果的首页的东西了,分为3个部分(头部,中间canvas部分,底部),头部基本随便写,底部有一个选座显示几排几座的效果,主要是中间部分
    三、SeatSelector.jsx

    import React,{Component} from 'react';
    import {data} from './mock/data.json';
    const SET_WIDTH = 50;
    const SET_HEIGHT = 50;
     const lastSeat = data[data.length-1];
    const canvas_width = lastSeat.x*SET_WIDTH;
    const canvas_height = lastSeat.y*SET_HEIGHT;
     
    class Details extends Component {
     componentDidMount(){
            this.ctx = this.refs.canvas.getContext('2d');
            const emptyImg = new Image();
            const selectImg = new Image();
            const soldImg = new Image();
            let count = 0;
            const loadCallback = ()=>{
                count++;
                if(count===3){
                    this.emptyImg = emptyImg;
                    this.selectImg = selectImg;
                    this.soldImg = soldImg;
                     this.drawSeat();
                }
            }
            emptyImg.onload = loadCallback;
            selectImg.onload = loadCallback;
            soldImg.onload = loadCallback;
     
            emptyImg.src = './empty.png';
            selectImg.src = './select.jpg';
            soldImg.src = './sold.jpg';
        }
        componentDidUpdate(){
            this.ctx.clearRect(0,0,canvas_width,canvas_height)
            this.drawSeat();
            this.drawSelectSeat();
        }
        drawSeat(){
            const seatData = data;
            seatData.forEach((item,index)=>{
                const {isSold,x,y} = item;
                const offsetLeft = (x-1)*SET_WIDTH;
                const offsetTop = (y-1)*SET_WIDTH;
                if(isSold){
                   this.ctx.drawImage(this.soldImg,offsetLeft,offsetTop,SET_WIDTH,SET_HEIGHT);
                }else{
                   this.ctx.drawImage(this.emptyImg,offsetLeft,offsetTop,SET_WIDTH,SET_HEIGHT);
                }
            })
        }
        drawSelectSeat = ()=>{
     
            const {selected} = this.props;
            selected.forEach((item,index)=>{
                const {isSold,x,y} = item;
                const offsetLeft = (x-1)*SET_WIDTH;
                const offsetTop = (y-1)*SET_WIDTH;
                this.ctx.drawImage(this.selectImg,offsetLeft,offsetTop,SET_WIDTH,SET_HEIGHT);
            })
     
        }
        clickSeat = (e)=>{
     
            let offset = this.refs.canvas.getBoundingClientRect()
            let pageX = e.pageX - offset.left;
            let pageY = e.pageY - offset.top;
     
            let xPos = Math.ceil(pageX/SET_WIDTH);
            let yPos = Math.ceil(pageY/SET_HEIGHT);
     
            let seat = data.find(seat=>seat.x===xPos && seat.y===yPos);
     
            if( seat.isSold  ){
                return ;
            }
     
            const selectIndex = this.props.selected.findIndex(item=>item.id === seat.id);
            if(selectIndex>-1){
                this.props.onRemove(seat.id);
            }else{
                if(this.props.selected.length >= 6){
                    alert("不能超过6个");
                }else{
                    this.props.onAdd(seat);
                }
            }
     
        }
     render() {
      return (
       <div>
      <canvas onClick={this.clickSeat}  ref='canvas' width={canvas_width} height={canvas_height}/>    
       </div>
      );
     }
     
    }
     
    export default Details;
    

    这是中间canvas比较重要的一块了,大家可以看看代码了
    四、Footer.jsx

    import React from 'react';
    import './footer.css';
    const Footer = ({data,onRemove}) => {
      return (
        <footer>
      <div className='seatNum'>
       <ul>
     
        {
         data.map(seat=>(
          <li key={seat.id} onClick={()=>onRemove(seat.id)}>
           <p>{seat.y}排{seat.x}座</p>
           <p>42.7元</p>
          </li>
         ))
        }
     
       </ul>
      </div>
      <div className='seatSelect'>请先选座</div>
        </footer>
      )
    }
     
    export default Footer;
    

    这是底部代码
    老规矩附带视频教程:https://www.3mooc.com/front/couinfo/989

    相关文章

      网友评论

          本文标题:在react中用canvas做一个电影院选座功能

          本文链接:https://www.haomeiwen.com/subject/whobpctx.html