mirror of
https://github.com/infeng/react-viewer.git
synced 2025-12-08 17:36:40 +00:00
complete viewer core
This commit is contained in:
parent
457aaa8178
commit
9ef3b349b0
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,3 @@
|
||||
node_modules/
|
||||
node_modules/
|
||||
dist/
|
||||
lib/
|
||||
@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import ViewerWrap from '../src/ViewerWrap';
|
||||
import Viewer from '../src/Viewer';
|
||||
const img2 = require('./images/landscape2.jpg');
|
||||
const img = require('./images/landscape.jpg');
|
||||
const img3 = require('./images/tibet-6.jpg');
|
||||
@ -18,7 +18,7 @@ class App extends React.Component<any, any> {
|
||||
return (
|
||||
<div>
|
||||
<button onClick={() => { this.setState({ visible: !this.state.visible }); } }>show</button>
|
||||
<ViewerWrap
|
||||
<Viewer
|
||||
visible={this.state.visible}
|
||||
onClose={() => { this.setState({ visible: false }); } }
|
||||
images={[img2, img, img3]}
|
||||
|
||||
6
getBabelCommonConfig.js
Normal file
6
getBabelCommonConfig.js
Normal file
@ -0,0 +1,6 @@
|
||||
module.exports = function getBabelCommonConfig() {
|
||||
const babelConfig = require('atool-build/lib/getBabelCommonConfig')();
|
||||
babelConfig.plugins.push([require.resolve('babel-plugin-transform-runtime'),
|
||||
{ polyfill: false }]);
|
||||
return babelConfig;
|
||||
};
|
||||
11
getTSCommonConfig.js
Normal file
11
getTSCommonConfig.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function () {
|
||||
return {
|
||||
target: 'es6',
|
||||
jsx: 'preserve',
|
||||
moduleResolution: 'node',
|
||||
declaration: true,
|
||||
allowSyntheticDefaultImports: true,
|
||||
};
|
||||
};
|
||||
41
gulpfile.js
Normal file
41
gulpfile.js
Normal file
@ -0,0 +1,41 @@
|
||||
const gulp = require('gulp');
|
||||
const ts = require('gulp-typescript');
|
||||
const tsConfig = require('./getTSCommonConfig')();
|
||||
const babelConfig = require('./getBabelCommonConfig')();
|
||||
delete babelConfig.cacheDirectory;
|
||||
const babel = require('gulp-babel');
|
||||
const transformLess = require('atool-build/lib/transformLess');
|
||||
const through2 = require('through2');
|
||||
const merge2 = require('merge2');
|
||||
|
||||
function babelify(js) {
|
||||
return js.pipe(babel(babelConfig))
|
||||
.pipe(gulp.dest('lib'));
|
||||
}
|
||||
|
||||
gulp.task('default', () => {
|
||||
const less = gulp.src(['src/' + '**/' + '*.less'])
|
||||
.pipe(through2.obj(function (file, encoding, next) {
|
||||
this.push(file.clone());
|
||||
if (file.path.match(/\/style\/index\.less$/)) {
|
||||
transformLess(file.path).then((css) => {
|
||||
file.contents = new Buffer(css);
|
||||
file.path = file.path.replace(/\.less$/, '.css');
|
||||
this.push(file);
|
||||
next();
|
||||
}).catch((e) => {
|
||||
console.error(e);
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest('lib'));
|
||||
const img = gulp.src(['src/' + '**/' + '*.png']).pipe(gulp.dest('lib'));
|
||||
const tsResult = gulp.src([
|
||||
'src/' + '**/' + '*.tsx',
|
||||
]).pipe(ts(tsConfig));
|
||||
const tsFiles = babelify(tsResult.js);
|
||||
const tsd = tsResult.dts.pipe(gulp.dest('lib'));
|
||||
return merge2([tsFiles, tsd]);
|
||||
});
|
||||
17
package.json
17
package.json
@ -2,11 +2,12 @@
|
||||
"name": "react-viewer",
|
||||
"version": "0.0.1",
|
||||
"description": "react image viewer",
|
||||
"main": "dist/ViewerWrap",
|
||||
"main": "dist/index",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "dora --port 8001 --plugins \"webpack,webpack-hmr,browser-history?index=/demo/index.html\"",
|
||||
"lint": "tslint -c tslint.json src/**/*.ts src/**/*.tsx"
|
||||
"lint": "tslint -c tslint.json src/**/*.ts src/**/*.tsx",
|
||||
"build": "atool-build --config webpack.config.prop.js && gulp"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -22,21 +23,33 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/infeng/react-viewer/issues"
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
"lib"
|
||||
],
|
||||
"typings": "lib/index.d.ts",
|
||||
"homepage": "https://github.com/infeng/react-viewer#readme",
|
||||
"devDependencies": {
|
||||
"@types/node": "^6.0.45",
|
||||
"@types/react": "^0.14.39",
|
||||
"@types/react-dom": "^0.14.17",
|
||||
"atool-build": "^0.8.1",
|
||||
"babel-plugin-transform-runtime": "^6.15.0",
|
||||
"babel-runtime": "^6.11.6",
|
||||
"dora": "^0.4.3",
|
||||
"dora-plugin-browser-history": "^0.2.0",
|
||||
"dora-plugin-webpack": "^0.8.1",
|
||||
"dora-plugin-webpack-hmr": "^0.2.1",
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-babel": "^6.1.2",
|
||||
"gulp-typescript": "^3.0.2",
|
||||
"html-loader": "^0.4.4",
|
||||
"html-webpack-plugin": "^2.22.0",
|
||||
"merge2": "^1.0.2",
|
||||
"pre-commit": "^1.1.3",
|
||||
"react": "^15.3.2",
|
||||
"react-dom": "^15.3.2",
|
||||
"through2": "^2.0.1",
|
||||
"tslint": "^3.15.1",
|
||||
"typescript": "^2.0.3",
|
||||
"webpack": "^1.13.2"
|
||||
|
||||
119
src/Viewer.tsx
119
src/Viewer.tsx
@ -1,78 +1,67 @@
|
||||
import * as React from 'react';
|
||||
import './style/index.less';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import ViewerCore from './ViewerCore';
|
||||
import ViewerNav from './ViewerNav';
|
||||
import ViewerProps from './ViewerProps';
|
||||
|
||||
function noop() {}
|
||||
export default class Viewer extends React.Component<ViewerProps, any> {
|
||||
private container: HTMLDivElement;
|
||||
private component: React.ReactNode;
|
||||
|
||||
interface ViewerState {
|
||||
activeIndex?: number;
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
export default class Viewer extends React.Component<ViewerProps, ViewerState> {
|
||||
static defaultProps = {
|
||||
visible: false,
|
||||
onClose: noop,
|
||||
images: [],
|
||||
activeIndex: 0,
|
||||
};
|
||||
|
||||
private prefixCls: string;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.prefixCls = 'react-viewer';
|
||||
|
||||
this.state = {
|
||||
activeIndex: this.props.activeIndex,
|
||||
};
|
||||
|
||||
this.handleChangeImg = this.handleChangeImg.bind(this);
|
||||
this.container = null;
|
||||
this.component = null;
|
||||
}
|
||||
|
||||
handleClose(e) {
|
||||
this.props.onClose();
|
||||
}
|
||||
|
||||
handleChangeImg(newIndex: number) {
|
||||
let newState = this.state;
|
||||
newState.activeIndex = newIndex;
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ViewerProps) {
|
||||
if (this.state.activeIndex !== nextProps.activeIndex) {
|
||||
this.setState({
|
||||
activeIndex: nextProps.activeIndex,
|
||||
});
|
||||
renderViewer() {
|
||||
if (this.props.visible || this.component) {
|
||||
if (!this.container) {
|
||||
this.container = document.createElement('div');
|
||||
}
|
||||
document.body.appendChild(this.container);
|
||||
let instance = this;
|
||||
ReactDOM.unstable_renderSubtreeIntoContainer(
|
||||
this,
|
||||
<ViewerCore
|
||||
{...this.props}
|
||||
/>,
|
||||
this.container,
|
||||
function () {
|
||||
instance.component = this;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
removeViewer() {
|
||||
if (this.container) {
|
||||
const container = this.container;
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
container.parentNode.removeChild(container);
|
||||
this.container = null;
|
||||
this.component = null;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.visible) {
|
||||
this.props.onClose();
|
||||
this.removeViewer();
|
||||
} else {
|
||||
this.removeViewer();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.renderViewer();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.renderViewer();
|
||||
}
|
||||
|
||||
render() {
|
||||
let activeImgSrc = '';
|
||||
if (this.props.images.length > 0) {
|
||||
activeImgSrc = this.props.images[this.state.activeIndex];
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{display: this.props.visible ? 'block' : 'none'}}>
|
||||
<div className={`${this.prefixCls}-mask`}></div>
|
||||
<div className={`${this.prefixCls}-close`} onClick={this.handleClose.bind(this)}></div>
|
||||
<ViewerCore
|
||||
prefixCls={this.prefixCls}
|
||||
imgSrc={activeImgSrc}
|
||||
visible={this.props.visible}
|
||||
/>
|
||||
<div className={`${this.prefixCls}-footer`}>
|
||||
<ViewerNav
|
||||
prefixCls={this.prefixCls}
|
||||
images={this.props.images}
|
||||
activeIndex={this.state.activeIndex}
|
||||
onChangeImg={this.handleChangeImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
169
src/ViewerCavans.tsx
Normal file
169
src/ViewerCavans.tsx
Normal file
@ -0,0 +1,169 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export interface ViewerCavansProps {
|
||||
prefixCls: string;
|
||||
imgSrc: string;
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
export interface ViewerCavansState {
|
||||
width?: number;
|
||||
top?: number;
|
||||
left?: number;
|
||||
isMouseDown?: boolean;
|
||||
mouseX?: number;
|
||||
mouseY?: number;
|
||||
}
|
||||
|
||||
export default class ViewerCavans extends React.Component<ViewerCavansProps, ViewerCavansState> {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.state = {
|
||||
width: 0,
|
||||
top: 15,
|
||||
left: null,
|
||||
isMouseDown: false,
|
||||
mouseX: 0,
|
||||
mouseY: 0,
|
||||
};
|
||||
|
||||
this.handleMouseScroll = this.handleMouseScroll.bind(this);
|
||||
this.handleMouseDown = this.handleMouseDown.bind(this);
|
||||
this.bindEvent = this.bindEvent.bind(this);
|
||||
this.handleMouseMove = this.handleMouseMove.bind(this);
|
||||
this.handleMouseUp = this.handleMouseUp.bind(this);
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.bindEvent();
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
}
|
||||
|
||||
resizeImg(imgSrc) {
|
||||
let img = new Image();
|
||||
img.src = imgSrc;
|
||||
img.onload = () => {
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
let imgWidth = img.width;
|
||||
let imgHeight = img.height;
|
||||
let aspectRatio = imgWidth / imgHeight;
|
||||
if (aspectRatio > 1) {
|
||||
width = Math.min(window.innerWidth * .9, imgWidth);
|
||||
height = (width / imgWidth) * imgHeight;
|
||||
}else {
|
||||
height = Math.min((window.innerHeight - 52) * .8, imgHeight);
|
||||
width = (height / imgHeight) * imgWidth;
|
||||
}
|
||||
let left = ( window.innerWidth - width ) / 2;
|
||||
let top = (window.innerHeight - height) / 2;
|
||||
this.setState({
|
||||
width: width,
|
||||
left: left,
|
||||
top: top,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
handleResize(e) {
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
}
|
||||
|
||||
handleMouseDown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState({
|
||||
isMouseDown: true,
|
||||
mouseX: e.nativeEvent.pageX,
|
||||
mouseY: e.nativeEvent.pageY,
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseMove(e) {
|
||||
if (this.state.isMouseDown) {
|
||||
let diffX = e.x - this.state.mouseX;
|
||||
let diffY = e.y - this.state.mouseY;
|
||||
this.setState({
|
||||
top: this.state.top + diffY,
|
||||
left: this.state.left + diffX,
|
||||
mouseX: e.x,
|
||||
mouseY: e.y,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseUp(e) {
|
||||
this.setState({
|
||||
isMouseDown: false,
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseScroll(e) {
|
||||
let direct: 0 | 1 | -1 = 0;
|
||||
if (e.wheelDelta) {
|
||||
direct = e.wheelDelta > 0 ? 1 : -1;
|
||||
}else if (e.detail) {
|
||||
direct = e.detail > 0 ? 1 : -1;
|
||||
}
|
||||
if (direct !== 0) {
|
||||
this.setState({
|
||||
width: this.state.width + direct * this.state.width * 0.05,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bindEvent(remove?: boolean) {
|
||||
let funcName = 'addEventListener';
|
||||
if (remove) {
|
||||
funcName = 'removeEventListener';
|
||||
}
|
||||
document[funcName]('mousewheel', this.handleMouseScroll, false);
|
||||
document[funcName]('click', this.handleMouseUp, false);
|
||||
document[funcName]('mousemove', this.handleMouseMove, false);
|
||||
window[funcName]('resize', this.handleResize, false);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ViewerCavansProps) {
|
||||
if (this.props.imgSrc !== nextProps.imgSrc) {
|
||||
this.resizeImg(nextProps.imgSrc);
|
||||
}
|
||||
if (!this.props.visible && nextProps.visible) {
|
||||
this.bindEvent();
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
}
|
||||
if (this.props.visible && !nextProps.visible) {
|
||||
this.bindEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let imgStyle: React.CSSProperties = {
|
||||
width: `${this.state.width}px`,
|
||||
marginTop: `${this.state.top}px`,
|
||||
marginLeft: this.state.left ? `${this.state.left}px` : 'auto',
|
||||
};
|
||||
|
||||
let imgClass = '';
|
||||
if (!this.state.isMouseDown) {
|
||||
imgClass = `${this.props.prefixCls}-transition`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${this.props.prefixCls}-cavans`}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
>
|
||||
<img
|
||||
ref="img"
|
||||
className={imgClass}
|
||||
src={this.props.imgSrc}
|
||||
style={imgStyle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,168 +1,78 @@
|
||||
import * as React from 'react';
|
||||
import './style/index.less';
|
||||
import ViewerCavans from './ViewerCavans';
|
||||
import ViewerNav from './ViewerNav';
|
||||
import ViewerProps from './ViewerProps';
|
||||
|
||||
export interface ViewerCoreProps {
|
||||
prefixCls: string;
|
||||
imgSrc: string;
|
||||
visible: boolean;
|
||||
function noop() {}
|
||||
|
||||
export interface ViewerCoreState {
|
||||
activeIndex?: number;
|
||||
}
|
||||
|
||||
interface ViewerCoreState {
|
||||
width?: number;
|
||||
top?: number;
|
||||
left?: number;
|
||||
isMouseDown?: boolean;
|
||||
mouseX?: number;
|
||||
mouseY?: number;
|
||||
}
|
||||
export default class ViewerCore extends React.Component<ViewerProps, ViewerCoreState> {
|
||||
static defaultProps = {
|
||||
visible: false,
|
||||
onClose: noop,
|
||||
images: [],
|
||||
activeIndex: 0,
|
||||
};
|
||||
|
||||
export default class ViewerCore extends React.Component<ViewerCoreProps, ViewerCoreState> {
|
||||
private prefixCls: string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.prefixCls = 'react-viewer';
|
||||
|
||||
this.state = {
|
||||
width: 0,
|
||||
top: 15,
|
||||
left: null,
|
||||
isMouseDown: false,
|
||||
mouseX: 0,
|
||||
mouseY: 0,
|
||||
activeIndex: this.props.activeIndex,
|
||||
};
|
||||
|
||||
this.handleMouseScroll = this.handleMouseScroll.bind(this);
|
||||
this.handleMouseDown = this.handleMouseDown.bind(this);
|
||||
this.bindEvent = this.bindEvent.bind(this);
|
||||
this.handleMouseMove = this.handleMouseMove.bind(this);
|
||||
this.handleMouseUp = this.handleMouseUp.bind(this);
|
||||
this.handleResize = this.handleResize.bind(this);
|
||||
this.handleChangeImg = this.handleChangeImg.bind(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.bindEvent();
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
handleClose(e) {
|
||||
this.props.onClose();
|
||||
}
|
||||
|
||||
resizeImg(imgSrc) {
|
||||
let img = new Image();
|
||||
img.src = imgSrc;
|
||||
img.onload = () => {
|
||||
let width = 0;
|
||||
let height = 0;
|
||||
let imgWidth = img.width;
|
||||
let imgHeight = img.height;
|
||||
let aspectRatio = imgWidth / imgHeight;
|
||||
if (aspectRatio > 1) {
|
||||
width = Math.min(window.innerWidth * .9, imgWidth);
|
||||
height = (width / imgWidth) * imgHeight;
|
||||
}else {
|
||||
height = Math.min((window.innerHeight - 52) * .8, imgHeight);
|
||||
width = (height / imgHeight) * imgWidth;
|
||||
}
|
||||
let left = ( window.innerWidth - width ) / 2;
|
||||
let top = (window.innerHeight - height) / 2;
|
||||
handleChangeImg(newIndex: number) {
|
||||
let newState = this.state;
|
||||
newState.activeIndex = newIndex;
|
||||
this.setState(newState);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ViewerProps) {
|
||||
if (this.state.activeIndex !== nextProps.activeIndex) {
|
||||
this.setState({
|
||||
width: width,
|
||||
left: left,
|
||||
top: top,
|
||||
activeIndex: nextProps.activeIndex,
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
handleResize(e) {
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
}
|
||||
|
||||
handleMouseDown(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.setState({
|
||||
isMouseDown: true,
|
||||
mouseX: e.nativeEvent.pageX,
|
||||
mouseY: e.nativeEvent.pageY,
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseMove(e) {
|
||||
if (this.state.isMouseDown) {
|
||||
let diffX = e.x - this.state.mouseX;
|
||||
let diffY = e.y - this.state.mouseY;
|
||||
this.setState({
|
||||
top: this.state.top + diffY,
|
||||
left: this.state.left + diffX,
|
||||
mouseX: e.x,
|
||||
mouseY: e.y,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleMouseUp(e) {
|
||||
this.setState({
|
||||
isMouseDown: false,
|
||||
});
|
||||
}
|
||||
|
||||
handleMouseScroll(e) {
|
||||
let direct: 0 | 1 | -1 = 0;
|
||||
if (e.wheelDelta) {
|
||||
direct = e.wheelDelta > 0 ? 1 : -1;
|
||||
}else if (e.detail) {
|
||||
direct = e.detail > 0 ? 1 : -1;
|
||||
}
|
||||
if (direct !== 0) {
|
||||
this.setState({
|
||||
width: this.state.width + direct * this.state.width * 0.05,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bindEvent(remove?: boolean) {
|
||||
let funcName = 'addEventListener';
|
||||
if (remove) {
|
||||
funcName = 'removeEventListener';
|
||||
}
|
||||
document[funcName]('mousewheel', this.handleMouseScroll, false);
|
||||
document[funcName]('click', this.handleMouseUp, false);
|
||||
document[funcName]('mousemove', this.handleMouseMove, false);
|
||||
window[funcName]('resize', this.handleResize, false);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: ViewerCoreProps) {
|
||||
if (this.props.imgSrc !== nextProps.imgSrc) {
|
||||
this.resizeImg(nextProps.imgSrc);
|
||||
}
|
||||
if (!this.props.visible && nextProps.visible) {
|
||||
this.bindEvent();
|
||||
this.resizeImg(this.props.imgSrc);
|
||||
}
|
||||
if (this.props.visible && !nextProps.visible) {
|
||||
this.bindEvent(true);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
let imgStyle: React.CSSProperties = {
|
||||
width: `${this.state.width}px`,
|
||||
marginTop: `${this.state.top}px`,
|
||||
marginLeft: this.state.left ? `${this.state.left}px` : 'auto',
|
||||
};
|
||||
|
||||
let imgClass = '';
|
||||
if (!this.state.isMouseDown) {
|
||||
imgClass = `${this.props.prefixCls}-transition`;
|
||||
let activeImgSrc = '';
|
||||
if (this.props.images.length > 0) {
|
||||
activeImgSrc = this.props.images[this.state.activeIndex];
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${this.props.prefixCls}-core`}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
>
|
||||
<img
|
||||
ref="img"
|
||||
className={imgClass}
|
||||
src={this.props.imgSrc}
|
||||
style={imgStyle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
<div style={{display: this.props.visible ? 'block' : 'none'}}>
|
||||
<div className={`${this.prefixCls}-mask`}></div>
|
||||
<div className={`${this.prefixCls}-close`} onClick={this.handleClose.bind(this)}></div>
|
||||
<ViewerCavans
|
||||
prefixCls={this.prefixCls}
|
||||
imgSrc={activeImgSrc}
|
||||
visible={this.props.visible}
|
||||
/>
|
||||
<div className={`${this.prefixCls}-footer`}>
|
||||
<ViewerNav
|
||||
prefixCls={this.prefixCls}
|
||||
images={this.props.images}
|
||||
activeIndex={this.state.activeIndex}
|
||||
onChangeImg={this.handleChangeImg}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -8,3 +8,5 @@ interface ViewerProps {
|
||||
/** 当前图像index */
|
||||
activeIndex?: number;
|
||||
}
|
||||
|
||||
export default ViewerProps;
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import Viewer from './Viewer';
|
||||
|
||||
export default class ViewerWrap extends React.Component<ViewerProps, any> {
|
||||
private container: HTMLDivElement;
|
||||
private component: React.ReactNode;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.container = null;
|
||||
this.component = null;
|
||||
}
|
||||
|
||||
renderViewer() {
|
||||
if (this.props.visible || this.component) {
|
||||
if (!this.container) {
|
||||
this.container = document.createElement('div');
|
||||
}
|
||||
document.body.appendChild(this.container);
|
||||
let instance = this;
|
||||
ReactDOM.unstable_renderSubtreeIntoContainer(
|
||||
this,
|
||||
<Viewer
|
||||
{...this.props}
|
||||
/>,
|
||||
this.container,
|
||||
function () {
|
||||
instance.component = this;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
removeViewer() {
|
||||
if (this.container) {
|
||||
const container = this.container;
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
container.parentNode.removeChild(container);
|
||||
this.container = null;
|
||||
this.component = null;
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.props.visible) {
|
||||
this.props.onClose();
|
||||
this.removeViewer();
|
||||
} else {
|
||||
this.removeViewer();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.renderViewer();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.renderViewer();
|
||||
}
|
||||
|
||||
render() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
3
src/index.tsx
Normal file
3
src/index.tsx
Normal file
@ -0,0 +1,3 @@
|
||||
import Viewer from './Viewer';
|
||||
|
||||
export default Viewer;
|
||||
@ -29,7 +29,7 @@
|
||||
z-index: @zIndex;
|
||||
}
|
||||
|
||||
&-core {
|
||||
&-cavans {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
@ -38,7 +38,7 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&-core > img {
|
||||
&-cavans > img {
|
||||
display: block;
|
||||
margin: 15px auto;
|
||||
width: auto;
|
||||
|
||||
68
webpack.config.prop.js
Normal file
68
webpack.config.prop.js
Normal file
@ -0,0 +1,68 @@
|
||||
const webpack = require('atool-build/lib/webpack');
|
||||
var path = require('path');
|
||||
|
||||
const packageName = require(path.join(process.cwd(), 'package.json')).name;
|
||||
|
||||
const entry = './src/index.tsx';
|
||||
|
||||
module.exports = function (webpackConfig) {
|
||||
|
||||
webpackConfig.entry = Object.assign({}, webpackConfig.entry, {
|
||||
['index.min']: entry,
|
||||
});
|
||||
|
||||
webpackConfig.externals = {
|
||||
react: {
|
||||
root: 'React',
|
||||
commonjs2: 'react',
|
||||
commonjs: 'react',
|
||||
amd: 'react',
|
||||
},
|
||||
'react-dom': {
|
||||
root: 'ReactDOM',
|
||||
commonjs2: 'react-dom',
|
||||
commonjs: 'react-dom',
|
||||
amd: 'react-dom',
|
||||
},
|
||||
};
|
||||
|
||||
webpackConfig.output = {
|
||||
path: path.resolve(__dirname, './dist'),
|
||||
filename: '[name].js',
|
||||
library: packageName,
|
||||
libraryTarget: 'umd',
|
||||
};
|
||||
|
||||
webpackConfig.plugins.some(function (plugin, i) {
|
||||
if (plugin instanceof webpack.optimize.CommonsChunkPlugin) {
|
||||
webpackConfig.plugins.splice(i, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
const uncompressedWebpackConfig = Object.assign({}, webpackConfig);
|
||||
|
||||
uncompressedWebpackConfig.entry = {
|
||||
[`index`]: entry,
|
||||
};
|
||||
|
||||
uncompressedWebpackConfig.plugins = webpackConfig.plugins.filter((plugin) => {
|
||||
const ret = !(plugin instanceof webpack.optimize.UglifyJsPlugin);
|
||||
return ret;
|
||||
});
|
||||
|
||||
uncompressedWebpackConfig.plugins = uncompressedWebpackConfig.plugins.filter((plugin) => {
|
||||
const ret = !(plugin instanceof webpack.DefinePlugin);
|
||||
return ret;
|
||||
});
|
||||
|
||||
uncompressedWebpackConfig.plugins.push(new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('development'),
|
||||
}));
|
||||
|
||||
return [
|
||||
webpackConfig,
|
||||
uncompressedWebpackConfig,
|
||||
];
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user