与使用 getBoundingClientRect 之前放置的位置相比,元素的位置不会保持不变

The position of the elements do not remain the same compared to their previous placed position using getBoundingClientRect

我将一些元素拖放到 div(包含背景图片)上并上传内容。在上传之前,我计算了丢弃的元素顶部、左侧位置 wrt 到父 div,这样当它们与正在传递的背景图像(png 或 jpeg)。但问题是元素放置的位置与其初始放置位置相比略有不同。

HTML 上传前

<div id="toget"
     class="dropzone"
     [ngStyle]="{'width':'100%',
                 'background-image': 'url('+urlFloorZoneIn+')',
                 'background-repeat': 'no-repeat',
                 'background-position': 'center',
                 'background-size': '100% 100%',
                 'border':'1px solid black',
                 'height':'340px',
                 'position': 'relative'}">

    <div class="box"
         *ngFor="let existingZone of existingDroppedItemZoneIn"
         [ngStyle] = "{'position': 'absolute' , 
                       'top.%':existingZone.spans[1], 
                       'left.%':existingZone.spans[0]}"
         (dragEnd)="onDragEnd($event,existingZone)">

          {{ existingZone.main }}
        <span>{{existingZone.spans[0]}}</span>
        <span>{{existingZone.spans[1]}}</span>

    </div>

</div>

计算左上角位置的TS代码

onDragEnd(event,b){


    const existingMovingBlockIndex = (this.existingDroppedItemZoneIn.indexOf(this.currentBox));
    if(existingMovingBlockIndex>-1){
        console.log(b)
        console.log(`got drag end x and y ${event.clientX} ${event.clientY}`)
        console.log(this.dr.onDragMove);

        const container_rect = this.parentparent.nativeElement.getBoundingClientRect();
        this.mouse.x = event.clientX - container_rect.left;
        this.mouse.y = event.clientY - container_rect.top;

        const{width,height} = this.parentparent.nativeElement.getBoundingClientRect();
        const perc_x = this.mouse.x / width * 100;
        const perc_y = this.mouse.y / height * 100;

        this.left = perc_x-5;
        this.topLeft = []
        this.topLeft.push(this.left);

        this.top = perc_y-5;
        this.topLeft.push(this.top);

        this.existingDroppedItemZoneIn[existingMovingBlockIndex].spans[0] = (perc_x);
        this.existingDroppedItemZoneIn[existingMovingBlockIndex].spans[1] = (perc_y);


    }
}

CSS

.box {
  width: 10%;
  height: 10%;
  background: rgba(254, 249, 247, 1);
  border: 1.5px solid #e24301;
  margin: 5px;
  line-height: 100px;
  text-align: center;
  font-size: 0.8rem;
}

.dropzone {
  padding: 20px;
  margin: 20px 0;
  background: lightgray;
  min-height: 200px;
  border: 1px solid black;
 }

在渲染之前,我获取了上面上传的 HTML 内容的顶部、左侧、背景图像值,并应用了 background-image top, left 值渲染下面的内容

不同屏幕渲染后

[![在此处输入图片描述][2]][2]

<ul>
    <li #allFloors
       *ngFor="let floor of buildings.floors"
       [ngStyle]="{'width': singleFloorFlagStyle ?'40%':'100%',
                   'background-image': 'url('+floor.urlFloorZoneIn+')', 
                   'background-repeat': 'no-repeat',
                   'background-position': 'center',
                   'background-size': '100% 100%',
                   'border':'1px solid black',
                   'height': singleFloorFlagStyle ? '340px' : '700px', 
                   'position': 'relative', 'max-width': '80%'}"
                   [ngClass]="{'width':'80% !important'}">

            <span (click)="loadFloorInfo(floor._id)">{{ floor.name }}</span>
            <div class="fs-heatmap-wrapper__content__box"
                *ngFor="let existingZone of floor.droppeditem"
                [ngStyle]="{'position':'absolute',
                            'top.%': existingZone.spans[1],
                            'left.%': existingZone.spans[0]}">

                {{ existingZone.main }}
             </div>      
    </li>
</ul>

CSS

.fs-heatmap-wrapper {
display: grid;
*min-height: 800px;
&__content {
    padding: 70px 40px 0;
    min-height: 300px;
    ul {
        margin: 0;
        padding: 0;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        li {
            list-style: none;
            min-width: 48%;
            margin: 12px;
            margin-bottom: 2.5%;
            span {
                cursor: pointer;
                background: #fff;
                text-align: left;
                font-weight: 800;
                font-size: 0.9rem;
                letter-spacing: 0.05rem;
                position: relative;
                top: -30px;
            }
        }
    }

&__box{
width: 100px;       
height: 100px;      
background: rgba(254, 249, 247, 1);     
border: 1.5px solid #e24301;        
margin: 5px;        
line-height: 100px;     
text-align: center;     
font-size: 0.8rem;

    }
  }        
}

这个问题的主要原因是您在 % 中提供的顶部和左侧 属性。不要将值转换为 %,而是尝试直接以像素为单位使用它们。

C - 可拖动元素,P - 放置区父元素

问题是您使用鼠标的指针位置来计算 C 相对于 P 的新位置,而 C 位置的实际来源是:

C.getBoundingClientRect().left - P.parent.getBoundingClientRect().left

鼠标指针可以放在 C 上的任何位置。假设我通过将鼠标指向 C 的中心来开始拖动 C,所以您得到的 event.clientX 不是从 C 开始的更新位置相对于客户端呈现,但它是:

(clientPosition of C + (clientPosition of Mouse Pointer - clientPosition of C))

肯定不是C的ClientPosition

所以只要使用第一个公式就可以纠正你的立场。您可以为可拖动元素分配 id,然后访问它们。

此外,在您的 Stackblitz 示例中,您在拖动结束后对拖动的元素同时使用变换和位置,这也会增加不正确的位置。使用其中之一。