• 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 Basic Memo
    移动端WEB开发备忘录
    重学前端
    roadhog 构建优化
    ES6 memo
    styled-components 背后的魔法
    怎么在多场景下使用不同的 git 账号 commit
    三方登录总结
    Promise 错误处理
    观察者模式 vs 发布-订阅模式
  • 原文地址:https://www.cnblogs.com/zj911005/p/10854922.html
Copyright © 2020-2023  润新知