Skip to content

Commit e486326

Browse files
committed
More colorful merge sort animation
1 parent e845a45 commit e486326

File tree

1 file changed

+59
-41
lines changed

1 file changed

+59
-41
lines changed

algorithms-helper/merge-sort.ts

+59-41
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,33 @@
1-
import { AnimateFunctionParams } from "../types"
1+
import { AnimateFunctionParams, AnimationStep } from "../types"
22
import {
33
changeBarsColor,
44
getNumberValueFromElementHeight,
55
postSortAnimation,
66
} from "../utils"
77

8-
interface animationHolder {
9-
compare?: [number, number]
10-
idxToInsertTo?: number
11-
moveFromIdx?: number
12-
shift?: number
13-
}
14-
158
interface mergeSortParams {
169
array: number[]
1710
start: number
1811
end: number
19-
animationHolder: animationHolder[]
12+
animationStepsHolder: AnimationStep[]
2013
}
2114

2215
interface mergeParams extends mergeSortParams {
2316
mid: number
2417
}
2518

2619
const merge = (params: mergeParams) => {
27-
let { array, start, mid, end, animationHolder: animations } = params
20+
let { array, start, mid, end, animationStepsHolder } = params
2821
let start2 = mid + 1
2922

3023
while (start <= mid && start2 <= end) {
31-
animations.push({ compare: [start, start2] })
24+
animationStepsHolder.push({ compare: [start, start2] })
3225
if (array[start] < array[start2]) {
26+
animationStepsHolder.push({ correctOrder: [start, start2] })
3327
start++
3428
} else {
35-
animations.push({
36-
idxToInsertTo: start,
37-
moveFromIdx: start2,
38-
shift: start2 - start,
39-
})
29+
animationStepsHolder.push({ wrongOrder: [start, start2] })
30+
animationStepsHolder.push({ swap: [start, start2] })
4031
const valueToMove = array[start2]
4132
let idxToShiftFrom = start2
4233

@@ -54,50 +45,77 @@ const merge = (params: mergeParams) => {
5445
}
5546

5647
const mergeSort = (params: mergeSortParams) => {
57-
const { array, start, end, animationHolder } = params
48+
const { array, start, end, animationStepsHolder } = params
5849
if (start >= end) return
5950

6051
const mid = Math.floor(start + (end - start) / 2)
61-
mergeSort({ array, start, end: mid, animationHolder })
62-
mergeSort({ array, start: mid + 1, end, animationHolder })
63-
merge({ array, start, mid, end, animationHolder })
52+
mergeSort({
53+
array,
54+
start,
55+
end: mid,
56+
animationStepsHolder: animationStepsHolder,
57+
})
58+
mergeSort({
59+
array,
60+
start: mid + 1,
61+
end,
62+
animationStepsHolder: animationStepsHolder,
63+
})
64+
merge({ array, start, mid, end, animationStepsHolder: animationStepsHolder })
6465
}
6566

6667
const animateMergeSort = (params: AnimateFunctionParams) => {
6768
const { bars, palette, sortingSpeed, callback } = params
68-
const array = bars.map((bar) => getNumberValueFromElementHeight(bar.style.height))
69-
// TODO: Add more key to the animation steps. E.g: correctOrder, wrongOrder, etc.
70-
const animations = []
71-
mergeSort({ array, start: 0, end: array.length - 1, animationHolder: animations })
69+
const array = bars.map((bar) =>
70+
getNumberValueFromElementHeight(bar.style.height)
71+
)
72+
73+
const animationSteps: AnimationStep[] = []
74+
mergeSort({
75+
array,
76+
start: 0,
77+
end: array.length - 1,
78+
animationStepsHolder: animationSteps,
79+
})
7280

7381
let previousOp: "compare" | "swap" = "compare"
74-
let previousActiveBars: HTMLElement[] = []
75-
animations.forEach((animation: animationHolder, idx) => {
82+
let previousActiveBars: HTMLElement[]
83+
animationSteps.forEach((animation, idx) => {
7684
setTimeout(() => {
77-
if (idx > 0 && previousOp === "compare") {
78-
setTimeout(() => {
79-
const [idx1, idx2] = animations[idx - 1].compare
80-
changeBarsColor([bars[idx1], bars[idx2]], palette.idle)
81-
}, 5)
85+
if (idx > 0) {
86+
changeBarsColor(previousActiveBars, palette.idle)
8287
}
8388

8489
if (animation.compare) {
8590
previousOp = "compare"
86-
const [idx1, idx2] = animation.compare
87-
const barsToOperate = [bars[idx1], bars[idx2]]
91+
const barsToOperate = animation.compare.map((idx) => bars[idx])
8892
changeBarsColor(barsToOperate, palette.compare)
8993
previousActiveBars = barsToOperate
90-
} else {
91-
const { idxToInsertTo, moveFromIdx } = animation
92-
previousOp = "swap"
93-
const barToMoveHeight = bars[moveFromIdx].style.height
94-
for (let x = moveFromIdx; x > idxToInsertTo; x--) {
95-
bars[x].style.height = bars[x - 1].style.height
94+
} else if (animation.wrongOrder) {
95+
const barsToOperate = animation.wrongOrder.map((idx) => bars[idx])
96+
changeBarsColor(barsToOperate, palette.wrongOrder)
97+
previousActiveBars = barsToOperate
98+
} else if (animation.correctOrder) {
99+
const barsToOperate = animation.correctOrder.map((idx) => bars[idx])
100+
changeBarsColor(barsToOperate, palette.correctOrder)
101+
previousActiveBars = barsToOperate
102+
} else if (animation.swap) {
103+
const [idx1, idx2] = animation.swap
104+
const movedBarHeight = bars[idx2].style.height
105+
const barsToOperate = bars.slice(idx1, idx2 + 1)
106+
107+
for (let i = idx2; i > idx1; i--) {
108+
bars[i].style.backgroundColor = palette.correctOrder
109+
bars[i].style.height = bars[i - 1].style.height
96110
}
97-
bars[idxToInsertTo].style.height = barToMoveHeight
111+
112+
bars[idx1].style.backgroundColor = palette.swap
113+
bars[idx1].style.height = movedBarHeight
114+
115+
previousActiveBars = barsToOperate
98116
}
99117

100-
if (idx === animations.length - 1 && callback) {
118+
if (idx === animationSteps.length - 1 && callback) {
101119
changeBarsColor(previousActiveBars, palette.idle)
102120
callback()
103121
postSortAnimation(bars, palette.correctOrder)

0 commit comments

Comments
 (0)