diff --git a/projects/app/src/components/Markdown/img/Image.tsx b/projects/app/src/components/Markdown/img/Image.tsx index 3bcf19a3b..2f0bd8d94 100644 --- a/projects/app/src/components/Markdown/img/Image.tsx +++ b/projects/app/src/components/Markdown/img/Image.tsx @@ -1,4 +1,4 @@ -import React, { WheelEventHandler, useState } from 'react'; +import React, { WheelEventHandler, useState, MouseEventHandler, TouchEventHandler, useRef } from 'react'; import { Box, Image, @@ -11,11 +11,32 @@ import { } from '@chakra-ui/react'; const MdImage = ({ src }: { src?: string }) => { + const imgRef = useRef(null); const [isLoading, setIsLoading] = useState(true); const [succeed, setSucceed] = useState(false); const { isOpen, onOpen, onClose } = useDisclosure(); const [scale, setScale] = useState(1); + const [positionLeft, setPositionLeft] = useState(0) + const [positionTop, setPositionTop] = useState(0) + const [store] = useState({ + scale: 1, + moveable: false, + pageX: 0, + pageY: 0, + pageX2: 0, + pageY2: 0, + originScale: 1 + }) + + // 自定义Modal关闭事件 + const customOnClose = (): void => { + setPositionLeft(0) + setPositionTop(0) + setScale(1) + onClose() + } + const handleWheel: WheelEventHandler = (e) => { setScale((prevScale) => { const newScale = prevScale + e.deltaY * 0.5 * -0.01; @@ -25,6 +46,153 @@ const MdImage = ({ src }: { src?: string }) => { }); }; + const handleTouchStart: TouchEventHandler = (event) => { + let touches = event.touches; + let events = touches[0];//单指 + let events2 = touches[1];//双指 + if (touches.length == 1) {// 单指操作 + store.pageX = events.pageX + store.pageY = events.pageY + store.moveable = true; + } else { + // 第一个触摸点的坐标 + store.pageX = events.pageX; + store.pageY = events.pageY; + store.moveable = true; + if (events2) { + store.pageX2 = events2.pageX; + store.pageY2 = events2.pageY; + } + store.originScale = store.scale || 1; + } + } + + const handleTouchMove: TouchEventHandler = (event) => { + if (!store.moveable) { + return; + } + let touches = event.touches; + let events = touches[0]; + let events2 = touches[1]; + //最大移动距离 + let moveMaxWith = (Number(imgRef.current?.width) * scale - window.innerWidth) / 2; + let moveMaxHeight = (Number(imgRef.current?.height) * scale - window.innerHeight) / 2; + + if (touches.length == 1) { + //未放大,不移动图片 + if (scale <= 1) + return; + + let pageX = store.pageX; + let pageY = store.pageY + let pageX2 = events.pageX; + let pageY2 = events.pageY; + + let newLeft = positionLeft + pageX2 / 20 - pageX / 20; + let newTop = positionTop + pageY2 / 20 - pageY / 20; + if (Math.abs(newLeft) > moveMaxWith) { + if (newLeft > 0) { + newLeft = moveMaxWith; + } + else { + newLeft = 0 - moveMaxWith; + } + } + // 放大倍数没超过屏高 + if (moveMaxHeight < 0) { + newTop = 0; + } + else if (Math.abs(newTop) > moveMaxHeight) { + if (newTop > 0) { + newTop = moveMaxHeight; + } + else { + newTop = 0 - moveMaxHeight; + } + } + + //控制图片移动 + setPositionLeft(newLeft) + setPositionTop(newTop) + } else { + // 双指移动 + if (events2) { + // 第2个指头坐标在touchmove时候获取 + store.pageX2 = events2.pageX; + store.pageY2 = events2.pageY; + + // 获取坐标之间的距离 + let getDistance = function (start: any, stop: any) { + //用到三角函数 + return Math.hypot(stop.x - start.x, + stop.y - start.y); + }; + // 双指缩放比例计算 + let zoom = getDistance({ + x: events.pageX, + y: events.pageY + }, { + x: events2.pageX, + y: events2.pageY + }) / getDistance({ + x: store.pageX, + y: store.pageY + }, { + x: store.pageX2, + y: store.pageY2 + }); + // 应用在元素上的缩放比例 + let newScale = store.originScale * zoom; + + // 缩放比例限制 + if (newScale > 10) { + newScale = 10; + } + if (newScale <= 1) { + newScale = 1; + } + + store.scale = newScale; + // 图像应用缩放效果 + setScale(newScale); + // 如果是缩小图片,则限制移动的距离 + if (Math.abs(positionLeft) > moveMaxWith) { + if (positionLeft > 0) { + setPositionLeft(moveMaxWith); + } + else { + setPositionLeft(0 - moveMaxWith); + } + } + + if (moveMaxHeight < 0) { + setPositionTop(0); + } + else if (Math.abs(positionTop) > moveMaxHeight) { + if (positionTop > 0) { + setPositionTop(moveMaxHeight); + } + else { + setPositionTop(0 - moveMaxHeight); + } + } + } + } + + } + + const handleTouchEnd: TouchEventHandler = (e) => { + store.moveable = false; + store.pageX2 = 0; + store.pageY2 = 0; + } + + const handleTouchCancel: TouchEventHandler = (e) => { + store.moveable = false; + store.pageX2 = 0; + store.pageY2 = 0; + } + return ( <> { onOpen(); }} /> - + { fallbackSrc={'/imgs/errImg.png'} fallbackStrategy={'onError'} objectFit={'contain'} + position={'relative'} + top={positionTop + 'px'} + left={positionLeft + "px"} onWheel={handleWheel} + onTouchStart={handleTouchStart} + onTouchMove={handleTouchMove} + onTouchEnd={handleTouchEnd} + onTouchCancel={handleTouchCancel} />