Bir web sayfasındaki metin çizimini nasıl canlandırabilirim?


229

Ortalanmış bir kelimeden oluşan bir web sayfam olmasını istiyorum.

Bu kelimenin bir animasyonla çizilmesini istiyorum, böylece sayfa kelimeyi yaptığımız gibi "yazıyor", yani bir noktada başlıyor ve sonuçta bir glif olacak şekilde zaman içinde çizgiler ve eğriler çiziyor.

Bunun <canvas>DOM ile mi yoksa DOM ile mi yapıldığı umurumda değil ve JavaScript veya CSS ile yapılıp yapılmadığı umurumda değil. JQuery'nin olmaması güzel olurdu, ancak gerekli değildir.

Bunu nasıl yapabilirim? Şanssız bir şekilde araştırdım .


2
Karakterleri gerçekten "el yazısıyla" nasıl düşündüm ve düşüncelerimi buraya gönderdim: stackoverflow.com/questions/12700731/…
markE

Bir codrops makalesinde gerçekten benzer bir şey var ( timpanusta bir demo ile )
Francisco

1
O günlerde Flash'ta animasyonlu hareketli maskeler kullanarak bu animasyonu yapıyordum. İhtiyacınız olan şey bir maskeye animasyon uygulamak, yani metni aşamalı olarak göstermesi anlamına gelir. Animasyon maske karelerinden oluşacaktı.
Tiberiu-Ionuț Stan

Tabii ki, metni eğrilere ayırabilmenin avantajına sahip olacaksınız. SVG'leri ve bazı SVG düzenleyicilerini (Illustrator veya metninizin SVG'sini oluşturabilen her şeyi) elle kullanmadan önce bunu kullanarak yapmanız gerekir. SVG'lerin maskeleri destekleyip desteklemediğini bilmiyorum, ancak eğer yaparlarsa, bu canlandırmak çok daha kolay olurdu.
Tiberiu-Ionuț Stan

SVG'yi kullanın ve animasyonu yapmak için SVG kodunu JavaScript ile değiştirin.
Demz

Yanıtlar:


264

Bu kelimenin bir animasyonla çizilmesini istiyorum, böylece sayfa kelimeyi yaptığımız gibi "yazıyor"

Tuval versiyonu

Bu, tek tek karakterleri daha çok elle yazmak gibi çizer. Açma / kapama sırasının karakter başına zamanla değiştiği uzun bir çizgi deseni kullanır. Ayrıca bir hız parametresi vardır.

Enstantane fotoğraf
Örnek animasyon (aşağıdaki demoya bakın)

Gerçekçiliği ve organik hissi arttırmak için, rastgele harf aralığı, bir y delta ofseti, saydamlık, çok ince bir dönüş ve son olarak zaten "el yazısı" bir yazı tipi kullanarak ekledim. Bunlar, çok çeşitli "yazma stilleri" sağlamak için dinamik parametreler olarak sarılabilir.

Daha gerçekçi bir görünüm için, yol verisi varsayılan olarak gerekli değildir. Ancak bu, elle yazılmış davranışa yaklaşan ve uygulanması kolay kısa ve etkili bir kod parçasıdır.

Nasıl çalışır

Bir çizgi deseni tanımlayarak yürüyen karıncalar, noktalı çizgiler vb. Oluşturabiliriz. Bundan "kapalı" nokta için çok uzun bir nokta tanımlayarak ve "açık" nokta kademeli olarak artırarak bundan yararlanarak, nokta uzunluğunu canlandırırken kontur verildiğinde çizgi çizme yanılsaması verecektir.

Kapalı nokta çok uzun olduğu için yinelenen desen görünmez (uzunluk, kullanılan yazı tipinin boyutuna ve özelliklerine göre değişir). Mektubun yolu bir uzunluğa sahip olacak, bu yüzden her noktanın en azından bu uzunluğu kapladığından emin olmalıyız.

Anahat için olduğu gibi birden fazla yoldan (örn. O, R, P vb.) Oluşan harfler için, biri içi boş kısım içindir, çizgiler aynı anda çizilmiş gibi görünecektir. Bu teknikle bu konuda fazla bir şey yapamayız, çünkü her bir yol segmentine ayrı ayrı konulmasını gerektirir.

uygunluk

Tuval öğesini desteklemeyen tarayıcılar için metni göstermenin alternatif bir yolu, örneğin stilize bir metin yerleştirilebilir:

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

gösteri

Bu canlı animasyonlu inme üretir ( bağımlılık yok ) -

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
Bunun için deliren tek kişi ben miyim? En azından ilk cevaptan çok daha iyi ve sorucının sorusuna en yakın görünüyor.
KhoPhi

5
Diğer yanıtı kullanarak bitirdim, çünkü hemen ertesi gün kullandığım ve daha sonra hiç dokunmadığım bir hızlı n-kirli kesmek olarak ihtiyacım vardı, ama bunu kabul ediyorum çünkü aradığım şeye çok daha yakın için.
Strugee

Birden çok satır ve uzun bir metin bloğu için nasıl yapabiliriz?
Saad Farooq

1
@ K3N Evet, aslında hoş bir dokunuş oldu: p Harika iş çıkardın.
keyser

1
@ AliAl-arnous, x'i karşı tarafa ayarlayabilir, eklemek yerine karakter genişliğini çıkarabilir, negatif negatif boşlukla dönüştürebilir ve karakterin diğer tarafında temizlemek için clearRect değerini değiştirebilirsiniz.

216

2019'u Düzenle


Gerçekçi animasyonlar oluşturabilen bir javascript kütüphanesi oluşturdum. Kullanımı kolaydır ve yazı tipi görevi gören özel bir JSON dosyası gerektirir.

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>

Ödemeye Github sayfasını dokümantasyon ve örnekler için. Ve Codepen


Önceki Cevap

Aşağıdaki örnek, tspanöğeleri dinamik olarak oluşturmak ve her birinin animasyonlarını oluşturmak için snap.js'yi kullanır stroke-dashoffset.

Önceki Cevap


SVG'leri kullanarak böyle bir şey yapabilirsiniz stroke-dasharray

keyframesAnimasyon olmadan böyle bir şey yapabilirsiniz

IE desteği için jquery / javascript kullanabilirsiniz


4
Vay canına, bu gerçekten ilginç. Orijinal kod snippet'inizi aldım ve yinelenen CSS özelliklerini kaldırarak, yüzde tabanlı ofsetleri ve dasharray değerlerini kullanarak ve kodun nasıl çalıştığını daha belirgin hale getirmek için kontur genişliğini değiştirerek biraz geliştirdim: jsfiddle.net/Ajedi32/gdc4azLn / 1 İsterseniz bu iyileştirmelerden herhangi birini cevabınızda düzenlemekten çekinmeyin.
Ajedi32

2
Bu, bu soru için tek bir destansı çözümdür, SVG, tarayıcının desteklememesi durumunda metni göstereceği kadar tuvalden (+1) daha iyidir.
Jeffery ThaGintoki

3
@JefferyThaGintoki bunu tuvalle de yapabilirsiniz, bunun yerine metni tuval etiketleri arasına yerleştirin, tuval metni desteklemiyorsa (veya gövde metnindeki diğer cevap gösterilerindeki gibi hareketli gif) görünecektir. Tarayıcı tuvali desteklemiyorsa, muhtemelen svg'yi de desteklemeyecektir.
torox

1
Ben SVG metin kullanımı harika olduğunu düşünüyorum, ancak merak ediyorum, bir noktada dolgu eklemek mümkün mü? sadece harflerin taslağı tüm projelerde hoş görünmüyor, şerefe! ve elbette bu cevaba +1
randomguy04

1
@ randomguy04 İlk snippet'i kontrol edin, bir dolgu efekti eklemek için düzenledim. $(this).css('fill', 'red')Animasyona geri çağrı olarak ekleyerek yapılır
Akshay

2

Sadece 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

Birçok testten sonra, bazı notlar. Amaç, kullanıcı etkileşimi gerektiren DOM ağır sayfalarında hızlı metin verilerini en az engelleme yöntemiyle görüntülemektir .

Elbette aynı şeyi başarmanın birçok yolu vardır. Bu örnekte, farklar açık olmayabilir, gerçekten karmaşık arayüzler için geçerlidir.

En yavaş : innerHTMLve satır içi stil. DOM her bir yinelemede yeniden hesaplanır. Tarayıcı treni korumak için çok çalışıyor. Hızlı bir şekilde başarısız olur ve bellek sızıntılarına ve donmalara neden olur:

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

Daha iyi bir yol : kullanma textContent, requestAnimationFrameve web animasyon API. Bu daha da sorunsuz gidiyor, DOM ağır sayfalarında açıkça görülüyor. Kullanıcı etkileşimleri yeniden çizimleri engellemez. Arayüzün iyi yanıt vermesini sağlamak için bazı boyamalar atlanabilir.

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>

Yukarıdaki örnekte, DOM hala metin taşması için yeniden hesaplanmaktadır. Hata ayıklayıcının sert yanıp söndüğünü görebiliriz. Bu gerçekten basamaklı unsurlar için önemlidir! Bu, javascript ve kullanıcı kaydırma işlemlerini yavaşlatabilir.

resim açıklamasını buraya girin

Tam güç : Verileri css contentkuralı ve css değişkenleriyle yenilemek için yalnızca css kullanmak mümkündür . Metin daha sonra seçilemez.

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>

resim açıklamasını buraya girin

Testlerim büyük gelişmeler gösterdi, javascript motoru diğer görevlerde hızla atlıyor. Bazen yukarıdaki örnekten biraz daha yavaş başlayabilir. Ancak bunun yanı sıra, bu, kullanıcıların kaydırmasını engellemez ve hata ayıklayıcı da beğenir, daha fazla sıçrama yapmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.