图片和文件预览组件(部分源码),可拖动,缩小,放大。 #41

简介: 图片和文件预览组件(部分源码),可拖动,缩小,放大。 #41

源码


/*
 * 图片预览组件
 * @Author: Jiang 
 * @since: 2018-12-21 13:54:00 
 */
import React from 'react';
import { Modal, Icon } from 'antd';
import PropTypes from 'prop-types';
import config from 'Common/config';
import { redirect } from 'Common/util';
import './index.less';
// 判断游览器
const USER_AGENT = navigator.userAgent;
export default class PreviewImage extends React.Component {
    constructor(props) {
        super(props);
        // 是否按下
        this.isDown = false;
        this.IMG_WIDTH = 300;
        this.IMG_HEIGHT = 300;
        // 放大或缩小比例
        this.zoomOut = 0;
        this.state = {
            // 移动的时候,更改距离和放大缩小
            imgStyle: {
                position: 'relative',
                left: '0px',
                top: '0px'
            },
            // 放大缩小比例
            num: 0,
            // 是否显示缩小放大比例
            isShowRate: false,
            // true 为图片模式, false为pdf|word|xls预览模式
            isShowPreView: false
        };
        // 图片按下事件
        this.handlerImgDown = this.handlerImgDown.bind(this);
        // 图片加载
        this.onload = this.onload.bind(this);
    }
    componentDidMount() {
        const { url, destruction } = this.props;
        // true 打开弹窗 false 预览pdf or xls or word
        if(this.getType(url)) {
            const getType = this.getType(url);
            if(document.addEventListener && USER_AGENT.indexOf('Firefox') > -1) {
                document.addEventListener('DOMMouseScroll', this.onScroll, false); 
            } else {
                document.body.onmousewheel = this.onScroll;
            }
            this.setState({
                isShowPreView: getType
            });
        } else {
            this.openUrl(url);
            destruction();
        }
    }
    // 销毁
    componentWillUnmount() {
        document.onmousemove = null;
        document.onmouseup = null;
        document.body.onmousewheel = null;
        document.removeEventListener('DOMMouseScroll', this.onScroll, false); 
    }
    // 取得文件后缀名
    getFileSuffix = url => {
        const fileArr = url.split('.');
        return fileArr[fileArr.length - 1].toLocaleLowerCase();
    }
    // 根据文件类型是跳转页面还是预览图片
    getType = url => {
        if(url) {
            let suffix = this.getFileSuffix(url);
            if(suffix.indexOf('?') > -1) {
                suffix = suffix.split('?')[0];
            }
            return config.FILE_TYPE.IMAGE.indexOf(suffix) > -1;
        }
    }
    // 缩小或放大
    onScroll = (e) => {
        const { num, imgStyle } = this.state;
        const event = e || window.event;
        let style = {};
        let wheelDelta;
        let wheelDeltaNumber;
        let rate;
        // firefox and safari 的滚动轴值不一样,其余的都是1200
        if(USER_AGENT.indexOf('Firefox') > -1) {
            // wheelDelta = 3 or -3
            wheelDelta = event.detail;
            wheelDeltaNumber = 30;
        } else if(USER_AGENT.indexOf('Safari') > -1) {
            // wheelDelta = 360 or -360
            wheelDelta = event.wheelDelta;
            wheelDeltaNumber = 3600;
        } else {
            // wheelDelta = 120 or -120
            wheelDelta = event.wheelDelta;
            wheelDeltaNumber = 1200;
        }
        // 如果比例达到100或者为1的时候,停止继续放大或缩小 > 0 放大, < 0 缩小
        if((num === 100 && wheelDelta > 0) || (num === 1 && wheelDelta < 0)) {
            return;
        }
        // 计算放大或缩小比例
        this.zoomOut = (this.zoomOut + wheelDelta / wheelDeltaNumber);
        style.width = this.IMG_WIDTH * (1 + this.zoomOut) + 'px';
        style.height = this.IMG_HEIGHT * (1 + this.zoomOut) + 'px';
        style.top = imgStyle.top;
        style.left = imgStyle.left;
        style.position = 'relative';
        // 换算成百分比,显示
        if(this.zoomOut.toFixed(1) * 100 < 0) {
            rate = 10 + (this.zoomOut.toFixed(1) * 100) / 10;
        } else {
            rate = parseInt(this.zoomOut.toFixed(1) * 100);
        }
        // 不允许出现百分之0
        rate = rate === 0 ? rate = 10 : rate;
        this.setState({
            imgStyle: style,
            num: rate,
            isShowRate: true
        });
    }
    // 打开pdf、xls、word等文件
    openUrl = url => {
        if(url) {
            redirect(url, '_blank'); 
        }
    }
    // 图片按下事件
    handlerImgDown = (e) => {
        e.preventDefault();
        const previewImg = document.getElementsByClassName('preview-image');
        this.isDown = true;
        this.currentX = e.clientX;
        this.currentY = e.clientY;
        this.offsetLeft = parseInt(previewImg[0].offsetLeft);
        this.offsetTop = parseInt(previewImg[0].offsetTop);
        this.handlerImgMove();
        // 移除事件
        document.onmouseup = () => {
            document.onmousemove = null;
            document.onmouseup = null;
            this.isDown = false;
        };
    }
    // 图片移动
    handlerImgMove = () => {
        document.onmousemove = (e) => {
            if(this.isDown) {
                const { imgStyle } = this.state;
                let style = {};
                style.width = imgStyle.width + 'px';
                style.height = imgStyle.height + 'px';
                style.left = e.clientX - (this.currentX - this.offsetLeft) + 'px';
                style.top = e.clientY - (this.currentY - this.offsetTop) + 'px';
                style.position = 'relative';
                this.setState({
                    imgStyle: style
                });
            }
        };
    }
    // 获取图片真实宽高
    onload = (e) => {
        this.IMG_WIDTH = e.target.width;
        this.IMG_HEIGHT = e.target.height;
    }
    render() {
        const { imgStyle, isShowRate, num } = this.state;
        const { url, hideModal } = this.props;
        const { isShowPreView } = this.state;
        return (
            <div className="c-c-preview-image">
                {
                    isShowPreView &&
                    <Modal
                        wrapClassName="c-c-preview-image-modal"
                        visible={true}
                        centered={true}
                        closable={false}
                        width="100%"
                        onCancel={hideModal}
                        footer={null}
                    >
                        <img
                            draggable="false"
                            alt="img"
                            className="preview-image select-cursor"
                            onMouseDown={this.handlerImgDown}
                            src={url}
                            onLoad={this.onload}
                            style={imgStyle}
                        />
                        {
                            isShowRate && 
                            <div className="viewer-tooltip">{num}%</div>
                        }
                    </Modal>
                }
                <Icon onClick={hideModal} className="close" type="close" />
            </div>
        );
    }
}
PreviewImage.propTypes = {
    // src or pdf or xls or word
    url: PropTypes.string,
};


@import "../../../common/asset/variable.less";
.c-c-preview-image {
    .close {
        position: fixed;
        padding: 15px;
        top: 0px;
        right: 0px;
        font-size: 32px;
        color: #333;
        cursor: pointer;
        z-index: 1002;
    }
}
.c-c-preview-image-modal {
    overflow: hidden;
    user-select: none;
    .viewer-tooltip {
        background-color: rgba(0,0,0,.8);
        border-radius: 10px;
        color: #fff;
        font-size: 12px;
        height: 20px;
        left: 50%;
        line-height: 20px;
        margin-left: -25px;
        margin-top: -10px;
        position: absolute;
        text-align: center;
        top: 50%;
        width: 50px;
        z-index: 1001;
    }
    .ant-modal-close-x {
        font-size: 32px;
    }
    .select-cursor {
        cursor: move;
        cursor: grab;
    }
    .ant-modal-close {
        position: fixed;
        color: #333;
    }
    .ant-modal-body {
        padding: 0px;
    }
    .ant-modal-content {
        background-color: transparent;
        box-shadow: none;
        position: absolute;
        user-select: none;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
    }
}
目录
相关文章
Elementui-Image组件,单个图片点击放大展示
Elementui-Image组件,单个图片点击放大展示
|
1月前
|
索引
【sgPhotoPlayer】自定义组件:图片预览,支持点击放大、缩小、旋转图片
【sgPhotoPlayer】自定义组件:图片预览,支持点击放大、缩小、旋转图片
|
1月前
|
JavaScript 容器
富文本的图片添加点击放大功能
思路:富文本加载后,dom出全部img元素,然后各自单独添加点击事件
103 3
|
1月前
win32编程 -- 滚轮实现放大或缩小图片
win32编程 -- 滚轮实现放大或缩小图片
22 0
|
1月前
|
测试技术 定位技术
【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动
【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动
|
Web App开发 移动开发 前端开发
移动端图片操作(二)——预览、旋转、合成
在上一节中已经提到了预览,预览可以通过data: URL格式或URL对象。
移动端图片操作(二)——预览、旋转、合成
|
12月前
|
JavaScript 前端开发 容器
手写图片拖拽、鼠标点位缩放
如题,无关技术背景,什么vue、react自己想用就用,这就是js加一点点css实现,意思就是可以任意迁。
160 0
|
计算机视觉
Qt实用技巧:代码中QIcon缩放(QPixmap的手动放大和QIcon自动缩小)
Qt实用技巧:代码中QIcon缩放(QPixmap的手动放大和QIcon自动缩小)
Qt实用技巧:代码中QIcon缩放(QPixmap的手动放大和QIcon自动缩小)
|
C++
duilib corner属性的贴图技巧——让图片自动贴到控件的的某一边或者一角并自适应控件的大小
转载请说明原出处,谢谢~~          Duilib给控件贴图功能可以附带多个属性,各个属性的配合可以达到许多效果。以下是duilib支持的所有贴图属性: 贴图描述:          Duilib的表现力丰富很大程度上得益于贴图描述的简单强大。
1734 0
|
移动开发 计算机视觉 Python
把图片按照指定大小剪裁,不够的地方加黑边
1 # -*- coding: utf-8 -*- 2 3 import os 4 import sys 5 import numpy as np 6 import cv2 7 8 IMAGE_SIZE = 224 9 10 11 # 按照指定图像大小调整尺寸 12 de...
1223 0

热门文章

最新文章