我在ReactJs中制作了一个图像查看器,因为我是新手,所以我坚持了一点。实际上我必须添加一个全屏选项。当用户点击任何特定图像时图像打开,并且有一个选项,如下一个,上一个,关闭,旋转和全屏(这是浏览器的高度和宽度),因此当用户点击全屏时,特定图像将获得完整窗口大小和用户仍然有像旋转,next.close和prev的选项。我搜索了这么多解决方案,但没有任何效果。
我尝试了很多东西,但它只是全屏全身但我想。中心图像是全屏显示选项,正如我所说。这是计算模态组件。
class GalleryModal extends React.Component {
constructor(props) {
super(props);
this.state = {
rotation: 0
};
this.rotate = this.rotate.bind(this);
}
render() {
const { rotation } = this.state;
if (this.props.isOpen === false) {
return null;
}
return (
<div className="modal-overlay" name={this.props.name}>
<div className="modal-body">
<a href="#" className="button" onClick={() => this.rotate()}>
<i className="fas fa-sync-alt" />
</a>
<a href="#" className="button" onClick={this.props.onPrev}>
<i className="fas fa-angle-left" />
</a>
<img
className="center_image"
id="image"
src={this.props.src}
style={{ transform: `rotate(${rotation}deg)` }}
/>
<a href="#" className="button" onClick={this.props.onNext}>
<i className="fas fa-angle-right" />
</a>
<a
className="modal-close"
href="#"
onClick={this.props.onClick}
>
<span className="fa fa-times" />
</a>
</div>
</div>
);
}
rotate() {
let newRotation = this.state.rotation + 90;
if (newRotation >= 360) {
newRotation = -360;
}
this.setState({
rotation: newRotation
});
}
}
这是我的代码,我很困惑如何添加全屏选项以及添加位置。
不得不使用一些css
技巧,但我相信这是你想要实现的。图像居中并占据窗口内可用的最大宽度;但是,如果你拉伸窗口,它会调整其宽度,直到达到其最大宽度(不建议将其拉伸超过其最大值,否则,你将得到像素化)。
通过将state
和类methods
提升为单个container
,以及使用setState()
callbacks更有效地管理state
和ternary operator(cond ? true : false
)来代替简单的if/else
条件语句,我确实简化了你的代码。
工作示例:https://codesandbox.io/s/zr5k7v0zp3
集装箱/画廊/ Gallery.js
import React from "react";
import GalleryImages from "../../components/GalleryImages/galleryImages";
import GalleryModal from "../../components/GalleryModal/galleryModal";
const imgUrls = [
"https://source.unsplash.com/3Z70SDuYs5g/800x600",
"https://source.unsplash.com/01vFmYAOqQ0/800x600",
"https://source.unsplash.com/2Bjq3A7rGn4/800x600",
"https://source.unsplash.com/t20pc32VbrU/800x600",
"https://source.unsplash.com/pHANr-CpbYM/800x600",
"https://source.unsplash.com/3PmwYw2uErY/800x600",
"https://source.unsplash.com/uOi3lg8fGl4/800x600",
"https://source.unsplash.com/CwkiN6_qpDI/800x600",
"https://source.unsplash.com/9O1oQ9SzQZQ/800x600",
"https://source.unsplash.com/E4944K_4SvI/800x600",
"https://source.unsplash.com/-hI5dX2ObAs/800x600",
"https://source.unsplash.com/vZlTg_McCDo/800x600"
];
export default class Gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
imgIndex: 0,
imgUrlLength: imgUrls.length,
showModal: false,
rotation: 0
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.nextClick = this.nextClick.bind(this);
this.prevClick = this.prevClick.bind(this);
this.rotateImage = this.rotateImage.bind(this);
}
openModal(index) {
this.setState({
showModal: true,
imgIndex: index
});
}
closeModal() {
this.setState({
showModal: false,
imgIndex: 0,
rotation: 0
});
}
nextClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === prevState.imgUrlLength - 1
? 0
: prevState.imgIndex + 1
};
});
}
prevClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === 0
? prevState.imgUrlLength - 1
: prevState.imgIndex - 1
};
});
}
rotateImage() {
this.setState(prevState => {
return {
rotation: prevState.rotation + 90 <= 270 ? prevState.rotation + 90 : 0
};
});
}
render() {
return (
<div className="container-fluid gallery-container">
<GalleryImages imgUrls={imgUrls} openModal={this.openModal} />
<GalleryModal
isOpen={this.state.showModal}
onClick={this.closeModal}
onNext={this.nextClick}
onPrev={this.prevClick}
rotateImage={this.rotateImage}
rotation={this.state.rotation}
src={imgUrls[this.state.imgIndex]}
/>
</div>
);
}
}
组件/ GalleryImages / galleryImages.js
import React from "react";
import PropTypes from "prop-types";
const GalleryImages = ({ imgUrls, openModal }) => {
return (
<div className="row">
{imgUrls.map((url, index) => {
return (
<div key={index} className="col-sm-6 col-md-3 col-xl-2">
<div className="gallery-card">
<img
key={index}
className="gallery-thumbnail"
src={url}
alt={`Image number ${index + 1}`}
/>
<span
className="card-icon-open fa fa-expand"
onClick={() => openModal(index)}
/>
</div>
</div>
);
})}
</div>
);
};
GalleryImages.propTypes = {
imgUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
openModal: PropTypes.func.isRequired
};
export default GalleryImages;
组件/ GalleryModal / galleryModal.js
import React from "react";
import PropTypes from "prop-types";
const GalleryModal = ({
isOpen,
onClick,
onNext,
onPrev,
rotateImage,
rotation,
src
}) => {
return isOpen ? (
<div className="modal-overlay">
<div className="modal-body">
<div className="close-modal">
<a className="modal-close" href="#" onClick={onClick}>
<span className="fa fa-times" />
</a>
</div>
<div className="rotate-container">
<a href="#" className="button" onClick={rotateImage}>
<i style={{ fontSize: 44 }} className="fas fa-sync-alt" />
</a>
</div>
<div className="image-container">
<div>
<a href="#" className="button" onClick={onPrev}>
<i className="fas fa-angle-left" />
</a>
</div>
<div>
<img
src={src}
style={{ transform: `rotate(${rotation}deg)`, width: "100%" }}
/>
</div>
<div>
<a href="#" className="button" onClick={onNext}>
<i className="fas fa-angle-right" />
</a>
</div>
</div>
</div>
</div>
) : null;
};
GalleryModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
onNext: PropTypes.func.isRequired,
onPrev: PropTypes.func.isRequired,
rotateImage: PropTypes.func.isRequired,
rotation: PropTypes.number.isRequired,
src: PropTypes.string
};
export default GalleryModal;
styles.css的
html,
body {
min-height: 100%;
height: 100%;
}
html {
font-size: 16px;
}
body {
position: relative;
font-size: 100%;
}
.button {
font-size: 50px;
color: #eee;
margin: 5px;
}
.card-icon-open {
display: block;
position: relative;
left: 45%;
top: 35px;
font-size: 30px;
width: 30px;
color: #fff;
cursor: pointer;
opacity: 0;
transform: translate(0%, -400%);
transition: all 0.25s ease-in-out;
}
.card-icon-open:focus,
.card-icon-open:hover {
color: #111;
}
.close-modal {
position: fixed;
top: 0;
right: 5px;
}
.fullscreen {
position: relative;
text-decoration: none;
font-size: 25px;
color: #eee;
z-index: 999;
}
.fullscreen:hover,
.fullscreen:focus,
.fullscreen:blur {
text-decoration: none;
color: red;
}
.gallery-container {
padding-top: 10px;
}
.gallery-card {
position: relative;
overflow: hidden;
margin-bottom: 10px;
}
.gallery-thumbnail {
max-width: 100%;
height: auto;
border-radius: 4px;
}
.gallery-thumbnail:focus ~ .card-icon-open,
.gallery-thumbnail:hover ~ .card-icon-open,
.gallery-thumbnail ~ .card-icon-open:focus,
.gallery-thumbnail ~ .card-icon-open:hover {
opacity: 1;
}
.image-container {
display: flex;
justify-content: center;
align-items: center;
}
.image-rotate {
font-size: 44px;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(21, 21, 21, 0.75);
}
.modal-body {
position: relative;
top: 15%;
z-index: 11;
padding: 0;
overflow: hidden;
max-width: 100%;
max-height: 100%;
}
.modal-close {
font-size: 44px;
z-index: 99;
color: #eee;
transition: all 0.25s ease-in-out;
}
.modal-close:focus,
.modal-close:hover {
color: red;
}
.rotate-container {
font-size: 44px;
position: fixed;
top: 0;
left: 5px;
}
我建议使用css视口单元,将组件设置为高度:100vh和宽度:100vw将使其成为全屏。然后,您可以根据希望全屏显示组件的方式有条件地渲染组件。