渲染后将图像容器宽度与图像宽度匹配 - React

时间:2021-07-02 16:52:32

标签: javascript html css reactjs react-native

enter image description here 我正在使用 react-image-marker,它在 div 内的图像上叠加标记。

 <ImageMarker
     src={props.asset.url}
     markers={markers}
     onAddMarker={(marker) => setMarkers([...markers, marker])}
     className="object-fit-contain  image-marker__image"
 />

DOM 元素如下:

<div class=“image-marker”>
    <img src=“src” class=“image-marker__image” />
</div>

为了使垂直长的图像适合屏幕,我添加了 css 以包含 div 内的图像

.image-marker {
  width: inherit;
  height: inherit;
}

.image-marker__image {
  object-fit:contain !important;
  width: inherit;
  height: inherit;
}

但现在图像只是整个标记区域的一个子部分。由于可以添加超出图像边界的标记,这是我不想要的。

你认为我可以如何解决这个问题。加载图像后,如何更改父 div 的宽度以确保它们具有相同的大小并且标记保留在图像边界中。如果可能,请用代码说明

1 个答案:

答案 0 :(得分:0)

通过在 useLayoutEffect() 中添加事件监听器解决了这个问题。在渲染后计算图像大小信息并相应地调整父 div 尺寸。最初以及发生调整大小时。

如果您认为您有更好的解决方案。请指定。


    useLayoutEffect(() => {
        const getRenderedSize = (contains, cWidth, cHeight, width, height, pos) => {
            var oRatio = width / height,
                cRatio = cWidth / cHeight;
            return function () {
                if (contains ? (oRatio > cRatio) : (oRatio < cRatio)) {
                    this.width = cWidth;
                    this.height = cWidth / oRatio;
                } else {
                    this.width = cHeight * oRatio;
                    this.height = cHeight;
                }
                this.left = (cWidth - this.width) * (pos / 100);
                this.right = this.width + this.left;
                return this;
            }.call({});
        }
    
        const getImgSizeInfo = (img) => {
            var pos = window.getComputedStyle(img).getPropertyValue('object-position').split(' ');
            return getRenderedSize(true,
                img.width,
                img.height,
                img.naturalWidth,
                img.naturalHeight,
                parseInt(pos[0]));
        }


        const imgDivs = reactDom.findDOMNode(imageCompRef.current).getElementsByClassName("image-marker__image")
        if (imgDivs) {
            if (imgDivs.length) {
                const thisImg = imgDivs[0]
                thisImg.addEventListener("load", (evt) => {
                    if (evt) {
                        if (evt.target) {
                            if (evt.target.naturalWidth && evt.target.naturalHeight) {
                                let renderedImgSizeInfo = getImgSizeInfo(evt.target)
                                if (renderedImgSizeInfo) {
                                    setOverrideWidth(Math.round(renderedImgSizeInfo.width))
                                }
                            }
                        }
                    }

                })
                
            }
        }

        function updateSize() {
            const thisImg = imgDivs[0]
            if (thisImg){
                let renderedImgSizeInfo = getImgSizeInfo(thisImg)
                if (renderedImgSizeInfo) {
                    setOverrideWidth((prev) => {
                        return null
                    })
                    setTimeout(() => {
                        setOverrideWidth((prev) => {
                            return setOverrideWidth(Math.round(renderedImgSizeInfo.width))
                        })
                    }, 390);

                }
            }
        }
        window.addEventListener('resize', updateSize);
        return () => window.removeEventListener('resize', updateSize);
    }, [])