看到按钮的一个有趣的效果
Saw an interesting effect for the button
我想在将鼠标悬停在 svg 对象上时创建与此站点上完全相同的效果 http://animejs.com/。
为此,我打开了 inkscape 并绘制了一条路径并保存了悬停前后的两个状态。
第一个状态:
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
style="fill:none; stroke:#ff17ff;"/>
</svg>
第二状态
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path d="m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z"
style="fill:none;stroke:#ff17ff"/>
</svg>
很可能需要在 js/jquery 中完成,请告诉我如何实现这种效果?如何以如此灵活的方式更改路径?
要为按钮的轮廓设置动画,您需要为参数设置动画 d
补丁
<animate attributeName="d" values="path1;path2" dur="2s" begin="btn.mouseover" />
.container {
width:25%;
height:25%;
}
<div class="container">
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path id="btn" d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
style="fill:none; stroke:#ff17ff;">
<animate attributeName="d" values="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z;m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z" dur="1s" begin="btn.mouseover" />
</path>
<text x="23" y="136" font-size="36" >mouseover</txt>
</svg>
</div>
我看到已经有答案了,但由于我已经准备好了,所以我将其发布。我正在使用 Javascript 而不是 SMIL 动画。
路径我已经准备好了。如果你看一下,我已经将每个命令都转换为 C
let rid = null;
let ry = [];
let speed = 1 / 10;
class pathsPair {
constructor(thePath, yes, no) {
this.path = thePath;
this.yes = yes;
this.no = no;
this.vals = this.getArgsRy(yes);
this.target = this.getArgsRy(no);
this.targetAlp = 0;
this.alp = 1;
this.light = 70;
}
getArgsRy(path) {
let d = path.getAttribute("d").replace(/\r?\n|\r/g, ""); //remove breaklines
if (d.charAt(0) == "m") {
d = "M" + d.slice(1);
}
let argsRX = /(?=[a-zA-Z])/;
let args = d.split(argsRX);
let ArgsRy = [];
args.map(arg => {
let argRy = arg
.slice(1)
.replace(/\-/g, " -")
.split(/[ ,]+/);
argRy.map((p, i) => {
if (p == "") {
argRy.splice(i, 1);
}
});
for (let i = 0; i < argRy.length; i++) {
argRy[i] = parseFloat(argRy[i]);
}
argRy.unshift(arg[0]);
ArgsRy.push(argRy);
});
return ArgsRy;
}
morph() {
let newD = "";
this.vals.map((v, vi) => {
let newStr = v[0];
for (let i = 1; i < v.length; i++) {
this.updateProp(vi, i);
newStr += v[i].toFixed(3) + " ";
}
newD += newStr + " ";
}); //
this.path.setAttributeNS(null, "d", newD);
}
updateProp(vi, i) {
let dist = this.target[vi][i] - this.vals[vi][i];
let vel = dist / 10;
this.vals[vi][i] += vel;
}
sayNO() {
this.target = this.getArgsRy(this.no);
this.targetAlp = 0;
}
sayYES() {
this.target = this.getArgsRy(this.yes);
this.targetAlp = 1;
}
}
let the_pair = new pathsPair(morphingPath, _2, _1);
console.log(the_pair);
svg.addEventListener("mouseover", function() {
console.log(rid);
if (rid) {
window.cancelAnimationFrame(rid);
rid = null;
}
the_pair.sayYES();
Frame();
});
svg.addEventListener("mouseleave", function() {
if (rid) {
window.cancelAnimationFrame(rid);
rid = null;
}
the_pair.sayNO();
Frame();
});
function Frame() {
rid = window.requestAnimationFrame(Frame);
the_pair.morph();
}
window.addEventListener("load", function() {
Frame();
});
svg{border:1px solid}
#morphingPath{fill:transparent; stroke:black;}
<svg id="svg" viewBox="0 90 210 70" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="_1" d="M11.000, 103.000 C75.000, 100.500 134.000, 101.500 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 148.500 69.000, 145.430 11.000, 145.000 z"
/>
<path id="_2" d="M11.000, 103.000 C73.000, 95.200 132.000, 96.700 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 154.700 69.000, 151.300 11.000, 145.000 z"
/>
</defs>
<path id="morphingPath" d=""
style="fill:none; stroke:#ff17ff;" />
</svg>
我想在将鼠标悬停在 svg 对象上时创建与此站点上完全相同的效果 http://animejs.com/。
为此,我打开了 inkscape 并绘制了一条路径并保存了悬停前后的两个状态。
第一个状态:
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
style="fill:none; stroke:#ff17ff;"/>
</svg>
第二状态
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path d="m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z"
style="fill:none;stroke:#ff17ff"/>
</svg>
很可能需要在 js/jquery 中完成,请告诉我如何实现这种效果?如何以如此灵活的方式更改路径?
要为按钮的轮廓设置动画,您需要为参数设置动画 d
补丁
<animate attributeName="d" values="path1;path2" dur="2s" begin="btn.mouseover" />
.container {
width:25%;
height:25%;
}
<div class="container">
<svg viewBox="0 0 210 297" xmlns="http://www.w3.org/2000/svg">
<path id="btn" d="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z"
style="fill:none; stroke:#ff17ff;">
<animate attributeName="d" values="m11 103c64-2.5 123-1.5 178 0v42c-61 3.5-120 0.43-178 0z;m11 103c62-7.8 121-6.3 178 0v42c-61 9.7-120 6.3-178 0z" dur="1s" begin="btn.mouseover" />
</path>
<text x="23" y="136" font-size="36" >mouseover</txt>
</svg>
</div>
我看到已经有答案了,但由于我已经准备好了,所以我将其发布。我正在使用 Javascript 而不是 SMIL 动画。
路径我已经准备好了。如果你看一下,我已经将每个命令都转换为 C
let rid = null;
let ry = [];
let speed = 1 / 10;
class pathsPair {
constructor(thePath, yes, no) {
this.path = thePath;
this.yes = yes;
this.no = no;
this.vals = this.getArgsRy(yes);
this.target = this.getArgsRy(no);
this.targetAlp = 0;
this.alp = 1;
this.light = 70;
}
getArgsRy(path) {
let d = path.getAttribute("d").replace(/\r?\n|\r/g, ""); //remove breaklines
if (d.charAt(0) == "m") {
d = "M" + d.slice(1);
}
let argsRX = /(?=[a-zA-Z])/;
let args = d.split(argsRX);
let ArgsRy = [];
args.map(arg => {
let argRy = arg
.slice(1)
.replace(/\-/g, " -")
.split(/[ ,]+/);
argRy.map((p, i) => {
if (p == "") {
argRy.splice(i, 1);
}
});
for (let i = 0; i < argRy.length; i++) {
argRy[i] = parseFloat(argRy[i]);
}
argRy.unshift(arg[0]);
ArgsRy.push(argRy);
});
return ArgsRy;
}
morph() {
let newD = "";
this.vals.map((v, vi) => {
let newStr = v[0];
for (let i = 1; i < v.length; i++) {
this.updateProp(vi, i);
newStr += v[i].toFixed(3) + " ";
}
newD += newStr + " ";
}); //
this.path.setAttributeNS(null, "d", newD);
}
updateProp(vi, i) {
let dist = this.target[vi][i] - this.vals[vi][i];
let vel = dist / 10;
this.vals[vi][i] += vel;
}
sayNO() {
this.target = this.getArgsRy(this.no);
this.targetAlp = 0;
}
sayYES() {
this.target = this.getArgsRy(this.yes);
this.targetAlp = 1;
}
}
let the_pair = new pathsPair(morphingPath, _2, _1);
console.log(the_pair);
svg.addEventListener("mouseover", function() {
console.log(rid);
if (rid) {
window.cancelAnimationFrame(rid);
rid = null;
}
the_pair.sayYES();
Frame();
});
svg.addEventListener("mouseleave", function() {
if (rid) {
window.cancelAnimationFrame(rid);
rid = null;
}
the_pair.sayNO();
Frame();
});
function Frame() {
rid = window.requestAnimationFrame(Frame);
the_pair.morph();
}
window.addEventListener("load", function() {
Frame();
});
svg{border:1px solid}
#morphingPath{fill:transparent; stroke:black;}
<svg id="svg" viewBox="0 90 210 70" xmlns="http://www.w3.org/2000/svg">
<defs>
<path id="_1" d="M11.000, 103.000 C75.000, 100.500 134.000, 101.500 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 148.500 69.000, 145.430 11.000, 145.000 z"
/>
<path id="_2" d="M11.000, 103.000 C73.000, 95.200 132.000, 96.700 189.000, 103.000 C189.000, 117.000 189.000, 131.000 189.000, 145.000 C128.000, 154.700 69.000, 151.300 11.000, 145.000 z"
/>
</defs>
<path id="morphingPath" d=""
style="fill:none; stroke:#ff17ff;" />
</svg>