1
0
mirror of https://gitee.com/coder-xiaomo/algorithm-visualization synced 2025-01-10 11:48:18 +08:00
Code Issues Projects Releases Wiki Activity GitHub Gitee

完成链表绘制;引入GSAP动画库;完成基本的两个元素交换动画

This commit is contained in:
程序员小墨 2022-05-17 00:31:19 +08:00
parent fc9fed1ecb
commit 87b69a9bf7
30 changed files with 433 additions and 76 deletions

View File

@ -1,6 +1,6 @@
# 数据结构可视化
# 算法可视化

View File

@ -131,4 +131,164 @@ class Shape {
.text(text)
.style("fill", workSpace.settings.colorMap["text"])
}
// 绘制一个链表
getLinkedListFragment(id, nodes) {
var settings = this.workSpace.settings
let displayMaxWidth = 1 * settings.innerSize.width
let displayMaxHeight = 1 * settings.innerSize.height
let areaWidth = 1 * nodes.length // 按照1个Unit来计算
let areaHeight = 1 // 按照1个Unit来计算
let oneUnit = 100
// 可以假设高度相等比较宽度,这样好理解
if (displayMaxWidth / displayMaxHeight > areaWidth / areaHeight) {
// 展示区域左右有多余空间
oneUnit = displayMaxHeight / areaHeight
} else {
// 展示区域上下有空间(或刚刚好)
oneUnit = displayMaxWidth / areaWidth
}
// 定义最大值
if (oneUnit > 120) oneUnit = 120
let fragment = document.createDocumentFragment()
fragment.customAttr = {
nodes: nodes,
type: "linkedList",
oneUnit: oneUnit
}
console.log(fragment.customAttr)
// <g></g> 元素不能设置 width 和 height
let g = d3.select(fragment)
.append("svg:g")
.attr("id", id)
.attr("fill", "white")
.attr("transform", `translate(${settings.margin.left}, ${settings.margin.top})`)
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i]
let _g = g.append("svg:g")
_g.append("svg:rect")
.attr("x", i * oneUnit)
.attr("y", 0)
.attr("width", oneUnit)
.attr("height", oneUnit)
.attr("fill", settings.colorMap["fill"])
.attr("stroke", settings.colorMap["stroke"])
_g.append("svg:text")
.text(node)
.attr("x", i * oneUnit + oneUnit / 2)
.attr("y", oneUnit / 2)
.attr("width", oneUnit)
.attr("height", oneUnit)
.attr("fill", settings.colorMap["text"])
// console.log(text.node().getBBox())
// console.log(text.node().getBoundingClientRect())
}
// g.append("svg:rect")
// .attr("width", oneUnit * nodes.length)
// .attr("height", oneUnit)
// .style("fill", "none")
// .style("stroke", "green")
return fragment
}
}
class VectorAnimation {
constructor(workSpace) {
this.workSpace = workSpace
}
swapElementAttr(attrName/* or attrNameList */, element1, element2) {
function exchange(attrName) {
// 保存 element1 的属性,将 element2 的属性赋值给 element1, 再将保存的属性赋值给 element2
var tmp = element1.getAttribute(attrName)
element1.setAttribute(attrName, element2.getAttribute(attrName))
element2.setAttribute(attrName, tmp)
}
if (typeof attrName === "string") {
exchange(attrName)
} else if (typeof attrName === "object") {
for (let i = 0; i < attrName.length; i++) {
exchange(attrName[i])
}
}
}
swapElementInnerHTML(element1, element2) {
var tmp = element1.innerHTML
element1.innerHTML = element2.innerHTML
element2.innerHTML = tmp
}
swapElementsAttr(elementPairList) {
// [
// [attrName or attrNameList, element1, element2],
// [attrName or attrNameList, element1, element2],
// ...
// ]
for (let i = 0; i < elementPairList.length; i++) {
let elementPair = elementPairList[i]
this.swapElementAttr(elementPair[0], elementPair[1], elementPair[2])
}
}
swapLinkedListItems(id, [fromIndex, toIndex]) {
var settings = this.workSpace.settings
let linkedList = document.getElementById(id)
let customAttr = linkedList.customAttr
console.log(customAttr)
var gList = linkedList.childNodes
let from = gList[fromIndex]
let to = gList[toIndex]
var deltaX = customAttr.oneUnit * (fromIndex - toIndex);
var deltaY = customAttr.oneUnit * 1.08
var animateSettings = {
duration: 0.3,
ease: "sine.inOut",
delay: 0,
yoyo: true,
}
var tl = gsap.timeline({
onComplete: function () {
console.log("success")
}
})
tl.add([
gsap.to(from.childNodes[0], { ...animateSettings, fill: settings.colorMap["fill_focus"] }),
gsap.to(to.childNodes[0], { ...animateSettings, fill: settings.colorMap["fill_focus"] }),
gsap.to(from.childNodes[1], { ...animateSettings, fill: settings.colorMap["text_focus"] }),
gsap.to(to.childNodes[1], { ...animateSettings, fill: settings.colorMap["text_focus"] }),
gsap.to(from.childNodes, { ...animateSettings, y: -deltaY }),
gsap.to(to.childNodes, { ...animateSettings, y: deltaY }),
]).add([
gsap.to(from.childNodes, { ...animateSettings, x: -deltaX }),
gsap.to(to.childNodes, { ...animateSettings, x: deltaX }),
]).add([
gsap.to(from.childNodes[0], { ...animateSettings, fill: settings.colorMap["fill"] }),
gsap.to(to.childNodes[0], { ...animateSettings, fill: settings.colorMap["fill"] }),
gsap.to(from.childNodes[1], { ...animateSettings, fill: settings.colorMap["text"] }),
gsap.to(to.childNodes[1], { ...animateSettings, fill: settings.colorMap["text"] }),
gsap.to(from.childNodes, { ...animateSettings, y: 0 }),
gsap.to(to.childNodes, { ...animateSettings, y: 0 }),
])
// // 首先元素的文字为了保证用户看起来不闪烁同时用transform临时交换元素的位置用户看起来就像是没有交换一样但是此时已经交换过了
// // 最后再把 transform 恢复即可
// this.swapElementInnerHTML(from, to)
}
}

View File

@ -13,20 +13,30 @@ var settings = {
width: null, // 带单位,通过 outerSize 计算得到
height: null, // 带单位,通过 outerSize 计算得到
margin: { // 不带单位
top: 20,
top: 180,
right: 20,
bottom: 20,
bottom: 180,
left: 20
},
oneUnit: { // 不带单位,通过 innerSize 计算得到
transverse: null, // 横向单位长度 ( innerSize 的 1% )
longitudinal: null // 纵向单位长度 ( innerSize 的 1% )
},
colorMap: {
"background": "#ddd",
"stroke": "#e02433", // 边框颜色
"fill": "#ffa4ab", // 填充颜色
"text": "blue", // 文本颜色
"stroke": "#e02433", // 边框颜色
"fill": "#ffa4ab", // 填充颜色
"fill_focus": "#ee737d", // 填充颜色
"text": "blue", // 文本颜色
"text_focus": "white", // 文本颜色
"red": "#f00",
"green": "#0f0",
},
animation: {
duration: 2000, // 不带单位,单位是毫秒
easing: "ease-in-out"
}
}
@ -34,10 +44,15 @@ settings.width = settings.outerSize.width + "px";
settings.height = settings.outerSize.height + "px";
settings.innerSize.width = settings.outerSize.width - settings.margin.left - settings.margin.right;
settings.innerSize.height = settings.outerSize.height - settings.margin.top - settings.margin.bottom;
settings.oneUnit.transverse = settings.innerSize.width / 100;
settings.oneUnit.longitudinal = settings.innerSize.height / 100;
console.log("settings", settings)
// 初始化
var workSpace = new WorkSpace(settings)
var shape = new Shape(workSpace)
var animation = new VectorAnimation(workSpace)
function initialize() {
@ -46,72 +61,83 @@ function initialize() {
initialize()
// 测试
shape.rectangle("ele1", {
x: 10,
y: 10,
width: "20%",
height: "30%",
fillColor: "blue",
strokeColor: "red"
}).style("stroke-width", "10px")
shape.circle("ele2", {
x: 200,
y: 50,
radius: "20px",
fillColor: "green",
strokeColor: "red"
})
shape.text("ele3", {
x: 200,
y: 150,
text: "文本",
fillColor: "red"
})
shape.line("ele4", {
x1: 100,
y1: 100,
x2: 200,
y2: 200,
strokeColor: "red"
// shape.rectangle("ele1", {
// x: 10,
// y: 10,
// width: "20%",
// height: "30%",
// fillColor: "blue",
// strokeColor: "red"
// }).style("stroke-width", "10px")
// shape.circle("ele2", {
// x: 200,
// y: 50,
// radius: "20px",
// fillColor: "green",
// strokeColor: "red"
// })
// shape.text("ele3", {
// x: 200,
// y: 150,
// text: "文本",
// fillColor: "red"
// })
// shape.line("ele4", {
// x1: 100,
// y1: 100,
// x2: 200,
// y2: 200,
// strokeColor: "red"
// })
// var data = []
// for (let i = 0; i < 20; i++) // 生成随机数
// data.push(Math.ceil(Math.random() * 10))
// var scale = {
// x: d3.scaleLinear()
// .domain([0, data.length - 1])
// .range([0, settings.innerSize.width]),
// y: d3.scaleLinear()
// .domain([0, d3.max(data)])
// .range([settings.innerSize.height, 0])
// }
// var line_generator = d3.line()
// .x(function (d, i) { return scale.x(i); })
// .y(function (d, i) { return scale.y(d); })
// // .curve(d3.curveBasis)
// // .curve(d3.curveCardinal)
// shape.path("ele5", line_generator(data), {
// fillColor: "none",
// strokeColor: "red"
// })
// shape.path("ele6", line_generator.curve(d3.curveCardinal)(data), {
// fillColor: "none",
// strokeColor: "green"
// })
// // shape.addShape("g", "axisX").attr("transform", `translate(${settings.margin.left}, ${settings.outerSize.height - settings.margin.bottom})`)//.attr("fill", "red")
// shape.axis("axisX", {
// transform: `translate(${settings.margin.left}, ${settings.outerSize.height - settings.margin.bottom})`,
// axis: d3.axisBottom(scale.x)
// })
// shape.axis("axisY", {
// transform: `translate(${settings.margin.left}, ${settings.margin.top})`,
// axis: d3.axisLeft(scale.y)
// })
// shape.addNode("ele7", 300, 200, "20px", "20px", "文本")
let fragment = shape.getLinkedListFragment("ele8", [1, 2, 3, 4, 5, 6, 7, 8, 9], { //
x: 100,
y: 100,
width: "100px",
height: "100px",
})
var data = []
for (let i = 0; i < 20; i++) // 生成随机数
data.push(Math.ceil(Math.random() * 10))
var scale = {
x: d3.scaleLinear()
.domain([0, data.length - 1])
.range([0, settings.innerSize.width]),
y: d3.scaleLinear()
.domain([0, d3.max(data)])
.range([settings.innerSize.height, 0])
}
var line_generator = d3.line()
.x(function (d, i) { return scale.x(i); })
.y(function (d, i) { return scale.y(d); })
// .curve(d3.curveBasis)
// .curve(d3.curveCardinal)
shape.path("ele5", line_generator(data), {
fillColor: "none",
strokeColor: "red"
})
shape.path("ele6", line_generator.curve(d3.curveCardinal)(data), {
fillColor: "none",
strokeColor: "green"
})
// shape.addShape("g", "axisX").attr("transform", `translate(${settings.margin.left}, ${settings.outerSize.height - settings.margin.bottom})`)//.attr("fill", "red")
shape.axis("axisX", {
transform: `translate(${settings.margin.left}, ${settings.outerSize.height - settings.margin.bottom})`,
axis: d3.axisBottom(scale.x)
})
shape.axis("axisY", {
transform: `translate(${settings.margin.left}, ${settings.margin.top})`,
axis: d3.axisLeft(scale.y)
})
shape.addNode("ele7", 300, 200, "20px", "20px", "文本")
// // 添加 g 元素
// primaryCanvas.append("g")
console.log(fragment)
workSpace.primaryCanvas.node().appendChild(fragment)
document.getElementById("ele8").customAttr = fragment.customAttr
setTimeout(() => {
animation.swapLinkedListItems("ele8", [0, 2])
}, 100)

View File

@ -0,0 +1,11 @@
/*!
* CSSRulePlugin 3.10.4
* https://greensock.com
*
* @license Copyright 2022, GreenSock. All rights reserved.
* Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership.
* @author: Jack Doyle, jack@greensock.com
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function h(){return"undefined"!=typeof window}function i(){return t||h()&&(t=window.gsap)&&t.registerPlugin&&t}function j(){return n||(s(),o||console.warn("Please gsap.registerPlugin(CSSPlugin, CSSRulePlugin)")),n}var t,n,c,o,s=function _initCore(e){t=e||i(),h()&&(c=document),t&&(o=t.plugins.css)&&(n=1)},r={version:"3.10.4",name:"cssRule",init:function init(e,t,n,i,s){if(!j()||void 0===e.cssText)return!1;var r=e._gsProxy=e._gsProxy||c.createElement("div");this.ss=e,this.style=r.style,r.style.cssText=e.cssText,o.prototype.init.call(this,r,t,n,i,s)},render:function render(e,t){for(var n,i=t._pt,s=t.style,r=t.ss;i;)i.r(e,i.d),i=i._next;for(n=s.length;-1<--n;)r[s[n]]=s[s[n]]},getRule:function getRule(e){j();var t,n,i,s,r=c.all?"rules":"cssRules",o=c.styleSheets,l=o.length,u=":"===e.charAt(0);for(e=(u?"":",")+e.split("::").join(":").toLowerCase()+",",u&&(s=[]);l--;){try{if(!(n=o[l][r]))continue;t=n.length}catch(e){console.warn(e);continue}for(;-1<--t;)if((i=n[t]).selectorText&&-1!==(","+i.selectorText.split("::").join(":").toLowerCase()+",").indexOf(e)){if(!u)return i.style;s.push(i.style)}}return s},register:s};i()&&t.registerPlugin(r),e.CSSRulePlugin=r,e.default=r;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
/*!
* EasePack 3.10.4
* https://greensock.com
*
* @license Copyright 2022, GreenSock. All rights reserved.
* Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership.
* @author: Jack Doyle, jack@greensock.com
*/
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e=e||self).window=e.window||{})}(this,function(e){"use strict";function f(){return w||"undefined"!=typeof window&&(w=window.gsap)&&w.registerPlugin&&w}function g(e,n){return!!(void 0===e?n:e&&!~(e+"").indexOf("false"))}function h(e){if(w=e||f()){r=w.registerEase;var n,t=w.parseEase(),o=function createConfig(t){return function(e){var n=.5+e/2;t.config=function(e){return t(2*(1-e)*e*n+e*e)}}};for(n in t)t[n].config||o(t[n]);for(n in r("slow",a),r("expoScale",s),r("rough",u),c)"version"!==n&&w.core.globals(n,c[n])}}function i(e,n,t){var o=(e=Math.min(1,e||.7))<1?n||0===n?n:.7:0,r=(1-e)/2,i=r+e,a=g(t);return function(e){var n=e+(.5-e)*o;return e<r?a?1-(e=1-e/r)*e:n-(e=1-e/r)*e*e*e*n:i<e?a?1===e?0:1-(e=(e-i)/r)*e:n+(e-n)*(e=(e-i)/r)*e*e*e:a?1:n}}function j(n,e,t){var o=Math.log(e/n),r=e-n;return t=t&&w.parseEase(t),function(e){return(n*Math.exp(o*(t?t(e):e))-n)/r}}function k(e,n,t){this.t=e,this.v=n,t&&(((this.next=t).prev=this).c=t.v-n,this.gap=t.t-e)}function l(e){"object"!=typeof e&&(e={points:+e||20});for(var n,t,o,r,i,a,f,s=e.taper||"none",u=[],c=0,p=0|(+e.points||20),l=p,v=g(e.randomize,!0),d=g(e.clamp),h=w?w.parseEase(e.template):0,x=.4*(+e.strength||1);-1<--l;)n=v?Math.random():1/p*l,t=h?h(n):n,o="none"===s?x:"out"===s?(r=1-n)*r*x:"in"===s?n*n*x:n<.5?(r=2*n)*r*.5*x:(r=2*(1-n))*r*.5*x,v?t+=Math.random()*o-.5*o:l%2?t+=.5*o:t-=.5*o,d&&(1<t?t=1:t<0&&(t=0)),u[c++]={x:n,y:t};for(u.sort(function(e,n){return e.x-n.x}),a=new k(1,1,null),l=p;l--;)i=u[l],a=new k(i.x,i.y,a);return f=new k(0,0,a.t?a:a.next),function(e){var n=f;if(e>n.t){for(;n.next&&e>=n.t;)n=n.next;n=n.prev}else for(;n.prev&&e<=n.t;)n=n.prev;return(f=n).v+(e-n.t)/n.gap*n.c}}var w,r,a=i(.7);(a.ease=a).config=i;var s=j(1,2);s.config=j;var u=l();(u.ease=u).config=l;var c={SlowMo:a,RoughEase:u,ExpoScaleEase:s};for(var n in c)c[n].register=h,c[n].version="3.10.4";f()&&w.registerPlugin(a),e.EasePack=c,e.ExpoScaleEase=s,e.RoughEase=u,e.SlowMo=a,e.default=c;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
/*!
* EaselPlugin 3.10.4
* https://greensock.com
*
* @license Copyright 2022, GreenSock. All rights reserved.
* Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership.
* @author: Jack Doyle, jack@greensock.com
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function k(){return"undefined"!=typeof window}function l(){return h||k()&&(h=window.gsap)&&h.registerPlugin&&h}function m(){return r||t&&t.createjs||t||{}}function n(e){return console.warn(e)}function o(e){var t=e.getBounds&&e.getBounds();t||(t=e.nominalBounds||{x:0,y:0,width:100,height:100},e.setBounds&&e.setBounds(t.x,t.y,t.width,t.height)),e.cache&&e.cache(t.x,t.y,t.width,t.height),n("EaselPlugin: for filters to display in EaselJS, you must call the object's cache() method first. GSAP attempted to use the target's getBounds() for the cache but that may not be completely accurate. "+e)}function p(e,t,r){(b=b||m().ColorFilter)||n("EaselPlugin error: The EaselJS ColorFilter JavaScript file wasn't loaded.");for(var i,l,s,u,a,f,c=e.filters||[],d=c.length;d--;)if(c[d]instanceof b){l=c[d];break}if(l||(l=new b,c.push(l),e.filters=c),s=l.clone(),null!=t.tint)i=h.utils.splitColor(t.tint),u=null!=t.tintAmount?+t.tintAmount:1,s.redOffset=i[0]*u,s.greenOffset=i[1]*u,s.blueOffset=i[2]*u,s.redMultiplier=s.greenMultiplier=s.blueMultiplier=1-u;else for(a in t)"exposure"!==a&&"brightness"!==a&&(s[a]=+t[a]);for(null!=t.exposure?(s.redOffset=s.greenOffset=s.blueOffset=255*(t.exposure-1),s.redMultiplier=s.greenMultiplier=s.blueMultiplier=1):null!=t.brightness&&(u=t.brightness-1,s.redOffset=s.greenOffset=s.blueOffset=0<u?255*u:0,s.redMultiplier=s.greenMultiplier=s.blueMultiplier=1-Math.abs(u)),d=8;d--;)l[a=M[d]]!==s[a]&&(f=r.add(l,a,l[a],s[a]))&&(f.op="easel_colorFilter");r._props.push("easel_colorFilter"),e.cacheID||o(e)}function u(e,t){if(!(e instanceof Array&&t instanceof Array))return t;var r,i,n=[],l=0,o=0;for(r=0;r<4;r++){for(i=0;i<5;i++)o=4===i?e[l+4]:0,n[l+i]=e[l]*t[i]+e[l+1]*t[i+5]+e[l+2]*t[i+10]+e[l+3]*t[i+15]+o;l+=5}return n}function z(e,t,r){(d=d||m().ColorMatrixFilter)||n("EaselPlugin: The EaselJS ColorMatrixFilter JavaScript file wasn't loaded.");for(var i,l,s,a,f=e.filters||[],c=f.length;-1<--c;)if(f[c]instanceof d){s=f[c];break}for(s||(s=new d(w.slice()),f.push(s),e.filters=f),l=s.matrix,i=w.slice(),null!=t.colorize&&(i=function _colorize(e,t,r){isNaN(r)&&(r=1);var i=h.utils.splitColor(t),n=i[0]/255,l=i[1]/255,o=i[2]/255,s=1-r;return u([s+r*n*x,r*n*y,r*n*_,0,0,r*l*x,s+r*l*y,r*l*_,0,0,r*o*x,r*o*y,s+r*o*_,0,0,0,0,0,1,0],e)}(i,t.colorize,Number(t.colorizeAmount))),null!=t.contrast&&(i=function _setContrast(e,t){return isNaN(t)?e:u([t+=.01,0,0,0,128*(1-t),0,t,0,0,128*(1-t),0,0,t,0,128*(1-t),0,0,0,1,0],e)}(i,Number(t.contrast))),null!=t.hue&&(i=function _setHue(e,t){if(isNaN(t))return e;t*=Math.PI/180;var r=Math.cos(t),i=Math.sin(t);return u([x+r*(1-x)+i*-x,y+r*-y+i*-y,_+r*-_+i*(1-_),0,0,x+r*-x+.143*i,y+r*(1-y)+.14*i,_+r*-_+-.283*i,0,0,x+r*-x+i*-(1-x),y+r*-y+i*y,_+r*(1-_)+i*_,0,0,0,0,0,1,0,0,0,0,0,1],e)}(i,Number(t.hue))),null!=t.saturation&&(i=function _setSaturation(e,t){if(isNaN(t))return e;var r=1-t,i=r*x,n=r*y,l=r*_;return u([i+t,n,l,0,0,i,n+t,l,0,0,i,n,l+t,0,0,0,0,0,1,0],e)}(i,Number(t.saturation))),c=i.length;-1<--c;)i[c]!==l[c]&&(a=r.add(l,c,l[c],i[c]))&&(a.op="easel_colorMatrixFilter");r._props.push("easel_colorMatrixFilter"),e.cacheID||o(),r._matrix=l}function A(e){h=e||l(),k()&&(t=window),h&&(g=1)}var h,g,t,r,b,d,M="redMultiplier,greenMultiplier,blueMultiplier,alphaMultiplier,redOffset,greenOffset,blueOffset,alphaOffset".split(","),w=[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],x=.212671,y=.71516,_=.072169,i={version:"3.10.4",name:"easel",init:function init(e,t,r,i,l){var o,s,u,a,f,c,d;for(o in g||(A(),h||n("Please gsap.registerPlugin(EaselPlugin)")),this.target=e,t)if(f=t[o],"colorFilter"===o||"tint"===o||"tintAmount"===o||"exposure"===o||"brightness"===o)u||(p(e,t.colorFilter||t,this),u=!0);else if("saturation"===o||"contrast"===o||"hue"===o||"colorize"===o||"colorizeAmount"===o)a||(z(e,t.colorMatrixFilter||t,this),a=!0);else if("frame"===o){if("string"==typeof f&&"="!==f.charAt(1)&&(c=e.labels))for(d=0;d<c.length;d++)c[d].label===f&&(f=c[d].position);(s=this.add(e,"gotoAndStop",e.currentFrame,f,i,l,Math.round))&&(s.op=o)}else null!=e[o]&&this.add(e,o,"get",f)},render:function render(e,t){for(var r=t._pt;r;)r.r(e,r.d),r=r._next;t.target.cacheID&&t.target.updateCache()},register:A,registerCreateJS:function(e){r=e}};l()&&h.registerPlugin(i),e.EaselPlugin=i,e.default=i;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
/*!
* ScrollToPlugin 3.10.4
* https://greensock.com
*
* @license Copyright 2022, GreenSock. All rights reserved.
* Subject to the terms at https://greensock.com/standard-license or for Club GreenSock members, the agreement issued with that membership.
* @author: Jack Doyle, jack@greensock.com
*/
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function k(){return"undefined"!=typeof window}function l(){return u||k()&&(u=window.gsap)&&u.registerPlugin&&u}function m(e){return"string"==typeof e}function n(e){return"function"==typeof e}function o(e,t){var o="x"===t?"Width":"Height",n="scroll"+o,r="client"+o;return e===T||e===i||e===c?Math.max(i[n],c[n])-(T["inner"+o]||i[r]||c[r]):e[n]-e["offset"+o]}function p(e,t){var o="scroll"+("x"===t?"Left":"Top");return e===T&&(null!=e.pageXOffset?o="page"+t.toUpperCase()+"Offset":e=null!=i[o]?i:c),function(){return e[o]}}function r(e,t){if(!(e=f(e)[0])||!e.getBoundingClientRect)return console.warn("scrollTo target doesn't exist. Using 0")||{x:0,y:0};var o=e.getBoundingClientRect(),n=!t||t===T||t===c,r=n?{top:i.clientTop-(T.pageYOffset||i.scrollTop||c.scrollTop||0),left:i.clientLeft-(T.pageXOffset||i.scrollLeft||c.scrollLeft||0)}:t.getBoundingClientRect(),l={x:o.left-r.left,y:o.top-r.top};return!n&&t&&(l.x+=p(t,"x")(),l.y+=p(t,"y")()),l}function s(e,t,n,l,i){return isNaN(e)||"object"==typeof e?m(e)&&"="===e.charAt(1)?parseFloat(e.substr(2))*("-"===e.charAt(0)?-1:1)+l-i:"max"===e?o(t,n)-i:Math.min(o(t,n),r(e,t)[n]-i):parseFloat(e)-i}function t(){u=l(),k()&&u&&document.body&&(T=window,c=document.body,i=document.documentElement,f=u.utils.toArray,u.config({autoKillThreshold:7}),v=u.config(),a=1)}var u,a,T,i,c,f,v,y={version:"3.10.4",name:"scrollTo",rawVars:1,register:function register(e){u=e,t()},init:function init(e,o,r,l,i){a||t();var c=this,f=u.getProperty(e,"scrollSnapType");c.isWin=e===T,c.target=e,c.tween=r,o=function _clean(e,t,o,r){if(n(e)&&(e=e(t,o,r)),"object"!=typeof e)return m(e)&&"max"!==e&&"="!==e.charAt(1)?{x:e,y:e}:{y:e};if(e.nodeType)return{y:e,x:e};var l,i={};for(l in e)i[l]="onAutoKill"!==l&&n(e[l])?e[l](t,o,r):e[l];return i}(o,l,e,i),c.vars=o,c.autoKill=!!o.autoKill,c.getX=p(e,"x"),c.getY=p(e,"y"),c.x=c.xPrev=c.getX(),c.y=c.yPrev=c.getY(),f&&"none"!==f&&(c.snap=1,c.snapInline=e.style.scrollSnapType,e.style.scrollSnapType="none"),null!=o.x?(c.add(c,"x",c.x,s(o.x,e,"x",c.x,o.offsetX||0),l,i),c._props.push("scrollTo_x")):c.skipX=1,null!=o.y?(c.add(c,"y",c.y,s(o.y,e,"y",c.y,o.offsetY||0),l,i),c._props.push("scrollTo_y")):c.skipY=1},render:function render(e,t){for(var n,r,l,i,s,p=t._pt,c=t.target,f=t.tween,u=t.autoKill,a=t.xPrev,y=t.yPrev,d=t.isWin,x=t.snap,g=t.snapInline;p;)p.r(e,p.d),p=p._next;n=d||!t.skipX?t.getX():a,l=(r=d||!t.skipY?t.getY():y)-y,i=n-a,s=v.autoKillThreshold,t.x<0&&(t.x=0),t.y<0&&(t.y=0),u&&(!t.skipX&&(s<i||i<-s)&&n<o(c,"x")&&(t.skipX=1),!t.skipY&&(s<l||l<-s)&&r<o(c,"y")&&(t.skipY=1),t.skipX&&t.skipY&&(f.kill(),t.vars.onAutoKill&&t.vars.onAutoKill.apply(f,t.vars.onAutoKillParams||[]))),d?T.scrollTo(t.skipX?n:t.x,t.skipY?r:t.y):(t.skipY||(c.scrollTop=t.y),t.skipX||(c.scrollLeft=t.x)),!x||1!==e&&0!==e||(r=c.scrollTop,n=c.scrollLeft,g?c.style.scrollSnapType=g:c.style.removeProperty("scroll-snap-type"),c.scrollTop=r+1,c.scrollLeft=n+1,c.scrollTop=r,c.scrollLeft=n),t.xPrev=t.x,t.yPrev=t.y},kill:function kill(e){var t="scrollTo"===e;!t&&"scrollTo_x"!==e||(this.skipX=1),!t&&"scrollTo_y"!==e||(this.skipY=1)}};y.max=o,y.getOffset=r,y.buildGetter=p,l()&&u.registerPlugin(y),e.ScrollToPlugin=y,e.default=y;if (typeof(window)==="undefined"||window!==e){Object.defineProperty(e,"__esModule",{value:!0})} else {delete e.default}});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
@ -8,6 +8,18 @@
<title>小墨 | 算法可视化 | Algorithm Visualization</title>
<link rel="stylesheet" href="./assets/css/index.css">
<style>
/* 调整 SVG 中文本定位点到文本中央 */
text {
text-anchor: middle;
dominant-baseline: middle;
}
svg {
user-select: none;
}
</style>
</head>
<body>
@ -52,7 +64,10 @@
</div>
<!-- D3.js refer: https://d3js.org/ -->
<script src="./assets/lib/d3/7.4.4/d3.js"></script>
<script src="./assets/lib/d3/7.4.4/d3.min.js"></script>
<!-- GSAP refer: https://greensock.com/docs/v3/Installation -->
<script src="./assets/lib/gsap/3.10.4/gsap.min.js"></script>
<!-- class -->
<script src="./assets/js/class.js"></script>
@ -62,7 +77,7 @@
<!-- 排序算法 -->
<script src="./assets/js/algorithm/sort.js"></script>
<!-- 算法测试 -->
<script src="./assets/js/algorithm/test.js"></script>
<!-- <script src="./assets/js/algorithm/test.js"></script> -->
</body>
</html>