Skip to content

Commit 8c59970

Browse files
committed
Add some animation. Add Mobile adaptation.
1 parent 4396458 commit 8c59970

15 files changed

+293
-103
lines changed

autopackup.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import hashlib
2+
import os
3+
import re
4+
import time
5+
6+
html_sha = ''
7+
js_sha = ''
8+
9+
while True:
10+
files = os.listdir('dist')
11+
for filename in files:
12+
filename = os.path.join('dist', filename)
13+
if filename.endswith('.html'):
14+
with open(filename, 'rb') as f:
15+
html_txt = f.read()
16+
if filename.endswith('.js'):
17+
with open(filename, 'rb') as f:
18+
js_txt = f.read()
19+
js_txt = js_txt.replace(b'\\', b'/placeholder/')
20+
new_html_sha = hashlib.sha256(html_txt).hexdigest()
21+
new_js_sha = hashlib.sha256(js_txt).hexdigest()
22+
if (new_html_sha != html_sha or new_js_sha != js_sha):
23+
print('Detect change. Packing...')
24+
new_html_txt = re.sub(rb'<script.*?></script>',
25+
b'<script>\n' + js_txt + b'\n</script>',
26+
html_txt)
27+
new_html_txt = new_html_txt.replace(b'/placeholder/', b'\\')
28+
with open('TreePlaygroundPackup.html', 'wb') as f:
29+
f.write(new_html_txt)
30+
print('Packed...')
31+
html_sha = new_html_sha
32+
js_sha = new_js_sha
33+
time.sleep(1)

dist/TreePlayground.html

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@
33

44
<head>
55
<meta charset="UTF-8">
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
77
<meta name="author" content="NitroMelon">
8-
<meta name="school" content="Tsinghua University">
8+
<meta name="institution" content="Tsinghua University">
99
<meta name="git" content="https://github.com/hwc0919/TreePlayground">
10+
<meta name="website" content="https://192.144.210.149/">
11+
<link rel="Shortcut Icon" href="/favicon.ico">
1012
<title>TreePlayground - NitroMelon</title>
1113
</head>
1214

1315
<body>
1416
<div id="header" style="position: fixed; left: 5px; top: 5px;">
1517
<p style="color: gray">Recommend Chrome on PC</p>
1618
</div>
17-
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'>
19+
<div id="TreePlayground" @mousemove='onTPMouseMove($event)' @touchmove='onTPMouseMove($event)'
20+
@mouseup="onTreeMouseLeave" @touchend="onTreeMouseLeave">
1821
<!-- Top Toolbar -->
1922
<div class="top-toolbar">
2023
<button class="btn btn-primary top-toolbar-item" type="button"
@@ -23,27 +26,27 @@
2326
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(1)">中序遍历</button>
2427
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(2)">后序遍历</button>
2528
<button class="btn btn-primary top-toolbar-item" type="button" @click="traversal(3)">层次遍历</button>
26-
<div id="trav-intrvl-ranger" class="top-toolbar-item">
27-
<h4 style="margin: 5px">遍历间隔: <label v-text="commonParams.interval + 'ms'">500ms</label></h4>
29+
<span id="interval-ranger" class="top-toolbar-item">
30+
<span style="margin: 5px">间隔: <label v-text="commonParams.interval + 'ms'">500ms</label></span>
2831
<input type="range" min="100" max="1500" value="500" step="100" v-model.number="commonParams.interval">
29-
</div>
32+
</span>
3033
</div>
3134
<!-- Left Toolbar -->
3235
<div class="left-toolbar">
33-
<button class="btn btn-default" type="button" @click="reset">Reset</button>
34-
<select id="tree-type-selector" v-model="curTreeType">
36+
<button class="btn btn-default left-toolbar-item" type="button" @click="reset">Reset</button>
37+
<select id="tree-type-selector" class="left-toolbar-item" v-model="curTreeType">
3538
<option v-for="status, ttype in availTreeTypes" v-text="ttype" :value="ttype" :disabled="!status">
3639
</option>
3740
</select>
38-
<div id="tree-scale-ranger">
39-
<input type="range" min="50" max="150" value="100" v-model.number="treeScale">
41+
<div id="tree-scale-ranger" class="left-toolbar-item">
4042
<h4>Scale: <label v-text="commonParams.treeScale + '%'"></h4>
43+
<input type="range" min="20" max="180" value="100" v-model.number="treeScale">
4144
</div>
4245
</div>
4346
<!-- Tree Visualization Part -->
44-
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;"
45-
@mousedown.self="onTreeMouseDown" @mouseup.self="onTreeMouseLeave" @touchstart.self="onTreeMouseDown"
46-
@touchend.self="onTreeMouseLeave">
47+
<div class="tree" ref="tree" :style="adjustScale" style="transform-origin: top;">
48+
<div class="tree-dragging-btn" @mousedown.self="onTreeMouseDown" @touchstart.self.prevent="onTreeMouseDown">
49+
</div>
4750
<!-- Top Functional Node -->
4851
<top-binnode id="trvl-sequence" :data="topSequence" @top-build="onTopBuild" @top-insert="onTopInsert"
4952
@top-search="onTopSearch" @top-help="onTopHelp" @top-proper="onTopProper"></top-binnode>

dist/bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { BST } from "./js/BST"
66
import { AVL } from "./js/AVL"
77
import { Splay } from "./js/Splay"
88

9-
var vm = new Vue({
9+
var tp = new Vue({
1010
el: "#TreePlayground",
1111
data: {
1212
availTreeTypes: { "BinTree": true, "BST": true, "AVL": true, "Splay": true, "RedBlack": false },
1313
commonParams: {
14-
curTreeType: "BinTree", // Important : Always use as `this.curTreeType`.
14+
curTreeType: "BST", // Important : Always use as `this.curTreeType`.
1515
treeScale: 100, // in %
1616
interval: 500 // in ms
1717
},
@@ -223,25 +223,27 @@ var vm = new Vue({
223223
this.alertAsync(`Step 1: Splay ${node.data}`, -1);
224224
node.active = true;
225225
setTimeout(() => {
226+
// Splay RM Step 1
226227
this.locks.rotateLock = true;
227228
this.splayAsync(node, (rootOrNull) => {
228229
if (rootOrNull === undefined) return false;
229230
if (rootOrNull === null) throw "Error in RemoveOne";
230231
let v = rootOrNull;
231232
let tree = this.tree;
232233
tree._size--;
233-
if (!v.rc || !v.rc) { // Splay Simple Situation
234+
if (!v.rc || !v.rc) { // Splay RM Step 2a
234235
if (!v.rc) { if (tree._root = v.lc) tree._root.parent = null; }
235236
else { if (tree._root = v.rc) tree._root.parent = null; }
236237
this.alertAsync(`Final: remove ${node.data}`, 2500);
237238
this.update();
238-
} else { // Splay Complex Situation
239+
} else { // Splay RM Step 2b
239240
node.active = false; node.deprecated = true;
240241
this.locks.trvlLock = true;
241242
this.alertAsync(`Step 2: Elevate Succ of ${node.data}`, -1);
242243
this.searchAsync(v.rc, v.data, (_, hot) => {
243244
this.locks.rotateLock = true;
244245
this.splayAsync(hot, (newRoot) => {
246+
// Splay RM Step 3
245247
this.alertAsync(`Step 3: Finally remove ${node.data}`, 2500);
246248
tree.reAttachAsLC(newRoot, v.lc);
247249
this.update();
@@ -272,11 +274,11 @@ var vm = new Vue({
272274
node.deprecated = true;
273275
this.locks.trvlLock = true; // TODO : change to srchLock
274276
this.searchAsync(node, succ.data, () => { // assert res === true
277+
// RM Step 2: Swap with Succ
275278
this.alertAsync(`Step 2: Swap with Succ`, -1);
276279
this.update();
277280
node.deprecated = true; succ.active = true;
278281
setTimeout(() => {
279-
// RM Step 2: Swap
280282
let t = node.data; node.data = succ.data; succ.data = t;
281283
node.deprecated = false; succ.active = false;
282284
node.active = true; succ.deprecated = true;
@@ -285,8 +287,10 @@ var vm = new Vue({
285287
setTimeout(() => {
286288
this.tree.removeAt(succ);
287289
this.update();
290+
// RM Step 4 : AVL reBalance
288291
if ("AVL" === this.curTreeType) {
289-
this.alertAsync(`Step 4: Solve AVL Unbalance`, -1);
292+
this.alertAsync(`Step 4: AVL reBalance`, -1);
293+
if (this.tree._hot) this.tree._hot.active = true;
290294
setTimeout(() => {
291295
this.locks.rotateLock = true;
292296
this.avlRmRotateAsync(this.tree._hot, () => {
@@ -494,10 +498,13 @@ var vm = new Vue({
494498
/* Dragger */
495499
/****************************************/
496500
onTreeMouseDown(event) {
501+
if (event.button !== 0 && event.type !== "touchstart") {
502+
this.isDragging = false; return false;
503+
}
497504
console.log("Start dragging")
498-
this.treeXY = [event.target.offsetLeft, event.target.offsetTop];
505+
this.treeXY = [this.$refs.tree.offsetLeft, this.$refs.tree.offsetTop];
499506
switch (event.type) {
500-
case "mousedown": this.mouseXY = [event.x, event.y]; break;
507+
case "mousedown": this.mouseXY = [event.clientX, event.clientY]; break;
501508
case "touchstart":
502509
this.mouseXY = [event.touches[0].clientX, event.touches[0].clientY];
503510
break;
@@ -509,7 +516,7 @@ var vm = new Vue({
509516
if (this.isDragging) {
510517
let newXY;
511518
switch (event.type) {
512-
case "mousemove": newXY = [event.x, event.y]; break;
519+
case "mousemove": newXY = [event.clientX, event.clientY]; break;
513520
case "touchmove":
514521
newXY = [event.touches[0].clientX, event.touches[0].clientY];
515522
break;
@@ -520,8 +527,10 @@ var vm = new Vue({
520527
}
521528
},
522529
onTreeMouseLeave(e) {
523-
console.log("End dragging")
524-
this.isDragging = false;
530+
if (this.isDragging) {
531+
console.log("End dragging")
532+
this.isDragging = false;
533+
}
525534
},
526535
/****************************************/
527536
/* Validators */
@@ -580,13 +589,12 @@ var vm = new Vue({
580589
},
581590
curTreeType: {
582591
get() { return this.commonParams.curTreeType; },
583-
set(newV) { this.commonParams.curTreeType = newV; this.init(); } // Important!!!
592+
set(newV) { this.commonParams.curTreeType = newV; this.init(); } // Important
584593
},
585594
treeScale: {
586595
get() { return this.commonParams.treeScale; },
587596
set(newV) { this.commonParams.treeScale = newV; }
588597
},
589-
590598
curTreeClass() {
591599
return this.treeClassMap[this.curTreeType];
592600
},
@@ -596,7 +604,7 @@ var vm = new Vue({
596604
},
597605
showExtr() {
598606
return true;
599-
}
607+
},
600608
},
601609
watch: {
602610
tree: {
@@ -609,14 +617,14 @@ var vm = new Vue({
609617
handler() {
610618
localStorage.commonParams = JSON.stringify(this.commonParams);
611619
}, deep: true
612-
}
620+
},
613621
},
614622
mounted() {
615623
try { this.commonParams = JSON.parse(localStorage.commonParams); }
616624
catch (err) { }
617-
if (this.availTreeTypes[this.curTreeType] == undefined) this.curTreeType = "BinTree";
625+
if (this.availTreeTypes[this.curTreeType] == undefined) this.curTreeType = "BST";
618626
this.init();
619627
},
620628
});
621629

622-
window.vm = vm;
630+
window.tp = tp;

src/components/components.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,8 @@ Vue.component('binnode', {
3939
return { showInput: false, updation: this.node.data }
4040
},
4141
template:
42-
`<div class="binnode intr-binnode" :style="{'left': node.x + 'px', 'top': node.y + 'px'}" :title="'height: ' + node.height"
43-
@click="divOnClick">
44-
<span v-show="!showInput" style="display: inline-block; width: 100%; height: 100%;">{{ node.data }}</span>
42+
`<div class="binnode intr-binnode" :style="{'left': node.x + 'px', 'top': node.y + 'px'}" @click="divOnClick">
43+
<span v-show="!showInput" :title="title" style="display: inline-block; width: 100%; height: 100%;">{{ node.data }}</span>
4544
<label v-show="showRemoveOne" class="node-delete-btn node-upper-btn" title="remove one"
4645
@click.stop="$emit('remove-one', node)">&times;</label>
4746
<label v-show="showRemoveBelow" class="subtree-delete-btn node-upper-btn" title="remove below"
@@ -72,6 +71,9 @@ Vue.component('binnode', {
7271
}
7372
},
7473
computed: {
74+
title() {
75+
return `height: ${this.node.height}\nsize: ${this.node.size()}\nnpl:${this.node.npl}`
76+
},
7577
/* **************************************** */
7678
/* ************ Remove Buttons ************ */
7779
/* **************************************** */

src/css/binnodes.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@
7171
z-index: 3;
7272
}
7373

74+
.binnode:hover {
75+
text-shadow: 0px 0px 1px;
76+
box-shadow: 0 0 5px;
77+
}
78+
7479
.binnode:hover .node-upper-btn, .binnode:hover .node-left-btn {
7580
opacity: 0.5;
7681
}

src/css/button.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
.btn:active {
1212
transform: scale(0.99);
13-
}
13+
transform-origin: left;
14+
}
1415

1516
.btn-default:hover {
1617
box-shadow: 0 0 1px 1px gray;

0 commit comments

Comments
 (0)