Skip to content

Commit 41d657b

Browse files
committed
Add Agida theme
1 parent d875e60 commit 41d657b

File tree

11 files changed

+624
-12
lines changed

11 files changed

+624
-12
lines changed

src/components/app/AppCheckbox.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,18 @@ export default class AppCheckbox extends Vue {
88
@Prop({ default: false }) value!: boolean
99
@Prop({ default: '' }) label!: string
1010

11-
get isActive() {
12-
return this.value
13-
}
14-
15-
get classes() {
11+
get classes(): Record<string, boolean> {
1612
return {
1713
checkbox: true,
1814
'checkbox--active': this.value
1915
}
2016
}
2117

22-
get idCheckbox() {
18+
get idCheckbox(): string {
2319
return `input-${(this as any)._uid}`
2420
}
2521

26-
changeState() {
22+
changeState(): void {
2723
this.$emit('input', !this.value)
2824
}
2925

@@ -41,9 +37,9 @@ export default class AppCheckbox extends Vue {
4137
onInput={ this.changeState }
4238
/>
4339
</div>
44-
<p for={ this.idCheckbox } class="input-label">
40+
<label for={ this.idCheckbox } class="input-label">
4541
{ this.label }
46-
</p>
42+
</label>
4743
</label>
4844
}
4945
}

src/components/themes/agida/index.tsx

Lines changed: 248 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* bezier-spline.js
2+
*
3+
* computes cubic bezier coefficients to generate a smooth
4+
* line through specified points. couples with SVG graphics
5+
* for interactive processing.
6+
*
7+
* For more info see:
8+
* http://www.particleincell.com/2012/bezier-splines/
9+
*
10+
* Lubos Brieda, Particle In Cell Consulting LLC, 2012
11+
* you may freely use this algorithm in your codes however where feasible
12+
* please include a link/reference to the source article
13+
*/
14+
/* computes control points given knots K, this is the brain of the operation */
15+
export function computeControlPoints(K: number[]) {
16+
const p1 = []
17+
const p2 = []
18+
const n = K.length - 1
19+
20+
/* rhs vector */
21+
const a = []
22+
const b = []
23+
const c = []
24+
const r = []
25+
26+
/* left most segment */
27+
a[0] = 0
28+
b[0] = 2
29+
c[0] = 1
30+
r[0] = K[0] + 2 * K[1]
31+
32+
/* internal segments */
33+
for (let i = 1; i < n - 1; i++) {
34+
a[i] = 1
35+
b[i] = 4
36+
c[i] = 1
37+
r[i] = 4 * K[i] + 2 * K[i + 1]
38+
}
39+
40+
/* right segment */
41+
a[n - 1] = 2
42+
b[n - 1] = 7
43+
c[n - 1] = 0
44+
r[n - 1] = 8 * K[n - 1] + K[n]
45+
46+
/* solves Ax=b with the Thomas algorithm (from Wikipedia) */
47+
for (let i = 1; i < n; i++) {
48+
const m: number = a[i] / b[i - 1]
49+
b[i] = b[i] - m * c[i - 1]
50+
r[i] = r[i] - m * r[i - 1]
51+
}
52+
53+
p1[n - 1] = r[n - 1] / b[n - 1]
54+
for (let i = n - 2; i >= 0; --i) p1[i] = (r[i] - c[i] * p1[i + 1]) / b[i]
55+
56+
/* we have p1, now compute p2 */
57+
for (let i = 0; i < n - 1; i++) p2[i] = 2 * K[i + 1] - p1[i + 1]
58+
59+
p2[n - 1] = 0.5 * (K[n] + p1[n - 1])
60+
61+
return { p1: p1, p2: p2 }
62+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Wavery, WaveConfigInterface } from './wave'
2+
3+
export function waveInit(data: WaveConfigInterface) {
4+
const wavery = new Wavery(data)
5+
6+
return wavery.generateSvg()
7+
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
import { computeControlPoints } from './bezier-spline'
2+
const svgns = 'http://www.w3.org/2000/svg'
3+
4+
export interface WaveConfigInterface {
5+
height: number;
6+
width: number;
7+
segmentCount: number;
8+
layerCount: number;
9+
variance: number;
10+
strokeWidth?: number;
11+
fillColor?: string;
12+
strokeColor?: string;
13+
transform?: string;
14+
animation?: boolean | WaveConfigAnimationInterface;
15+
}
16+
17+
export interface WaveConfigAnimationInterface {
18+
time?: number;
19+
steps?: number;
20+
}
21+
22+
interface Point {
23+
x: number;
24+
y: number;
25+
}
26+
27+
const defaultAnimationValues = {
28+
steps: 3,
29+
time: 40000,
30+
timingFunction: 'ease',
31+
iteration: 'infinite'
32+
}
33+
34+
export class Wavery {
35+
properties!: WaveConfigInterface
36+
points: Point[][] = []
37+
animationPoints: Point[][][] = [];
38+
39+
constructor(properties: WaveConfigInterface) {
40+
this.properties = properties
41+
this.points = this.generatePoints()
42+
43+
if (this.needAnimation) {
44+
const { steps } = this.animation
45+
46+
Array.from(Array(steps)).forEach(() => {
47+
this.animationPoints.push(this.generatePoints())
48+
})
49+
}
50+
}
51+
52+
get animation() {
53+
const animation = this.properties.animation
54+
const isBoolean = typeof animation === 'boolean'
55+
56+
return isBoolean ? defaultAnimationValues : { ...defaultAnimationValues, ...animation }
57+
}
58+
59+
get cellWidth() {
60+
return this.properties.width / this.properties.segmentCount
61+
}
62+
63+
get cellHeight() {
64+
return this.properties.height / this.properties.layerCount
65+
}
66+
67+
get needAnimation() {
68+
return this.properties.animation
69+
}
70+
71+
get pathList() {
72+
const pathList = []
73+
74+
for (let i = 0; i < this.points.length; i++) {
75+
pathList.push(this.generateClosedPath(i))
76+
}
77+
78+
return pathList
79+
}
80+
81+
generatePoints(): Point[][] {
82+
const { cellWidth, cellHeight } = this
83+
const { width, height, variance } = this.properties
84+
const moveLimitX = cellWidth * variance * 0.2
85+
const moveLimitY = cellHeight * variance
86+
const points = []
87+
88+
for (let y = cellHeight; y <= height; y += cellHeight) {
89+
const pointsPerLayer = []
90+
pointsPerLayer.push({ x: 0, y: Math.floor(y) })
91+
92+
for (let x = cellWidth; x < width; x += cellWidth) {
93+
const varietalY = y - moveLimitY / 2 + Math.random() * moveLimitY
94+
const varietalX = x - moveLimitX / 2 + Math.random() * moveLimitX
95+
pointsPerLayer.push({
96+
x: Math.floor(varietalX),
97+
y: Math.floor(varietalY)
98+
})
99+
}
100+
pointsPerLayer.push({ x: width, y: Math.floor(y) })
101+
points.push(pointsPerLayer)
102+
}
103+
104+
return points
105+
}
106+
107+
generateClosedPath(index: number) {
108+
const animatedPathList: string[] = []
109+
110+
const { fillColor, strokeColor, strokeWidth, transform } = this.properties
111+
const style = { fillColor, strokeColor, strokeWidth, transform }
112+
113+
const path = this.generatePath(this.points[index])
114+
115+
if (this.needAnimation) {
116+
this.animationPoints.forEach((waves) => {
117+
animatedPathList.push(this.generatePath(waves[index]))
118+
})
119+
}
120+
121+
return {
122+
...style,
123+
d: path,
124+
animatedPath: animatedPathList
125+
}
126+
}
127+
128+
generatePath(points: Point[]) {
129+
const xPoints = points.map((p) => p.x)
130+
const yPoints = points.map((p) => p.y)
131+
132+
const leftCornerPoint = { x: 0, y: this.properties.height + this.cellHeight }
133+
const rightCornerPoint = { x: this.properties.width, y: this.properties.height + this.cellHeight }
134+
const xControlPoints = computeControlPoints(xPoints)
135+
const yControlPoints = computeControlPoints(yPoints)
136+
137+
let path =
138+
`M ${leftCornerPoint.x},${leftCornerPoint.y} ` +
139+
`C ${leftCornerPoint.x},${leftCornerPoint.y} ` +
140+
`${xPoints[0]},${yPoints[0]} ` +
141+
`${xPoints[0]},${yPoints[0]} `
142+
143+
for (let i = 0; i < xPoints.length - 1; i++) {
144+
path +=
145+
`C ${xControlPoints.p1[i]},${yControlPoints.p1[i]} ` +
146+
`${xControlPoints.p2[i]},${yControlPoints.p2[i]} ` +
147+
`${xPoints[i + 1]},${yPoints[i + 1]} `
148+
}
149+
150+
path +=
151+
`C ${xPoints[xPoints.length - 1]},${yPoints[xPoints.length - 1]} ` +
152+
`${rightCornerPoint.x},${rightCornerPoint.y} ` +
153+
`${rightCornerPoint.x},${rightCornerPoint.y} Z`
154+
155+
return path
156+
}
157+
158+
private generateKeyframe(percent: number, d: string) {
159+
return `${percent}% {d: path("${d}")}`
160+
}
161+
162+
generateAnimationStyle(index: number) {
163+
const path = this.pathList[index]
164+
const { steps } = this.animation
165+
if (!path) { return }
166+
167+
const animationList = Array.from(Array(steps + 2)).map((_, index, { length }) => {
168+
const isBound = index === 0 || index + 1 === length
169+
const percent = index * (100 / (steps + 1))
170+
return this.generateKeyframe(percent, isBound ? path.d : path.animatedPath[index - 1])
171+
})
172+
173+
console.log({ animationList })
174+
175+
return `.path-${index}{
176+
animation:pathAnim-${index} ${this.animation.time}ms;
177+
animation-timing-function: ${this.animation.timingFunction};
178+
animation-iteration-count: ${this.animation.iteration};
179+
}
180+
181+
@keyframes pathAnim-${index}{
182+
${animationList.join('')}
183+
}`
184+
}
185+
186+
generateSvg() {
187+
return {
188+
svg: {
189+
width: this.properties.width,
190+
height: this.properties.height + this.cellHeight,
191+
xmlns: svgns,
192+
paths: this.pathList
193+
}
194+
}
195+
}
196+
}

src/components/themes/destruction/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default class DestructionTheme extends Vue {
3434
renderOptions: {
3535
externalTimeUse: true
3636
},
37-
renderHook: function() {
37+
renderHook() {
3838
const gl = this as unknown as GL
3939

4040
if (!gl.programInfo.uniforms.position) {

src/style/general.styl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,5 @@
1414
.transition-group
1515
position: relative
1616

17-
.background-image
18-
mask url('../assets/images/masks/main.svg') 50% 50% / 100% 80% no-repeat border-box
17+
// .background-image
18+
// mask url('../assets/images/masks/main.svg') 50% 50% / 100% 80% no-repeat border-box

src/style/themes/agida.styl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.waves--top
2+
position absolute
3+
top 0
4+
left 0
5+
transform-origin 50% 100%
6+
transform: translate(-50%, -100%) rotate(calc(180deg - var(--angle)))
7+
8+
.waves--bottom
9+
position absolute
10+
bottom 0
11+
right 0
12+
transform-origin 50% 100%
13+
transform translateX(50%) rotate(calc(-90deg + (90deg - var(--angle))))
14+

src/style/themes/index.styl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
@import './agida.styl'
12
@import './osmos.styl'
23
@import './space.styl'
34
@import './suprematism.styl'

0 commit comments

Comments
 (0)