屏幕錄制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數據需要乘以2watermarkRule.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,所以頁面渲染數據需要除2const 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}><RndmaxHeight={375}maxWidth={375}size={rndSize}position={rndPosition}bounds="parent"onDragStart={this.handleDragStart}onDragStop={this.handleDragStop}onResizeStart={this.handleResizeStart}onResizeStop={this.handleResizeStop}resizeParentMore={true} // 如果需要阻止父容器跟隨大小變化,可以設置為falseenableResizing={{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}><imgsrc={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}
希望以上代碼對大家有幫助??