Skip to content

Commit

Permalink
Mask Animation End + Animator from, to changes
Browse files Browse the repository at this point in the history
  • Loading branch information
fecapark committed Jun 6, 2022
1 parent eeb84f3 commit 99b6ead
Show file tree
Hide file tree
Showing 23 changed files with 1,065 additions and 129 deletions.
4 changes: 2 additions & 2 deletions @types/AnimationHistory-Type/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ declare module "AnimationHistory-Type" {
}

export interface HistoryData extends ValidatableData {
from: Array<number>;
to: Array<number>;
from: () => Array<number>;
to: () => Array<number>;
}
}
12 changes: 7 additions & 5 deletions @types/Animator-Type/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ declare module "Animator-Type" {
type Nullable = import("global-types").Nullable;

export type BezierValue = [number, number, number, number];
export type OnEndFunction = ({ target }: { target: HTMLElement }) => void;
export type OnFunction = ({ target }: { target: HTMLElement }) => void;
export type AnimatorClosure = (() => boolean) | Nullable;

interface EssentialData {
Expand All @@ -15,21 +15,23 @@ declare module "Animator-Type" {
interface StyleData {
prop: string;
fvalue: string;
from: Array<number>;
to: Array<number>;
from: () => Array<number>;
to: () => Array<number>;
}

interface Custom extends EssentialData {
delay?: number;
bezier?: string | BezierValue;
onEnd?: OnEndFunction;
onStart?: OnFunction;
onEnd?: OnFunction;
pauseOnEnd?: boolean;
}

interface Parsed extends EssentialData {
delay: number;
bezier: BezierValue;
onEnd: OnEndFunction;
onStart: OnFunction;
onEnd: OnFunction;
pauseOnEnd: boolean;
}
}
Expand Down
2 changes: 1 addition & 1 deletion jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"testEnvironment": "jsdom",
"moduleNameMapper": {
"^@/(.*)$": "<rootDir>/$1",
"\\.(css|less|scss)$": "<rootDir>/src/mock-dummy.ts"
"\\.(css|less|scss)$": "<rootDir>/src/jest-mock-module.ts"
},
"testMatch": [
"<rootDir>/**/*.test.(js|jsx|ts|tsx)",
Expand Down
64 changes: 64 additions & 0 deletions src/components/Buttons/CircleButton/CircleButton.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
.circle-button {
all: unset;

display: inline-flex;
justify-content: center;
align-items: center;

// 사지방에서 테스팅 해야함.
position: sticky;
bottom: 2em;
margin-top: 2em;

// sticky 되먼 이거로 하고싶음... 그게 아니면 평소에는 중간에 놓기
// align-self: flex-end;
align-self: center;

overflow: hidden;
border-radius: 50%;

background-color: $secondary-color;
cursor: pointer;
z-index: 1000;

width: 3.6em;
height: 3.6em;
font-size: 20px;

transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1);

&.hidden {
transition: 0.25s cubic-bezier(0, 0, 0.2, 1);
opacity: 0;
font-size: 0;
}

i {
color: white;
}

.ripple {
position: absolute;
background-color: black;
opacity: 0.15;
border-radius: 50%;
width: 1.5em;
height: 1.5em;
transform: translate3d(-50%, -50%, 0);
animation: ripple-effect cubic-bezier(0, 0, 0.2, 1) 0.8s forwards;
}
}

@keyframes ripple-effect {
0% {
opacity: 0.15;
width: 1.5em;
height: 1.5em;
}

100% {
opacity: 0;
width: 12em;
height: 12em;
}
}
74 changes: 74 additions & 0 deletions src/components/Buttons/CircleButton/CircleButton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import "./CircleButton.scss";
import Component from "../../../core/Component/Component";
import { setShadow } from "../../../lib/shadow/shadow";

interface ButtonOptions {
shadowLevel?: number;
hiddenAtStart?: boolean;
}

export default class CircleButton extends Component {
private ripple: HTMLElement | null = null;

constructor(
private readonly onTouch: () => void,
{ shadowLevel = 0, hiddenAtStart = false }: ButtonOptions = {}
) {
super({
tagName: "button",
classNames: ["circle-button", hiddenAtStart ? "hidden" : ""],
});
setShadow(this.container, shadowLevel);

this.render();
}

handleButtonEvent(e: PointerEvent) {
e.stopPropagation();
this.onTouch();
}

renderRipple(e: PointerEvent) {
this.removeRipple();

this.ripple = document.createElement("div");
this.ripple.classList.add("ripple");

const bRect: DOMRect = this.container.getBoundingClientRect();
this.ripple.style.top = `${e.clientY - bRect.top}px`;
this.ripple.style.left = `${e.clientX - bRect.left}px`;

this.appendElementsTo("", this.ripple);
}

removeRipple() {
if (!this.ripple) return;

this.ripple.remove();
this.ripple = null;
}

render() {
this.container.removeEventListener(
"pointerup",
this.handleButtonEvent.bind(this)
);
this.container.removeEventListener(
"pointerdown",
this.renderRipple.bind(this)
);

this.container.innerHTML = `
<i class="fa-solid fa-arrow-right"></i>
`;

this.container.addEventListener(
"pointerdown",
this.renderRipple.bind(this)
);
this.container.addEventListener(
"pointerup",
this.handleButtonEvent.bind(this)
);
}
}
76 changes: 76 additions & 0 deletions src/components/Cards/HeadInfoCard/HeadInfoCard.scss
Original file line number Diff line number Diff line change
@@ -1,9 +1,60 @@
@mixin result-profile-mixin {
.result-profile-container {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;

font-size: 12px;
color: black;
background-color: white;
padding: 15px;

i {
cursor: pointer;
font-size: 14px;
color: $secondary-text-color;

opacity: 0;
}

.info-name-container {
width: 100%;

display: flex;
flex-direction: column;
margin-left: 15px;

.info-name {
font-size: 16px;
font-weight: 900;
margin-bottom: 3px;
color: $primary-color;

opacity: 0;
}

.info-remember {
font-size: 11px;
color: $secondary-text-color;
letter-spacing: 0.3px;

opacity: 0;
}
}

.info-tag-container {
}
}
}

.info-card.head {
display: flex;
flex-direction: column;
justify-content: center;
background-color: $primary-color;
padding: 0 25px;
overflow: hidden;

.title-text {
letter-spacing: 0.5px;
Expand All @@ -20,4 +71,29 @@
color: rgba(255, 255, 255, 0.95);
opacity: 0;
}

.dark-mask {
position: absolute;
width: 0;
height: 0;
border-radius: 50%;
background-color: $dark-primary-color;
}

.sub-mask {
position: absolute;
width: 0;
height: 0;
border-radius: 50%;
background-color: white;
overflow: hidden;

display: flex;
justify-content: center;
align-items: center;

@include result-profile-mixin();
}

@include result-profile-mixin();
}
43 changes: 39 additions & 4 deletions src/components/Cards/HeadInfoCard/HeadInfoCard.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,51 @@
import "./HeadInfoCard.scss";
import Component from "../../../core/Component/Component";
import { executeAnimation } from "./HeadInfoCardMask.ani";

export default class HeadInfoCard extends Component {
constructor() {
super({ classNames: ["info-card", "head"] });

this.store.setDefaultState("maskTriggered", false);
this.store.setAction("triggerMask", () => {
return { maskTriggered: true };
});

this.render();
}

public triggerMask() {
this.store.dispatch("triggerMask", {});
}

render() {
this.container.innerHTML = `
<span class="title-text">반가워요!</span>
<span class="sub-title-text">사용자님이 누군지 알려주세요.</span>
`;
if (!this.store.getState("maskTriggered")) {
this.container.innerHTML = `
<span class="title-text">반가워요!</span>
<span class="sub-title-text">사용자님이 누군지 알려주세요.</span>
`;
} else {
this.container.innerHTML = `
<div class="dark-mask"></div>
<div class="sub-mask">
<div class="result-profile-container">
<i class="fa-solid fa-chevron-left"></i>
<div class="info-name-container">
<span class="info-name">환영합니다, 박상혁님.</span>
<span class="info-remember">이제부터 박상혁님을 기억할게요.</span>
</div>
<div class="info-tag-container"></div>
</div>
</div>
`;

requestAnimationFrame(() => {
executeAnimation(
this.container,
this.qs(".dark-mask")!,
this.qs(".sub-mask")!
);
});
}
}
}
Loading

0 comments on commit 99b6ead

Please sign in to comment.