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);
更多精彩

