웹 페이지에서 텍스트 그림을 애니메이션으로 만들려면 어떻게해야합니까?


229

하나의 중심 단어가있는 웹 페이지를 갖고 싶습니다.

이 단어를 애니메이션으로 그려서 페이지가 우리가하는 것과 같은 방식으로 단어를 "쓰기"합니다. 즉, 한 지점에서 시작하여 시간이 지남에 따라 선과 곡선을 그려서 최종 결과가 글리프가되도록합니다.

이것이 끝나면 상관 없어 <canvas> DOM인지 DOM인지 상관하지 않으며 JavaScript 또는 CSS 중 어느 것이 든 상관하지 않습니다. jQuery가 없으면 좋지만 필수는 아닙니다.

어떻게해야합니까? 운없이 철저하게 검색했습니다 .


2
실제로 캐릭터를 "필기"하는 방법에 대해 몇 가지 생각을하고 여기에 내 생각을 게시했습니다. stackoverflow.com/questions/12700731/…
markE


1
당시에는 애니메이션 스프라이트 마스크를 사용하여 Flash에서이 애니메이션을 수행했습니다. 필요한 것은 마스크에 애니메이션을 적용하여 텍스트를 점진적으로 표시하는 것입니다. 애니메이션은 마스크 프레임으로 만들어집니다.
Tiberiu-Ionuț Stan

물론, 텍스트를 곡선으로 나눌 수 있다는 이점이 있습니다. SVG와 일부 SVG 편집기 (Illustrator 또는 기타 텍스트의 SVG를 만들 수있는 모든 것)를 사용하기 전에이 작업을 수행해야합니다. SVG가 마스크를 지원하는지 모르겠지만, 그렇다면 마스크를 사용하는 것이 훨씬 쉬워집니다.
Tiberiu-Ionuț Stan

SVG를 사용하고 JavaScript로 SVG 코드를 조작하여 애니메이션을 만듭니다.
Demz

답변:


264

이 단어를 애니메이션으로 그려서 페이지가 우리가하는 것과 같은 방식으로 단어를 "쓰기"하려고합니다

캔버스 버전

이것은 하나의 문자를 손으로 쓰는 것과 비슷하게 그릴 것입니다. 문자마다 시간에 따라 켜기 / 끄기 순서가 바뀌는 긴 대시 패턴을 사용합니다. 속도 파라미터도 있습니다.

스냅 사진
애니메이션 예 (아래 데모 참조)

사실감과 자연스러운 느낌을 높이기 위해 임의의 문자 간격, y 델타 오프셋, 투명도, 매우 미묘한 회전을 추가하고 이미 "필기"글꼴을 사용했습니다. 이들은 광범위한 "쓰기 스타일"을 제공하기 위해 동적 매개 변수로 래핑 될 수 있습니다.

더욱 사실적으로 보이려면 기본적으로 필요하지 않은 경로 데이터가 필요합니다. 그러나 이것은 손으로 작성한 동작과 비슷하고 구현하기 쉬운 짧고 효율적인 코드입니다.

작동 원리

대시 패턴을 정의함으로써 행진하는 개미, 점선 등을 만들 수 있습니다. "off"도트에 대해 매우 긴 도트를 정의하고 점진적으로 "on"도트를 증가시켜이를 활용하면 도트 길이에 애니메이션을 적용하는 동안 획을 칠 때 선을 그리는 것처럼 보입니다.

오프 도트가 너무 길기 때문에 반복 패턴이 보이지 않습니다 (사용되는 서체의 크기와 특성에 따라 길이가 다름). 문자의 경로는 길이를 가지므로 적어도이 길이를 덮는 각 점이 있는지 확인해야합니다.

외곽선과 같이 하나 이상의 경로 (f.ex. O, R, P 등)로 구성된 문자의 경우 중공 부분에 대한 선이 동시에 그려지는 것처럼 보입니다. 이 방법을 사용하면 각 경로 세그먼트에 대한 액세스가 개별적으로 스트로크되어야하므로이 작업에 대해 많은 것을 할 수 없습니다.

적합성

캔버스 요소를 지원하지 않는 브라우저의 경우 텍스트를 표시하는 다른 방법 (예 : 스타일이 지정된 텍스트)을 태그 사이에 배치 할 수 있습니다.

<canvas ...>
    <div class="txtStyle">STROKE-ON CANVAS</div>
</canvas>

데모

라이브 애니메이션 스트로크를 생성합니다 ( 종속성 없음 ).

var ctx = document.querySelector("canvas").getContext("2d"),
    dashLen = 220, dashOffset = dashLen, speed = 5,
    txt = "STROKE-ON CANVAS", x = 30, i = 0;

ctx.font = "50px Comic Sans MS, cursive, TSCu_Comic, sans-serif"; 
ctx.lineWidth = 5; ctx.lineJoin = "round"; ctx.globalAlpha = 2/3;
ctx.strokeStyle = ctx.fillStyle = "#1f2f90";

(function loop() {
  ctx.clearRect(x, 0, 60, 150);
  ctx.setLineDash([dashLen - dashOffset, dashOffset - speed]); // create a long dash mask
  dashOffset -= speed;                                         // reduce dash length
  ctx.strokeText(txt[i], x, 90);                               // stroke letter

  if (dashOffset > 0) requestAnimationFrame(loop);             // animate
  else {
    ctx.fillText(txt[i], x, 90);                               // fill final letter
    dashOffset = dashLen;                                      // prep next char
    x += ctx.measureText(txt[i++]).width + ctx.lineWidth * Math.random();
    ctx.setTransform(1, 0, 0, 1, 0, 3 * Math.random());        // random y-delta
    ctx.rotate(Math.random() * 0.005);                         // random rotation
    if (i < txt.length) requestAnimationFrame(loop);
  }
})();
canvas {background:url(http://i.imgur.com/5RIXWIE.png)}
<canvas width=630></canvas>


21
나는 이것에 미치게 될 유일한 사람인가? 적어도 첫 번째 답변보다 훨씬 우수하고 질문자의 질문에 가장 가깝습니다.
KhoPhi

5
나는 다른 대답을 사용하여 끝났습니다. 다음 날에 사용한 빠른 n- 핵심 핵으로 즉시 필요했지만 다시는 만지지 않았지만 내가보고있는 것에 더 가깝기 때문에 이것을 받아들이고 있습니다. 에 대한.
투쟁

여러 줄과 긴 텍스트 블록으로 어떻게 만들 수 있습니까?
Saad Farooq

1
@ K3N 그렇습니다. 실제로 멋진 터치였습니다.
keyser

1
@ AliAl-arnous x를 반대쪽 끝으로 설정하고 추가하는 대신 char 너비를 빼고 음수 음수로 변환하고 clearRect를 변경하여 char의 다른 쪽에서 지울 수 있습니다.

216

2019 년 편집


현실적인 애니메이션을 만들 수있는 자바 스크립트 라이브러리를 만들었습니다. 사용하기 쉽고 글꼴 역할을하는 특수 JSON 파일이 필요합니다.

var vara = new Vara("#container", "https://rawcdn.githack.com/akzhy/Vara/ed6ab92fdf196596266ae76867c415fa659eb348/fonts/Satisfy/SatisfySL.json", [{
  text: "Hello World!!",
  fontSize: 48,
  y:10
}, {
  text: "Realistic Animations",
  fontSize: 34,
  color:"#f44336"
}], {
  strokeWidth: 2,
  textAlign:"center"
});
#container {
  padding: 30px;
}
<script src="https://rawcdn.githack.com/akzhy/Vara/16e30acca2872212e28735cfdbaba696a355c780/src/vara.min.js"></script>
<div id="container"></div>

점검 설명서 및 예제 Github 페이지 를 확인 하십시오 . 그리고 코드 펜


이전 답변

아래 예제는 snap.js를 사용하여 동적으로 생성 tspan 요소 만든 다음 각 요소에 애니메이션을 적용합니다 stroke-dashoffset.

이전 답변


svg를 사용하여 이와 같은 작업을 수행 할 수 있습니다 stroke-dasharray

없이 keyframes애니메이션이 다음과 같이 할 수 있습니다

그리고 IE 지원을 위해 jquery / javascript를 사용할 수 있습니다


4
와우, 정말 재미 있어요. 원래 코드 스 니펫을 가져 와서 중복 CSS 속성을 제거하고 백분율 기반 오프셋과 대시 배열 값을 사용하고 스트로크 너비를 변경하여 코드 작동 방식을보다 명확하게 표시하여 약간 개선했습니다 .jsfiddle.net / Ajedi32 / gdc4azLn / 1 원하는 경우 개선 사항을 자유롭게 수정하십시오.
Ajedi32

2
이것은이 질문에 대한 하나의 서사시적인 해결책입니다 .SVG가 캔버스 (+1)보다 낫습니다. 브라우저가 지원하지 않는 경우 텍스트를 대신 표시합니다.
Jeffery ThaGintoki

3
@JefferyThaGintoki 캔버스를 사용 하여이 작업을 수행 할 수 있습니다. 캔버스가 지원되지 않는 경우 캔버스 태그 사이에 텍스트를 배치하면 텍스트 (또는 본문 텍스트의 다른 답변에 표시된 애니메이션 GIF)가 대신 나타납니다. 브라우저가 캔버스를 지원하지 않으면 아마도 svg도 지원하지 않을 것입니다.

1
SVG 텍스트를 사용하는 것이 훌륭하다고 생각하지만 궁금합니다. 어딘가에 채우기를 추가 할 수 있습니까? 글자의 윤곽 만 모든 프로젝트에서 멋지게 보이지는 않습니다. 그리고 물론이 답변에 +1
randomguy04

1
@ randomguy04 첫 번째 스 니펫을 확인하십시오. 채우기 효과를 추가하기 위해 편집했습니다. $(this).css('fill', 'red')애니메이션에 콜백을 추가하면 됩니다
Akshay

2

CSS 만 :

@keyframes fadein_left {
  from {
    left: 0;
  }
  to {
    left: 100%;
  }
}

#start:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0%;
  opacity: 0.7;
  height: 25px;
  background: #fff;
  animation: fadein_left 3s;
}
<div id="start">
  some text some text some text some text some text
</div>


0

많은 테스트를 거친 후 몇 가지 참고 사항이 있습니다. 목표는 사용자 상호 작용이 필요한 DOM이 많은 페이지 에서 빠른 텍스트 데이터를 가장 블로킹 방식으로 표시 하는 것입니다.

물론 동일한 것을 달성하는 방법에는 여러 가지가 있습니다. 이 예제에서는 차이점이 명확하지 않을 수 있으며 실제로 복잡한 인터페이스에 적용됩니다.

가장 느림 : innerHTML인라인 스타일. DOM은 각 반복마다 재 계산됩니다. 브라우저가 열차를 유지하기 위해 열심히 노력하고 있습니다. 빠르게 실패하여 메모리 누수가 발생하여 정지됩니다.

setInterval(function(){
  out.innerHTML = `<span style="position:fixed;top:${~~(Math.random() * 220)}px">${Math.random() * 1000}<span>`
},1)
<h1 id="out"></h1>

더 좋은 방법 : 사용 textContent, requestAnimationFrame그리고 웹 애니메이션 API를. 이것은 훨씬 매끄럽게 진행되며 DOM 무거운 페이지에서는 분명합니다. 사용자 상호 작용은 다시 그리기를 차단하지 않습니다. 인터페이스의 응답 성을 유지하기 위해 일부 다시 그리기를 건너 뛸 수 있습니다.

let job
const paint = () => {
  job = requestAnimationFrame(paint)
  out.textContent = Math.random() * 1000
  out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(paint)
#out{
position: fixed}
<h1 id="out"></h1>

위의 예에서 텍스트 오버플로에 대해 DOM이 여전히 다시 계산되고 있습니다. 디버거가 깜빡이는 것을 볼 수 있습니다. 이것은 계단식 요소에 정말로 중요합니다! 그래도 자바 스크립트 및 사용자 스크롤 속도가 느려질 수 있습니다.

여기에 이미지 설명을 입력하십시오

최대 전력 : CSS content규칙 및 CSS 변수로 데이터를 새로 고치기 위해 CSS 만 사용할 수 있습니다 . 그러면 텍스트를 선택할 수 없습니다.

let job
const paint = () => {
  job = requestAnimationFrame(paint)
  out.setAttribute('data-before', Math.random() * 1000)
  out.animate([{top: ~~(Math.random() * 220)+"px"},{top:0}],{duration: 1,iterations: 1})
}

/* Start looping -----------------------------------------*/
requestAnimationFrame(paint)
#out{
  position: fixed
  
  }
#out:before {
   content: attr(data-before)
 }
<h1 id="out"></h1>

여기에 이미지 설명을 입력하십시오

내 테스트는 크게 개선되었으며 Javascript 엔진은 다른 작업에서 빠르게 건너 뜁니다. 때로는 위의 예보다 약간 느리게 시작할 수 있습니다. 그러나 그 외에도 사용자 스크롤을 차단하지 않으며 디버거도 더 이상 점프하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.