如何从路径中心"transform: scale()"?



我想增加悬停部分的大小,同时保持它们的原始位置增加描边宽度(这不是它应该工作的方式,因为我希望整个路径由"实际路径"组成)

在这样做的时候,它们也会改变位置,看起来执行升级的原点并不与路径的中心对应,而是与左上角对应。

[1] transform-origin: center;这不是我想在这里做的,因为它将原点设置为图像的中心,而不是路径的中心。

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 1500 1500" xmlns="http://www.w3.org/2000/svg" id="logo">
<style type="text/css">
<!-- segments -->
.logo_segment {
fill:#000;
transition: all .2s ease-in-out;
<!-- transform-origin: center; < [1] Doesn't work the way I want to-->
}
.logo_segment:hover {
transform: scale(1.05);
transition: all .2s ease-in-out;
}
</style>
<!-- segments; clockwise, starting left-->
<path stroke="red" stroke-width="5" class="logo_segment" d="m390.56 934.47-3e-3 -369.1-6e-3 6e-3 -300.53-173.36-0.01962 2e-3 -0.002003 715.79h3e-3l300.58-173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m410.21 531.4 318.07-183.59 2.0982-1.1952-0.02653-345.87 0.00601-0.74104-620.16 357.8-0.67685 0.24497 300.69 173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m769.58 346.54 320.1 184.8v0.0693l300.57-173.32-0.036-0.0367-619.97-357.68-0.65801-0.36979-0.01 344.55"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m1109.4 565.35 0.01 369.46v0.01l300.56 173.35 0.053-716.15-0.071-0.0183-300.55 173.35"/>
</svg>

解决这个问题的一种方法是确保元素的中心为0,0。我在示例中添加了一个额外的<polygon>,以便您可以看到它以0,0为中心。

在这个例子中,我重用了包裹在<g>中的<polygon>。所有的转换都是在<g>上完成的,所以<polygon>上唯一的转换是悬停时的比例。

(<polygon>的点是通过试错找到的。它们可以被计算…)

.logo_segment {
transition: all .2s ease-in-out;
}
.logo_segment:hover {
transform: scale(1.05);
transition: all .2s ease-in-out;
}
<svg version="1.1" viewBox="0 0 1500 1500" xmlns="http://www.w3.org/2000/svg" id="logo">
<defs>
<g id="segment">
<polygon class="logo_segment" points="184,150 357,-150 -357,-150 -184,150" stroke="red" stroke-width="5" />
</g>
</defs>
<!--extra polygon to show that center is 0,0 -->
<polygon class="logo_segment" points="184,150 357,-150 -357,-150 -184,150" stroke="red" stroke-width="5" />
<use href="#segment" transform="translate(750 750) rotate(30) translate(0 -510)" fill="gray" />
<use href="#segment" transform="translate(750 750) rotate(90) translate(0 -510)" />
<use href="#segment" transform="translate(750 750) rotate(150) translate(0 -510)" />
<use href="#segment" transform="translate(750 750) rotate(210) translate(0 -510)" />
<use href="#segment" transform="translate(750 750) rotate(270) translate(0 -510)" />
<use href="#segment" transform="translate(750 750) rotate(330) translate(0 -510)" />
</svg>

您只需将transform-origin:center与transform-box:fill-box结合使用,将该框设置为路径框。

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" viewBox="0 0 1500 1500" xmlns="http://www.w3.org/2000/svg" id="logo">
<style type="text/css">
<!-- segments -->
.logo_segment {
fill:#000;
transform-origin: center;
transform-box: fill-box;
transition: all .2s ease-in-out;
<!-- transform-origin: center; < [1] Doesn't work the way I want to-->
}
.logo_segment:hover {
transform: scale(1.05);
transition: all .2s ease-in-out;
}
</style>
<!-- segments; clockwise, starting left-->
<path stroke="red" stroke-width="5" class="logo_segment" d="m390.56 934.47-3e-3 -369.1-6e-3 6e-3 -300.53-173.36-0.01962 2e-3 -0.002003 715.79h3e-3l300.58-173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m410.21 531.4 318.07-183.59 2.0982-1.1952-0.02653-345.87 0.00601-0.74104-620.16 357.8-0.67685 0.24497 300.69 173.35"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m769.58 346.54 320.1 184.8v0.0693l300.57-173.32-0.036-0.0367-619.97-357.68-0.65801-0.36979-0.01 344.55"/>
<path stroke="red" stroke-width="5" class="logo_segment" d="m1109.4 565.35 0.01 369.46v0.01l300.56 173.35 0.053-716.15-0.071-0.0183-300.55 173.35"/>
</svg>

你必须为6个<path>形状中的每一个计算Scale中心点(实际上是平移)。

使用一个标准的JavaScript Web组件<svg-hexagon>来动态创建。

我把动画留给你:

customElements.define("svg-hexagon", class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg viewBox="0 0 1500 1500">` +
`<style>path{stroke:red;stroke-width:15;fill:lightgreen}path:hover{fill:gold}</style>` +
`<g transform="scale(0.8) translate(200 200)"></g></svg>`;
let paths = this.querySelector("g");
let xPos = 360;
for (let i = 0; i < 6; i++) {
let path = document.createElementNS("http://www.w3.org/2000/svg", "path");
let pathlocation = `rotate(${i*60} 750 750)`;
path.setAttribute("transform", pathlocation);
path.setAttribute("d", `m${xPos} 935 0-369 0 0-301-173 0 0 0 716h0l301-173`);
paths.append(path);
path.onmouseenter = (e) => {
let {left,top,x,y,width,height } = path.getBBox();
let scale = 1.5;
let cx = -(x + (width / 2)) * (scale - 1);
let cy = -(y + (height / 2)) * (scale - 1);
path.setAttribute("transform",
`${pathlocation} translate(${cx} ${cy}) scale(${scale})`);
paths.append(path); // put path on top, there is no z-index in SVG
}
path.onmouseleave = (e) => {
if(!e.ctrlKey) path.setAttribute("transform", pathlocation);
}
}
}
})
svg-hexagon {
width: 180px;
display: inline-block;
background: rebeccapurple
}
<svg-hexagon></svg-hexagon>
<svg-hexagon></svg-hexagon>
<svg-hexagon></svg-hexagon>

最新更新