屏幕录制2025-03-10 10.16.06
以下代码仅提供左侧可视化区域
右侧数据根据你们的存储数据来
大家直接看Rnd标签设置的属性即可!!!!!
/**
* 用户拖拽水印的最终位置信息
*/
export interface ProductWatermarkValue {
watermark?: ProductWatermarkManagerValue;
position: {
x: number; // 水印在图片上的水平位置
y: number; // 水印在图片上的垂直位置
};
size: {
width: number; // 水印的宽度(相对于商品图片的宽度)
height: number; // 水印的高度(相对于商品图片的高度)
};
}
/**
* 用户上传的水印详细信息,比如路径,宽高
*/
export interface ProductWatermarkManagerValue {
id: string;
name: string;
fileUrl: string;
width: number;
height: number;
type: ProductWatermarkManagerValueType;
}
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Rnd } from 'react-rnd';
import { Dispatch } from 'redux';
import { actions } from '@comall-backend-builder/core';
import { Entity } from '@comall-backend-builder/core/lib/parser';
import './index.less';
const prefix = 'product-main-image-watermark-preview';
interface Props {
dispatch: Dispatch;
entity: Entity;
componentId: any;
preview: any;
}
interface State {
/**
* 正在操作中
*/
isDragging: boolean;
}
export class productMainImageWatermarkRulePreview extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
isDragging: false,
};
}
getWatermarkRule = () => {
const { preview } = this.props;
return preview?.baseInfo?.watermarkRule;
};
getPreviewProduct = () => {
const { preview } = this.props;
const goods = preview?.baseInfo?.goods || [];
const isPreviewGoods = goods.find((item: any) => {
return item.isPreview;
});
return isPreviewGoods;
};
onChangeWatermarkRule = (ruleWatermark: any) => {
const { dispatch, componentId } = this.props;
dispatch(actions.formChangeAction(componentId, 'baseInfo.watermarkRule', ruleWatermark));
};
handleDragStart = (e: any) => {
e.preventDefault();
e.stopPropagation();
this.setState({
isDragging: true,
});
};
handleDragStop = (e: any, d: any) => {
e.preventDefault();
e.stopPropagation();
this.setState({
isDragging: false,
});
const watermarkRule = this.getWatermarkRule();
watermarkRule.position = {
x: d.x > 0 ? d.x * 2 : 0,
y: d.y > 0 ? d.y * 2 : 0,
};
this.onChangeWatermarkRule({ ...watermarkRule });
};
handleResizeStart = (e: any) => {
e.preventDefault();
e.stopPropagation();
this.setState({
isDragging: true,
});
};
handleResizeStop = (e: any, direction: any, ref: any, delta: any, position: any) => {
e.preventDefault();
e.stopPropagation();
this.setState({
isDragging: false,
});
const watermarkRule = this.getWatermarkRule();
const sizeWidth = ref.style.width.replace('px', '');
const sizeHeight = ref.style.height.replace('px', '');
//因为左侧模拟器是375px,后端存储的是750px的,所以Rnd数据需要乘以2
watermarkRule.size = {
width: `${sizeWidth * 2}px`,
height: `${sizeHeight * 2}px`,
};
watermarkRule.position = {
x: position.x > 0 ? position.x * 2 : 0,
y: position.y > 0 ? position.y * 2 : 0,
};
this.onChangeWatermarkRule({ ...watermarkRule });
};
render() {
const watermarkRule = this.getWatermarkRule();
if (!watermarkRule) {
return null;
}
const { position, size, watermark } = watermarkRule;
const previewGoods = this.getPreviewProduct();
const pic = previewGoods?.productPic || '';
const { isDragging } = this.state;
const style = {
backgroundImage: pic ? `url(${pic})` : undefined,
};
const sizeWidth = size && size.width ? size.width.replace('px', '') : 0;
const sizeHeight = size && size.height ? size.height.replace('px', '') : 0;
//因为后端存储的是750px的,左侧模拟器是375px,所以页面渲染数据需要除2
const rndSize = {
width: `${sizeWidth / 2}px`,
height: `${sizeHeight / 2}px`,
};
const rndPosition = {
x: position.x / 2,
y: position.y / 2,
};
console.log('存储大小size,position', size, position);
console.log('展示大小rndSize,rndPosition', rndSize, rndPosition);
const isDraggingStyle = {
opacity: isDragging ? 0.8 : 1,
border: isDragging ? '2px solid #1890ff' : undefined,
};
return (
<div className={prefix}>
<div className={`${prefix}__bg`} style={style}>
<Rnd
maxHeight={375}
maxWidth={375}
size={rndSize}
position={rndPosition}
bounds="parent"
onDragStart={this.handleDragStart}
onDragStop={this.handleDragStop}
onResizeStart={this.handleResizeStart}
onResizeStop={this.handleResizeStop}
resizeParentMore={true} // 如果需要阻止父容器跟随大小变化,可以设置为false
enableResizing={{
top: true,
right: true,
bottom: true,
left: true,
topRight: true,
bottomRight: true,
bottomLeft: true,
topLeft: true,
}}
resizeHandles={['se', 'sw', 'ne', 'nw']}
style={isDraggingStyle}
onClick={(e: any) => e.stopPropagation()}
lockAspectRatio={true}
>
<img
src={watermark?.fileUrl}
alt=""
style={{ width: '100%', height: '100%' }}
/>
</Rnd>
</div>
</div>
);
}
}
const mapStateToProps = (_state: any, props: any) => {
let preview = null;
let componentId = null;
const entityId = props.entity.id;
for (var compId in _state.components) {
const comp = _state.components[compId];
if (
(comp.type === 'CreateForm' || comp.type === 'EditForm') &&
comp.entityId === entityId
) {
preview = comp.fields;
componentId = compId;
}
}
return { preview: preview, componentId: componentId };
};
export const ProductMainImageWatermarkRulePreview = connect(mapStateToProps)(
productMainImageWatermarkRulePreview
);
.product-main-image-watermark-preview{
&__bg{
margin-right: 10px;
overflow: hidden;
width: 375px ;
min-width: 375px;
height: 375px;
position: relative;
border: 1px solid #ccc;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
}
开发过程中遇到的问题
1.在使用过程中,火狐浏览器出现一拖拽,就打开了浏览器新标签页
解决方案:在方法调用处理中新增以下两个代码
e.preventDefault();
e.stopPropagation();
2.在使用过程中,用户需要自己上传的水印在左侧渲染中,拉伸时,是等比例放大或缩小的,而不是用户自己控制拉伸大小
解决方案:Rnd标签设置属性
lockAspectRatio={true}
希望以上代码对大家有帮助❤️