携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
示例
实现功能: 点击放大/缩小按钮实现画布内图片/其他shape跟随比例放大缩小
思路
-
其他实现思路 通过konva的scale相关api实现
-
我的方案: (因为有一些其他复杂shape等操作,所以采用该方案)
- 封装Stage组件,内含Image、shape等
- Stage组件外层容器,控制容器缩放比例
- Stage组件内部拿容器的ClientHeight、ClientWidth计算缩放比例
- 根据缩放比例对应处理相关shape的attr等属性值
关键代码
组件容器代码
<div className="image-priview"
ref={imgScrollBoxRef}
style={{ display: 'block', overflow: 'auto' }}
>
<div className="image-box" style={{ width: `${sizes.width}%`, height: `${sizes.height}%`, transform: `rotate(${sizes.deg}deg)`, margin: 'auto' }} ref={imageBoxRef}>
<div className="stage-view" id="stage-view" >
<ImageStage
ImageUrl={selectImgItem.image}
ImageWidth={selectImgItem.width}
ImageHeight={selectImgItem.height}
imageBox={imageBoxRef}
sizes={sizes}
ref={ImageStageRef}
/>
</div>
</div>
</div>
组件代码
useEffect(() => {
// 尺寸变化后重新计算坐标值
setWidth(ImageBox.current.clientWidth * sizes.width / lastSize.width);
setHeight(ImageBox.current.clientHeight * sizes.height / lastSize.height );
if (rectangles.length > 0) {
setShapeProps({
...shapeProps,
x: (shapeProps.x * sizes.width / lastSize.width),
y: (shapeProps.y * sizes.height / lastSize.height),
width: (shapeProps.width * sizes.width / lastSize.width),
height: (shapeProps.height * sizes.height / lastSize.height),
});
}
setLastSize(sizes);
}, [sizes]);
<Stage
ref={StageRef}
onMouseUp={onMouseUp}
onMousemove={onMousemove}
onMouseDown={onMouseDown}
rotation={0}
width={width}
height={height}
>
<Layer
width={width}
height={height}
>
{/* 图片底图图层 */}
<Image
width={width}
height={height}
ref={ImageRef}
image={image} />
<Rect
onClick={(e) => {
}}
onTap={(e) => {
}}
onDragStart={(e) => {
}}
onTransformStart={(e) => {
}}
{...shapeProps}
draggable={draggable}
onDragMove={(e) => {
}}
onDragEnd={(e) => {
}}
onTransform={(e) => {
const node = shapeRef.current;
const scaleX = node.scaleX();
const scaleY = node.scaleY();
node.scaleX(1);
node.scaleY(1);
onChange({
...shapeProps,
x: node.x(),
y: node.y(),
// set minimal value
width: Math.max(5, node.width() * scaleX),
height: Math.max(node.height() * scaleY),
});
}}
onTransformEnd={(e) => {
const node = shapeRef.current;
const scaleX = node.scaleX();
const scaleY = node.scaleY();
node.scaleX(1);
node.scaleY(1);
onChange({
...shapeProps,
x: node.x(),
y: node.y(),
// set minimal value
width: Math.max(5, node.width() * scaleX),
height: Math.max(node.height() * scaleY),
});
}}
/>
{isSelected &&
<Transformer
keepRatio={false} // 拖动四角不保存比例
ref={trRef}
rotateEnabled={false} // 禁止旋转
boundBoxFunc={(oldBox, newBox) => {
// limit resize
if (newBox.width < 5 || newBox.height < 5) {
return oldBox;
}
return newBox;
}}
/>
}
</Layer>
</Stage