原文:CSS3火焰文字特效制作教程

用一句很俗气的话概括这两天的情况就是:“最近很忙”,虽然手头上有不少很酷的HTML5和CSS3资源,但确实没时间将它们的实现过程写成教程分享给大家。今天刚完成了一个神秘的项目,空下来来博客园写点东西。今天给大家分享2个CSS3火焰文字特效,并且将实现的思路和核心代码写成教程分享给大家。

第一个是静态的火焰文字效果,先看看效果图:

看着图的效果很酷吧。

同时你也可以在这里查看火焰文字的DEMO演示

下面是实现的源码,由于是静态的文字效果,所以代码相当比较简单。

HTML代码,就一个h1标签:

  1. <h1 id="fire">HTML5 Tricks</h1>

然后是CSS3代码:

  1. #fire{
  2. text-align: center;
  3. margin: 100px auto;
  4. font-family: "Comic Sans MS";
  5. font-size: 80px;
  6. color: white;
  7. text-shadow: 0 0 20px #fefcc9, 10px -10px 30px #feec85, -20px -20px 40px #ffae34, 20px -40px 50px #ec760c, -20px -60px 60px #cd4606, 0 -80px 70px #973716, 10px -90px 80px #451b0e;
  8.  
  9. }
  10.  
  11. body {background:black; }

这里简单说一下,主要是用了CSS3的text-shadow属性实现文字阴影,这里定义了7层的层叠阴影,用阶梯变化的颜色和一定的阴影半径模拟出火焰从里到外的颜色渐变。

第二个是带动画的火焰文字特效,说实话,和上一个相比,这个不怎么像火焰,但我还是称它火焰吧。先来看看效果图:

看看,是不是很大气。

要看动起来的效果,可以查看DEMO演示

然后再分析一下源代码,由于涉及到CSS3动画,所以利用了JS代码动态改变CSS样式。

先是HTML代码,构造了一个div容器:

  1. <div id="canvasContainer"></div>

下面是JS代码:

  1. function Stats()
  2. {
  3. this.init();
  4. }
  5.  
  6. Stats.prototype =
  7. {
  8. init: function()
  9. {
  10. this.frames = 0;
  11. this.framesMin = 100;
  12. this.framesMax = 0;
  13.  
  14. this.time = new Date().getTime();
  15. this.timePrev = new Date().getTime();
  16.  
  17. this.container = document.createElement("div");
  18. this.container.style.position = 'absolute';
  19. this.container.style.fontFamily = 'Arial';
  20. this.container.style.fontSize = '10px';
  21. this.container.style.backgroundColor = '#000020';
  22. this.container.style.opacity = '0.9';
  23. this.container.style.width = '80px';
  24. this.container.style.paddingTop = '2px';
  25.  
  26. this.framesText = document.createElement("div");
  27. this.framesText.style.color = '#00ffff';
  28. this.framesText.style.marginLeft = '3px';
  29. this.framesText.style.marginBottom = '3px';
  30. this.framesText.innerHTML = '<strong>FPS</strong>';
  31. this.container.appendChild(this.framesText);
  32.  
  33. this.canvas = document.createElement("canvas");
  34. this.canvas.width = 74;
  35. this.canvas.height = 30;
  36. this.canvas.style.display = 'block';
  37. this.canvas.style.marginLeft = '3px';
  38. this.canvas.style.marginBottom = '3px';
  39. this.container.appendChild(this.canvas);
  40.  
  41. this.context = this.canvas.getContext("2d");
  42. this.context.fillStyle = '#101030';
  43. this.context.fillRect(0, 0, this.canvas.width, this.canvas.height );
  44.  
  45. this.contextImageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
  46.  
  47. setInterval( bargs( function( _this ) { _this.update(); return false; }, this ), 1000 );
  48. },
  49.  
  50. getDisplayElement: function()
  51. {
  52. return this.container;
  53. },
  54.  
  55. tick: function()
  56. {
  57. this.frames++;
  58. },
  59.  
  60. update: function()
  61. {
  62. this.time = new Date().getTime();
  63.  
  64. this.fps = Math.round((this.frames * 1000 ) / (this.time - this.timePrev)); //.toPrecision(2);
  65.  
  66. this.framesMin = Math.min(this.framesMin, this.fps);
  67. this.framesMax = Math.max(this.framesMax, this.fps);
  68.  
  69. this.framesText.innerHTML = '<strong>' + this.fps + ' FPS</strong> (' + this.framesMin + '-' + this.framesMax + ')';
  70.  
  71. this.contextImageData = this.context.getImageData(1, 0, this.canvas.width - 1, 30);
  72. this.context.putImageData(this.contextImageData, 0, 0);
  73.  
  74. this.context.fillStyle = '#101030';
  75. this.context.fillRect(this.canvas.width - 1, 0, 1, 30);
  76.  
  77. this.index = ( Math.floor(30 - Math.min(30, (this.fps / 60) * 30)) );
  78.  
  79. this.context.fillStyle = '#80ffff';
  80. this.context.fillRect(this.canvas.width - 1, this.index, 1, 1);
  81.  
  82. this.context.fillStyle = '#00ffff';
  83. this.context.fillRect(this.canvas.width - 1, this.index + 1, 1, 30 - this.index);
  84.  
  85. this.timePrev = this.time;
  86. this.frames = 0;
  87. }
  88. }
  89.  
  90. // Hack by Spite
  91.  
  92. function bargs( _fn )
  93. {
  94. var args = [];
  95. for( var n = 1; n < arguments.length; n++ )
  96. args.push( arguments[ n ] );
  97. return function () { return _fn.apply( this, args ); };
  98. }
  99.  
  100. (function (window){
  101.  
  102. var Sakri = window.Sakri || {};
  103. window.Sakri = window.Sakri || Sakri;
  104.  
  105. Sakri.MathUtil = {};
  106.  
  107. //return number between 1 and 0
  108. Sakri.MathUtil.normalize = function(value, minimum, maximum){
  109. return (value - minimum) / (maximum - minimum);
  110. };
  111.  
  112. //map normalized number to values
  113. Sakri.MathUtil.interpolate = function(normValue, minimum, maximum){
  114. return minimum + (maximum - minimum) * normValue;
  115. };
  116.  
  117. //map a value from one set to another
  118. Sakri.MathUtil.map = function(value, min1, max1, min2, max2){
  119. return Sakri.MathUtil.interpolate( Sakri.MathUtil.normalize(value, min1, max1), min2, max2);
  120. };
  121.  
  122. Sakri.MathUtil.hexToRgb = function(hex) {
  123. // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  124. var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  125. hex = hex.replace(shorthandRegex, function(m, r, g, b) {
  126. return r + r + g + g + b + b;
  127. });
  128.  
  129. var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  130. return result ? {
  131. r: parseInt(result[1], 16),
  132. g: parseInt(result[2], 16),
  133. b: parseInt(result[3], 16)
  134. } : null;
  135. }
  136.  
  137. Sakri.MathUtil.getRandomNumberInRange = function(min, max){
  138. return min + Math.random() * (max - min);
  139. };
  140.  
  141. Sakri.MathUtil.getRandomIntegerInRange = function(min, max){
  142. return Math.round(Sakri.MathUtil.getRandomNumberInRange(min, max));
  143. };
  144.  
  145. }(window));
  146.  
  147. //has a dependency on Sakri.MathUtil
  148.  
  149. (function (window){
  150.  
  151. var Sakri = window.Sakri || {};
  152. window.Sakri = window.Sakri || Sakri;
  153.  
  154. Sakri.Geom = {};
  155.  
  156. //==================================================
  157. //=====================::POINT::====================
  158. //==================================================
  159.  
  160. Sakri.Geom.Point = function (x,y){
  161. this.x = isNaN(x) ? 0 : x;
  162. this.y = isNaN(y) ? 0 : y;
  163. };
  164.  
  165. Sakri.Geom.Point.prototype.clone = function(){
  166. return new Sakri.Geom.Point(this.x,this.y);
  167. };
  168.  
  169. Sakri.Geom.Point.prototype.update = function(x, y){
  170. this.x = isNaN(x) ? this.x : x;
  171. this.y = isNaN(y) ? this.y : y;
  172. };
  173.  
  174. //==================================================
  175. //===================::RECTANGLE::==================
  176. //==================================================
  177.  
  178. Sakri.Geom.Rectangle = function (x, y, width, height){
  179. this.update(x, y, width, height);
  180. };
  181.  
  182. Sakri.Geom.Rectangle.prototype.update = function(x, y, width, height){
  183. this.x = isNaN(x) ? 0 : x;
  184. this.y = isNaN(y) ? 0 : y;
  185. this.width = isNaN(width) ? 0 : width;
  186. this.height = isNaN(height) ? 0 : height;
  187. };
  188.  
  189. Sakri.Geom.Rectangle.prototype.getRight = function(){
  190. return this.x + this.width;
  191. };
  192.  
  193. Sakri.Geom.Rectangle.prototype.getBottom = function(){
  194. return this.y + this.height;
  195. };
  196.  
  197. Sakri.Geom.Rectangle.prototype.getCenter = function(){
  198. return new Sakri.Geom.Point(this.getCenterX(), this.getCenterY());
  199. };
  200.  
  201. Sakri.Geom.Rectangle.prototype.getCenterX = function(){
  202. return this.x + this.width/2;
  203. };
  204.  
  205. Sakri.Geom.Rectangle.prototype.getCenterY=function(){
  206. return this.y + this.height/2;
  207. };
  208.  
  209. Sakri.Geom.Rectangle.prototype.containsPoint = function(x, y){
  210. return x >= this.x && y >= this.y && x <= this.getRight() && y <= this.getBottom();
  211. };
  212.  
  213. Sakri.Geom.Rectangle.prototype.clone = function(){
  214. return new Sakri.Geom.Rectangle(this.x, this.y, this.width, this.height);
  215. };
  216.  
  217. Sakri.Geom.Rectangle.prototype.toString = function(){
  218. return "Rectangle{x:"+this.x+" , y:"+this.y+" , width:"+this.width+" , height:"+this.height+"}";
  219. };
  220.  
  221. }(window));
  222.  
  223. /**
  224. * Created by sakri on 27-1-14.
  225. * has a dependecy on Sakri.Geom
  226. * has a dependecy on Sakri.BitmapUtil
  227. */
  228.  
  229. (function (window){
  230.  
  231. var Sakri = window.Sakri || {};
  232. window.Sakri = window.Sakri || Sakri;
  233.  
  234. Sakri.CanvasTextUtil = {};
  235.  
  236. //returns the biggest font size that best fits into given width
  237. Sakri.CanvasTextUtil.getFontSizeForWidth = function(string, fontProps, width, canvas, fillStyle, maxFontSize){
  238. if(!canvas){
  239. var canvas = document.createElement("canvas");
  240. }
  241. if(!fillStyle){
  242. fillStyle = "#000000";
  243. }
  244. if(isNaN(maxFontSize)){
  245. maxFontSize = 500;
  246. }
  247. var context = canvas.getContext('2d');
  248. context.font = fontProps.getFontString();
  249. context.textBaseline = "top";
  250.  
  251. var copy = fontProps.clone();
  252. //console.log("getFontSizeForWidth() 1 : ", copy.fontSize);
  253. context.font = copy.getFontString();
  254. var textWidth = context.measureText(string).width;
  255.  
  256. //SOME DISAGREEMENT WHETHER THIS SHOOULD BE WITH && or ||
  257. if(textWidth < width){
  258. while(context.measureText(string).width < width){
  259. copy.fontSize++;
  260. context.font = copy.getFontString();
  261. if(copy.fontSize > maxFontSize){
  262. console.log("getFontSizeForWidth() max fontsize reached");
  263. return null;
  264. }
  265. }
  266. }else if(textWidth > width){
  267. while(context.measureText(string).width > width){
  268. copy.fontSize--;
  269. context.font = copy.getFontString();
  270. if(copy.fontSize < 0){
  271. console.log("getFontSizeForWidth() min fontsize reached");
  272. return null;
  273. }
  274. }
  275. }
  276. //console.log("getFontSizeForWidth() 2 : ", copy.fontSize);
  277. return copy.fontSize;
  278. };
  279.  
  280. //=========================================================================================
  281. //==============::CANVAS TEXT PROPERTIES::====================================
  282. //========================================================
  283.  
  284. Sakri.CanvasTextProperties = function(fontWeight, fontStyle, fontSize, fontFace){
  285. this.setFontWeight(fontWeight);
  286. this.setFontStyle(fontStyle);
  287. this.setFontSize(fontSize);
  288. this.fontFace = fontFace ? fontFace : "sans-serif";
  289. };
  290.  
  291. Sakri.CanvasTextProperties.NORMAL = "normal";
  292. Sakri.CanvasTextProperties.BOLD = "bold";
  293. Sakri.CanvasTextProperties.BOLDER = "bolder";
  294. Sakri.CanvasTextProperties.LIGHTER = "lighter";
  295.  
  296. Sakri.CanvasTextProperties.ITALIC = "italic";
  297. Sakri.CanvasTextProperties.OBLIQUE = "oblique";
  298.  
  299. Sakri.CanvasTextProperties.prototype.setFontWeight = function(fontWeight){
  300. switch (fontWeight){
  301. case Sakri.CanvasTextProperties.NORMAL:
  302. case Sakri.CanvasTextProperties.BOLD:
  303. case Sakri.CanvasTextProperties.BOLDER:
  304. case Sakri.CanvasTextProperties.LIGHTER:
  305. this.fontWeight = fontWeight;
  306. break;
  307. default:
  308. this.fontWeight = Sakri.CanvasTextProperties.NORMAL;
  309. }
  310. };
  311.  
  312. Sakri.CanvasTextProperties.prototype.setFontStyle = function(fontStyle){
  313. switch (fontStyle){
  314. case Sakri.CanvasTextProperties.NORMAL:
  315. case Sakri.CanvasTextProperties.ITALIC:
  316. case Sakri.CanvasTextProperties.OBLIQUE:
  317. this.fontStyle = fontStyle;
  318. break;
  319. default:
  320. this.fontStyle = Sakri.CanvasTextProperties.NORMAL;
  321. }
  322. };
  323.  
  324. Sakri.CanvasTextProperties.prototype.setFontSize = function(fontSize){
  325. if(fontSize && fontSize.indexOf && fontSize.indexOf("px")>-1){
  326. var size = fontSize.split("px")[0];
  327. fontProperites.fontSize = isNaN(size) ? 24 : size;//24 is just an arbitrary number
  328. return;
  329. }
  330. this.fontSize = isNaN(fontSize) ? 24 : fontSize;//24 is just an arbitrary number
  331. };
  332.  
  333. Sakri.CanvasTextProperties.prototype.clone = function(){
  334. return new Sakri.CanvasTextProperties(this.fontWeight, this.fontStyle, this.fontSize, this.fontFace);
  335. };
  336.  
  337. Sakri.CanvasTextProperties.prototype.getFontString = function(){
  338. return this.fontWeight + " " + this.fontStyle + " " + this.fontSize + "px " + this.fontFace;
  339. };
  340.  
  341. }(window));
  342.  
  343. window.requestAnimationFrame =
  344. window.__requestAnimationFrame ||
  345. window.requestAnimationFrame ||
  346. window.webkitRequestAnimationFrame ||
  347. window.mozRequestAnimationFrame ||
  348. window.oRequestAnimationFrame ||
  349. window.msRequestAnimationFrame ||
  350. (function () {
  351. return function (callback, element) {
  352. var lastTime = element.__lastTime;
  353. if (lastTime === undefined) {
  354. lastTime = 0;
  355. }
  356. var currTime = Date.now();
  357. var timeToCall = Math.max(1, 33 - (currTime - lastTime));
  358. window.setTimeout(callback, timeToCall);
  359. element.__lastTime = currTime + timeToCall;
  360. };
  361. })();
  362.  
  363. var readyStateCheckInterval = setInterval( function() {
  364. if (document.readyState === "complete") {
  365. clearInterval(readyStateCheckInterval);
  366. init();
  367. }
  368. }, 10);
  369.  
  370. //========================
  371. //general properties for demo set up
  372. //========================
  373.  
  374. var canvas;
  375. var context;
  376. var canvasContainer;
  377. var htmlBounds;
  378. var bounds;
  379. var minimumStageWidth = 250;
  380. var minimumStageHeight = 250;
  381. var maxStageWidth = 1000;
  382. var maxStageHeight = 600;
  383. var resizeTimeoutId = -1;
  384. var stats;
  385.  
  386. function init(){
  387. canvasContainer = document.getElementById("canvasContainer");
  388. window.onresize = resizeHandler;
  389. stats = new Stats();
  390. canvasContainer.appendChild( stats.getDisplayElement() );
  391. commitResize();
  392. }
  393.  
  394. function getWidth( element ){return Math.max(element.scrollWidth,element.offsetWidth,element.clientWidth );}
  395. function getHeight( element ){return Math.max(element.scrollHeight,element.offsetHeight,element.clientHeight );}
  396.  
  397. //avoid running resize scripts repeatedly if a browser window is being resized by dragging
  398. function resizeHandler(){
  399. context.clearRect(0,0,canvas.width, canvas.height);
  400. clearTimeout(resizeTimeoutId);
  401. clearTimeoutsAndIntervals();
  402. resizeTimeoutId = setTimeout(commitResize, 300 );
  403. }
  404.  
  405. function commitResize(){
  406. if(canvas){
  407. canvasContainer.removeChild(canvas);
  408. }
  409. canvas = document.createElement('canvas');
  410. canvas.style.position = "absolute";
  411. context = canvas.getContext("2d");
  412. canvasContainer.appendChild(canvas);
  413.  
  414. htmlBounds = new Sakri.Geom.Rectangle(0,0, getWidth(canvasContainer) , getHeight(canvasContainer));
  415. if(htmlBounds.width >= maxStageWidth){
  416. canvas.width = maxStageWidth;
  417. canvas.style.left = htmlBounds.getCenterX() - (maxStageWidth/2)+"px";
  418. }else{
  419. canvas.width = htmlBounds.width;
  420. canvas.style.left ="0px";
  421. }
  422. if(htmlBounds.height > maxStageHeight){
  423. canvas.height = maxStageHeight;
  424. canvas.style.top = htmlBounds.getCenterY() - (maxStageHeight/2)+"px";
  425. }else{
  426. canvas.height = htmlBounds.height;
  427. canvas.style.top ="0px";
  428. }
  429. bounds = new Sakri.Geom.Rectangle(0,0, canvas.width, canvas.height);
  430. context.clearRect(0,0,canvas.width, canvas.height);
  431.  
  432. if(bounds.width<minimumStageWidth || bounds.height<minimumStageHeight){
  433. stageTooSmallHandler();
  434. return;
  435. }
  436.  
  437. var textInputSpan = document.getElementById("textInputSpan");
  438. textInputSpan.style.top = htmlBounds.getCenterY() + (bounds.height/2) + 20 +"px";
  439. textInputSpan.style.left = (htmlBounds.getCenterX() - getWidth(textInputSpan)/2)+"px";
  440.  
  441. startDemo();
  442. }
  443.  
  444. function stageTooSmallHandler(){
  445. var warning = "Sorry, bigger screen required :(";
  446. context.font = "bold normal 24px sans-serif";
  447. context.fillText(warning, bounds.getCenterX() - context.measureText(warning).width/2, bounds.getCenterY()-12);
  448. }
  449.  
  450. //========================
  451. //Demo specific properties
  452. //========================
  453.  
  454. var animating = false;
  455. var particles = [];
  456. var numParticles = 4000;
  457. var currentText = "SAKRI";
  458. var fontRect;
  459. var fontProperties = new Sakri.CanvasTextProperties(Sakri.CanvasTextProperties.BOLD, null, 100);
  460. var animator;
  461. var particleSource = new Sakri.Geom.Point();;
  462. var particleSourceStart = new Sakri.Geom.Point();
  463. var particleSourceTarget = new Sakri.Geom.Point();
  464.  
  465. var redParticles = ["#fe7a51" , "#fdd039" , "#fd3141"];
  466. var greenParticles = ["#dbffa6" , "#fcf8fd" , "#99de5e"];
  467. var pinkParticles = ["#fef4f7" , "#f2a0c0" , "#fb3c78"];
  468. var yellowParticles = ["#fdfbd5" , "#fff124" , "#f4990e"];
  469. var blueParticles = ["#9ca2df" , "#222a6d" , "#333b8d"];
  470.  
  471. var particleColorSets = [redParticles, greenParticles, pinkParticles, yellowParticles, blueParticles];
  472. var particleColorIndex = 0;
  473.  
  474. var renderParticleFunction;
  475. var renderBounds;
  476. var particleCountOptions = [2000, 4000, 6000, 8000, 10000, 15000, 20000 ];
  477. var pixelParticleCountOptions = [10000, 40000, 60000, 80000, 100000, 150000 ];
  478.  
  479. function clearTimeoutsAndIntervals(){
  480. animating = false;
  481. }
  482.  
  483. function startDemo(){
  484.  
  485. fontRect = new Sakri.Geom.Rectangle(Math.floor(bounds.x + bounds.width*.2), 0, Math.floor(bounds.width - bounds.width*.4), bounds.height);
  486. fontProperties.fontSize = 100;
  487. fontProperties.fontSize = Sakri.CanvasTextUtil.getFontSizeForWidth(currentText, fontProperties, fontRect.width, canvas);
  488. fontRect.y = Math.floor(bounds.getCenterY() - fontProperties.fontSize/2);
  489. fontRect.height = fontProperties.fontSize;
  490. renderBounds = fontRect.clone();
  491. renderBounds.x -= Math.floor(canvas.width *.1);
  492. renderBounds.width += Math.floor(canvas.width *.2);
  493. renderBounds.y -= Math.floor(fontProperties.fontSize *.5);
  494. renderBounds.height += Math.floor(fontProperties.fontSize *.6);
  495. context.font = fontProperties.getFontString();
  496.  
  497. createParticles();
  498. context.globalAlpha = globalAlpha;
  499. animating = true;
  500. loop();
  501. }
  502.  
  503. function loop(){
  504. if(!animating){
  505. return;
  506. }
  507. stats.tick();
  508. renderParticles();
  509. window.requestAnimationFrame(loop, canvas);
  510. }
  511.  
  512. function createParticles(){
  513. context.clearRect(0,0,canvas.width, canvas.height);
  514. context.fillText(currentText, fontRect.x, fontRect.y);
  515. var imageData = context.getImageData(fontRect.x, fontRect.y, fontRect.width, fontRect.height);
  516. var data = imageData.data;
  517. var length = data.length;
  518. var rowWidth = fontRect.width*4;
  519. var i, y, x;
  520.  
  521. particles = [];
  522. for(i=0; i<length; i+=4){
  523. if(data[i+3]>0){
  524. y = Math.floor(i / rowWidth);
  525. x = fontRect.x + (i - y * rowWidth) / 4;
  526. particles.push(x);//x
  527. particles.push(fontRect.y + y);//y
  528. particles.push(x);//xOrigin
  529. particles.push(fontRect.y + y);//yOrigin
  530. }
  531. }
  532.  
  533. //console.log(particles.length);
  534. context.clearRect(0,0,canvas.width, canvas.height);
  535.  
  536. //pre calculate random numbers used for particle movement
  537. xDirections = [];
  538. yDirections = [];
  539. for(i=0; i<directionCount; i++){
  540. xDirections[i] = -7 + Math.random() * 14;
  541. yDirections[i] = Math.random()* - 5;
  542. }
  543. }
  544.  
  545. var xDirections, yDirections;
  546. //fidget with these to manipulate effect
  547. var globalAlpha = .11; //amount of trails or tracers
  548. var xWind = 0; //all particles x is effected by this
  549. var threshold = 60; //if a pixels red component is less than this, return particle to it's original position
  550. var amountRed = 25; //amount of red added to a pixel occupied by a particle
  551. var amountGreen = 12; //amount of green added to a pixel occupied by a particle
  552. var amountBlue = 1; //amount of blue added to a pixel occupied by a particle
  553. var directionCount = 100; //number of random pre-calculated x and y directions
  554.  
  555. function renderParticles(){
  556. //fill renderBounds area with a transparent black, and render a nearly black text
  557. context.fillStyle = "#000000";
  558. context.fillRect(renderBounds.x, renderBounds.y, renderBounds.width, renderBounds.height);
  559. context.fillStyle = "#010000";
  560. context.fillText(currentText, fontRect.x, fontRect.y);
  561.  
  562. var randomRed = amountRed -5 + Math.random()*10;
  563. var randomGreen = amountGreen -2 + Math.random()*4;
  564.  
  565. var imageData = context.getImageData(renderBounds.x, renderBounds.y, renderBounds.width, renderBounds.height);
  566. var data = imageData.data;
  567. var rowWidth = imageData.width * 4;
  568. var index, i, length = particles.length;
  569. var d = Math.floor(Math.random()*30);
  570. xWind += (-.5 + Math.random());//move randomly left or right
  571. xWind = Math.min(xWind, 1.5);//clamp to a maximum wind
  572. xWind = Math.max(xWind, -1.5);//clamp to a minimum wind
  573. for(i=0; i<length; i+=4, d++ ){
  574.  
  575. particles[i] += (xDirections[d % directionCount] + xWind);
  576. particles[i+1] += yDirections[d % directionCount];
  577.  
  578. index = Math.round(particles[i] - renderBounds.x) * 4 + Math.round(particles[i+1] - renderBounds.y) * rowWidth;
  579.  
  580. data[index] += randomRed;
  581. data[index + 1] += randomGreen;
  582. data[index + 2] += amountBlue;
  583.  
  584. //if pixels red component is below set threshold, return particle to orgin
  585. if( data[index] < threshold){
  586. particles[i] = particles[i+2];
  587. particles[i+1] = particles[i+3];
  588. }
  589. }
  590. context.putImageData(imageData, renderBounds.x, renderBounds.y);
  591. }
  592.  
  593. var maxCharacters = 10;
  594.  
  595. function changeText(){
  596. var textInput = document.getElementById("textInput");
  597. if(textInput.value && textInput.text!=""){
  598. if(textInput.value.length > maxCharacters){
  599. alert("Sorry, there is only room for "+maxCharacters+" characters. Try a shorter name.");
  600. return;
  601. }
  602. if(textInput.value.indexOf(" ")>-1){
  603. alert("Sorry, no support for spaces right now :(");
  604. return;
  605. }
  606. currentText = textInput.value;
  607. clearTimeoutsAndIntervals();
  608. animating = false;
  609. setTimeout(commitResize, 100);
  610. }
  611. }
  612.  
  613. function changeSettings(){
  614. clearTimeoutsAndIntervals();
  615. animating = false;
  616. setTimeout(commitResize, 100);
  617. }
  618.  
  619. function setParticleNumberOptions(values){
  620. var selector = document.getElementById("particlesSelect");
  621. if(selector.options.length>0 && parseInt(selector.options[0].value) == values[0] ){
  622. return;
  623. }
  624. while(selector.options.length){
  625. selector.remove(selector.options.length-1);
  626. }
  627. for(var i=0;i <values.length; i++){
  628. selector.options[i] = new Option(values[i], values[i], i==0, i==0);
  629. }
  630. }

这两款CSS3火焰文字效果都还不错吧,如果你真的对HTML5感兴趣,可以点这里邮件订阅一下,注意需要登录邮箱确认订阅,这样有好的HTML5资源我会用邮件发送给你。

另外,如果你有微博,也可以用微博关注获取最新的HTML5资源和教程,我的新浪微博腾讯微博

最后把这两款CSS3火焰文字特效的源码共享一下,下载地址1>>   |    下载地址2>>

CSS3火焰文字特效制作教程的更多相关文章

  1. 10个优秀的 HTML5 & CSS3 下拉菜单制作教程

    下拉菜单是一个很常见的效果,在网站设计中被广泛使用.通过使用下拉菜单,设计者不仅可以在网站设计中营造出色的视觉吸引力,但也可以为网站提供了一个有效的导航方案.使用 HTML5 和 CSS3 可以更容易 ...

  2. HTML5火焰文字特效DEMO演示

    效果展示:http://hovertree.com/texiao/html5/26/ 效果图: 扫描二维码查看效果:

  3. HTML5火焰文字特效DEMO演示---转载

    只有google支持 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> &l ...

  4. 11个优秀的HTML5 & CSS3下拉菜单制作教程

    下拉菜单是一个很常见的效果,在网站设计中被广泛使用.通过使用下拉菜单,设计者不仅可以在网站设计中营造出色的视觉吸引力,但也可以为网站提供了一个有效的导航方案.使用HTML5和CSS3可以更容易创造视觉 ...

  5. 10个优秀的 HTML5 &amp; CSS3 下拉菜单制作教程

    下拉菜单是一个非经常见的效果.在站点设计中被广泛使用.通过使用下拉菜单.设计者不仅能够在站点设计中营造出色的视觉吸引力,但也能够为站点提供了一个有效的导航方案.使用 HTML5 和 CSS3 能够更e ...

  6. css3火焰文字样式代码

    css样式: <style type="text/css"> body{background:#000;} *{margin:0;padding:0;transitio ...

  7. jQuery文字特效制作文字鼠标滑过多彩色变色显示

    <!DOCTYPE html><head> <meta http-equiv="Content-Type" content="text/ht ...

  8. HTML5/CSS3(PrefixFree.js) 3D文字特效

    之前在园子里看到一个HTML5/CSS3的文字特效(这里),觉得挺好玩的所以小小的研究了下,不过发现代码都是针对webkit以及FF的所以IE跪了. Runjs 我将示例中的代码进行了精简,后来发现C ...

  9. 7款震撼人心的HTML5文字特效

    1.CSS3五彩文字特效 文字带阴影效果 这是一款非常具有卡通形象的CSS3五彩文字特效,虽然没有迷人的动画效果,但是五彩缤纷的文字展现在屏幕上也是非常酷的,再加上每一个文字都有不同角度的阴影效果,加 ...

随机推荐

  1. Visual Studio 使用及调试必知必会

    原文:Visual Studio 使用及调试必知必会   一:C# CODING 技巧 1:TODO 然后 CTRL + W + T,打开任务列表,选中 Comments,就会显示所有待做的任务 2: ...

  2. Block学习一门:基本使用,使用block包NSURLRequest异步请求

    首先,看一下下面的代码: void (^myFirstBlock)(int theOne,int theTwo) = ^(int theOne,int theTwo){ NSLog(@"== ...

  3. Android尽量避免使用开发jpg图片

    因为jpgeasy失真,因此,Android尽量避免使用开发.jpg图片,相反,使用.png图片,它使用LZ77衍生无损数据压缩算法. 事实上在这一点上,Google他已经暗示我们: 发现了没有,在r ...

  4. 对SA权限的再突破 (对付xplog70.dll被删)转载

    原文:对SA权限的再突破 (对付xplog70.dll被删)转载 对SA权限的再突破 (对付xplog70.dll被删)转载 转载自:http://www.bitscn.com/plus/view.p ...

  5. 介绍一款替代SSMS的sqlserver管理工具 toad for sqlserver5.7

    原文:介绍一款替代SSMS的sqlserver管理工具 toad for sqlserver5.7 toad for sqlserver5.7 虽然SSMS很好很强大,不过有时候使用一些第三方工具可以 ...

  6. hibernate它 11.many2many双向

    表结构: 类图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd29iZW5kaWFua3Vu/font/5a6L5L2T/fontsize/400/fi ...

  7. LeetCode: Palindrome Partitioning [131]

    [称号] Given a string s, partition s such that every substring of the partition is a palindrome. Retur ...

  8. TFS:TF30042 数据库已满 处理方法

    原文:TFS:TF30042 数据库已满 处理方法 今天早上,公司打来电话,说TFS(Team Foundation Server)微软源代码管理软件签入不了,报错:TF30042 数据库已满. 经过 ...

  9. MAC OSX 进程间通信

    Mac OS在下面IPC方式很多类型,大约如下. 1. Mach API  2. CFMessagePort  3. Distributed Objects (DO) NSDistributedNot ...

  10. cocos2d-x使用CCClippingNode实现跑马灯

    直接在代码,这是一个很好的包layer,可以直接调用  //原来白白 bool TestLayer::init() { CCSize size = CCDirector::sharedDirector ...