react 对img图片进行放大 缩小 拖拽

javascript 复制代码
import React, { Component } from 'react';
import BaseComponent from "../../../../base/BaseComponent";
import zoomInIcon from "./images/zoom-in.png";
import zoomOutIcon from "./images/zoom-out.png";

export default class DetailPicture extends BaseComponent {
    static defaultProps = {};
    static propTypes = {};

    constructor(props) {
        super(props);
        this.state = {
            zoomLevel: 100, // 初始缩放级别为100%
            dragging: false,
            offsetX: 0,
            offsetY: 0,
            translateX: 0,
            translateY: 0,
            lastTranslateX: 0,
            lastTranslateY: 0,
            scale: 1, // 缩放比例
        };
    }

    handleZoomIn = () => {
        // 将缩放级别增加20%
        this.setState(prevState => ({
            zoomLevel: Math.min(prevState.zoomLevel + 20, 500),
            scale: (prevState.zoomLevel + 20) / 100,
        }));
    };

    handleZoomOut = () => {
        // 将缩放级别减小20%
        this.setState(prevState => ({
            zoomLevel: Math.max(prevState.zoomLevel - 20, 20),
            scale: (prevState.zoomLevel - 20) / 100,
        }));
    };

    handleMouseDown = (event) => {
        event.preventDefault();
        this.setState({
            dragging: true,
            offsetX: event.clientX,
            offsetY: event.clientY,
            lastTranslateX: this.state.translateX,
            lastTranslateY: this.state.translateY,
        });
        document.addEventListener('mousemove', this.handleMouseMove);
        document.addEventListener('mouseup', this.handleMouseUp);
    };

    handleMouseMove = (event) => {
        if (this.state.dragging) {
            const { offsetX, offsetY, lastTranslateX, lastTranslateY, scale } = this.state;
            const dx = (event.clientX - offsetX) / scale;
            const dy = (event.clientY - offsetY) / scale;
            this.setState({
                translateX: lastTranslateX + dx,
                translateY: lastTranslateY + dy,
            });
        }
    };

    handleMouseUp = () => {
        this.setState({ dragging: false });
        document.removeEventListener('mousemove', this.handleMouseMove);
        document.removeEventListener('mouseup', this.handleMouseUp);
    };


    render() {
        const { detailData = {} } = this.props;
        const { storageFile = {} } = detailData;
        const { path = "" } = storageFile;
        const { scale , translateX , translateY} = this.state;

        return (
            <div style={{ position: 'relative', width: '100%', height: '100%', display: 'flex' }}>
                <img
                    src={path}
                    style={{
                        maxWidth: '100%',
                        maxHeight: '100%',
                        margin: 'auto',
                        transform: `scale(${scale}) translate(${translateX}px, ${translateY}px)`, // 根据缩放级别和平移应用变换
                        transition: 'transform 0.3s ease-in-out', // 添加平滑的过渡效果
                        cursor: this.state.dragging ? 'grabbing' : 'grab',
                    }}
                    id={this.props.id}
                    onMouseDown={this.handleMouseDown}
                />

                <div style={{ position: 'absolute', top: 10, right: 10, zIndex: 1 }}>
                    <img
                        src={zoomOutIcon}
                        alt="Zoom In"
                        onClick={this.handleZoomIn}
                        style={{ cursor: 'pointer', marginRight: '5px' }}
                    />
                    <img
                        src={zoomInIcon}
                        alt="Zoom Out"
                        onClick={this.handleZoomOut}
                        style={{ cursor: 'pointer' }}
                    />
                </div>
            </div>
        );
    }
}

效果展示

可放大 缩小 并且拖拽

相关推荐
梦曦i3 小时前
@meng-xi/create-uni-app vs unibest:轻量脚手架与重型框架的定位之争
前端·uni-app
平头哥技术团队3 小时前
Day 10 | 工欲善其事:VS Code 配置与项目归档
android·开发语言·前端·javascript·html·交互
乌恩大侠4 小时前
GH200 新增 NVMe SSD 分区、格式化与挂载完整流程
运维·服务器·前端
yume_sibai4 小时前
Element Plus 数据展示组件完全指南(15个核心组件)
前端·javascript·vue.js
qiuhaipeng14 小时前
Claude code 升级后上下文长度变短问题
java·前端·数据库
zzz_23684 小时前
个人 AI 记忆如何跨工具复用:用 Markdown、索引和 Skill 搭一个可治理的记忆库
前端·人工智能·react.js·前端框架·agent·agent测评
剑之所向6 小时前
.NET 官方`System.Threading.Channels`
前端·javascript·数据库
计算机魔术师7 小时前
GPT-6 Astra幻觉砍到2%,却被一种老招数轻松绕过
前端
cjy0001117 小时前
2026AI 产品如何从一次性 Demo 变成可重复使用的业务工具?
前端·人工智能·fde
IT_陈寒7 小时前
React的状态更新坑得我差点加班到天亮
前端·人工智能·后端