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);