fix: image viewer flick
This commit is contained in:
@@ -115,9 +115,7 @@ const SingleImage: React.FC<SingleImageProps> = (props) => {
|
|||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className="thumb-img"
|
className="thumb-img"
|
||||||
style={{
|
style={{ ...thumImgWrapStyle }}
|
||||||
...thumImgWrapStyle
|
|
||||||
}}
|
|
||||||
ref={imgWrapper}
|
ref={imgWrapper}
|
||||||
>
|
>
|
||||||
<>
|
<>
|
||||||
@@ -158,10 +156,11 @@ const SingleImage: React.FC<SingleImageProps> = (props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AutoImage
|
<AutoImage
|
||||||
|
style={{ objectFit: 'cover' }}
|
||||||
preview={preview}
|
preview={preview}
|
||||||
autoSize={autoSize}
|
autoSize={autoSize}
|
||||||
src={dataUrl}
|
src={dataUrl}
|
||||||
width={imgSize.width || 100}
|
width={imgSize.width || '100%'}
|
||||||
height={imgSize.height || 100}
|
height={imgSize.height || 100}
|
||||||
onLoad={handleOnLoad}
|
onLoad={handleOnLoad}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
.markdown-viewer {
|
.markdown-viewer {
|
||||||
font-family: var(--font-family) !important;
|
font-family: var(--font-family) !important;
|
||||||
|
word-wrap: break-word;
|
||||||
|
|
||||||
.hr {
|
.hr {
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const renderDistributionInfo = useCallback(
|
const renderDistributionInfo = useCallback(
|
||||||
(severList: any[], label: string) => {
|
(severList: any[]) => {
|
||||||
if (!severList.length) {
|
if (!severList.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -340,7 +340,7 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
>
|
>
|
||||||
<InfoCircleOutlined className="m-r-5" />
|
<InfoCircleOutlined className="m-r-5" />
|
||||||
{intl.formatMessage({
|
{intl.formatMessage({
|
||||||
id: label
|
id: 'models.table.acrossworker'
|
||||||
})}
|
})}
|
||||||
</Tag>
|
</Tag>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -468,12 +468,10 @@ const InstanceItem: React.FC<InstanceItemProps> = ({
|
|||||||
>
|
>
|
||||||
{renderOffloadInfo}
|
{renderOffloadInfo}
|
||||||
{renderDistributionInfo(
|
{renderDistributionInfo(
|
||||||
instanceData.distributed_servers?.rpc_servers || [],
|
instanceData.distributed_servers?.rpc_servers || []
|
||||||
'models.table.llamaAcrossworker'
|
|
||||||
)}
|
)}
|
||||||
{renderDistributionInfo(
|
{renderDistributionInfo(
|
||||||
instanceData.distributed_servers?.ray_actors || [],
|
instanceData.distributed_servers?.ray_actors || []
|
||||||
'models.table.vllmAcrossworker'
|
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
|
||||||
|
const ImageCanvas = ({ imageUrl }) => {
|
||||||
|
const canvasRef = useRef(null);
|
||||||
|
const [scale, setScale] = useState(1);
|
||||||
|
const [offset, setOffset] = useState({ x: 0, y: 0 });
|
||||||
|
const [image, setImage] = useState(null);
|
||||||
|
const requestRef = useRef();
|
||||||
|
|
||||||
|
// 加载图片
|
||||||
|
useEffect(() => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = imageUrl;
|
||||||
|
img.onload = () => {
|
||||||
|
setImage(img);
|
||||||
|
};
|
||||||
|
}, [imageUrl]);
|
||||||
|
|
||||||
|
// 绘制图片
|
||||||
|
const drawImage = () => {
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
if (image) {
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(offset.x, offset.y);
|
||||||
|
ctx.scale(scale, scale);
|
||||||
|
ctx.drawImage(image, 0, 0);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求下一帧绘制
|
||||||
|
requestRef.current = requestAnimationFrame(drawImage);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 启动动画循环
|
||||||
|
useEffect(() => {
|
||||||
|
requestRef.current = requestAnimationFrame(drawImage);
|
||||||
|
return () => cancelAnimationFrame(requestRef.current);
|
||||||
|
}, [image, scale, offset]);
|
||||||
|
|
||||||
|
// 处理滚轮事件
|
||||||
|
const handleWheel = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const { deltaY, clientX, clientY } = event;
|
||||||
|
const canvas = canvasRef.current;
|
||||||
|
const rect = canvas.getBoundingClientRect();
|
||||||
|
const mouseX = clientX - rect.left;
|
||||||
|
const mouseY = clientY - rect.top;
|
||||||
|
|
||||||
|
const zoomFactor = deltaY > 0 ? 0.9 : 1.1; // 缩小或放大
|
||||||
|
const newScale = scale * zoomFactor;
|
||||||
|
|
||||||
|
// 计算新的偏移量,确保以鼠标位置为中心缩放
|
||||||
|
const newOffsetX = mouseX - (mouseX - offset.x) * zoomFactor;
|
||||||
|
const newOffsetY = mouseY - (mouseY - offset.y) * zoomFactor;
|
||||||
|
|
||||||
|
setScale(newScale);
|
||||||
|
setOffset({ x: newOffsetX, y: newOffsetY });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<canvas
|
||||||
|
ref={canvasRef}
|
||||||
|
width={800}
|
||||||
|
height={600}
|
||||||
|
onWheel={handleWheel}
|
||||||
|
style={{ border: '1px solid black' }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ImageCanvas;
|
||||||
Reference in New Issue
Block a user