【问题标题】:clip-path dynamic transformations to fill container剪辑路径动态转换以填充容器
【发布时间】:2019-02-10 08:57:11
【问题描述】:

我正在开发一个反应组件,我希望能够传递任何图像及其尺寸,一个从矩形区域的 x、y 宽度和高度计算的剪辑路径。这部分我工作得很好。然后我想将这个剪裁区域缩放回来以填充一个 div,目前我有这个 div 只是原始图像尺寸以保持简单。我有正确计算缩放部分,但无法计算出转换缩放的剪辑路径区域的数学。这是我的组件(在 Typescript 中):


interface RootProps {
  links: Link[];
}

interface RootState {

}

class Root extends React.Component<RootProps, RootState> {
  constructor(props) {
    super(props);
    this.state = {

    }
  }

    pp = (x: number, y: number): string => {
        return x + "% " + y + "%"
    }


    renderClippedImage = (name: string, x: number, y: number, width: number, height: number) => {
        let iWidth = 600;
        let iHeight = 360;

        let p1 = {
            x: (x / iWidth) * 100,
            y: (y / iHeight) * 100
        }
        let p2 = {
            x: (x / iWidth) * 100,
            y: ((y + height) / iHeight) * 100
        }
        let p3 = {
            x: ((x + width) / iWidth) * 100,
            y: ((y + height) / iHeight) * 100
        }
        let p4 = {
            x: ((x + width) / iWidth) * 100,
            y: (y / iHeight) * 100
        }


        let clipPathString = 'polygon(' +
            this.pp(p1.x, p1.y) + ', ' +
            this.pp(p2.x, p2.y) + ', ' +
            this.pp(p3.x, p3.y) + ', ' +
            this.pp(p4.x, p4.y) + ')';

        let pX = (x) / iWidth;
        let pY = (y) / iHeight;
        let portionCoverageX = (width) / iWidth;
        let portionCoverageY = (height) / iHeight;

        let scaleX = 1;
        let scaleY = 1;
        if (portionCoverageX > 0) {
            scaleX = 1 / portionCoverageX;
        }
        if (portionCoverageY > 0) {
            scaleY = 1 / portionCoverageY;
        }

        let translateX = -(((pX * scaleX) / 2) * 100); //this doesn't work
        let translateY = 0; //similar issues getting this to work

        let pathClipping = {
            WebkitClipPath: clipPathString,
            clipPath: clipPathString,
            transform: 'translateX(' + translateX + '%) translateY(' + translateY + '%) scaleX(' + scaleX + ') scaleY(' + scaleY + ')'
        }

        console.log({
            name: name,
            pX: pX,
            pY: pY,
            portionCoverageX: portionCoverageX,
            portionCoverageY: portionCoverageY,
            scaleX: scaleX,
            scaleY: scaleY,
            translateX: translateX,
            translateY: translateY
        })

        return (
            <div style={{ textAlign: 'center', width: '100%', backgroundColor: 'lightseagreen' }}>
                <b>{name}</b><br />
                <div style={{ display: 'inline-block', width: 640, height: 360, backgroundColor: 'darkslateblue' }}>
                    <img width="640" height="360" src="https://placekitten.com/640/360" style={pathClipping} />
                </div>
            </div>
        )
    }

    render() {
        return (
            <div style={{textAlign: 'center'}}>
        <b>Original</b><br />
                <img width="640" height="360" src="https://placekitten.com/640/360" />
                <br />
                {this.renderClippedImage("one", 80, 100, 200, 100)}
                <br />
                {this.renderClippedImage("two", 50, 50, 150, 100)}
                <br />
                {this.renderClippedImage("three", 300, 10, 300, 340)}
            </div>
        )
    }

}

ReactDOM.render(<Root />, document.getElementById('mount-node'));

这是一个代码笔,您可以在其中看到,我当前的数学实际上适用于场景 3,但它也需要适用于 1、2 和任何其他合法区域组合。

https://codepen.io/anon/pen/xMWGRO

我认为我正在努力解决的具体问题是:

let translateX = (((pX * iWidth) / 2)); //this doesn't work for all examples

translateY 是一个类似的问题,任何帮助将不胜感激。

【问题讨论】:

    标签: reactjs math scale translate clip-path


    【解决方案1】:

    我认为您可以将transform-origin 设置为top left,这样您就可以更简单地计算变换位置和比例。

    let scaleX = iWidth / width;
    let scaleY = iHeight / height;
    
    let pX = x / iWidth;
    let pY = y / iHeight;
    let translateX = -pX * 100 * scaleX;
    let translateY = -pY * 100 * scaleY;
    
    let pathClipping = {
      WebkitClipPath: clipPathString,
      clipPath: clipPathString,
      transformOrigin: `top left`,
      transform: `
        translate(${translateX}%, ${translateY}%)
        scale(${scaleX}, ${scaleY})
      `
    };
    

    在此处查看codesandbox

    【讨论】:

    • 就是这样!我看到您在代码笔末尾使用另一个运行/示例故意用无效尺寸破坏了它,很好,我计划以其他方式处理。是的,这解决了我的问题,有趣的 transformOrigin 属性,甚至没有尝试将其混合,但这是有道理的。
    • 啊,if (coverageX &gt; 0) 是你的支票,对吧?我忘了把那个放回去。您可能可以通过数学计算使其也适用于默认变换原点(中心),但如果不是必需的,将其设置为左上角会更简单。
    • 实际上,我认为我从未处理过或范围(例如比源图像更宽的区域)值,但这应该很容易添加。正如您在左上角提到的,您修改后的数学为我解决了这个问题,谢谢。
    猜你喜欢
    • 1970-01-01
    • 2020-05-11
    • 2013-06-27
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 2016-09-02
    • 2021-02-14
    相关资源
    最近更新 更多