动画 SVG 组对象 - 使用样式组件进行变换旋转不会围绕圆原点旋转

Posted

技术标签:

【中文标题】动画 SVG 组对象 - 使用样式组件进行变换旋转不会围绕圆原点旋转【英文标题】:Animating SVG group object - transform rotate with styled-components doesnt rotate around circle origin 【发布时间】:2021-09-15 16:59:54 【问题描述】:

我有一个 SVG 圆圈和一些线条对象,它们制作了一个简单的十字准线鼠标光标,我正在尝试使用样式组件对其进行动画处理。当光标悬停在某些对象上时,我希望光标内的线条元素围绕构成光标的圆形元素的原点旋转。一个 redux useSelector 钩子可以访问被悬停的组件的 mouseover/mouseout 状态。这部分效果很好,使用这种方法可以引发简单的笔触颜色变化

const Cursor = (props) => 

const hoverState = useSelector(state => state.gameState.targetHovered);

// ... 
return (
        <Crosshair isHovering=hoverState position=props.position>
                <circle 
                    cx=cursorCoordinates.cx
                    cy=cursorCoordinates.cy
                    r=cursorCoordinates.outerRadius
                    style=cursorStyle 
                />
                <circle 
                    cx=cursorCoordinates.cx
                    cy=cursorCoordinates.cy
                    r=cursorCoordinates.innerRadius
                    style=cursorStyle 
                />

                <line 
                    id="top"
                    x1=cursorCoordinates.cx - cursorCoordinates.outerRadius 
                    y1=cursorCoordinates.cy
                    x2=cursorCoordinates.cx - cursorCoordinates.innerRadius
                    y2=cursorCoordinates.cy
                    style=crossHairStyle
                />
                <line 
                    id="bottom"
                    x1=cursorCoordinates.cx + cursorCoordinates.innerRadius 
                    y1=cursorCoordinates.cy
                    x2=cursorCoordinates.cx + cursorCoordinates.outerRadius
                    y2=cursorCoordinates.cy
                    style=crossHairStyle
                />
        </Crosshair>
    );

以及样式化组件的代码...

const lockOn = (x, y) => keyframes`
    0% 
        transform: rotate(0deg);
    

    100%  
        transform: rotate(90deg);
    
`;

const Crosshair = styled.g`
    transform-origin: $props => props.position.x $props => props.position.y;
    animation: $props => props.isHovering ? lockOn : 'none' 1s linear;
`;

我尝试以多种不同的方式表达关键帧,但每次,当光标悬停在目标对象上时,动画不会旋转样式组组件中的元素,而是将其扔到正确的,好像变换原点不知何故不正确。从 Crosshair 中删除 transform-origin 表现出相同的行为

我确定我犯了一个简单的语法错误。有什么想法吗?

【问题讨论】:

想必你需要 transform-b​​ox: fill-box;如果这不起作用,请提供minimal reproducible example,即我们可以直接自己运行的东西。 @RobertLongson 是的,这就是解决方案。 styled.g 中只有 2 行代码(见下文) 【参考方案1】:

正如@RobertLongson 在 cmets 中指出的那样,解决方案是添加

transform-box: fill-box;

在 styled.g 组件内,否则 transform-origin 是 SVG 对象的中心。有关 MDN 文档的更多详细信息,请点击此处:https://developer.mozilla.org/en-US/docs/Web/CSS/transform-box

添加转换原点也是必要的。注意动画中需要“向前”以防止在光标仍悬停在对象上时重置它

const lockOn = (x, y) => keyframes`
    from 
        transform: rotate(0deg);
    

    to  
        transform: rotate(90deg);
    
`;

const Crosshair = styled.g`
    transform-origin: 50% 50%;
    transform-box: fill-box;
    animation: $props => props.isHovering ? lockOn : 'none' 0.3s linear forwards;
`;

【讨论】:

以上是关于动画 SVG 组对象 - 使用样式组件进行变换旋转不会围绕圆原点旋转的主要内容,如果未能解决你的问题,请参考以下文章

Safari SVG 变换原点缩放动画

CSS 样式转换与 svg 转换

使用 animate 标签为转换(旋转)的 SVG 组设置动画

SVG 变换原点 CSS 动画 – Firefox 错误

如何相对于其中心点旋转或缩放(变换)SVG 路径?

样式化组件中的 SVG 动画