增加脉冲特效
This commit is contained in:
parent
12659bcb48
commit
04b56a5181
@ -55,7 +55,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
.connection-line {
|
.connection-line {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: var(--animation-5s);
|
transition: var(--animation-7s);
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
16
src/hook/algorithm/range-tree.js
Normal file
16
src/hook/algorithm/range-tree.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export class RangeTreeMap {
|
||||||
|
constructor() {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
this.horizontal = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
this.vertical = new Map();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ import { WireRender } from './wire';
|
|||||||
import { pinkLog, redLog } from '../utils';
|
import { pinkLog, redLog } from '../utils';
|
||||||
import { treeviewData } from '@/components/treeview/tree';
|
import { treeviewData } from '@/components/treeview/tree';
|
||||||
import { dotConnect } from './yosys';
|
import { dotConnect } from './yosys';
|
||||||
|
import { CrossDotRender } from './cross-dot';
|
||||||
|
|
||||||
export class NetlistRender {
|
export class NetlistRender {
|
||||||
/**
|
/**
|
||||||
@ -284,6 +285,7 @@ export class NetlistRender {
|
|||||||
*/
|
*/
|
||||||
async renderLine(parentSelection, computedLayout) {
|
async renderLine(parentSelection, computedLayout) {
|
||||||
this.wireRender = new WireRender(parentSelection, this);
|
this.wireRender = new WireRender(parentSelection, this);
|
||||||
|
this.crossDotRender = new CrossDotRender(parentSelection, this);
|
||||||
|
|
||||||
for (const edge of computedLayout.edges) {
|
for (const edge of computedLayout.edges) {
|
||||||
for (const section of edge.sections || []) {
|
for (const section of edge.sections || []) {
|
||||||
|
@ -27,6 +27,8 @@ export class WireRender {
|
|||||||
*/
|
*/
|
||||||
this.id2manager = rootRender.id2manager;
|
this.id2manager = rootRender.id2manager;
|
||||||
|
|
||||||
|
this.idCounter = 0;
|
||||||
|
|
||||||
this.arrowHeight = 12;
|
this.arrowHeight = 12;
|
||||||
this.arrowWidth = 12;
|
this.arrowWidth = 12;
|
||||||
}
|
}
|
||||||
@ -58,6 +60,7 @@ export class WireRender {
|
|||||||
|
|
||||||
|
|
||||||
this.data.push({
|
this.data.push({
|
||||||
|
id: this.idCounter,
|
||||||
svg: lineSvg,
|
svg: lineSvg,
|
||||||
endPoint: points.at(-1),
|
endPoint: points.at(-1),
|
||||||
arrow: {
|
arrow: {
|
||||||
@ -69,6 +72,8 @@ export class WireRender {
|
|||||||
},
|
},
|
||||||
active: false
|
active: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.idCounter ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -89,6 +94,8 @@ export class WireRender {
|
|||||||
.attr("fill", "none")
|
.attr("fill", "none")
|
||||||
.attr('stroke', 'var(--wire-color)');
|
.attr('stroke', 'var(--wire-color)');
|
||||||
|
|
||||||
|
const arrows = new Map();
|
||||||
|
|
||||||
let arrowSelections = this.selection.selectAll('svg.line-arrow')
|
let arrowSelections = this.selection.selectAll('svg.line-arrow')
|
||||||
.data(data)
|
.data(data)
|
||||||
.enter()
|
.enter()
|
||||||
@ -105,6 +112,10 @@ export class WireRender {
|
|||||||
element.setAttribute('opacity', 'var(--line-arrow-opacity)');
|
element.setAttribute('opacity', 'var(--line-arrow-opacity)');
|
||||||
|
|
||||||
return element;
|
return element;
|
||||||
|
})
|
||||||
|
.each(function(data) {
|
||||||
|
const selection = d3.select(this);
|
||||||
|
arrows.set(data.id, selection);
|
||||||
});
|
});
|
||||||
|
|
||||||
arrowSelections.raise();
|
arrowSelections.raise();
|
||||||
@ -129,7 +140,7 @@ export class WireRender {
|
|||||||
console.log(pathLength);
|
console.log(pathLength);
|
||||||
// 1400 的长度差不多配 3500 ?
|
// 1400 的长度差不多配 3500 ?
|
||||||
const duration = pathLength / 14 * 35;
|
const duration = pathLength / 14 * 35;
|
||||||
let transition = pivot.transition().duration(duration);
|
let transition = pivot.transition().duration(3500);
|
||||||
transition.attrTween('transform', () => {
|
transition.attrTween('transform', () => {
|
||||||
return t => {
|
return t => {
|
||||||
const x = cubicBezierAnimation(t, 0, pathLength);
|
const x = cubicBezierAnimation(t, 0, pathLength);
|
||||||
@ -161,14 +172,20 @@ export class WireRender {
|
|||||||
|
|
||||||
lineSelections.on('mouseenter', function(_, data) {
|
lineSelections.on('mouseenter', function(_, data) {
|
||||||
const selection = d3.select(this);
|
const selection = d3.select(this);
|
||||||
// 移动到最上层
|
|
||||||
selection.raise();
|
selection.raise();
|
||||||
selection.attr('stroke', 'var(--wire-active-color)');
|
selection.attr('stroke', 'var(--wire-active-color)');
|
||||||
|
|
||||||
|
const arrowSelection = arrows.get(data.id);
|
||||||
|
arrowSelection.raise();
|
||||||
|
arrowSelection.selectAll('path').attr('fill', 'var(--wire-active-color)');
|
||||||
});
|
});
|
||||||
|
|
||||||
lineSelections.on('mouseleave', function(_, data) {
|
lineSelections.on('mouseleave', function(_, data) {
|
||||||
const selection = d3.select(this);
|
const selection = d3.select(this);
|
||||||
selection.attr('stroke', 'var(--wire-color)');
|
selection.attr('stroke', 'var(--wire-color)');
|
||||||
|
|
||||||
|
const arrowSelection = arrows.get(data.id);
|
||||||
|
arrowSelection.selectAll('path').attr('fill', 'var(--wire-color)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
101
src/hook/skin/plusation.js
Normal file
101
src/hook/skin/plusation.js
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
let PluseIDCount = 0;
|
||||||
|
|
||||||
|
class PulseLine {
|
||||||
|
constructor() {
|
||||||
|
// 维护这部分的 id
|
||||||
|
PluseIDCount++;
|
||||||
|
this.pluseId = PluseIDCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData(pathString) {
|
||||||
|
this.path = pathString
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PulseLineSvgConfig} config
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
svgDoc(config) {
|
||||||
|
config = config || {};
|
||||||
|
const pluseStartColor = config.pluseStartColor || 'white';
|
||||||
|
const pluseMiddleColor = config.pluseMiddleColor || '#CB81DA';
|
||||||
|
const pluseEndColor = config.pluseEndColor || 'rgb(70, 70, 222)';
|
||||||
|
const transform = config.transform || 'translate(0 0)';
|
||||||
|
const duration = config.duration || 5000;
|
||||||
|
|
||||||
|
this.duration = duration;
|
||||||
|
|
||||||
|
const gId = 'pluse-g' + this.pluseId;
|
||||||
|
const pId = 'pluse-p' + this.pluseId;
|
||||||
|
const mId = 'pluse-m' + this.pluseId;
|
||||||
|
const uId = 'pluse-u' + this.pluseId;
|
||||||
|
const pathString = this.path;
|
||||||
|
|
||||||
|
const parser = new DOMParser();
|
||||||
|
|
||||||
|
const svgString = `<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<radialGradient id="${gId}">
|
||||||
|
<stop offset="0%" stop-color="${pluseStartColor}" />
|
||||||
|
<stop offset="25%" stop-color="${pluseMiddleColor}" />
|
||||||
|
<stop offset="95%" stop-opacity="0" stop-color="${pluseEndColor}" />
|
||||||
|
</radialGradient>
|
||||||
|
<mask id="${mId}">
|
||||||
|
<use id="${uId}" href="#${pId}"
|
||||||
|
stroke="white" stroke-width="5" fill="none"
|
||||||
|
stroke-dasharray="100 200" stroke-linecap="round" />
|
||||||
|
</mask>
|
||||||
|
<path id="${pId}" d="${pathString}" />
|
||||||
|
</defs>
|
||||||
|
<use href="#${pId}" transform="${transform}" stroke="#CB81DA"
|
||||||
|
stroke-width="1" fill="rgba(203, 129, 218, 0.1)"/>
|
||||||
|
<g transform="${transform}" mask="url(#${mId})">
|
||||||
|
<circle r="50" fill="url(#${gId})">
|
||||||
|
<animateMotion dur="5000ms" repeatCount="indefinite">
|
||||||
|
<mpath href="#${pId}" />
|
||||||
|
</animateMotion>
|
||||||
|
</circle>
|
||||||
|
</g>
|
||||||
|
</svg>`;
|
||||||
|
|
||||||
|
const svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
|
||||||
|
return svgDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
animation() {
|
||||||
|
const pId = 'pluse-p' + this.pluseId;
|
||||||
|
const uId = 'pluse-u' + this.pluseId;
|
||||||
|
|
||||||
|
const pathElement = document.getElementById(pId);
|
||||||
|
const pluseElement = document.getElementById(uId);
|
||||||
|
|
||||||
|
const pathLength = pathElement.getTotalLength();
|
||||||
|
|
||||||
|
const keyframes = new KeyframeEffect(
|
||||||
|
pluseElement, [{
|
||||||
|
strokeDasharray: `100 ${pathLength}`,
|
||||||
|
strokeDashoffset: "100"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
strokeDasharray: `100 ${pathLength}`,
|
||||||
|
strokeDashoffset: `-${pathLength - 100}`
|
||||||
|
}
|
||||||
|
], {
|
||||||
|
duration: this.duration,
|
||||||
|
iterations: Infinity
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const pulsationAnimation = new Animation(keyframes, document.timeline);
|
||||||
|
return pulsationAnimation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef PulseLineSvgConfig
|
||||||
|
* @property {string} pluseStartColor
|
||||||
|
* @property {string} pluseMiddleColor
|
||||||
|
* @property {string} pluseEndColor
|
||||||
|
* @property {string} transform
|
||||||
|
* @property {number} duration
|
||||||
|
*/
|
Loading…
x
Reference in New Issue
Block a user