React实现PPT预览(伪)
-
前言
最近有个react项目需要实现一系列文档的预览,一开始觉得这还不简单,react-file-viewer直接一键搞定,然后发现这个插件不支持PPT文件的预览,我又去查资料进行了面向百度编程,可惜全都是利用微软提供的接口,微软提供的接口需要文件是公网可访问的,公司内部项目肯定是不能公网访问的,所以怎么办呢?没办法只能用个非常蠢的办法,轮播图呗!转图片的事就让后端去弄吧!(前后端从此恩断义绝)
-
准备工作
其实也没啥准备工作,偷懒选手表示antd组件库搞起,我用的是yarn管理react项目的依赖包,所以 yarn add antd。
然后就是写组件了,这里多说一句个人项目设计的原因,数据是从父组件传递到的子组件,都是在src文件夹下,话不多说,上代码。
-
代码步骤
第一步:父组件ContentFile.js
判断文件是否是ppt就不多说了,主要是传数据以及数据格式。
数据格式:
state = {
isPPT: false,
pptContent: [],
data: [
{
key: '5',
number: '5',
name: 'reactPPT测试',
uploader: 'xxxx',
fileKey: "0000",
uploadTime: '2020-06-1918:44:01',
url: "https://www.baidu.com",
file: {
name: "《梦界》毕业答辩演示——答辩版.ppt",
content: [
{key: 1, pic: "ceshi/pptCeShi/u105.png"},
{key: 2, pic: "ceshi/pptCeShi/u106.png"},
{key: 3, pic: "ceshi/pptCeShi/u107.png"},
{key: 4, pic: "ceshi/pptCeShi/u108.png"},
{key: 5, pic: "ceshi/pptCeShi/u109.png"},
{key: 6, pic: "ceshi/pptCeShi/u110.png"},
{key: 7, pic: "ceshi/pptCeShi/u111.png"},
{key: 8, pic: "ceshi/pptCeShi/u112.png"},
{key: 9, pic: "ceshi/pptCeShi/u113.png"},
{key: 10, pic: "ceshi/pptCeShi/u114.png"},
{key: 11, pic: "ceshi/pptCeShi/u115.png"},
{key: 12, pic: "ceshi/pptCeShi/u116.png"},
{key: 13, pic: "ceshi/pptCeShi/u117.png"},
{key: 14, pic: "ceshi/pptCeShi/u118.png"},
{key: 15, pic: "ceshi/pptCeShi/u119.png"},
{key: 16, pic: "ceshi/pptCeShi/u120.png"},
]
},
},
],
};
你的fetch(其他请求后台的也可以)请求的数据按照data的样子来就可以,实际上只需要file那部分就可以了(你不至于连个数据格式也不知道吧。)避免被喷,放个超级简易版的数据。
data: {
name: "《梦界》毕业答辩演示——答辩版.ppt",
content: [
{key: 1, pic: "ceshi/pptCeShi/u105.png"},
{key: 2, pic: "ceshi/pptCeShi/u106.png"},
{key: 3, pic: "ceshi/pptCeShi/u107.png"},
{key: 4, pic: "ceshi/pptCeShi/u108.png"},
{key: 5, pic: "ceshi/pptCeShi/u109.png"},
{key: 6, pic: "ceshi/pptCeShi/u110.png"},
{key: 7, pic: "ceshi/pptCeShi/u111.png"},
{key: 8, pic: "ceshi/pptCeShi/u112.png"},
{key: 9, pic: "ceshi/pptCeShi/u113.png"},
{key: 10, pic: "ceshi/pptCeShi/u114.png"},
{key: 11, pic: "ceshi/pptCeShi/u115.png"},
{key: 12, pic: "ceshi/pptCeShi/u116.png"},
{key: 13, pic: "ceshi/pptCeShi/u117.png"},
{key: 14, pic: "ceshi/pptCeShi/u118.png"},
{key: 15, pic: "ceshi/pptCeShi/u119.png"},
{key: 16, pic: "ceshi/pptCeShi/u120.png"},
]
},
记得放在父组件的state里面(因为这是个测试数据)
render部分代码:(不多解释了,就是用来传参数的位置)
const {data} = this.state.data.file;(这里其实我把数据放在了一个pptContent里,不过既然只是实现ppt就直接这样就可以)
如果你用的简易版
const {data} = this.state.data;
return部分代码:
<div style={{
float: "left",
margin: "auto",
width: "100%",
}}>
<PrevPPT dataPic={pptContent}/>
</div>
这个`PrevPPT 就是我们的插件了,dataPic就是传过去的数据,pptContent就是参数,修改成你定义的名字就行(如果你是粘贴的代码那就是改成data)
子组件PrevPPT.js
直接上完整代码:
import React from 'react' ;
import {LeftCircleFilled, RightCircleFilled} from '@ant-design/icons'
import {message} from "antd";
import "../style/index.css"
class PrevPPT extends React.Component {
state = {
currentPage: 1
};
PageUp = (pagePrev) => {//参数为当前页面以及接下来需要显示的页面
if (pagePrev > 1) {
this.setState({
currentPage: pagePrev - 1,
});
let pageNext = pagePrev - 1;
this.changeCSS(pagePrev,pageNext);
} else {
message.warn("当前页为第一页!", 1)
}
};
PageDown = (pagePrev, pageMax) => {//参数为当前页面以及接下来需要显示的页面
if (pagePrev < pageMax) {
this.setState({
currentPage: pagePrev + 1,
});
let pageNext = pagePrev + 1;
this.changeCSS(pagePrev,pageNext);
} else {
message.warn("当前页为末尾页!", 1)
}
};
toPPTPage = (key)=>{
console.log(key);
this.setState({
currentPage:key,
});
let pageNext = key;
let pagePrev = this.state.currentPage;
this.changeCSS(pagePrev,pageNext);
};
//精简代码(修改样式)
changeCSS = (pagePrev,pageNext)=>{
document.getElementById("data-pic-" + pagePrev).style.display = "none";
document.getElementById("data-pic-" + pageNext).style.display = "block";
document.getElementById("span-" + pagePrev).style.backgroundColor = "rgba(199,199,199,0.81)";
document.getElementById("span-" + pageNext).style.backgroundColor = "rgba(16,142,233,0.81)";
};
render() {
const data = this.props.dataPic;
const currentPage = this.state.currentPage;
const items = [];
const span = [];
for (let i = 0; i <= data.length - 1; i++) {
let wid = 90 / (data.length) + "%";
let space = 10 / (data.length) + "%";
if (i === 0) {
items.push(<img key={data[i].key} id={"data-pic-" + data[i].key}
src={require("../" + data[i].pic)}//本地测试环境写法
// src={data[i].pic}//生产环境
alt={"第" + data[i].key + "页"} title={"第" + data[i].key + "页"}
style={{display: "block", margin: "auto", float: "left", width: "80%"}}/>);
span.push(
<span id={"span-" + data[i].key} className={"pptSpan"} title={"第" + data[i].key + "页"} style={{
width: wid,
marginLeft: space,
backgroundColor: "rgba(16,142,233,0.81)",
}}
onClick={()=>this.toPPTPage(data[i].key)}
> </span>
)
} else {
items.push(<img key={data[i].key} id={"data-pic-" + data[i].key}
src={require("../" + data[i].pic)}//本地测试环境写法
// src={data[i].pic}//生产环境
alt={"第" + data[i].key + "页"} title={"第" + data[i].key + "页"}
style={{display: "none", margin: "auto", float: "left", width: "80%"}}/>);
span.push(
<span id={"span-" + data[i].key} className={"pptSpan"} title={"第" + data[i].key + "页"} style={{
width: wid,
marginLeft: space,
}}
onClick={()=>this.toPPTPage(data[i].key)}
> </span>
)
}
}
return (
<div style={{
float: "left",
margin: "auto",
width: "100%",
}}>
<div style={{
float: "left",
margin: "auto",
width: "10%",
paddingTop: "20%",
}}>
<a href="#!" title={"上一页"}
onClick={() => this.PageUp(currentPage)}
>
<LeftCircleFilled
style={{
fontSize: "36px",
}}
/>
</a>
</div>
{items}
<div style={{
float: "right",
margin: "auto",
width: "10%",
paddingTop: "20%",
}}>
<a href="#!" title={"下一页"}
onClick={() => this.PageDown(currentPage, items.length)}
>
<RightCircleFilled
style={{
fontSize: "36px",
float: "right",
}}
/>
</a>
</div>
<div style={{
width: "100%",
float: "left",
marginTop: 10,
padding: " 0 12% ",
}}>
{span}
</div>
</div>
)
}
}
export default PrevPPT;
这里还得多一句嘴,就是测试数据的路径如果是“…/xxx/xxx”类型的,使用require()获取需要变成"…/"+“xxx/xxx”,路径看情况自行修改。我的图片文件放在src的新建ceshi文件夹下。
再补一个css代码index.css
video{
width: 800px;
}
.body {
height: 900px;
min-height: 900px;
}
.head {
overflow: hidden;
margin-top: 10px;
padding-left: 10px;
padding-right: 10px;
}
.main {
height: 100%;
}
.main_mid {
height: 100%;
}
.main_left {
float: left;
width: 20%;
background-color: white;
border-radius: 5px;
margin-top: 10px;
height: 98%;
}
.main_right {
overflow: hidden;
background-color: white;
padding: 20px;
float: right;
width: 79%;
margin-top: 10px;
border-radius: 5px;
height: 98%;
}
.pptSpan{
height:10px ;
float: left;
background-color: rgba(199,199,199,0.81);
}
.pptSpan:hover{
background-color: rgba(16,142,233,0.81) !important;
}
这个css代码呢,只有最后两个是这个组件的,其余的emmmm我是懒得删除了。
子组件的功能呢,我就贴图演示了,看看代码基本就知道,巨简单,所以说我就是闲得无聊才发这个博客,o(︶︿︶)o 唉…
这里是预览效果图:
你以为我只是为了让你看截图吗?看妹子!至于这个对话框,用的是antd的对话框,属性你设置一下就ok了,然后把组件丢进去,没怎么测试,我好像给这个组件摁死了布局,应该可以直接放在div盒子里面(我不保证!)
4.尾言
我就是闲的慌,脑壳子嗡嗡的,看了黑神话:悟空,我想去学虚幻4了,哇,暴毙…