krpano和react的结合展示

import React, { Component } from 'react'
import { pages, ProductActions } from 'products-sdk'
import Slider from 'react-slick'
import classnames from 'classnames';
import ShowDialogDom from '../../components/showDialog';
import ShowImgDom from '../../components/showImg';
import { connect } from 'react-redux';
import styles from './index.scss'
import * as utils from '../../utils'

const Loading = () => (
  <div className="module-loader-wrap">
    <div className="module-loader">
      <div className="sk-folding-cube">
        <div className="sk-cube1 sk-cube" />
        <div className="sk-cube2 sk-cube" />
        <div className="sk-cube4 sk-cube" />
        <div className="sk-cube3 sk-cube" />
      </div>
      <div className="module-loader-message">初始化模块中 ...</div>
    </div>
  </div>
)

class Panorama extends Component {
  constructor(props) {
    super(props)
    this.state = {
      canAutoPlay: false,
      factories: null,
      playing: false,
      showDialog: false,
      showIntro: window.innerWidth > 768 ? true : false,
      showGallery: false,
      showhotDialog: false,
      dubbing: false,
      dubComplete: false,
      show720: true,
      currentPano: {},
      hotspotId: '',
      sliderIndex: 0,
      scale: false
    }
    this.audioResource = process.env.PUBLIC_PATH + '/static/music/bg.mp3'
    this.audio = new Audio(this.audioResource);
    this.audio.volume = 0.3
    this.audio.addEventListener(
      'ended',
      () => {
        this.audio.currentTime = 0;
        this.audio.play()
      },
      false
    )
  }

  componentWillMount() {
    const { api, match } = this.props;
    const id = match.params.id;
    const pano = document.createElement('div');

    pano.setAttribute('id', 'pano');
    document.title = '智能工厂'
    document.body.appendChild(pano);
    api.get(`/catalog/categories/${id}`).then(data => {
      this.setState({
        factories: data.data.products
      })
      this.init(data.data.products)
      this.audio.play().then(() => {
        this.setState({
          canAutoPlay: true,
          playing: true
        })
      }).catch(err => {
        this.setState({
          canAutoPlay: false,
          playing: false
        })
      })
      this.audio.addEventListener(
        'ended',
        () => {
          this.audio.currentTime = 0
          this.audio.play();
          this.setState({
            canAutoPlay:true
          })
        },
        false
      )
    })
  }

  componentDidMount() {
    const { history, api } = this.props;
    window.showModal = id => { //弹窗的图文信息
      if (this.state.dubComplete || !this.state.dubbing) {
        this.keepPause = true
      } else {
        this.keepPause = false
      }

      if (!this.state.playing) {
        this.keepMusicPause = true
      } else {
        this.keepMusicPause = false
      }

      this.audio.pause()
      this.pauseSound()
      this.setState({
        hotspotId: id,
        showhotDialog: true,
        playing: false,
        dubbing: false,
        show720: false
      })
    }
    window.sceneTo = id => {

      const parentId = 'e20c8539bc5844b1a5f1b0fe544eb553'
      window.sceneToPanoInAnotherCatagory(parentId, id)
    }

    window.screenToChild = id => {
      const { showDialog, showhotDialog } = this.state;
      if (id && (showhotDialog === false || showDialog === false)) {
        history.push(`/factory/panorama/e20c8539bc5844b1a5f1b0fe544eb553/${id}`);
      }
    }
    window.sceneToPanoInAnotherCatagory = (category, product) => {
      history.push(`/factory/panorama/${category}/${product}`)
    }
    window.playDub = () => {
      if (this.krpano) {
        console.log('this.kepano====>>>', this.krpano);
        const xmlPath = this.krpano.get('network.currentxmlpath')
        const request = new XMLHttpRequest()

        request.onload = this.playDub;
        request.open('get', xmlPath + 'files/dub.mp3', true);
        request.responseType = "arraybuffer";
        request.send()
      }
    }
    window.dubcomplete = () => {
      this.setState({
        dubbing: false,
        dubComplete: true,
      })
    }
    window.panoClicked = () => {
      if (this.state.showGallery) {
        this.setState({
          showGallery: false
        })
      }
    }
    window.keepIntro = () => {
      //keepIntro为xml加载完毕后调用,此时隐藏移动端的场景导航文字
      if (window.innerWidth <= 768) {
        this.krpano.set('layer[prev_text].visible', 'false')
        this.krpano.set('layer[next_text].visible', 'false')
      }

      const { showIntro, currentPano } = this.state
      if (showIntro && currentPano && currentPano.description) {
        this.slideNext()
      }
    }
  }

  componentWillReceiveProps(nextProps, nextState) {
    const { api, match } = this.props

    if (nextProps.match.params.id !== match.params.id) {
      api.get(`/catalog/categories/${nextProps.match.params.id}`).then(data => {
        this.setState({
          showDialog: false, // 通过面包屑进行场景跳转时,应该关闭上一个场景中的弹窗
          showhotDialog: false,
          showGallery: false,
          factories: data.data.products
        })
        this.init(data.data.products)
      })
    } else if (nextProps.match.params.panoId !== match.params.panoId) {
      this.setState({
        showDialog: false, // 通过面包屑进行场景跳转时,应该关闭上一个场景中的弹窗
        showhotDialog: false,
      })
      this.loadScene(nextProps.match.params.panoId)
    }

    return true
  }

  componentWillUnmount() {
    if (this.krpano) removepano('krpanoSWFObject')
    const pano = document.getElementById('pano')
    document.body.removeChild(pano);
    this.audio.pause()
    this.pauseSound()
    this.props.module.name = '智能工厂'
  }
  loadScene = id => {
    this.pauseSound()

    const pano = this.state.factories.filter(f => f._id === id)[0]

    if (pano) {
      this.krpano.call(`
        loadpano(${pano.web3d.url}, null, MERGE, BLEND(0.75));
      `)

      this.setState({
        currentPano: pano
      })
    }
  }

  customizationShareItems = (context) => {
    return {
      name: _.get(context, 'module.name'),
      href: window.location.href
    }
  }
  togglePlayAndPause = (param) => {
    const { playing, dubbing } = this.state;
    if (param === 'play') {
      playing === false ? this.play() : this.pause()
      this.setState((prevState, props) => ({
        playing: !prevState.playing
      }))
    } else if (param === 'sound') {
      console.log('dubbing===>>>',dubbing);
      dubbing === false ? this.resumeSound() : this.pauseSound()
      this.setState((prevState, props) => ({
        dubbing: !dubbing
      }))
    }
  }
  play = () => {
    this.audio.play();
    this.audio.addEventListener(
      'ended',
      () => {
        this.audio.currentTime = 0;
        this.audio.play()
      },
      false
    )
    this.setState({ playing: false })
  }
  pause = () => {
    this.audio.pause();
    this.setState({ playing: true })
  }
  playDub = (event) => {
    console.log('this.state.canAutoPlay===>>>',!this.state.showDialog,!this.state.showhotDialog);
    if (event && event.target.status == '200' && (this.state.showhotDialog === false && this.state.showDialog === false)) {
      console.log(this.state.dubbing);
      this.krpano.call('playsound(dub, dub.mp3, 1, dubcomplete)');
      this.setState({
        dubbing: true
      })
    }
  }
  pauseSound = () => {
    this.krpano.call('pausesound(dub)');
    this.setState({
      dubbing: false
    })
  }
  resumeSound = () => {
    this.krpano.call('resumesound(dub)');
    this.krpano.call('playsound(dub, dub.mp3, 1, dubcomplete)');
    this.setState({
      dubbing: true
    })
  }
  init = (products) => {
    const panoid = this.props.match.params.panoId;
    _.map(products, (product, index) => {
      if (product._id === panoid) {
        const web3d = product['web3d'];
        if (web3d && web3d.type === 'web3d' && web3d.url) {
          this.initKrpano({
            xml: web3d.url,
            target: 'pano',
            html5: 'only',
            bgcolor: 'transparent',
            mobilescale: 1.0,
            passQueryParameters: false,
            initvars: {
              skinPath: process.env.PUBLIC_PATH + '/static/skin'
            }
          })
        }
        this.setState({
          currentPano: product
        })
      }
    })


  }
  initKrpano = config => {
    if (this.krpano) removepano('krpanoSWFObject')
    embedpano(config)
    this.krpano = document.getElementById('krpanoSWFObject');
  }
  closeImg = () => { //click inside the popover to enlarge the image
    this.setState({
      scale: false
    })
  }
  close = () => { //close windows
    if (!this.keepMusicPause) {
      this.audio.play()
      this.audio.addEventListener(
        'ended',
        () => {
          this.audio.currentTime = 0
          this.audio.play()
        },
        false
      )
    }

    if (!this.keepPause) {
      this.resumeSound()
    }

    this.setState({
      showDialog: false,
      showhotDialog: false,
      show720: true,
      playing: !this.keepMusicPause,
      dubbing: !this.keepPause,
      hotspotId: ''
    })
  }
  toggleGallery = () => {
    // 操作gallery时,Introduction将被关闭,“下一个场景”按钮需要恢复原位
    this.resumeNext()
    this.setState(prev => ({
      showGallery: !prev.showGallery,
      showIntro: false,
      show720: !prev.show720
    }))
  }
  toggleIntro = () => {
    this.audio.pause()
    this.pauseSound()
    this.setState(prev => {
      return {
        showDialog: !prev.showDialog,
        showhotDialog: !prev.showhotDialog,
      }
    })
  }
  resumeNext = () => {
    this.krpano.set('layer[next_image].x', '0')
    this.krpano.set('layer[next_text].x', '26')
  }
  handleScene = id => {
    const categories = this.context.categories
    const belongTo = Object.values(categories.byId).find(c => {
      return c.products.some(p => p === id)
    })
    const categoryId = belongTo
      ? belongTo._id
      : 'e20c8539bc5844b1a5f1b0fe544eb553'
    window.sceneToPanoInAnotherCatagory(categoryId, id)

    this.setState({
      showGallery: false
    })
  }
  renderGallery = context => {
    const { products, categories, currentPano, match } = context
    const categoryId = match.params.id
    const panoId = match.params.panoId || (currentPano && currentPano._id)
    const currentProducts = categories.byId[categoryId].products
    return currentProducts.map((f, i) => {
      if (!f) return
      const cover =
        (f.cover &&
          (f.cover.thumbnail ||
            (f.cover.current && f.cover.current.thumbnail))) ||
        ''
      const isActive = f._id === (currentPano && currentPano._id)

      if (isActive) {
        this.slideGalleryToView(i + 1);
      }

      return (
        <div
          key={i}
          onClick={e => {
            this.handleScene(f._id)
          }}
          className={classnames(styles.item, isActive && styles.active)}
        >
          <img className={styles.cover} src={cover} alt={cover} />
          <div className={styles.name}>{f.name}</div>
        </div>
      )
    })
  }
  slideGalleryToView = i => {
    const itemOffsetLeft = 10 + 170 * i
    const halfGalleryWidth = window.innerWidth / 2
    if (this.gallery) {
      if (
        itemOffsetLeft > halfGalleryWidth ||
        itemOffsetLeft < this.gallery.scrollLeft
      ) {
        this.gallery.scrollLeft = itemOffsetLeft - halfGalleryWidth
      }
    }

  }
  // 待重构
  handleBreadcrumb = cid => {
    let tmp = [];
    const { currentPano } = this.state
    const panoid = currentPano._id;
    tmp.push({
      to: `/factory/panorama/${cid}/${panoid}`,
      name: `${currentPano.name}`
    })
    return tmp
  }
  renderPageContent = context => {
    this.context = context;
    let that = this;
    const {
      playing,
      factories,
      hotspotId,
      showGallery,
      showDialog,
      dubbing,
      showhotDialog,
      currentPano,
      show720
    } = this.state
    if (!factories) {
      return <Loading />
    }
    const { match, categories, getCategoryItem } = context;
    let hotId = 'f15b865cc35a4e80a6f3b668b0efc43a';
    let categoryHot = categories && categories.byId[hotId]; //热点的展示
    if (categoryHot && !categoryHot.loaded) {
      categoryHot = getCategoryItem(hotId);
    }
    const id = match.params.id;

    const panoId = panoId || currentPano._id;
    return (
      <div className={classnames(styles.panoCon, window.orbitBridge && styles.orbitstyle)}
      >
        <div
          className={classnames(
            styles.bottom,
            showGallery && styles.show,
            showDialog || showhotDialog ? styles.pointEvent : styles.pointAuto
          )}
        >
          {
            show720 && <div className={styles.iconImg}></div>
          }

          <div
            className={classnames(
              styles.btns,
            )}
          >
            {currentPano &&
              currentPano.description && (
                <div
                  className={classnames(styles.btn, styles.toggleIntro)}
                  onClick={() => this.toggleIntro()}
                ></div>
              )}
            <div
              className={classnames(styles.btn, styles.toggleGallery)}
              onClick={this.toggleGallery}
            ></div>
            <div
              className={classnames(styles.btn, dubbing ? styles.dubPlay : styles.dubPause)}
              onClick={() => this.togglePlayAndPause('sound')}
            ></div>
            <div
              className={classnames(styles.btn, playing ? styles.play : styles.pause)}
              onClick={() => this.togglePlayAndPause('play')}
            ></div>
          </div>
          <div className={styles.gallery} ref={el => (this.gallery = el)}>
            <div className={styles.container}>
              {this.renderGallery(context)}
            </div>
          </div>
        </div>
        <div
          ref={
            (ref) => {
              if (ref) {
                $(ref).find('img').css({ 'width': '100%', 'height': 'auto' });
                $(ref).find('video').css({ 'width': '100%', 'height': 'auto' });
                $(ref).find('img').map((i, c) => {
                  $(c).unbind();
                  $(c).click(function () {
                    if (window.orbitBride) {
                      window.orbitBride.invoke({
                        method: 'openImges',
                        params: {
                          items: [{ url: c.src }]
                        },
                        error: function (err) {
                          console.error('error:', err);
                        },
                        success: function (result) {
                          console.log('result:', result);
                        }
                      });
                    } else {
                      that.setState({
                        imageUrl: [c.src],
                        scale: true
                      })
                    }
                  })
                })
              }
            }
          }
        >
          {
            (showDialog || showhotDialog) &&
            <ShowDialogDom
              id={showDialog === true ? panoId : showhotDialog && hotspotId}
              productArray={showDialog === true ? factories : showhotDialog && categoryHot.products}
              showDialog={showDialog}
              close={() => { this.close() }}
            />
          }
        </div>

        {
          this.state.scale &&
          <ShowImgDom scale={this.state.scale} imageUrl={this.state.imageUrl} closeImg={() => { this.closeImg() }} />
        }
      </div>
    )
  }

  render() {
    let addition = [];
    document.title = this.state.currentPano.name;
    // addition = this.handleBreadcrumb(this.props.match.params.id)
    this.props.module.name = this.state.currentPano.name || ''
    const parents = [
      { to: '/', name: utils.getString('HOME', '首页') },
      { to: '/factory/list/5c9354ef58d4bd6f02a71581', name: '智能工厂' },
      ...addition,
    ]
    return (
      <pages.seriesInfo
        {...this.props}
        {...this.state}
        ref={ref => {
          this.page = ref
        }}
        hideSidebar={true}
        parents={parents}
        getResourceUrl={this.getResourceUrl}
        renderPageContent={this.renderPageContent}
        customizationShareItems={this.customizationShareItems}
        title={this.state.currentPano.name}
      />
    )
  }
  getResourceUrl = (item) => {
    const { module } = this.props
    const { id } = this.state;
    const prefix = _.get(module, 'config.general.router.prefix') || 'products'
    const _id = item._id;
    return `${window.location.origin}/${prefix}/list/${_id}${window.location.search}`
  }

}
const mapStateToProps = (state, ownProps) => {
  const id = ownProps.match.params.id

  return {
    id
  };
}
const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    getCategoryItem: id => {
      return dispatch(ProductActions.getCategoryItem(id))
    }
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(Panorama);

 

上一篇:javascript-React set-state在获取成功功能中不更新(在按键事件上)


下一篇:setState各在什么时候执行同步/异步