增加脉冲特效
This commit is contained in:
parent
bdc3181797
commit
ebb45b12a1
@ -129,126 +129,16 @@ export class WireRender {
|
|||||||
|
|
||||||
if (data.active) {
|
if (data.active) {
|
||||||
const pathSelection = d3.select(this);
|
const pathSelection = d3.select(this);
|
||||||
// 如果当前激活,显示数据流向
|
const pulse = new PulseLine();
|
||||||
// const pathLength = pathSelection.node().getTotalLength();
|
id2PluseLine.set(data.id, pulse);
|
||||||
|
|
||||||
const g = _this.selection.append("g")
|
pulse.loadToSelection(_this.selection, data);
|
||||||
.attr("mask", "url(#m1)");
|
pulse.startAnimation();
|
||||||
|
|
||||||
// 创建 mask
|
|
||||||
const mask = g.append("mask")
|
|
||||||
.attr('id', 'm1')
|
|
||||||
|
|
||||||
mask.append("use")
|
|
||||||
.attr("id", "u1")
|
|
||||||
.attr("href", "#p1")
|
|
||||||
.attr("stroke", "white")
|
|
||||||
.attr("stroke-width", 7)
|
|
||||||
.attr("fill", "none")
|
|
||||||
.attr('stroke-dasharray', '200 300')
|
|
||||||
.attr("stroke-linecap", "round");
|
|
||||||
|
|
||||||
// 创建 radialGradient
|
|
||||||
const radialGradient = g.append("radialGradient")
|
|
||||||
.attr("id", "g1");
|
|
||||||
|
|
||||||
radialGradient.append("stop")
|
|
||||||
.attr("offset", "0%")
|
|
||||||
.attr("stop-color", "white");
|
|
||||||
|
|
||||||
radialGradient.append("stop")
|
|
||||||
.attr("offset", "25%")
|
|
||||||
.attr("stop-color", "#CB81DA");
|
|
||||||
|
|
||||||
radialGradient.append("stop")
|
|
||||||
.attr("offset", "95%")
|
|
||||||
.attr("stop-opacity", 0)
|
|
||||||
.attr("stop-color", "rgb(70, 70, 222)");
|
|
||||||
|
|
||||||
// 创建 path
|
|
||||||
g.append("path")
|
|
||||||
.attr("id", "p1")
|
|
||||||
.attr('stroke-width', 10)
|
|
||||||
.attr("fill", "none")
|
|
||||||
.attr("d", data.svg);
|
|
||||||
|
|
||||||
// 创建 circle 和 animateMotion
|
|
||||||
g.append("circle")
|
|
||||||
.attr("r", 100)
|
|
||||||
.attr("fill", "url(#g1)")
|
|
||||||
.append("animateMotion")
|
|
||||||
.attr("dur", "3000ms")
|
|
||||||
.attr("repeatCount", "indefinite")
|
|
||||||
.append("mpath")
|
|
||||||
.attr("href", "#p1");
|
|
||||||
|
|
||||||
let p1 = document.getElementById('p1');
|
|
||||||
let u1 = document.getElementById('u1');
|
|
||||||
|
|
||||||
const pathLength = p1.getTotalLength();
|
|
||||||
|
|
||||||
var u1Keyframes = new KeyframeEffect(
|
|
||||||
u1, [{
|
|
||||||
strokeDasharray: `200 ${pathLength - 200}`,
|
|
||||||
strokeDashoffset: "200"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
strokeDasharray: `200 ${pathLength}`,
|
|
||||||
strokeDashoffset: `-${pathLength - 200}`
|
|
||||||
}
|
|
||||||
], {
|
|
||||||
duration: 3000,
|
|
||||||
iterations: Infinity
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const pulsationAnimation = new Animation(u1Keyframes, document.timeline);
|
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
const motion = g.selectAll('animateMotion').node();
|
|
||||||
console.log(motion);
|
|
||||||
motion.setAttribute('begin', '0s');
|
|
||||||
motion.beginElement();
|
|
||||||
|
|
||||||
pulsationAnimation.play();
|
|
||||||
});
|
|
||||||
|
|
||||||
// const pivot = _this.selection
|
|
||||||
// .append('circle')
|
|
||||||
// .attr('r', 6)
|
|
||||||
// .attr('fill', 'var(--wire-ball-color)');
|
|
||||||
|
|
||||||
// // 进行一次动画
|
|
||||||
// function renderOneAnimation() {
|
|
||||||
// console.log(pathLength);
|
|
||||||
// // 1400 的长度差不多配 3500 ?
|
|
||||||
// const duration = pathLength / 14 * 35;
|
|
||||||
// let transition = pivot.transition().duration(3500);
|
|
||||||
// transition.attrTween('transform', () => {
|
|
||||||
// return t => {
|
|
||||||
// const x = cubicBezierAnimation(t, 0, pathLength);
|
|
||||||
// const point = pathSelection.node().getPointAtLength(x);
|
|
||||||
// return `translate(${point.x},${point.y})`;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// transition = transition.on('end', function() {
|
|
||||||
// if (id2animation.has(data.id)) {
|
|
||||||
// renderOneAnimation();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// // 动画结束后重新启动动画
|
|
||||||
// id2animation.set(data.id, {
|
|
||||||
// pivot,
|
|
||||||
// transition
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// renderOneAnimation();
|
|
||||||
} else {
|
} else {
|
||||||
if (id2animation.has(data.id)) {
|
if (id2PluseLine.has(data.id)) {
|
||||||
const { pivot, transition } = id2animation.get(data.id);
|
const pulse = id2PluseLine.get(data.id);
|
||||||
pivot.remove();
|
pulse.destory();
|
||||||
id2animation.delete(data.id);
|
id2PluseLine.delete(data.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -4,98 +4,133 @@ let PluseIDCount = 0;
|
|||||||
|
|
||||||
export class PulseLine {
|
export class PulseLine {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.animation = undefined;
|
||||||
|
this.pluseId = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadData(pathString, id) {
|
|
||||||
this.path = pathString;
|
|
||||||
this.pluseId = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {d3.Selection} parentSelection
|
* @param {d3.Selection} parentSelection
|
||||||
*/
|
*/
|
||||||
loadToSelection(parentSelection, config) {
|
loadToSelection(parentSelection, data) {
|
||||||
config = config || {};
|
this.pluseId = data.id;
|
||||||
const pluse = parentSelection.append('g');
|
|
||||||
|
|
||||||
const gId = 'pluse-g' + this.pluseId;
|
const gId = 'pluse-g' + data.id;
|
||||||
const pId = 'pluse-p' + this.pluseId;
|
const pId = 'pluse-p' + data.id;
|
||||||
const mId = 'pluse-m' + this.pluseId;
|
const mId = 'pluse-m' + data.id;
|
||||||
const uId = 'pluse-u' + this.pluseId;
|
const uId = 'pluse-u' + data.id;
|
||||||
|
|
||||||
pluse.append('radialGradient')
|
const g = parentSelection.append("g")
|
||||||
.attr("id", gId)
|
|
||||||
.selectAll("stop")
|
|
||||||
.data([
|
|
||||||
{ offset: "0%", color: "white" },
|
|
||||||
{ offset: "25%", color: "#CB81DA" },
|
|
||||||
{ offset: "95%", color: "rgb(70, 70, 222)", opacity: 0 }
|
|
||||||
])
|
|
||||||
.enter()
|
|
||||||
.append("stop")
|
|
||||||
.attr("offset", d => d.offset)
|
|
||||||
.attr("stop-color", d => d.color)
|
|
||||||
.attr("stop-opacity", d => d.opacity || 1);
|
|
||||||
|
|
||||||
pluse.append("path")
|
|
||||||
.attr("id", pId)
|
|
||||||
.attr('fill', 'none')
|
|
||||||
.attr("d", "M133,613 L470,613 L470,515.5 L661,515.5");
|
|
||||||
|
|
||||||
const mask = pluse.append("mask")
|
|
||||||
.attr("id", mId);
|
|
||||||
|
|
||||||
mask.append("use")
|
|
||||||
.attr("id", uId)
|
|
||||||
.attr("href", pId)
|
|
||||||
.attr("stroke", "white")
|
|
||||||
.attr("stroke-width", 5)
|
|
||||||
.attr("fill", "none")
|
|
||||||
.attr("stroke-dasharray", "100 200")
|
|
||||||
.attr("stroke-linecap", "round");
|
|
||||||
|
|
||||||
// 创建使用 mask 和 radialGradient 的 <g>
|
|
||||||
const maskedG = pluse.append("g")
|
|
||||||
.attr("mask", `url(#${mId})`);
|
.attr("mask", `url(#${mId})`);
|
||||||
|
|
||||||
|
this.g = g;
|
||||||
|
|
||||||
|
// 创建 mask
|
||||||
|
const mask = parentSelection.append("mask")
|
||||||
|
.attr('id', mId);
|
||||||
|
|
||||||
|
const maskPathSelection = mask.append("use")
|
||||||
|
.attr("id", uId)
|
||||||
|
.attr("href", "#" + pId)
|
||||||
|
.attr("stroke", "white")
|
||||||
|
.attr("stroke-width", 7)
|
||||||
|
.attr("fill", "none")
|
||||||
|
.attr('stroke-dasharray', '200 300')
|
||||||
|
.attr("stroke-linecap", "round");
|
||||||
|
|
||||||
|
this.maskPathSelection = maskPathSelection;
|
||||||
|
|
||||||
|
// 创建 radialGradient
|
||||||
|
const radialGradient = g.append("radialGradient")
|
||||||
|
.attr("id", gId);
|
||||||
|
|
||||||
|
radialGradient.append("stop")
|
||||||
|
.attr("offset", "0%")
|
||||||
|
.attr("stop-color", "white");
|
||||||
|
|
||||||
|
radialGradient.append("stop")
|
||||||
|
.attr("offset", "25%")
|
||||||
|
.attr("stop-color", "#CB81DA");
|
||||||
|
|
||||||
|
radialGradient.append("stop")
|
||||||
|
.attr("offset", "95%")
|
||||||
|
.attr("stop-opacity", 0)
|
||||||
|
.attr("stop-color", "rgb(70, 70, 222)");
|
||||||
|
|
||||||
|
// 创建 path
|
||||||
|
const pathSelection = g.append("path")
|
||||||
|
.attr("id", pId)
|
||||||
|
.attr('stroke-width', 10)
|
||||||
|
.attr("fill", "none")
|
||||||
|
.attr("d", data.svg);
|
||||||
|
|
||||||
|
this.pathSelection = pathSelection;
|
||||||
|
|
||||||
// 创建 circle 和 animateMotion
|
// 创建 circle 和 animateMotion
|
||||||
maskedG.append("circle")
|
g.append("circle")
|
||||||
.attr("r", 50)
|
.attr("r", 100)
|
||||||
.attr("fill", `url(#${pId})`)
|
.attr("fill", `url(#${gId})`)
|
||||||
.append("animateMotion")
|
.append("animateMotion")
|
||||||
.attr("dur", "4500ms")
|
.attr("dur", "3000ms")
|
||||||
.attr("repeatCount", "indefinite")
|
.attr("repeatCount", "indefinite")
|
||||||
.append("mpath")
|
.append("mpath")
|
||||||
.attr("href", `#${pId}`);
|
.attr("href", "#" + pId);
|
||||||
}
|
}
|
||||||
|
|
||||||
animation() {
|
startAnimation() {
|
||||||
const pId = 'pluse-p' + this.pluseId;
|
if (this.animation) {
|
||||||
const uId = 'pluse-u' + this.pluseId;
|
requestAnimationFrame(() => {
|
||||||
|
const motionElement = this.g.selectAll('animateMotion').node();
|
||||||
const pathElement = document.getElementById(pId);
|
motionElement.setAttribute('begin', '0s');
|
||||||
const pluseElement = document.getElementById(uId);
|
motionElement.beginElement();
|
||||||
|
this.animation.play();
|
||||||
const pathLength = pathElement.getTotalLength();
|
});
|
||||||
|
} else {
|
||||||
const keyframes = new KeyframeEffect(
|
const pathElement = this.pathSelection.node();
|
||||||
pluseElement, [{
|
const pluseElement = this.maskPathSelection.node();
|
||||||
strokeDasharray: `100 ${pathLength}`,
|
|
||||||
strokeDashoffset: "100"
|
const pathLength = pathElement.getTotalLength();
|
||||||
},
|
|
||||||
{
|
const keyframes = new KeyframeEffect(
|
||||||
strokeDasharray: `100 ${pathLength}`,
|
pluseElement, [{
|
||||||
strokeDashoffset: `-${pathLength - 100}`
|
strokeDasharray: `200 ${pathLength - 200}`,
|
||||||
|
strokeDashoffset: "200"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
strokeDasharray: `200 ${pathLength}`,
|
||||||
|
strokeDashoffset: `-${pathLength - 200}`
|
||||||
|
}
|
||||||
|
], {
|
||||||
|
duration: 3000,
|
||||||
|
iterations: Infinity
|
||||||
}
|
}
|
||||||
], {
|
);
|
||||||
duration: this.duration,
|
|
||||||
iterations: Infinity
|
const pulsationAnimation = new Animation(keyframes, document.timeline);
|
||||||
}
|
this.animation = pulsationAnimation;
|
||||||
);
|
|
||||||
|
|
||||||
const pulsationAnimation = new Animation(keyframes, document.timeline);
|
requestAnimationFrame(() => {
|
||||||
return pulsationAnimation;
|
const motionElement = this.g.selectAll('animateMotion').node();
|
||||||
|
motionElement.setAttribute('begin', '0s');
|
||||||
|
motionElement.beginElement();
|
||||||
|
|
||||||
|
pulsationAnimation.play();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pauseAnimation() {
|
||||||
|
if (!this.animation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.animation.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
destory() {
|
||||||
|
if (this.g) {
|
||||||
|
this.g.selectAll('*').remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user