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


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.