Як я можу оживити малюнок тексту на веб-сторінці?


229

Я хочу мати веб-сторінку з одним центрованим словом.

Я хочу, щоб це слово було намальовано анімацією, щоб сторінка "записувала" слово так само, як і ми, тобто воно починається в один момент і малює лінії та криві з часом, так що кінцевим результатом є гліф.

Мені все одно, чи це робиться з <canvas>DOM або DOM, і мені байдуже, чи це робиться за допомогою JavaScript або CSS. Відсутність jQuery було б непогано, але не потрібно.

Як я можу це зробити? Я шукав вичерпно, не пощастивши.


2
Я поклав деякі думки в тому , як насправді «Рукописні» персонажів і розмістив мої думки тут: stackoverflow.com/questions/12700731 / ...
MARKE

Щось насправді схоже на статтю про копрідемонстрацією на тимпану )
Francisco Presencia

1
Ще в ті часи я робив цю анімацію у Flash, використовуючи анімовані спрайтові маски. Вам потрібно анімувати маску, а це означає, що вона поступово розкриває текст. Анімація була б виготовлена ​​з маскових кадрів.
Tiberiu-Ionuț Stan

Звичайно, ви б мали користь від того, щоб розбити текст на криві. Вам слід зробити це, використовуючи перед тим, як вручну використовувати SVG-файли та якийсь редактор SVG (Illustrator, або що-небудь ще, може створити SVG-текст). Я не знаю, чи підтримують SVG маски, але якщо вони будуть, то це стане набагато простіше оживити.
Tiberiu-Ionuț Stan

Використовуйте SVG та маніпулюйте кодом SVG за допомогою JavaScript, щоб зробити анімацію.
Демз

Відповіді:


264

Я хочу, щоб це слово було намальовано анімацією, щоб сторінка "записувала" це слово так само, як і ми

Полотна версія

Це дозволить намалювати поодинокі символи, подібні до того, як писали б від руки. Він використовує довгу схему тире, де замовлення на вмикання / вимкнення змінюється з часом за графік. Він також має параметр швидкості.

Знімок
Приклад анімації (див. Демонстрацію нижче)

Для посилення реалізму та органічного почуття я додав випадкові інтервали між літерами, зсув дельти y, прозорість, дуже тонке обертання і, нарешті, використовуючи вже "рукописний" шрифт. Вони можуть бути завершені як динамічні параметри, щоб забезпечити широкий спектр "стилів написання".

Для ще більш реалістичного вигляду потрібні будуть дані про шлях, які за замовчуванням не є. Але це короткий та ефективний фрагмент коду, який наближає рукописну поведінку та простий у виконанні.

Як це працює

Визначаючи малюнок тире, ми можемо створити маршові мурашки, пунктирні лінії тощо. Скориставшись цим, визначивши дуже довгу точку для "вимкненої" точки та поступово збільшуючи крапку "ввімкнено", це створить ілюзію промальовування лінії при погладжуванні під час анімації довжини точки.

Оскільки точка відключення настільки довга, повторюваний візерунок не буде видно (довжина буде змінюватися залежно від розміру та характеристик використовуваного шрифту). Шлях листа буде мати довжину, тому нам потрібно переконатися, що у нас є кожна крапка, щонайменше покриває цю довжину.

Для літер, які складаються з декількох контурів (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
Хіба я єдиний, що божеволію від цього? Принаймні, виглядає так реально, як мінімум, краще, ніж перша відповідь, і найближче до питання запитувача.
Хофі

5
Я в кінцевому підсумку скористався іншою відповіддю, тому що мені це було потрібно відразу як швидкий п-брудний злом, який я використовував наступного дня, а потім більше ніколи не торкався, але я приймаю цю, тому що це набагато ближче до того, що я шукав для.
strugee

Як ми можемо зробити це для декількох рядків та довгого текстового блоку?
Саад Фарук

1
@ K3N Так, насправді це був приємний штрих: p Чудова робота.
клавішник

1
@ AliAl-arnous ви можете встановити х на протилежний кінець, відняти ширину символів замість додавання, перетворити з заперечуваним негативним пробілом та змінити clearRect, щоб очистити з іншого боку таблиці.

216

Редагувати 2019 рік


Я створив бібліотеку javascript, яка може створювати реалістичні анімації. Він простий у використанні і вимагає спеціального файлу 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, використовуючи зміщення на основі відсотків та значення dasharray, а також змінивши ширину обведення, щоб зрозуміти, як працює код: jsfiddle.net/Ajedi32/gdc4azLn / 1 Сміливо редагуйте будь-яке з цих удосконалень у своїй відповіді, якщо хочете.
Ajedi32

2
це одне епічне рішення цього питання, SVG краще, ніж полотно (+1), оскільки у випадку, якщо браузер його не підтримує, він натомість покаже текст.
Jeffery ThaGintoki

3
@JefferyThaGintoki ви можете це зробити і з полотном, просто розмістіть текст між тегами полотна, якщо на ньому не підтримується текст (або анімований gif, як показано в іншій відповіді в тексті тексту). Якщо браузер не підтримує канву, він, ймовірно, також не підтримує svg.
torox

1
Я думаю, що використання SVG тексту чудово, але мені цікаво, чи можна додати заливку в якийсь момент? лише контури листів не виглядають приємно у всіх проектах, ура! і звичайно +1 до цієї відповіді
randomguy04

1
@ randomguy04 Перевірте перший фрагмент, я його відредагував, щоб додати ефект заповнення. Це робиться шляхом додавання $(this).css('fill', 'red')до анімації в якості зворотного дзвінка
Акшай

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і веб - анімації апі. Це стає більш плавним, це очевидно на важких сторінках 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 все ще перераховується для переповнення тексту. Ми можемо бачити, як відладчик сильно блимає. Це справді має значення для каскадних елементів! Це все ще може уповільнити JavaScript та прокрутки користувачів.

введіть тут опис зображення

Повна потужність : Можливо використовувати 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 швидко пропускає інші завдання. Іноді це може починатися трохи повільніше, ніж наведений вище приклад. Але крім цього, це не блокує прокрутки користувачів, а налагоджувач також подобається, більше немає стрибків.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.