html弹性动画,html5 canvas弹性字符串文字动画特效

特效描述:html5 canvas弹性字符串 文字动画特效。html5基于canvas制作拖动文字字符串弹性动画特效。

代码结构

1. 引入JS

2. HTML代码

/**

* requestAnimationFrame

*/

window.requestAnimationFrame = (function(){

return window.requestAnimationFrame ||

window.webkitRequestAnimationFrame ||

window.mozRequestAnimationFrame ||

window.oRequestAnimationFrame ||

window.msRequestAnimationFrame ||

function (callback) { window.setTimeout(callback, 1000 / 60); };

})();

/**

* ElasticString

*/

var ElasticString = (function(document) {

'use strict';

/**

* @constructor

*/

function ElasticString(fontSize, fontFamily, friction, spring) {

this._fontSize = fontSize;

this.points = [];

this.fontFamily = fontFamily || 'serif';

if (friction !== undefined) this.friction = friction;

if (spring !== undefined) this.spring = spring;

this._endPoint = new Point();

this._ctx = document.createElement('canvas').getContext('2d');

}

ElasticString.prototype = {

points: null,

fontFamily: 'serif',

friction: 0.02,

spring: 0.6,

_text: '',

_fontSize: 1,

_endPoint: null,

setFontSize: function(fontSize) {

this._fontSize = fontSize;

this.setText(this._text);

},

getFontSize: function() { return this._fontSize; },

setText: function(text, positions) {

var points = this.points,

p, letter, between,

i, len;

if (text.length < points.length) {

points = points.slice(0, text.length);

}

this._ctx.font = this._fontSize + 'px ' + this.fontFamily;

for (i = 0, len = text.length; i < len; i++) {

letter = text.charAt(i);

between = this._ctx.measureText(letter).width;

p = points[i];

if (p) {

p.letter = letter;

p.between = between;

} else {

p = new Point(letter, between);

points[i] = p;

}

if (positions && positions.length) {

p.x = p.px = positions[i][0];

p.y = p.py = positions[i][1];

}

}

this.points = points;

this._text = text;

},

getText: function() { return this._text; },

render: function(ctx) {

var points = this.points,

pointBetween = this._fontSize,

spring = this.spring,

text = this.text,

dx, dy, dist, scale,

p0, p1, size, angle,

i, len;

points.push(this._endPoint);

this._updatePoint(points[0]);

for (i = 0, len = points.length - 1; i < len; i++) {

p0 = points[i];

p1 = points[i + 1];

this._updatePoint(p1);

dx = p0.x - p1.x;

dy = p0.y - p1.y;

dist = Math.sqrt(dx * dx + dy * dy);

scale = dist ? (p0.between - dist) / dist * 0.5 * spring : 0;

dx *= scale;

dy *= scale;

p0.x += dx;

p0.y += dy;

p1.x -= dx;

p1.y -= dy;

}

for (i = 0; i < len; i++) {

p0 = points[i];

p1 = points[i + 1];

dx = p1.x - p0.x;

dy = p1.y - p0.y;

dist = Math.sqrt(dx * dx + dy * dy);

angle = Math.atan2(dy, dx);

ctx.save();

size = pointBetween > dist ? pointBetween : dist;

ctx.font = size + 'px ' + this.fontFamily;

ctx.translate(p0.x, p0.y);

ctx.rotate(angle);

ctx.fillText(p0.letter, 0, 0);

ctx.restore();

}

points.pop();

},

_updatePoint: function(p) {

var friction = 1 - this.friction,

px = p.px,

py = p.py;

p.px = p.x;

p.py = p.y;

if (p.fixed) return;

p.x += (p.x - px) * friction;

p.y += (p.y - py) * friction;

}

};

/**

* Point

*/

function Point(letter, between, x, y) {

this.letter = letter || '';

this.between = between || 0;

this.x = this.px = x || 0;

this.y = this.py = y || 0;

}

Point.prototype = {

letter: '',

between: 1,

x: 0,

y: 0

};

return ElasticString;

})(document);

(function(window, document) {

'use strict';

// Configs

var TEXT = 'The quick brown fox jumps over the lazy dog.',

FONT_SIZE = 25;

// Vars

var canvas, context,

elasticString,

mouse = { x: 0, y: 0 },

drag = null,

gui, guiOptions;

// Init

function init() {

var pos = [], i, len;

canvas = document.getElementById('c');

context = canvas.getContext('2d');

resize(null);

elasticString = new ElasticString(FONT_SIZE, 'Georgia, serif');

for (i = 0, len = TEXT.length; i < len; i++) {

if (i === 0)

pos.push([100, 100]);

else

pos.push([canvas.width * Math.random(), canvas.height * Math.random()]);

}

elasticString.setText(TEXT, pos);

window.addEventListener('resize', resize, false);

canvas.addEventListener('mousemove', mouseMove, false);

canvas.addEventListener('mousedown', mouseDown, false);

document.body.addEventListener('mouseup', mouseUp, false);

// GUI

guiOptions = {

text: elasticString.getText(),

fontSize: elasticString.getFontSize()

};

gui = new dat.GUI();

gui.add(guiOptions, 'text').onFinishChange(function() {

elasticString.setText(guiOptions.text);

});

gui.add(guiOptions, 'fontSize', 1, 50).onChange(function() {

elasticString.setFontSize(guiOptions.fontSize);

});

gui.add(elasticString, 'friction', 0, 1);

gui.add(elasticString, 'spring', 0, 1);

gui.close();

update();

}

// Event Listeners

function resize(e) {

canvas.width = window.innerWidth;

canvas.height = window.innerHeight;

context.fillStyle = '#3a3a2c';

}

function mouseMove(e) {

mouse.x = e.clientX;

mouse.y = e.clientY;

}

function mouseDown(e) {

var points = elasticString.points,

p,

hit = null,

rangeSq = FONT_SIZE * FONT_SIZE,

hitNear = FONT_SIZE * FONT_SIZE,

mx = e.clientX,

my = e.clientY,

dx, dy, distSq,

i, len;

for (i = 0, len = points.length; i < len; i++) {

p = points[i];

dx = mx - p.x;

dy = my - p.y;

distSq = dx * dx + dy * dy;

if (distSq < rangeSq && distSq < hitNear) {

hitNear = distSq;

hit = points[i];

}

}

drag = hit;

}

function mouseUp(e) {

drag = null;

}

// Update

function update() {

var points = elasticString.points,

p,

w = canvas.width,

h = canvas.height,

i, len;

if (drag) {

drag.x = mouse.x;

drag.y = mouse.y;

}

for (i = 0, len = points.length; i < len; i++) {

p = points[i];

if (0 > p.x) p.x = 0;

if (w < p.x) p.x = w;

if (0 > p.y) p.y = 0;

if (h < p.y) p.y = h;

}

context.clearRect(0, 0, canvas.width, canvas.height);

elasticString.render(context);

requestAnimationFrame(update);

}

// Run

init();

})(window, document);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值