{"id":82087,"date":"2024-10-31T15:18:34","date_gmt":"2024-10-31T11:48:34","guid":{"rendered":"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/"},"modified":"2024-10-31T15:18:34","modified_gmt":"2024-10-31T11:48:34","slug":"building-interactive-emoji-animations-in-react-4o5c","status":"publish","type":"post","link":"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/","title":{"rendered":"\u0633\u0627\u062e\u062a \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627\u06cc \u0627\u06cc\u0645\u0648\u062c\u06cc \u062a\u0639\u0627\u0645\u0644\u06cc \u062f\u0631 React \u269b\ufe0f\ud83c\udfaf"},"content":{"rendered":"<p>Summarize this content to 400 words in Persian Lang \u0622\u06cc\u0627 \u062a\u0627 \u0628\u0647 \u062d\u0627\u0644 \u0628\u0647 \u0627\u06cc\u0646 \u0641\u06a9\u0631 \u06a9\u0631\u062f\u0647 \u0627\u06cc\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u062e\u0648\u062f \u0631\u0627 \u062a\u0639\u0627\u0645\u0644\u06cc \u062a\u0631 \u06a9\u0646\u06cc\u062f\u061f \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 React hooks \u0648 Web Animation API \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0628\u0647 \u0634\u0645\u0627 \u0646\u0634\u0627\u0646 \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc Kollabe\u060c \u0627\u0628\u0632\u0627\u0631 \u0631\u0627\u06cc\u06af\u0627\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u067e\u0648\u06a9\u0631 \u0645\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0631\u062f\u0645.<\/p>\n<p>  \u0686\u0627\u0644\u0634<\/p>\n<p>\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u06cc\u06a9\u0646\u0648\u0627\u062e\u062a \u0634\u0648\u062f\u060c \u0628\u0647 \u062e\u0635\u0648\u0635 \u062f\u0631 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0627\u0632 \u0631\u0627\u0647 \u062f\u0648\u0631. \u062f\u0631 \u062d\u06cc\u0646 \u0633\u0627\u062e\u062a\u0646 Kollabe\u060c \u0645\u0627 \u0645\u06cc \u062e\u0648\u0627\u0633\u062a\u06cc\u0645 \u0639\u0646\u0627\u0635\u0631 \u062a\u0639\u0627\u0645\u0644\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645 \u06a9\u0647:<\/p>\n<p>\u0627\u0639\u0636\u0627\u06cc \u062a\u06cc\u0645 \u0631\u0627 \u062f\u0631\u06af\u06cc\u0631 \u0646\u06af\u0647 \u062f\u0627\u0631\u06cc\u062f<br \/>\n\u06af\u0632\u06cc\u0646\u0647 \u0647\u0627\u06cc \u0628\u0627\u0632\u062e\u0648\u0631\u062f \u063a\u06cc\u0631\u06a9\u0644\u0627\u0645\u06cc \u0631\u0627 \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u06cc\u062f<br \/>\n\u062c\u0644\u0633\u0627\u062a \u0627\u0632 \u0631\u0627\u0647 \u062f\u0648\u0631 \u0631\u0627 \u0634\u062e\u0635\u06cc \u062a\u0631 \u06a9\u0646\u06cc\u062f<br \/>\n\u06cc\u06a9 \u0639\u0627\u0645\u0644 \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u0628\u062f\u0648\u0646 \u0628\u0647 \u062e\u0637\u0631 \u0627\u0646\u062f\u0627\u062e\u062a\u0646 \u0639\u0645\u0644\u06a9\u0631\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/p>\n<p>  \u0631\u0627\u0647 \u062d\u0644: \u0627\u0645\u0648\u062c\u06cc \u0647\u0627\u06cc \u067e\u0631\u0646\u062f\u0647<\/p>\n<p>\u0645\u0627 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u06a9\u0631\u062f\u06cc\u0645 \u06a9\u0647 \u0628\u0647 \u0627\u0639\u0636\u0627\u06cc \u062a\u06cc\u0645 \u0627\u062c\u0627\u0632\u0647 \u0645\u06cc\u200c\u062f\u0647\u062f \u0628\u0627 \u067e\u0631\u062a\u0627\u0628 \u06a9\u0631\u062f\u0646 \u0627\u06cc\u0645\u0648\u062c\u06cc\u200c\u0647\u0627 \u062f\u0631 \u0633\u0631\u0627\u0633\u0631 \u0635\u0641\u062d\u0647 \u0628\u0647 \u062a\u062e\u0645\u06cc\u0646\u200c\u0647\u0627 \u0648\u0627\u06a9\u0646\u0634 \u0646\u0634\u0627\u0646 \u062f\u0647\u0646\u062f. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0633\u0627\u062e\u062a \u0622\u0646 \u0622\u0645\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<p>  \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u0648 \u06a9\u0627\u0631\u0622\u0645\u062f\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f:<\/p>\n<p>import { useCallback, useRef } from &#8220;react&#8221;;<\/p>\n<p>interface Point {<br \/>\n  x: number;<br \/>\n  y: number;<br \/>\n}<\/p>\n<p>interface DOMRect {<br \/>\n  left: number;<br \/>\n  top: number;<br \/>\n  width: number;<br \/>\n  height: number;<br \/>\n}<\/p>\n<p>\/**<br \/>\n * Generates a random number within a specified range.<br \/>\n *\/<br \/>\nconst getRandomNumber = (<br \/>\n  min = 0.1,<br \/>\n  max = 0.4,<br \/>\n  isPositive = Math.random() &lt; 0.5,<br \/>\n): number =&gt; {<br \/>\n  const random = Math.random() * (max &#8211; min) + min;<br \/>\n  return isPositive ? random : -random;<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Calculates the center position of a DOM element.<br \/>\n *\/<br \/>\nconst getCenterPosition = (rect: DOMRect): Point =&gt; ({<br \/>\n  x: rect.left + rect.width \/ 2,<br \/>\n  y: rect.top + rect.height \/ 2,<br \/>\n});<\/p>\n<p>\/**<br \/>\n * Calculates the target position with a random offset from the center.<br \/>\n *\/<br \/>\nconst getTargetPosition = (rect: DOMRect): Point =&gt; {<br \/>\n  const center = getCenterPosition(rect);<br \/>\n  return {<br \/>\n    x: center.x &#8211; getRandomNumber(0, 15, true),<br \/>\n    y: center.y &#8211; getRandomNumber(0, 25, true),<br \/>\n  };<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Calculates the midpoint between two points.<br \/>\n *\/<br \/>\nconst getMidpoint = (start: Point, target: Point): Point =&gt; ({<br \/>\n  x: (start.x + target.x) \/ 2,<br \/>\n  y: (start.y + target.y) \/ 2,<br \/>\n});<\/p>\n<p>\/**<br \/>\n * Calculates the distance between two points.<br \/>\n *\/<br \/>\nconst getDistance = (start: Point, target: Point): number =&gt; {<br \/>\n  return Math.sqrt(<br \/>\n    Math.pow(target.x &#8211; start.x, 2) + Math.pow(target.y &#8211; start.y, 2),<br \/>\n  );<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Calculates the control point for the quadratic Bezier curve.<br \/>\n *\/<br \/>\nconst getControlPoint = (start: Point, target: Point): Point =&gt; {<br \/>\n  const midpoint = getMidpoint(start, target);<br \/>\n  const distance = getDistance(start, target);<\/p>\n<p>  const angle = Math.atan2(target.y &#8211; start.y, target.x &#8211; start.x);<br \/>\n  const perpAngle = angle + Math.PI \/ 2;<br \/>\n  const controlPointDistance = distance * getRandomNumber(0.2, 0.4, true);<\/p>\n<p>  return {<br \/>\n    x: midpoint.x + Math.cos(perpAngle) * controlPointDistance,<br \/>\n    y: midpoint.y + Math.sin(perpAngle) * controlPointDistance,<br \/>\n  };<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Creates and styles the emoji element.<br \/>\n *\/<br \/>\nconst createEmojiElement = (<br \/>\n  emoji: string,<br \/>\n  startPoint: Point,<br \/>\n): HTMLDivElement =&gt; {<br \/>\n  const emojiElement = document.createElement(&#8220;div&#8221;);<br \/>\n  Object.assign(emojiElement.style, {<br \/>\n    position: &#8220;fixed&#8221;,<br \/>\n    fontSize: &#8220;24px&#8221;,<br \/>\n    pointerEvents: &#8220;none&#8221;,<br \/>\n    zIndex: &#8220;1&#8221;,<br \/>\n    left: &#8220;0&#8221;,<br \/>\n    top: &#8220;0&#8221;,<br \/>\n    transform: `translate(${startPoint.x}px, ${startPoint.y}px) translate(-50%, -50%)`,<br \/>\n  });<br \/>\n  emojiElement.textContent = emoji;<br \/>\n  document.body.appendChild(emojiElement);<br \/>\n  return emojiElement;<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Calculates a point on a quadratic Bezier curve.<br \/>\n *\/<br \/>\nconst calculateBezierPoint = (<br \/>\n  start: Point,<br \/>\n  control: Point,<br \/>\n  target: Point,<br \/>\n  progress: number,<br \/>\n): Point =&gt; {<br \/>\n  const easeProgress = 1 &#8211; Math.pow(1 &#8211; progress, 2);<br \/>\n  return {<br \/>\n    x:<br \/>\n      Math.pow(1 &#8211; easeProgress, 2) * start.x +<br \/>\n      2 * (1 &#8211; easeProgress) * easeProgress * control.x +<br \/>\n      Math.pow(easeProgress, 2) * target.x,<br \/>\n    y:<br \/>\n      Math.pow(1 &#8211; easeProgress, 2) * start.y +<br \/>\n      2 * (1 &#8211; easeProgress) * easeProgress * control.y +<br \/>\n      Math.pow(easeProgress, 2) * target.y,<br \/>\n  };<br \/>\n};<\/p>\n<p>\/**<br \/>\n * Custom hook for throwing emoji animations.<br \/>\n *\/<br \/>\nexport const useEmojiThrow = () =&gt; {<br \/>\n  const animationRef = useRef&lt;number&gt;();<br \/>\n  const emojiRef = useRef&lt;HTMLDivElement | null&gt;(null);<\/p>\n<p>  const throwEmoji = useCallback(<br \/>\n    (emoji: string, sourceId: string, targetId: string) =&gt; {<br \/>\n      const sourceEl = document.getElementById(sourceId);<br \/>\n      const targetEl = document.getElementById(targetId);<\/p>\n<p>      if (!sourceEl || !targetEl) return;<\/p>\n<p>      const startRect = sourceEl.getBoundingClientRect();<br \/>\n      const targetRect = targetEl.getBoundingClientRect();<\/p>\n<p>      const startPoint = getCenterPosition(startRect);<br \/>\n      const targetPoint = getTargetPosition(targetRect);<br \/>\n      const controlPoint = getControlPoint(startPoint, targetPoint);<\/p>\n<p>      const emojiElement = createEmojiElement(emoji, startPoint);<br \/>\n      emojiRef.current = emojiElement;<\/p>\n<p>      let startTime = performance.now();<br \/>\n      const duration = 1000; \/\/ Animation duration in milliseconds<\/p>\n<p>      const animate = (currentTime: number) =&gt; {<br \/>\n        const elapsed = currentTime &#8211; startTime;<br \/>\n        const progress = Math.min(elapsed \/ duration, 1);<\/p>\n<p>        const position = calculateBezierPoint(<br \/>\n          startPoint,<br \/>\n          controlPoint,<br \/>\n          targetPoint,<br \/>\n          progress,<br \/>\n        );<\/p>\n<p>        emojiElement.style.transform =<br \/>\n          `translate(${position.x}px, ${position.y}px) translate(-50%, -50%)`;<\/p>\n<p>        if (progress &lt; 1) {<br \/>\n          animationRef.current = requestAnimationFrame(animate);<br \/>\n        } else {<br \/>\n          emojiElement.style.transform =<br \/>\n            `translate(${targetPoint.x}px, ${targetPoint.y}px) translate(-50%, -50%)`;<br \/>\n          setTimeout(() =&gt; {<br \/>\n            emojiElement.remove();<br \/>\n          }, duration);<br \/>\n        }<br \/>\n      };<\/p>\n<p>      requestAnimationFrame(() =&gt; {<br \/>\n        startTime = performance.now();<br \/>\n        animate(startTime);<br \/>\n      });<br \/>\n    },<br \/>\n    [],<br \/>\n  );<\/p>\n<p>  const cleanup = useCallback(() =&gt; {<br \/>\n    if (animationRef.current) {<br \/>\n      cancelAnimationFrame(animationRef.current);<br \/>\n    }<br \/>\n    if (emojiRef.current) {<br \/>\n      emojiRef.current.remove();<br \/>\n    }<br \/>\n  }, []);<\/p>\n<p>  return { throwEmoji, cleanup };<br \/>\n};<\/p>\n<p>  \u0646\u062d\u0648\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0622\u0646<\/p>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0645\u062b\u0627\u0644 \u06a9\u0627\u0645\u0644 \u0627\u0632 \u0646\u062d\u0648\u0647 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0627\u06cc\u0645\u0648\u062c\u06cc \u062f\u0631 \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a React \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<p>import React from &#8216;react&#8217;;<br \/>\nimport { useEmojiThrow } from &#8216;.\/useEmojiThrow&#8217;;<\/p>\n<p>const PlanningPokerRoom: React.FC = () =&gt; {<br \/>\n  const { throwEmoji } = useEmojiThrow();<\/p>\n<p>  const handleEmojiClick = (emoji: string) =&gt; {<br \/>\n    \/\/ Assuming you have elements with these IDs in your DOM<br \/>\n    throwEmoji(emoji, &#8220;source-player-avatar&#8221;, &#8220;target-player-avatar&#8221;);<br \/>\n  };<\/p>\n<p>  return (<br \/>\n    &lt;div className=&#8221;poker-room&#8221;&gt;<br \/>\n      &lt;div id=&#8221;source-player-avatar&#8221; className=&#8221;avatar&#8221;&gt;<br \/>\n        Player 1<br \/>\n      &lt;\/div&gt;<\/p>\n<p>      &lt;div className=&#8221;emoji-controls&#8221;&gt;<br \/>\n        &lt;button onClick={() =&gt; handleEmojiClick(&#8220;\ud83c\udf89&#8221;)}&gt;Throw Confetti&lt;\/button&gt;<br \/>\n        &lt;button onClick={() =&gt; handleEmojiClick(&#8220;\ud83d\udc4d&#8221;)}&gt;Throw Thumbs Up&lt;\/button&gt;<br \/>\n        &lt;button onClick={() =&gt; handleEmojiClick(&#8220;\u2764\ufe0f&#8221;)}&gt;Throw Heart&lt;\/button&gt;<br \/>\n      &lt;\/div&gt;<\/p>\n<p>      &lt;div id=&#8221;target-player-avatar&#8221; className=&#8221;avatar&#8221;&gt;<br \/>\n        Player 2<br \/>\n      &lt;\/div&gt;<br \/>\n    &lt;\/div&gt;<br \/>\n  );<br \/>\n};<\/p>\n<p>export default PlanningPokerRoom;<\/p>\n<p>  \u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc<\/p>\n<p>\u062d\u0631\u06a9\u062a \u0637\u0628\u06cc\u0639\u06cc: \u0627\u0632 \u0645\u0646\u062d\u0646\u06cc \u0647\u0627\u06cc Bezier \u062f\u0631\u062c\u0647 \u062f\u0648\u0645 \u0628\u0631\u0627\u06cc \u062d\u0631\u06a9\u062a \u0635\u0627\u0641 \u0648 \u0642\u0648\u0633 \u0645\u0627\u0646\u0646\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<p>\u062a\u0635\u0627\u062f\u0641\u06cc \u0633\u0627\u0632\u06cc: \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u062c\u0632\u0626\u06cc \u0631\u0627 \u0628\u0647 \u0645\u0648\u0642\u0639\u06cc\u062a \u0647\u0627 \u0648 \u0645\u0633\u06cc\u0631\u0647\u0627\u06cc \u0647\u062f\u0641 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/p>\n<p>\u0639\u0645\u0644\u06a9\u0631\u062f: \u0645\u0648\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 requestAnimationFrame \u0628\u0631\u0627\u06cc \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627\u06cc \u0631\u0648\u0627\u0646<\/p>\n<p>\u067e\u0627\u06a9\u0633\u0627\u0632\u06cc: \u0634\u0627\u0645\u0644 \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u0645\u0646\u0627\u0633\u0628 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627 \u0648 \u0639\u0646\u0627\u0635\u0631 DOM \u0627\u0633\u062a<\/p>\n<p>\u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc TypeScript: \u0628\u0631\u0627\u06cc \u062a\u062c\u0631\u0628\u0647 \u0628\u0647\u062a\u0631 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u06a9\u0627\u0645\u0644\u0627 \u062a\u0627\u06cc\u067e \u0634\u062f\u0647 \u0627\u0633\u062a<\/p>\n<p>  \u062c\u0632\u0626\u06cc\u0627\u062a \u0641\u0646\u06cc<\/p>\n<p>\u0627\u06cc\u0646 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u062a\u0648\u0633\u0637:<\/p>\n<p>\u0645\u062d\u0627\u0633\u0628\u0647 \u0645\u0648\u0642\u0639\u06cc\u062a \u0647\u0627\u06cc \u0634\u0631\u0648\u0639 \u0648 \u067e\u0627\u06cc\u0627\u0646 \u0627\u0632 \u0639\u0646\u0627\u0635\u0631 DOM<br \/>\n\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u0639\u0646\u0635\u0631 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0645\u0648\u0642\u062a<br \/>\n\u0645\u062a\u062d\u0631\u06a9 \u0633\u0627\u0632\u06cc \u0622\u0646 \u062f\u0631 \u0627\u0645\u062a\u062f\u0627\u062f \u0645\u0646\u062d\u0646\u06cc Bezier<br \/>\n\u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u067e\u0633 \u0627\u0632 \u062a\u06a9\u0645\u06cc\u0644 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646<\/p>\n<p>\u0631\u0627 useEmojiThrow \u0647\u0648\u06a9 \u062a\u0645\u0627\u0645 \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc \u0647\u0627 \u0631\u0627 \u06a9\u0646\u062a\u0631\u0644 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u06cc\u06a9 \u0631\u0627\u0628\u0637 \u0633\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0647\u0627 \u0628\u06cc\u0646 \u0647\u0631 \u062f\u0648 \u0639\u0646\u0635\u0631 \u062f\u0631 \u0635\u0641\u062d\u0647 \u0634\u0645\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<p>  \u0622\u0646 \u0631\u0627 \u062f\u0631 \u0639\u0645\u0644 \u0628\u0628\u06cc\u0646\u06cc\u062f<\/p>\n<p>\u0622\u06cc\u0627 \u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u062f \u0627\u06cc\u0646 \u06a9\u062f \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u0645\u062d\u06cc\u0637 \u062a\u0648\u0644\u06cc\u062f \u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f\u061f \u0627\u062a\u0627\u0642 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0645\u0627 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u062f\u0631 \u0622\u0646 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0634\u06a9\u0644\u06a9\u200c\u0647\u0627 \u0631\u0627 \u0628\u0647 \u0628\u0627\u0632\u06cc\u06a9\u0646\u0627\u0646 \u0631\u0628\u0627\u062a \u067e\u0631\u062a\u0627\u0628 \u06a9\u0646\u06cc\u062f \u06cc\u0627 \u062c\u0644\u0633\u0647 \u067e\u0648\u06a9\u0631 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0631\u06cc\u0632\u06cc \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 Kollabe \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>  \u0645\u0644\u0627\u062d\u0638\u0627\u062a \u0639\u0645\u0644\u06a9\u0631\u062f<\/p>\n<p>\u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627 \u0627\u0632 \u062a\u0628\u062f\u06cc\u0644 \u0647\u0627\u06cc CSS \u0628\u0631\u0627\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u0628\u0647\u062a\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u0646\u062f<br \/>\n\u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0646\u0634\u062a \u062d\u0627\u0641\u0638\u0647\u060c \u0639\u0646\u0627\u0635\u0631 \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc \u062a\u0645\u06cc\u0632 \u0645\u06cc \u0634\u0648\u0646\u062f<br \/>\n\u0645\u062d\u0627\u0633\u0628\u0627\u062a \u0628\u0647\u06cc\u0646\u0647 \u0634\u062f\u0647 \u0648 \u062f\u0631 \u0635\u0648\u0631\u062a \u0627\u0645\u06a9\u0627\u0646 \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc \u0634\u0648\u0646\u062f<br \/>\n\u0641\u0631\u06cc\u0645 \u0647\u0627\u06cc \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u062f\u0631 \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u0644\u063a\u0648 \u0645\u06cc \u0634\u0648\u0646\u062f<\/p>\n<p>  \u0633\u0641\u0627\u0631\u0634\u06cc \u0633\u0627\u0632\u06cc \u0647\u0627\u06cc \u0628\u0627\u0644\u0642\u0648\u0647<\/p>\n<p>\u0634\u0645\u0627 \u0628\u0647 \u0631\u0627\u062d\u062a\u06cc \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u06a9\u062f \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f:<\/p>\n<p>\u062a\u0646\u0638\u06cc\u0645 \u0645\u062f\u062a \u0632\u0645\u0627\u0646 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646<br \/>\n\u062a\u063a\u06cc\u06cc\u0631 \u0627\u0646\u062f\u0627\u0632\u0647 \u0627\u06cc\u0645\u0648\u062c\u06cc<br \/>\n\u062a\u063a\u06cc\u06cc\u0631 \u062a\u0635\u0627\u062f\u0641\u06cc \u0645\u0633\u06cc\u0631<br \/>\n\u0627\u0641\u06a9\u062a\u200c\u0647\u0627\u06cc \u0686\u0631\u062e\u0634 \u06cc\u0627 \u0645\u0642\u06cc\u0627\u0633\u200c\u0628\u0646\u062f\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<br \/>\n\u062a\u0648\u0627\u0628\u0639 \u0645\u062e\u062a\u0644\u0641 \u062a\u0633\u0647\u06cc\u0644 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/p>\n<p>  \u0627\u06cc\u0646 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0627\u0633\u062a<\/p>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u0639\u0646\u0627\u0635\u0631 \u062a\u0639\u0627\u0645\u0644\u06cc \u0645\u0627\u0646\u0646\u062f \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0631\u0627 \u0628\u0647 \u062a\u062c\u0631\u0628\u06cc\u0627\u062a \u062a\u06cc\u0645\u06cc \u062c\u0630\u0627\u0628 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0646\u062f. \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062f \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f \u0648 \u0627\u06af\u0631 \u0628\u0647 \u062f\u0646\u0628\u0627\u0644 \u0631\u0627\u0647 \u062d\u0644 \u0622\u0645\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0647\u0633\u062a\u06cc\u062f\u060c Kollabe \u0631\u0627 \u0628\u0631\u0627\u06cc \u062c\u0644\u0633\u0627\u062a \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062a\u06cc\u0645 \u062e\u0648\u062f \u0627\u0645\u062a\u062d\u0627\u0646 \u06a9\u0646\u06cc\u062f.<\/p>\n<p>\u0622\u06cc\u0627 \u062a\u0627 \u0628\u0647 \u062d\u0627\u0644 \u0628\u0647 \u0627\u06cc\u0646 \u0641\u06a9\u0631 \u06a9\u0631\u062f\u0647 \u0627\u06cc\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u062e\u0648\u062f \u0631\u0627 \u062a\u0639\u0627\u0645\u0644\u06cc \u062a\u0631 \u06a9\u0646\u06cc\u062f\u061f \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 React hooks \u0648 Web Animation API \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0628\u0647 \u0634\u0645\u0627 \u0646\u0634\u0627\u0646 \u062e\u0648\u0627\u0647\u0645 \u062f\u0627\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0627\u06cc\u0646 \u0648\u06cc\u0698\u06af\u06cc \u0631\u0627 \u0628\u0631\u0627\u06cc Kollabe\u060c \u0627\u0628\u0632\u0627\u0631 \u0631\u0627\u06cc\u06af\u0627\u0646 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u067e\u0648\u06a9\u0631 \u0645\u0627 \u0627\u06cc\u062c\u0627\u062f \u06a9\u0631\u062f\u0645.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter-rtl ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">\u0641\u0647\u0631\u0633\u062a \u0645\u0637\u0627\u0644\u0628<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%DA%86%D8%A7%D9%84%D8%B4\" >\u0686\u0627\u0644\u0634<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D8%B1%D8%A7%D9%87_%D8%AD%D9%84_%D8%A7%D9%85%D9%88%D8%AC%DB%8C_%D9%87%D8%A7%DB%8C_%D9%BE%D8%B1%D9%86%D8%AF%D9%87\" >\u0631\u0627\u0647 \u062d\u0644: \u0627\u0645\u0648\u062c\u06cc \u0647\u0627\u06cc \u067e\u0631\u0646\u062f\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%DA%A9%D8%A7%D9%85%D9%84\" >\u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D9%86%D8%AD%D9%88%D9%87_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%A7%D8%B2_%D8%A2%D9%86\" >\u0646\u062d\u0648\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0622\u0646<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D9%88%DB%8C%DA%98%DA%AF%DB%8C_%D9%87%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C%D8%AF%DB%8C\" >\u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D8%AC%D8%B2%D8%A6%DB%8C%D8%A7%D8%AA_%D9%81%D9%86%DB%8C\" >\u062c\u0632\u0626\u06cc\u0627\u062a \u0641\u0646\u06cc<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D8%A2%D9%86_%D8%B1%D8%A7_%D8%AF%D8%B1_%D8%B9%D9%85%D9%84_%D8%A8%D8%A8%DB%8C%D9%86%DB%8C%D8%AF\" >\u0622\u0646 \u0631\u0627 \u062f\u0631 \u0639\u0645\u0644 \u0628\u0628\u06cc\u0646\u06cc\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D9%85%D9%84%D8%A7%D8%AD%D8%B8%D8%A7%D8%AA_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF\" >\u0645\u0644\u0627\u062d\u0638\u0627\u062a \u0639\u0645\u0644\u06a9\u0631\u062f<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C_%D8%B3%D8%A7%D8%B2%DB%8C_%D9%87%D8%A7%DB%8C_%D8%A8%D8%A7%D9%84%D9%82%D9%88%D9%87\" >\u0633\u0641\u0627\u0631\u0634\u06cc \u0633\u0627\u0632\u06cc \u0647\u0627\u06cc \u0628\u0627\u0644\u0642\u0648\u0647<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/nabfollower.com\/blog\/building-interactive-emoji-animations-in-react-4o5c\/#%D8%A7%DB%8C%D9%86_%D9%87%D9%85%D9%87_%DA%86%DB%8C%D8%B2_%D8%A7%D8%B3%D8%AA\" >\u0627\u06cc\u0646 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0627\u0633\u062a<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"%DA%86%D8%A7%D9%84%D8%B4\"><\/span>\n<p>  \u0686\u0627\u0644\u0634<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u06cc\u06a9\u0646\u0648\u0627\u062e\u062a \u0634\u0648\u062f\u060c \u0628\u0647 \u062e\u0635\u0648\u0635 \u062f\u0631 \u062a\u0646\u0638\u06cc\u0645\u0627\u062a \u0627\u0632 \u0631\u0627\u0647 \u062f\u0648\u0631. \u062f\u0631 \u062d\u06cc\u0646 \u0633\u0627\u062e\u062a\u0646 Kollabe\u060c \u0645\u0627 \u0645\u06cc \u062e\u0648\u0627\u0633\u062a\u06cc\u0645 \u0639\u0646\u0627\u0635\u0631 \u062a\u0639\u0627\u0645\u0644\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u0645 \u06a9\u0647:<\/p>\n<ul>\n<li>\u0627\u0639\u0636\u0627\u06cc \u062a\u06cc\u0645 \u0631\u0627 \u062f\u0631\u06af\u06cc\u0631 \u0646\u06af\u0647 \u062f\u0627\u0631\u06cc\u062f<\/li>\n<li>\u06af\u0632\u06cc\u0646\u0647 \u0647\u0627\u06cc \u0628\u0627\u0632\u062e\u0648\u0631\u062f \u063a\u06cc\u0631\u06a9\u0644\u0627\u0645\u06cc \u0631\u0627 \u0627\u0631\u0627\u0626\u0647 \u062f\u0647\u06cc\u062f<\/li>\n<li>\u062c\u0644\u0633\u0627\u062a \u0627\u0632 \u0631\u0627\u0647 \u062f\u0648\u0631 \u0631\u0627 \u0634\u062e\u0635\u06cc \u062a\u0631 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u06cc\u06a9 \u0639\u0627\u0645\u0644 \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u0628\u062f\u0648\u0646 \u0628\u0647 \u062e\u0637\u0631 \u0627\u0646\u062f\u0627\u062e\u062a\u0646 \u0639\u0645\u0644\u06a9\u0631\u062f \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B1%D8%A7%D9%87_%D8%AD%D9%84_%D8%A7%D9%85%D9%88%D8%AC%DB%8C_%D9%87%D8%A7%DB%8C_%D9%BE%D8%B1%D9%86%D8%AF%D9%87\"><\/span>\n<p>  \u0631\u0627\u0647 \u062d\u0644: \u0627\u0645\u0648\u062c\u06cc \u0647\u0627\u06cc \u067e\u0631\u0646\u062f\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p><\/p>\n<p>\u0645\u0627 \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647\u200c\u0633\u0627\u0632\u06cc \u06a9\u0631\u062f\u06cc\u0645 \u06a9\u0647 \u0628\u0647 \u0627\u0639\u0636\u0627\u06cc \u062a\u06cc\u0645 \u0627\u062c\u0627\u0632\u0647 \u0645\u06cc\u200c\u062f\u0647\u062f \u0628\u0627 \u067e\u0631\u062a\u0627\u0628 \u06a9\u0631\u062f\u0646 \u0627\u06cc\u0645\u0648\u062c\u06cc\u200c\u0647\u0627 \u062f\u0631 \u0633\u0631\u0627\u0633\u0631 \u0635\u0641\u062d\u0647 \u0628\u0647 \u062a\u062e\u0645\u06cc\u0646\u200c\u0647\u0627 \u0648\u0627\u06a9\u0646\u0634 \u0646\u0634\u0627\u0646 \u062f\u0647\u0646\u062f. \u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u0646\u062d\u0648\u0647 \u0633\u0627\u062e\u062a \u0622\u0646 \u0622\u0645\u062f\u0647 \u0627\u0633\u062a:<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D9%BE%DB%8C%D8%A7%D8%AF%D9%87_%D8%B3%D8%A7%D8%B2%DB%8C_%DA%A9%D8%A7%D9%85%D9%84\"><\/span>\n<p>  \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0627\u0645\u0644 \u0648 \u06a9\u0627\u0631\u0622\u0645\u062f\u06cc \u0627\u0633\u062a \u06a9\u0647 \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f:\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useCallback<\/span><span class=\"p\">,<\/span> <span class=\"nx\">useRef<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">react<\/span><span class=\"dl\">\"<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">Point<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">x<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">y<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"kr\">interface<\/span> <span class=\"nx\">DOMRect<\/span> <span class=\"p\">{<\/span>\n  <span class=\"nl\">left<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">top<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">width<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n  <span class=\"nl\">height<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">}<\/span>\n\n<span class=\"cm\">\/**\n * Generates a random number within a specified range.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getRandomNumber<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span>\n  <span class=\"nx\">min<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.1<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">max<\/span> <span class=\"o\">=<\/span> <span class=\"mf\">0.4<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">isPositive<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">()<\/span> <span class=\"o\">&lt;<\/span> <span class=\"mf\">0.5<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">):<\/span> <span class=\"kr\">number<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">random<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">random<\/span><span class=\"p\">()<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"nx\">max<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">min<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">min<\/span><span class=\"p\">;<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">isPositive<\/span> <span class=\"p\">?<\/span> <span class=\"nx\">random<\/span> <span class=\"p\">:<\/span> <span class=\"o\">-<\/span><span class=\"nx\">random<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the center position of a DOM element.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getCenterPosition<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">rect<\/span><span class=\"p\">:<\/span> <span class=\"nx\">DOMRect<\/span><span class=\"p\">):<\/span> <span class=\"nx\">Point<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">({<\/span>\n  <span class=\"na\">x<\/span><span class=\"p\">:<\/span> <span class=\"nx\">rect<\/span><span class=\"p\">.<\/span><span class=\"nx\">left<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">rect<\/span><span class=\"p\">.<\/span><span class=\"nx\">width<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">y<\/span><span class=\"p\">:<\/span> <span class=\"nx\">rect<\/span><span class=\"p\">.<\/span><span class=\"nx\">top<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">rect<\/span><span class=\"p\">.<\/span><span class=\"nx\">height<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">});<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the target position with a random offset from the center.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getTargetPosition<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">rect<\/span><span class=\"p\">:<\/span> <span class=\"nx\">DOMRect<\/span><span class=\"p\">):<\/span> <span class=\"nx\">Point<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">center<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getCenterPosition<\/span><span class=\"p\">(<\/span><span class=\"nx\">rect<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">x<\/span><span class=\"p\">:<\/span> <span class=\"nx\">center<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">-<\/span> <span class=\"nf\">getRandomNumber<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">15<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span><span class=\"p\">),<\/span>\n    <span class=\"na\">y<\/span><span class=\"p\">:<\/span> <span class=\"nx\">center<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">-<\/span> <span class=\"nf\">getRandomNumber<\/span><span class=\"p\">(<\/span><span class=\"mi\">0<\/span><span class=\"p\">,<\/span> <span class=\"mi\">25<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span><span class=\"p\">),<\/span>\n  <span class=\"p\">};<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the midpoint between two points.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getMidpoint<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">):<\/span> <span class=\"nx\">Point<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">({<\/span>\n  <span class=\"na\">x<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">,<\/span>\n  <span class=\"na\">y<\/span><span class=\"p\">:<\/span> <span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">)<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">});<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the distance between two points.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getDistance<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">):<\/span> <span class=\"kr\">number<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">sqrt<\/span><span class=\"p\">(<\/span>\n    <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">+<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">),<\/span>\n  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Calculates the control point for the quadratic Bezier curve.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">getControlPoint<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">):<\/span> <span class=\"nx\">Point<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">midpoint<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getMidpoint<\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">distance<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getDistance<\/span><span class=\"p\">(<\/span><span class=\"nx\">start<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">angle<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">atan2<\/span><span class=\"p\">(<\/span><span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">,<\/span> <span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">);<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">perpAngle<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">angle<\/span> <span class=\"o\">+<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nx\">PI<\/span> <span class=\"o\">\/<\/span> <span class=\"mi\">2<\/span><span class=\"p\">;<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">controlPointDistance<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">distance<\/span> <span class=\"o\">*<\/span> <span class=\"nf\">getRandomNumber<\/span><span class=\"p\">(<\/span><span class=\"mf\">0.2<\/span><span class=\"p\">,<\/span> <span class=\"mf\">0.4<\/span><span class=\"p\">,<\/span> <span class=\"kc\">true<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">x<\/span><span class=\"p\">:<\/span> <span class=\"nx\">midpoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">+<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">cos<\/span><span class=\"p\">(<\/span><span class=\"nx\">perpAngle<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">controlPointDistance<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">y<\/span><span class=\"p\">:<\/span> <span class=\"nx\">midpoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">+<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">sin<\/span><span class=\"p\">(<\/span><span class=\"nx\">perpAngle<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">controlPointDistance<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">};<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Creates and styles the emoji element.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">createEmojiElement<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span>\n  <span class=\"nx\">emoji<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">startPoint<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">):<\/span> <span class=\"nx\">HTMLDivElement<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">emojiElement<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nf\">createElement<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">div<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"nb\">Object<\/span><span class=\"p\">.<\/span><span class=\"nf\">assign<\/span><span class=\"p\">(<\/span><span class=\"nx\">emojiElement<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span><span class=\"p\">,<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">position<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">fixed<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">fontSize<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">24px<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">pointerEvents<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">none<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">zIndex<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">1<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">left<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">0<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">top<\/span><span class=\"p\">:<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">0<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">transform<\/span><span class=\"p\">:<\/span> <span class=\"s2\">`translate(<\/span><span class=\"p\">${<\/span><span class=\"nx\">startPoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">}<\/span><span class=\"s2\">px, <\/span><span class=\"p\">${<\/span><span class=\"nx\">startPoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">}<\/span><span class=\"s2\">px) translate(-50%, -50%)`<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">});<\/span>\n  <span class=\"nx\">emojiElement<\/span><span class=\"p\">.<\/span><span class=\"nx\">textContent<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">emoji<\/span><span class=\"p\">;<\/span>\n  <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nx\">body<\/span><span class=\"p\">.<\/span><span class=\"nf\">appendChild<\/span><span class=\"p\">(<\/span><span class=\"nx\">emojiElement<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">return<\/span> <span class=\"nx\">emojiElement<\/span><span class=\"p\">;<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Calculates a point on a quadratic Bezier curve.\n *\/<\/span>\n<span class=\"kd\">const<\/span> <span class=\"nx\">calculateBezierPoint<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span>\n  <span class=\"nx\">start<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">control<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">target<\/span><span class=\"p\">:<\/span> <span class=\"nx\">Point<\/span><span class=\"p\">,<\/span>\n  <span class=\"nx\">progress<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">,<\/span>\n<span class=\"p\">):<\/span> <span class=\"nx\">Point<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">easeProgress<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">progress<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">);<\/span>\n  <span class=\"k\">return<\/span> <span class=\"p\">{<\/span>\n    <span class=\"na\">x<\/span><span class=\"p\">:<\/span>\n      <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">easeProgress<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">+<\/span>\n      <span class=\"mi\">2<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">easeProgress<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">easeProgress<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">control<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span> <span class=\"o\">+<\/span>\n      <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"nx\">easeProgress<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">,<\/span>\n    <span class=\"na\">y<\/span><span class=\"p\">:<\/span>\n      <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">easeProgress<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">start<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">+<\/span>\n      <span class=\"mi\">2<\/span> <span class=\"o\">*<\/span> <span class=\"p\">(<\/span><span class=\"mi\">1<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">easeProgress<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">easeProgress<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">control<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span> <span class=\"o\">+<\/span>\n      <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">pow<\/span><span class=\"p\">(<\/span><span class=\"nx\">easeProgress<\/span><span class=\"p\">,<\/span> <span class=\"mi\">2<\/span><span class=\"p\">)<\/span> <span class=\"o\">*<\/span> <span class=\"nx\">target<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">,<\/span>\n  <span class=\"p\">};<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"cm\">\/**\n * Custom hook for throwing emoji animations.\n *\/<\/span>\n<span class=\"k\">export<\/span> <span class=\"kd\">const<\/span> <span class=\"nx\">useEmojiThrow<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">animationRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"kr\">number<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">();<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"nx\">emojiRef<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">useRef<\/span><span class=\"o\">&lt;<\/span><span class=\"nx\">HTMLDivElement<\/span> <span class=\"o\">|<\/span> <span class=\"kc\">null<\/span><span class=\"o\">&gt;<\/span><span class=\"p\">(<\/span><span class=\"kc\">null<\/span><span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">throwEmoji<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useCallback<\/span><span class=\"p\">(<\/span>\n    <span class=\"p\">(<\/span><span class=\"na\">emoji<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"na\">sourceId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">,<\/span> <span class=\"na\">targetId<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">sourceEl<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nf\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"nx\">sourceId<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">targetEl<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">document<\/span><span class=\"p\">.<\/span><span class=\"nf\">getElementById<\/span><span class=\"p\">(<\/span><span class=\"nx\">targetId<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"o\">!<\/span><span class=\"nx\">sourceEl<\/span> <span class=\"o\">||<\/span> <span class=\"o\">!<\/span><span class=\"nx\">targetEl<\/span><span class=\"p\">)<\/span> <span class=\"k\">return<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">startRect<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">sourceEl<\/span><span class=\"p\">.<\/span><span class=\"nf\">getBoundingClientRect<\/span><span class=\"p\">();<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">targetRect<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">targetEl<\/span><span class=\"p\">.<\/span><span class=\"nf\">getBoundingClientRect<\/span><span class=\"p\">();<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">startPoint<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getCenterPosition<\/span><span class=\"p\">(<\/span><span class=\"nx\">startRect<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">targetPoint<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getTargetPosition<\/span><span class=\"p\">(<\/span><span class=\"nx\">targetRect<\/span><span class=\"p\">);<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">controlPoint<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">getControlPoint<\/span><span class=\"p\">(<\/span><span class=\"nx\">startPoint<\/span><span class=\"p\">,<\/span> <span class=\"nx\">targetPoint<\/span><span class=\"p\">);<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">emojiElement<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">createEmojiElement<\/span><span class=\"p\">(<\/span><span class=\"nx\">emoji<\/span><span class=\"p\">,<\/span> <span class=\"nx\">startPoint<\/span><span class=\"p\">);<\/span>\n      <span class=\"nx\">emojiRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">emojiElement<\/span><span class=\"p\">;<\/span>\n\n      <span class=\"kd\">let<\/span> <span class=\"nx\">startTime<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">performance<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">();<\/span>\n      <span class=\"kd\">const<\/span> <span class=\"nx\">duration<\/span> <span class=\"o\">=<\/span> <span class=\"mi\">1000<\/span><span class=\"p\">;<\/span> <span class=\"c1\">\/\/ Animation duration in milliseconds<\/span>\n\n      <span class=\"kd\">const<\/span> <span class=\"nx\">animate<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"na\">currentTime<\/span><span class=\"p\">:<\/span> <span class=\"kr\">number<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">elapsed<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">currentTime<\/span> <span class=\"o\">-<\/span> <span class=\"nx\">startTime<\/span><span class=\"p\">;<\/span>\n        <span class=\"kd\">const<\/span> <span class=\"nx\">progress<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">Math<\/span><span class=\"p\">.<\/span><span class=\"nf\">min<\/span><span class=\"p\">(<\/span><span class=\"nx\">elapsed<\/span> <span class=\"o\">\/<\/span> <span class=\"nx\">duration<\/span><span class=\"p\">,<\/span> <span class=\"mi\">1<\/span><span class=\"p\">);<\/span>\n\n        <span class=\"kd\">const<\/span> <span class=\"nx\">position<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">calculateBezierPoint<\/span><span class=\"p\">(<\/span>\n          <span class=\"nx\">startPoint<\/span><span class=\"p\">,<\/span>\n          <span class=\"nx\">controlPoint<\/span><span class=\"p\">,<\/span>\n          <span class=\"nx\">targetPoint<\/span><span class=\"p\">,<\/span>\n          <span class=\"nx\">progress<\/span><span class=\"p\">,<\/span>\n        <span class=\"p\">);<\/span>\n\n        <span class=\"nx\">emojiElement<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span><span class=\"p\">.<\/span><span class=\"nx\">transform<\/span> <span class=\"o\">=<\/span> \n          <span class=\"s2\">`translate(<\/span><span class=\"p\">${<\/span><span class=\"nx\">position<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">}<\/span><span class=\"s2\">px, <\/span><span class=\"p\">${<\/span><span class=\"nx\">position<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">}<\/span><span class=\"s2\">px) translate(-50%, -50%)`<\/span><span class=\"p\">;<\/span>\n\n        <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">progress<\/span> <span class=\"o\">&lt;<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">animationRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">requestAnimationFrame<\/span><span class=\"p\">(<\/span><span class=\"nx\">animate<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\n          <span class=\"nx\">emojiElement<\/span><span class=\"p\">.<\/span><span class=\"nx\">style<\/span><span class=\"p\">.<\/span><span class=\"nx\">transform<\/span> <span class=\"o\">=<\/span> \n            <span class=\"s2\">`translate(<\/span><span class=\"p\">${<\/span><span class=\"nx\">targetPoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">x<\/span><span class=\"p\">}<\/span><span class=\"s2\">px, <\/span><span class=\"p\">${<\/span><span class=\"nx\">targetPoint<\/span><span class=\"p\">.<\/span><span class=\"nx\">y<\/span><span class=\"p\">}<\/span><span class=\"s2\">px) translate(-50%, -50%)`<\/span><span class=\"p\">;<\/span>\n          <span class=\"nf\">setTimeout<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n            <span class=\"nx\">emojiElement<\/span><span class=\"p\">.<\/span><span class=\"nf\">remove<\/span><span class=\"p\">();<\/span>\n          <span class=\"p\">},<\/span> <span class=\"nx\">duration<\/span><span class=\"p\">);<\/span>\n        <span class=\"p\">}<\/span>\n      <span class=\"p\">};<\/span>\n\n      <span class=\"nf\">requestAnimationFrame<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n        <span class=\"nx\">startTime<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">performance<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">();<\/span>\n        <span class=\"nf\">animate<\/span><span class=\"p\">(<\/span><span class=\"nx\">startTime<\/span><span class=\"p\">);<\/span>\n      <span class=\"p\">});<\/span>\n    <span class=\"p\">},<\/span>\n    <span class=\"p\">[],<\/span>\n  <span class=\"p\">);<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">cleanup<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useCallback<\/span><span class=\"p\">(()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">animationRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nf\">cancelAnimationFrame<\/span><span class=\"p\">(<\/span><span class=\"nx\">animationRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">);<\/span>\n    <span class=\"p\">}<\/span>\n    <span class=\"k\">if <\/span><span class=\"p\">(<\/span><span class=\"nx\">emojiRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\n      <span class=\"nx\">emojiRef<\/span><span class=\"p\">.<\/span><span class=\"nx\">current<\/span><span class=\"p\">.<\/span><span class=\"nf\">remove<\/span><span class=\"p\">();<\/span>\n    <span class=\"p\">}<\/span>\n  <span class=\"p\">},<\/span> <span class=\"p\">[]);<\/span>\n\n  <span class=\"k\">return<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">throwEmoji<\/span><span class=\"p\">,<\/span> <span class=\"nx\">cleanup<\/span> <span class=\"p\">};<\/span>\n<span class=\"p\">};<\/span>\n<\/code><\/pre>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%86%D8%AD%D9%88%D9%87_%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87_%D8%A7%D8%B2_%D8%A2%D9%86\"><\/span>\n<p>  \u0646\u062d\u0648\u0647 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 \u0622\u0646<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u062f\u0631 \u0627\u06cc\u0646\u062c\u0627 \u06cc\u06a9 \u0645\u062b\u0627\u0644 \u06a9\u0627\u0645\u0644 \u0627\u0632 \u0646\u062d\u0648\u0647 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u0627\u06cc\u0645\u0648\u062c\u06cc \u062f\u0631 \u06a9\u0627\u0645\u067e\u0648\u0646\u0646\u062a React \u0622\u0648\u0631\u062f\u0647 \u0634\u062f\u0647 \u0627\u0633\u062a:\n<\/p>\n<div class=\"highlight js-code-highlight\">\n<pre class=\"highlight typescript\"><code><span class=\"k\">import<\/span> <span class=\"nx\">React<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">react<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n<span class=\"k\">import<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">useEmojiThrow<\/span> <span class=\"p\">}<\/span> <span class=\"k\">from<\/span> <span class=\"dl\">'<\/span><span class=\"s1\">.\/useEmojiThrow<\/span><span class=\"dl\">'<\/span><span class=\"p\">;<\/span>\n\n<span class=\"kd\">const<\/span> <span class=\"nx\">PlanningPokerRoom<\/span><span class=\"p\">:<\/span> <span class=\"nx\">React<\/span><span class=\"p\">.<\/span><span class=\"nx\">FC<\/span> <span class=\"o\">=<\/span> <span class=\"p\">()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n  <span class=\"kd\">const<\/span> <span class=\"p\">{<\/span> <span class=\"nx\">throwEmoji<\/span> <span class=\"p\">}<\/span> <span class=\"o\">=<\/span> <span class=\"nf\">useEmojiThrow<\/span><span class=\"p\">();<\/span>\n\n  <span class=\"kd\">const<\/span> <span class=\"nx\">handleEmojiClick<\/span> <span class=\"o\">=<\/span> <span class=\"p\">(<\/span><span class=\"na\">emoji<\/span><span class=\"p\">:<\/span> <span class=\"kr\">string<\/span><span class=\"p\">)<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"p\">{<\/span>\n    <span class=\"c1\">\/\/ Assuming you have elements with these IDs in your DOM<\/span>\n    <span class=\"nf\">throwEmoji<\/span><span class=\"p\">(<\/span><span class=\"nx\">emoji<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">source-player-avatar<\/span><span class=\"dl\">\"<\/span><span class=\"p\">,<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">target-player-avatar<\/span><span class=\"dl\">\"<\/span><span class=\"p\">);<\/span>\n  <span class=\"p\">};<\/span>\n\n  <span class=\"k\">return <\/span><span class=\"p\">(<\/span>\n    <span class=\"o\">&lt;<\/span><span class=\"nx\">div<\/span> <span class=\"nx\">className<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">poker-room<\/span><span class=\"dl\">\"<\/span><span class=\"o\">&gt;<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"nx\">div<\/span> <span class=\"nx\">id<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">source-player-avatar<\/span><span class=\"dl\">\"<\/span> <span class=\"nx\">className<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">avatar<\/span><span class=\"dl\">\"<\/span><span class=\"o\">&gt;<\/span>\n        <span class=\"nx\">Player<\/span> <span class=\"mi\">1<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"sr\">\/div<\/span><span class=\"err\">&gt;\n<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"nx\">div<\/span> <span class=\"nx\">className<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">emoji-controls<\/span><span class=\"dl\">\"<\/span><span class=\"o\">&gt;<\/span>\n        <span class=\"o\">&lt;<\/span><span class=\"nx\">button<\/span> <span class=\"nx\">onClick<\/span><span class=\"o\">=<\/span><span class=\"p\">{()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">handleEmojiClick<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">\ud83c\udf89<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)}<\/span><span class=\"o\">&gt;<\/span><span class=\"nx\">Throw<\/span> <span class=\"nx\">Confetti<\/span><span class=\"o\">&lt;<\/span><span class=\"sr\">\/button<\/span><span class=\"err\">&gt;\n<\/span>        <span class=\"o\">&lt;<\/span><span class=\"nx\">button<\/span> <span class=\"nx\">onClick<\/span><span class=\"o\">=<\/span><span class=\"p\">{()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">handleEmojiClick<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">\ud83d\udc4d<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)}<\/span><span class=\"o\">&gt;<\/span><span class=\"nx\">Throw<\/span> <span class=\"nx\">Thumbs<\/span> <span class=\"nx\">Up<\/span><span class=\"o\">&lt;<\/span><span class=\"sr\">\/button<\/span><span class=\"err\">&gt;\n<\/span>        <span class=\"o\">&lt;<\/span><span class=\"nx\">button<\/span> <span class=\"nx\">onClick<\/span><span class=\"o\">=<\/span><span class=\"p\">{()<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"nf\">handleEmojiClick<\/span><span class=\"p\">(<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">\u2764\ufe0f<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)}<\/span><span class=\"o\">&gt;<\/span><span class=\"nx\">Throw<\/span> <span class=\"nx\">Heart<\/span><span class=\"o\">&lt;<\/span><span class=\"sr\">\/button<\/span><span class=\"err\">&gt;\n<\/span>      <span class=\"o\">&lt;<\/span><span class=\"sr\">\/div<\/span><span class=\"err\">&gt;\n<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"nx\">div<\/span> <span class=\"nx\">id<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">target-player-avatar<\/span><span class=\"dl\">\"<\/span> <span class=\"nx\">className<\/span><span class=\"o\">=<\/span><span class=\"dl\">\"<\/span><span class=\"s2\">avatar<\/span><span class=\"dl\">\"<\/span><span class=\"o\">&gt;<\/span>\n        <span class=\"nx\">Player<\/span> <span class=\"mi\">2<\/span>\n      <span class=\"o\">&lt;<\/span><span class=\"sr\">\/div<\/span><span class=\"err\">&gt;\n<\/span>    <span class=\"o\">&lt;<\/span><span class=\"sr\">\/div<\/span><span class=\"err\">&gt;\n<\/span>  <span class=\"p\">);<\/span>\n<span class=\"p\">};<\/span>\n\n<span class=\"k\">export<\/span> <span class=\"k\">default<\/span> <span class=\"nx\">PlanningPokerRoom<\/span><span class=\"p\">;<\/span>\n<\/code><\/pre>\n<\/div>\n<h2><span class=\"ez-toc-section\" id=\"%D9%88%DB%8C%DA%98%DA%AF%DB%8C_%D9%87%D8%A7%DB%8C_%DA%A9%D9%84%DB%8C%D8%AF%DB%8C\"><\/span>\n<p>  \u0648\u06cc\u0698\u06af\u06cc \u0647\u0627\u06cc \u06a9\u0644\u06cc\u062f\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ol>\n<li>\n<strong>\u062d\u0631\u06a9\u062a \u0637\u0628\u06cc\u0639\u06cc<\/strong>: \u0627\u0632 \u0645\u0646\u062d\u0646\u06cc \u0647\u0627\u06cc Bezier \u062f\u0631\u062c\u0647 \u062f\u0648\u0645 \u0628\u0631\u0627\u06cc \u062d\u0631\u06a9\u062a \u0635\u0627\u0641 \u0648 \u0642\u0648\u0633 \u0645\u0627\u0646\u0646\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/li>\n<li>\n<strong>\u062a\u0635\u0627\u062f\u0641\u06cc \u0633\u0627\u0632\u06cc<\/strong>: \u062a\u063a\u06cc\u06cc\u0631\u0627\u062a \u062c\u0632\u0626\u06cc \u0631\u0627 \u0628\u0647 \u0645\u0648\u0642\u0639\u06cc\u062a \u0647\u0627 \u0648 \u0645\u0633\u06cc\u0631\u0647\u0627\u06cc \u0647\u062f\u0641 \u0627\u0636\u0627\u0641\u0647 \u0645\u06cc \u06a9\u0646\u062f<\/li>\n<li>\n<strong>\u0639\u0645\u0644\u06a9\u0631\u062f<\/strong>: \u0645\u0648\u0627\u0631\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 <code>requestAnimationFrame<\/code> \u0628\u0631\u0627\u06cc \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627\u06cc \u0631\u0648\u0627\u0646<\/li>\n<li>\n<strong>\u067e\u0627\u06a9\u0633\u0627\u0632\u06cc<\/strong>: \u0634\u0627\u0645\u0644 \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u0645\u0646\u0627\u0633\u0628 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627 \u0648 \u0639\u0646\u0627\u0635\u0631 DOM \u0627\u0633\u062a<\/li>\n<li>\n<strong>\u067e\u0634\u062a\u06cc\u0628\u0627\u0646\u06cc TypeScript<\/strong>: \u0628\u0631\u0627\u06cc \u062a\u062c\u0631\u0628\u0647 \u0628\u0647\u062a\u0631 \u062a\u0648\u0633\u0639\u0647 \u062f\u0647\u0646\u062f\u0647 \u06a9\u0627\u0645\u0644\u0627 \u062a\u0627\u06cc\u067e \u0634\u062f\u0647 \u0627\u0633\u062a<\/li>\n<\/ol>\n<h2><span class=\"ez-toc-section\" id=\"%D8%AC%D8%B2%D8%A6%DB%8C%D8%A7%D8%AA_%D9%81%D9%86%DB%8C\"><\/span>\n<p>  \u062c\u0632\u0626\u06cc\u0627\u062a \u0641\u0646\u06cc<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u06cc\u0646 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u062a\u0648\u0633\u0637:<\/p>\n<ol>\n<li>\u0645\u062d\u0627\u0633\u0628\u0647 \u0645\u0648\u0642\u0639\u06cc\u062a \u0647\u0627\u06cc \u0634\u0631\u0648\u0639 \u0648 \u067e\u0627\u06cc\u0627\u0646 \u0627\u0632 \u0639\u0646\u0627\u0635\u0631 DOM<\/li>\n<li>\u0627\u06cc\u062c\u0627\u062f \u06cc\u06a9 \u0639\u0646\u0635\u0631 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0645\u0648\u0642\u062a<\/li>\n<li>\u0645\u062a\u062d\u0631\u06a9 \u0633\u0627\u0632\u06cc \u0622\u0646 \u062f\u0631 \u0627\u0645\u062a\u062f\u0627\u062f \u0645\u0646\u062d\u0646\u06cc Bezier<\/li>\n<li>\u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u067e\u0633 \u0627\u0632 \u062a\u06a9\u0645\u06cc\u0644 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646<\/li>\n<\/ol>\n<p>\u0631\u0627 <code>useEmojiThrow<\/code> \u0647\u0648\u06a9 \u062a\u0645\u0627\u0645 \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc \u0647\u0627 \u0631\u0627 \u06a9\u0646\u062a\u0631\u0644 \u0645\u06cc \u06a9\u0646\u062f \u0648 \u06cc\u06a9 \u0631\u0627\u0628\u0637 \u0633\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0647\u0627 \u0628\u06cc\u0646 \u0647\u0631 \u062f\u0648 \u0639\u0646\u0635\u0631 \u062f\u0631 \u0635\u0641\u062d\u0647 \u0634\u0645\u0627 \u0641\u0631\u0627\u0647\u0645 \u0645\u06cc \u06a9\u0646\u062f.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A2%D9%86_%D8%B1%D8%A7_%D8%AF%D8%B1_%D8%B9%D9%85%D9%84_%D8%A8%D8%A8%DB%8C%D9%86%DB%8C%D8%AF\"><\/span>\n<p>  \u0622\u0646 \u0631\u0627 \u062f\u0631 \u0639\u0645\u0644 \u0628\u0628\u06cc\u0646\u06cc\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0622\u06cc\u0627 \u0645\u06cc \u062e\u0648\u0627\u0647\u06cc\u062f \u0627\u06cc\u0646 \u06a9\u062f \u0631\u0627 \u062f\u0631 \u06cc\u06a9 \u0645\u062d\u06cc\u0637 \u062a\u0648\u0644\u06cc\u062f \u0645\u0634\u0627\u0647\u062f\u0647 \u06a9\u0646\u06cc\u062f\u061f \u0627\u062a\u0627\u0642 \u0622\u0632\u0645\u0627\u06cc\u0634\u06cc \u0645\u0627 \u0631\u0627 \u0628\u0631\u0631\u0633\u06cc \u06a9\u0646\u06cc\u062f \u06a9\u0647 \u062f\u0631 \u0622\u0646 \u0645\u06cc\u200c\u062a\u0648\u0627\u0646\u06cc\u062f \u0634\u06a9\u0644\u06a9\u200c\u0647\u0627 \u0631\u0627 \u0628\u0647 \u0628\u0627\u0632\u06cc\u06a9\u0646\u0627\u0646 \u0631\u0628\u0627\u062a \u067e\u0631\u062a\u0627\u0628 \u06a9\u0646\u06cc\u062f \u06cc\u0627 \u062c\u0644\u0633\u0647 \u067e\u0648\u06a9\u0631 \u0628\u0631\u0646\u0627\u0645\u0647\u200c\u0631\u06cc\u0632\u06cc \u062e\u0648\u062f \u0631\u0627 \u062f\u0631 Kollabe \u0634\u0631\u0648\u0639 \u06a9\u0646\u06cc\u062f.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"%D9%85%D9%84%D8%A7%D8%AD%D8%B8%D8%A7%D8%AA_%D8%B9%D9%85%D9%84%DA%A9%D8%B1%D8%AF\"><\/span>\n<p>  \u0645\u0644\u0627\u062d\u0638\u0627\u062a \u0639\u0645\u0644\u06a9\u0631\u062f<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<ul>\n<li>\u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u0647\u0627 \u0627\u0632 \u062a\u0628\u062f\u06cc\u0644 \u0647\u0627\u06cc CSS \u0628\u0631\u0627\u06cc \u0639\u0645\u0644\u06a9\u0631\u062f \u0628\u0647\u062a\u0631 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0645\u06cc \u06a9\u0646\u0646\u062f<\/li>\n<li>\u0628\u0631\u0627\u06cc \u062c\u0644\u0648\u06af\u06cc\u0631\u06cc \u0627\u0632 \u0646\u0634\u062a \u062d\u0627\u0641\u0638\u0647\u060c \u0639\u0646\u0627\u0635\u0631 \u0628\u0647 \u062f\u0631\u0633\u062a\u06cc \u062a\u0645\u06cc\u0632 \u0645\u06cc \u0634\u0648\u0646\u062f<\/li>\n<li>\u0645\u062d\u0627\u0633\u0628\u0627\u062a \u0628\u0647\u06cc\u0646\u0647 \u0634\u062f\u0647 \u0648 \u062f\u0631 \u0635\u0648\u0631\u062a \u0627\u0645\u06a9\u0627\u0646 \u0630\u062e\u06cc\u0631\u0647 \u0645\u06cc \u0634\u0648\u0646\u062f<\/li>\n<li>\u0641\u0631\u06cc\u0645 \u0647\u0627\u06cc \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u062f\u0631 \u067e\u0627\u06a9\u0633\u0627\u0632\u06cc \u0644\u063a\u0648 \u0645\u06cc \u0634\u0648\u0646\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C_%D8%B3%D8%A7%D8%B2%DB%8C_%D9%87%D8%A7%DB%8C_%D8%A8%D8%A7%D9%84%D9%82%D9%88%D9%87\"><\/span>\n<p>  \u0633\u0641\u0627\u0631\u0634\u06cc \u0633\u0627\u0632\u06cc \u0647\u0627\u06cc \u0628\u0627\u0644\u0642\u0648\u0647<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0634\u0645\u0627 \u0628\u0647 \u0631\u0627\u062d\u062a\u06cc \u0645\u06cc \u062a\u0648\u0627\u0646\u06cc\u062f \u06a9\u062f \u0631\u0627 \u062a\u063a\u06cc\u06cc\u0631 \u062f\u0647\u06cc\u062f:<\/p>\n<ul>\n<li>\u062a\u0646\u0638\u06cc\u0645 \u0645\u062f\u062a \u0632\u0645\u0627\u0646 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646<\/li>\n<li>\u062a\u063a\u06cc\u06cc\u0631 \u0627\u0646\u062f\u0627\u0632\u0647 \u0627\u06cc\u0645\u0648\u062c\u06cc<\/li>\n<li>\u062a\u063a\u06cc\u06cc\u0631 \u062a\u0635\u0627\u062f\u0641\u06cc \u0645\u0633\u06cc\u0631<\/li>\n<li>\u0627\u0641\u06a9\u062a\u200c\u0647\u0627\u06cc \u0686\u0631\u062e\u0634 \u06cc\u0627 \u0645\u0642\u06cc\u0627\u0633\u200c\u0628\u0646\u062f\u06cc \u0631\u0627 \u0627\u0636\u0627\u0641\u0647 \u06a9\u0646\u06cc\u062f<\/li>\n<li>\u062a\u0648\u0627\u0628\u0639 \u0645\u062e\u062a\u0644\u0641 \u062a\u0633\u0647\u06cc\u0644 \u0631\u0627 \u0627\u062c\u0631\u0627 \u06a9\u0646\u06cc\u062f<\/li>\n<\/ul>\n<h2><span class=\"ez-toc-section\" id=\"%D8%A7%DB%8C%D9%86_%D9%87%D9%85%D9%87_%DA%86%DB%8C%D8%B2_%D8%A7%D8%B3%D8%AA\"><\/span>\n<p>  \u0627\u06cc\u0646 \u0647\u0645\u0647 \u0686\u06cc\u0632 \u0627\u0633\u062a<br \/>\n<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>\u0627\u0641\u0632\u0648\u062f\u0646 \u0639\u0646\u0627\u0635\u0631 \u062a\u0639\u0627\u0645\u0644\u06cc \u0645\u0627\u0646\u0646\u062f \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0645\u06cc \u062a\u0648\u0627\u0646\u062f \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u0627\u0633\u062a\u0627\u0646\u062f\u0627\u0631\u062f \u0631\u0627 \u0628\u0647 \u062a\u062c\u0631\u0628\u06cc\u0627\u062a \u062a\u06cc\u0645\u06cc \u062c\u0630\u0627\u0628 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0646\u062f. \u0628\u0627 \u062e\u06cc\u0627\u0644 \u0631\u0627\u062d\u062a \u0627\u0632 \u0627\u06cc\u0646 \u06a9\u062f \u062f\u0631 \u067e\u0631\u0648\u0698\u0647 \u0647\u0627\u06cc \u062e\u0648\u062f \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u06a9\u0646\u06cc\u062f \u0648 \u0627\u06af\u0631 \u0628\u0647 \u062f\u0646\u0628\u0627\u0644 \u0631\u0627\u0647 \u062d\u0644 \u0622\u0645\u0627\u062f\u0647 \u0628\u0631\u0627\u06cc \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0647\u0633\u062a\u06cc\u062f\u060c Kollabe \u0631\u0627 \u0628\u0631\u0627\u06cc \u062c\u0644\u0633\u0627\u062a \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062a\u06cc\u0645 \u062e\u0648\u062f \u0627\u0645\u062a\u062d\u0627\u0646 \u06a9\u0646\u06cc\u062f.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summarize this content to 400 words in Persian Lang \u0622\u06cc\u0627 \u062a\u0627 \u0628\u0647 \u062d\u0627\u0644 \u0628\u0647 \u0627\u06cc\u0646 \u0641\u06a9\u0631 \u06a9\u0631\u062f\u0647 \u0627\u06cc\u062f \u06a9\u0647 \u0686\u06af\u0648\u0646\u0647 \u0628\u0631\u0646\u0627\u0645\u0647 \u0631\u06cc\u0632\u06cc \u062c\u0644\u0633\u0627\u062a \u067e\u0648\u06a9\u0631 \u062e\u0648\u062f \u0631\u0627 \u062a\u0639\u0627\u0645\u0644\u06cc \u062a\u0631 \u06a9\u0646\u06cc\u062f\u061f \u0628\u06cc\u0627\u06cc\u06cc\u062f \u0628\u0627 \u0627\u0633\u062a\u0641\u0627\u062f\u0647 \u0627\u0632 React hooks \u0648 Web Animation API \u06cc\u06a9 \u0633\u06cc\u0633\u062a\u0645 \u0627\u0646\u06cc\u0645\u06cc\u0634\u0646 \u067e\u0631\u062a\u0627\u0628 \u0627\u06cc\u0645\u0648\u062c\u06cc \u0633\u0631\u06af\u0631\u0645 \u06a9\u0646\u0646\u062f\u0647 \u0631\u0627 \u067e\u06cc\u0627\u062f\u0647 \u0633\u0627\u0632\u06cc \u06a9\u0646\u06cc\u0645. \u0645\u0646 \u0628\u0647 \u0634\u0645\u0627 \u0646\u0634\u0627\u0646 \u062e\u0648\u0627\u0647\u0645 &hellip;<\/p>\n","protected":false},"author":2,"featured_media":82088,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"","fifu_image_alt":"","footnotes":""},"categories":[339],"tags":[],"class_list":["post-82087","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev"],"_links":{"self":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/82087","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/comments?post=82087"}],"version-history":[{"count":0,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/posts\/82087\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media\/82088"}],"wp:attachment":[{"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/media?parent=82087"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/categories?post=82087"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nabfollower.com\/blog\/wp-json\/wp\/v2\/tags?post=82087"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}