澳门新葡萄京娱乐场 3

澳门新葡萄京娱乐场C++ GDI+ 带阴影的文字功能的实现

用GDI+的优秀图形输出功能可以非常方便的实现文字特效,其中一个带阴影的文字便是其中一例。

澳门新葡萄京娱乐场 ,对于艺术字和文字特效大家一定不陌生,对于英文来说,实现各种艺术字很简单,因为英文只有26个字母,加上阿拉伯数字也就几十个,只需要设计一个字体库生成ttf文件提供给各个平台加载就可以了。但是对于汉字来说,文字量巨大,针对每个汉字设计ttf实在不是理想的选择。而最近项目需要汉字的文字特效和动画效果,因此自己实现了一个Android平台的文字特效和动画效果库。

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

许多简单的文字特效只是简单的将文字用不同的颜色与不同的位置输出一次或多次,本文所讨论的阴影效果借助GDI+的反走样能力生成透明的阴影与半阴影。
这儿所述的方法先在绘图平面上绘制一个比预期小的文字,然后放大它。

先几个简单的效果图

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

由于代码注释很详细,直接上代码:

澳门新葡萄京娱乐场 1

澳门新葡萄京娱乐场 2

ULONG_PTRg_gdiPlusToken=NULL;//GDI+初始化voidCMFCApplication1Dlg::OnBnClickedOk(){usingnamespaceGdiplus;if(NULL==g_gdiPlusToken){Gdiplus::GdiplusStartupInputgdiplusStartupInput;Gdiplus::GdiplusStartup(g_gdiPlusToken,gdiplusStartupInput,NULL);}CRectClientRC;CStringWstrTxt(19:20:30);m_picBox.GetClientRect(ClientRC);RectFdesRC(ClientRC.left,ClientRC.top,ClientRC.Width(),ClientRC.Height());PointFtxtPos(0,0);FontFamilyfontFamily(LTimesNewRoman);Gdiplus::Fontfont(fontFamily,100,FontStyleBold,UnitPixel);Graphicsg(m_picBox.GetDC()-m_hDC);//1.0填充背景色g.FillRectangle(Gdiplus::SolidBrush(Color::LightSlateGray),desRC);//2.0创建一个小尺寸的内存位图,设置它的长宽为总尺寸的1/4Bitmapbmp(ClientRC.Width()/4,ClientRC.Height()/4,g);//2.1设置绘制模式为反走样模式Graphics*pTempG=Graphics::FromImage(bmp);pTempG-SetTextRenderingHint(TextRenderingHintAntiAlias);//2.2创建一个矩阵,使字体为原来的1/4,阴影距离也为你要设置文本的1/4左右Matrixmx(0.25f,0,0,0.25f,3,3);pTempG-SetTransform(mx);//2.3在位图上绘制文本,使用有透明度的画笔pTempG-DrawString(strTxt,-1,font,txtPos,NULL,SolidBrush(Color(128,0,0,0)));//3.1插值模式为高质量双三次插值法,插值法非常重要,因为双三次插值使文本的边模糊,这样就出现阴影与半影效果g.SetInterpolationMode(InterpolationModeHighQualityBicubic);//3.2设置绘制模式为反走样模式以保证正确的范围g.SetTextRenderingHint(TextRenderingHintAntiAlias);//3.3把位图显示在屏幕上,在两个方向上都放大4倍g.DrawImage(bmp,desRC,0,0,bmp.GetWidth(),bmp.GetHeight(),UnitPixel);//3.4把文本绘制到绘图平面上,使用白色字体g.DrawString(strTxt,-1,font,txtPos,NULL,SolidBrush(Color::White));//4.0释放内存if(NULL!=pTempG){deletepTempG;pTempG=NULL;}}

上图中只是几个自己实现的简单的特效demo,这个库好处是可以创造属于自己的特效字体。下面我们来说说怎样创建自己的字体特效:

看着图的效果很酷吧。

1.demo和库可以在github上下载:https://github.com/lltvcn/FreeText/
2.demo中点击“创建字体模版”就可以进入创建模版的页面。
3.对于文字特效模版我们可以对照ps软件,每个文字其实是有很多层叠加起来的,从而实现了很多效果,例如上图的缩放效果就是由多个不同大小和透明度的文字层叠加而成。
对于上图中抖音效果其实就是由三个不容颜色的文字层偏移叠加而成。
4.每一层叠加的文字和android原生文字可以支持的效果是一样的,例如渐变,描边,阴影等等。
5.不仅可以叠加文字,还可以叠加图片,如上图中倒数第二个例子,就是在文字下方叠加了一个背景图。
6.此外,demo中还提供了切割和偏移等效果,即把文字切割成两部分或者多个部分做平移。实现的逻辑既是把多层文字看作一张图片做各种操作。
7.完成文字特效后点击生成模版,取一个名字就可以保存到本地,在sd
卡上FontDemo/data下面就可以找到对应的文字模版了。
8.在需要文字模版的app中只要用github下载的demo中的库内的STextView加载相应的模块,即可以显示对应的文字特效了。
9.除了静态特效,还提供了一个动画特效的框架,上图是本人实现的几个简单的动画特效,需要的话可以自行拓展。动画特效没有支持生成模版,是在代码中实现的,需要的也可以生成模版使用。

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

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

HTML代码,就一个h1标签:

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

然后是CSS3代码:

#fire{  text-align: center;  margin: 100px auto;  font-family: "Comic Sans MS";  font-size: 80px;  color: white;  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;    }    body {background:black; }

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

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

澳门新葡萄京娱乐场 3

看看,是不是很大气。

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

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

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

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

下面是JS代码:

澳门新葡萄京娱乐场 4澳门新葡萄京娱乐场 5

function Stats()  {    this.init();  }    Stats.prototype =    {    init: function()    {      this.frames = 0;      this.framesMin = 100;      this.framesMax = 0;        this.time = new Date().getTime();      this.timePrev = new Date().getTime();        this.container = document.createElement("div");      this.container.style.position = 'absolute';      this.container.style.fontFamily = 'Arial';      this.container.style.fontSize = '10px';      this.container.style.backgroundColor = '#000020';      this.container.style.opacity = '0.9';      this.container.style.width = '80px';      this.container.style.paddingTop = '2px';        this.framesText = document.createElement("div");      this.framesText.style.color = '#00ffff';      this.framesText.style.marginLeft = '3px';      this.framesText.style.marginBottom = '3px';      this.framesText.innerHTML = '<strong>FPS</strong>';      this.container.appendChild(this.framesText);        this.canvas = document.createElement("canvas");      this.canvas.width = 74;      this.canvas.height = 30;      this.canvas.style.display = 'block';      this.canvas.style.marginLeft = '3px';      this.canvas.style.marginBottom = '3px';      this.container.appendChild(this.canvas);        this.context = this.canvas.getContext("2d");      this.context.fillStyle = '#101030';      this.context.fillRect(0, 0, this.canvas.width, this.canvas.height );        this.contextImageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);        setInterval( bargs( function( _this ) { _this.update(); return false; }, this ), 1000 );    },      getDisplayElement: function()    {      return this.container;    },      tick: function()    {      this.frames++;    },      update: function()    {      this.time = new Date().getTime();        this.fps = Math.round((this.frames * 1000 ) / (this.time - this.timePrev)); //.toPrecision(2);        this.framesMin = Math.min(this.framesMin, this.fps);      this.framesMax = Math.max(this.framesMax, this.fps);        this.framesText.innerHTML = '<strong>' + this.fps + ' FPS</strong> (' + this.framesMin + '-' + this.framesMax + ')';        this.contextImageData = this.context.getImageData(1, 0, this.canvas.width - 1, 30);      this.context.putImageData(this.contextImageData, 0, 0);        this.context.fillStyle = '#101030';      this.context.fillRect(this.canvas.width - 1, 0, 1, 30);        this.index = ( Math.floor(30 - Math.min(30, (this.fps / 60) * 30)) );        this.context.fillStyle = '#80ffff';      this.context.fillRect(this.canvas.width - 1, this.index, 1, 1);        this.context.fillStyle = '#00ffff';      this.context.fillRect(this.canvas.width - 1, this.index + 1, 1, 30 - this.index);        this.timePrev = this.time;      this.frames = 0;    }  }    // Hack by Spite    function bargs( _fn )  {    var args = [];    for( var n = 1; n < arguments.length; n++ )      args.push( arguments[ n ] );    return function () { return _fn.apply( this, args ); };  }      (function (window){      var Sakri = window.Sakri || {};    window.Sakri = window.Sakri || Sakri;      Sakri.MathUtil = {};      //return number between 1 and 0    Sakri.MathUtil.normalize = function(value, minimum, maximum){      return (value - minimum) / (maximum - minimum);    };      //map normalized number to values    Sakri.MathUtil.interpolate = function(normValue, minimum, maximum){      return minimum + (maximum - minimum) * normValue;    };      //map a value from one set to another    Sakri.MathUtil.map = function(value, min1, max1, min2, max2){      return Sakri.MathUtil.interpolate( Sakri.MathUtil.normalize(value, min1, max1), min2, max2);    };        Sakri.MathUtil.hexToRgb = function(hex) {      // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")      var shorthandRegex = /^#?([a-fd])([a-fd])([a-fd])$/i;      hex = hex.replace(shorthandRegex, function(m, r, g, b) {        return r + r + g + g + b + b;      });        var result = /^#?([a-fd]{2})([a-fd]{2})([a-fd]{2})$/i.exec(hex);      return result ? {        r: parseInt(result[1], 16),        g: parseInt(result[2], 16),        b: parseInt(result[3], 16)      } : null;    }      Sakri.MathUtil.getRandomNumberInRange = function(min, max){      return min + Math.random() * (max - min);    };      Sakri.MathUtil.getRandomIntegerInRange = function(min, max){      return Math.round(Sakri.MathUtil.getRandomNumberInRange(min, max));    };      }(window));      //has a dependency on Sakri.MathUtil    (function (window){      var Sakri = window.Sakri || {};    window.Sakri = window.Sakri || Sakri;      Sakri.Geom = {};      //==================================================    //=====================::POINT::====================    //==================================================      Sakri.Geom.Point = function (x,y){      this.x = isNaN(x) ? 0 : x;      this.y = isNaN(y) ? 0 : y;    };      Sakri.Geom.Point.prototype.clone = function(){      return new Sakri.Geom.Point(this.x,this.y);    };      Sakri.Geom.Point.prototype.update = function(x, y){      this.x = isNaN(x) ? this.x : x;      this.y = isNaN(y) ? this.y : y;    };        //==================================================    //===================::RECTANGLE::==================    //==================================================      Sakri.Geom.Rectangle = function (x, y, width, height){      this.update(x, y, width, height);    };      Sakri.Geom.Rectangle.prototype.update = function(x, y, width, height){      this.x = isNaN(x) ? 0 : x;      this.y = isNaN(y) ? 0 : y;      this.width = isNaN(width) ? 0 : width;      this.height = isNaN(height) ? 0 : height;    };      Sakri.Geom.Rectangle.prototype.getRight = function(){      return this.x + this.width;    };      Sakri.Geom.Rectangle.prototype.getBottom = function(){      return this.y + this.height;    };      Sakri.Geom.Rectangle.prototype.getCenter = function(){      return new Sakri.Geom.Point(this.getCenterX(), this.getCenterY());    };      Sakri.Geom.Rectangle.prototype.getCenterX = function(){      return this.x + this.width/2;    };      Sakri.Geom.Rectangle.prototype.getCenterY=function(){      return this.y + this.height/2;    };      Sakri.Geom.Rectangle.prototype.containsPoint = function(x, y){      return x >= this.x && y >= this.y && x <= this.getRight() && y <= this.getBottom();    };        Sakri.Geom.Rectangle.prototype.clone = function(){      return new Sakri.Geom.Rectangle(this.x, this.y, this.width, this.height);    };      Sakri.Geom.Rectangle.prototype.toString = function(){      return "Rectangle{x:"+this.x+" , y:"+this.y+" , width:"+this.width+" , height:"+this.height+"}";    };      }(window));        /**       * Created by sakri on 27-1-14.       * has a dependecy on Sakri.Geom       * has a dependecy on Sakri.BitmapUtil       */    (function (window){      var Sakri = window.Sakri || {};    window.Sakri = window.Sakri || Sakri;      Sakri.CanvasTextUtil = {};      //returns the biggest font size that best fits into given width    Sakri.CanvasTextUtil.getFontSizeForWidth = function(string, fontProps, width, canvas, fillStyle, maxFontSize){      if(!canvas){        var canvas = document.createElement("canvas");      }      if(!fillStyle){        fillStyle = "#000000";      }      if(isNaN(maxFontSize)){        maxFontSize = 500;      }      var context = canvas.getContext('2d');      context.font = fontProps.getFontString();      context.textBaseline = "top";        var copy = fontProps.clone();      //console.log("getFontSizeForWidth() 1  : ", copy.fontSize);      context.font = copy.getFontString();      var textWidth = context.measureText(string).width;        //SOME DISAGREEMENT WHETHER THIS SHOOULD BE WITH && or ||      if(textWidth < width){        while(context.measureText(string).width < width){          copy.fontSize++;          context.font = copy.getFontString();          if(copy.fontSize > maxFontSize){            console.log("getFontSizeForWidth() max fontsize reached");            return null;          }        }      }else if(textWidth > width){        while(context.measureText(string).width > width){          copy.fontSize--;          context.font = copy.getFontString();          if(copy.fontSize < 0){            console.log("getFontSizeForWidth() min fontsize reached");            return null;          }        }      }      //console.log("getFontSizeForWidth() 2  : ", copy.fontSize);      return copy.fontSize;    };        //=========================================================================================    //==============::CANVAS TEXT PROPERTIES::====================================    //========================================================      Sakri.CanvasTextProperties = function(fontWeight, fontStyle, fontSize, fontFace){      this.setFontWeight(fontWeight);      this.setFontStyle(fontStyle);      this.setFontSize(fontSize);      this.fontFace = fontFace ? fontFace : "sans-serif";    };      Sakri.CanvasTextProperties.NORMAL = "normal";    Sakri.CanvasTextProperties.BOLD = "bold";    Sakri.CanvasTextProperties.BOLDER = "bolder";    Sakri.CanvasTextProperties.LIGHTER = "lighter";      Sakri.CanvasTextProperties.ITALIC = "italic";    Sakri.CanvasTextProperties.OBLIQUE = "oblique";        Sakri.CanvasTextProperties.prototype.setFontWeight = function(fontWeight){      switch (fontWeight){        case Sakri.CanvasTextProperties.NORMAL:        case Sakri.CanvasTextProperties.BOLD:        case Sakri.CanvasTextProperties.BOLDER:        case Sakri.CanvasTextProperties.LIGHTER:          this.fontWeight = fontWeight;          break;        default:          this.fontWeight = Sakri.CanvasTextProperties.NORMAL;      }    };      Sakri.CanvasTextProperties.prototype.setFontStyle = function(fontStyle){      switch (fontStyle){        case Sakri.CanvasTextProperties.NORMAL:        case Sakri.CanvasTextProperties.ITALIC:        case Sakri.CanvasTextProperties.OBLIQUE:          this.fontStyle = fontStyle;          break;        default:          this.fontStyle = Sakri.CanvasTextProperties.NORMAL;      }    };      Sakri.CanvasTextProperties.prototype.setFontSize = function(fontSize){      if(fontSize && fontSize.indexOf && fontSize.indexOf("px")>-1){        var size = fontSize.split("px")[0];        fontProperites.fontSize = isNaN(size) ? 24 : size;//24 is just an arbitrary number        return;      }      this.fontSize = isNaN(fontSize) ? 24 : fontSize;//24 is just an arbitrary number    };      Sakri.CanvasTextProperties.prototype.clone = function(){      return new Sakri.CanvasTextProperties(this.fontWeight, this.fontStyle, this.fontSize, this.fontFace);    };      Sakri.CanvasTextProperties.prototype.getFontString = function(){      return this.fontWeight + " " + this.fontStyle + " " + this.fontSize + "px " + this.fontFace;    };    }(window));      window.requestAnimationFrame =          window.__requestAnimationFrame ||                  window.requestAnimationFrame ||                  window.webkitRequestAnimationFrame ||                  window.mozRequestAnimationFrame ||                  window.oRequestAnimationFrame ||                  window.msRequestAnimationFrame ||                  (function () {                      return function (callback, element) {                          var lastTime = element.__lastTime;                          if (lastTime === undefined) {                              lastTime = 0;                          }                          var currTime = Date.now();                          var timeToCall = Math.max(1, 33 - (currTime - lastTime));                          window.setTimeout(callback, timeToCall);                          element.__lastTime = currTime + timeToCall;                      };                  })();    var readyStateCheckInterval = setInterval( function() {      if (document.readyState === "complete") {          clearInterval(readyStateCheckInterval);          init();      }  }, 10);    //========================  //general properties for demo set up  //========================    var canvas;  var context;  var canvasContainer;  var htmlBounds;  var bounds;  var minimumStageWidth = 250;  var minimumStageHeight = 250;  var maxStageWidth = 1000;  var maxStageHeight = 600;  var resizeTimeoutId = -1;  var stats;    function init(){      canvasContainer = document.getElementById("canvasContainer");      window.onresize = resizeHandler;      stats = new Stats();      canvasContainer.appendChild( stats.getDisplayElement() );      commitResize();  }    function getWidth( element ){return Math.max(element.scrollWidth,element.offsetWidth,element.clientWidth );}  function getHeight( element ){return Math.max(element.scrollHeight,element.offsetHeight,element.clientHeight );}    //avoid running resize scripts repeatedly if a browser window is being resized by dragging  function resizeHandler(){      context.clearRect(0,0,canvas.width, canvas.height);      clearTimeout(resizeTimeoutId);      clearTimeoutsAndIntervals();      resizeTimeoutId = setTimeout(commitResize, 300 );  }    function commitResize(){      if(canvas){          canvasContainer.removeChild(canvas);      }      canvas = document.createElement('canvas');      canvas.style.position = "absolute";      context = canvas.getContext("2d");      canvasContainer.appendChild(canvas);        htmlBounds = new Sakri.Geom.Rectangle(0,0, getWidth(canvasContainer) , getHeight(canvasContainer));      if(htmlBounds.width >= maxStageWidth){          canvas.width = maxStageWidth;          canvas.style.left = htmlBounds.getCenterX() - (maxStageWidth/2)+"px";      }else{          canvas.width = htmlBounds.width;          canvas.style.left ="0px";      }      if(htmlBounds.height > maxStageHeight){          canvas.height = maxStageHeight;          canvas.style.top = htmlBounds.getCenterY() - (maxStageHeight/2)+"px";      }else{          canvas.height = htmlBounds.height;          canvas.style.top ="0px";      }      bounds = new Sakri.Geom.Rectangle(0,0, canvas.width, canvas.height);      context.clearRect(0,0,canvas.width, canvas.height);        if(bounds.width<minimumStageWidth || bounds.height<minimumStageHeight){          stageTooSmallHandler();          return;      }        var textInputSpan = document.getElementById("textInputSpan");      textInputSpan.style.top = htmlBounds.getCenterY() + (bounds.height/2) + 20 +"px";      textInputSpan.style.left = (htmlBounds.getCenterX() - getWidth(textInputSpan)/2)+"px";        startDemo();  }    function stageTooSmallHandler(){      var warning = "Sorry, bigger screen required :(";      context.font = "bold normal 24px sans-serif";      context.fillText(warning, bounds.getCenterX() - context.measureText(warning).width/2, bounds.getCenterY()-12);  }          //========================  //Demo specific properties  //========================    var animating = false;  var particles = [];  var numParticles = 4000;  var currentText = "SAKRI";  var fontRect;  var fontProperties = new Sakri.CanvasTextProperties(Sakri.CanvasTextProperties.BOLD, null, 100);  var animator;  var particleSource = new Sakri.Geom.Point();;  var particleSourceStart = new Sakri.Geom.Point();  var particleSourceTarget = new Sakri.Geom.Point();    var redParticles = ["#fe7a51" , "#fdd039" , "#fd3141"];  var greenParticles = ["#dbffa6" , "#fcf8fd" , "#99de5e"];  var pinkParticles = ["#fef4f7" , "#f2a0c0" , "#fb3c78"];  var yellowParticles = ["#fdfbd5" , "#fff124" , "#f4990e"];  var blueParticles = ["#9ca2df" , "#222a6d" , "#333b8d"];    var particleColorSets = [redParticles, greenParticles, pinkParticles, yellowParticles, blueParticles];  var particleColorIndex = 0;    var renderParticleFunction;  var renderBounds;  var particleCountOptions = [2000, 4000, 6000, 8000, 10000, 15000, 20000 ];  var pixelParticleCountOptions = [10000, 40000, 60000, 80000, 100000, 150000 ];    function clearTimeoutsAndIntervals(){      animating = false;  }    function startDemo(){        fontRect = new Sakri.Geom.Rectangle(Math.floor(bounds.x + bounds.width*.2), 0, Math.floor(bounds.width - bounds.width*.4), bounds.height);      fontProperties.fontSize = 100;      fontProperties.fontSize = Sakri.CanvasTextUtil.getFontSizeForWidth(currentText, fontProperties, fontRect.width, canvas);      fontRect.y = Math.floor(bounds.getCenterY() - fontProperties.fontSize/2);      fontRect.height = fontProperties.fontSize;      renderBounds = fontRect.clone();      renderBounds.x -= Math.floor(canvas.width *.1);      renderBounds.width += Math.floor(canvas.width *.2);      renderBounds.y -= Math.floor(fontProperties.fontSize *.5);      renderBounds.height += Math.floor(fontProperties.fontSize *.6);      context.font = fontProperties.getFontString();        createParticles();      context.globalAlpha = globalAlpha;      animating = true;      loop();  }      function loop(){      if(!animating){          return;      }      stats.tick();      renderParticles();      window.requestAnimationFrame(loop, canvas);  }      function createParticles(){      context.clearRect(0,0,canvas.width, canvas.height);      context.fillText(currentText, fontRect.x, fontRect.y);      var imageData = context.getImageData(fontRect.x, fontRect.y, fontRect.width, fontRect.height);      var data = imageData.data;      var length = data.length;      var rowWidth = fontRect.width*4;      var i, y, x;        particles = [];      for(i=0; i<length; i+=4){          if(data[i+3]>0){              y = Math.floor(i / rowWidth);              x = fontRect.x + (i - y * rowWidth) / 4;              particles.push(x);//x              particles.push(fontRect.y + y);//y              particles.push(x);//xOrigin              particles.push(fontRect.y + y);//yOrigin          }      }        //console.log(particles.length);      context.clearRect(0,0,canvas.width, canvas.height);        //pre calculate random numbers used for particle movement      xDirections = [];      yDirections = [];      for(i=0; i<directionCount; i++){          xDirections[i] = -7 + Math.random() * 14;          yDirections[i] = Math.random()* - 5;      }  }      var xDirections, yDirections;  //fidget with these to manipulate effect  var globalAlpha = .11; //amount of trails or tracers  var xWind = 0; //all particles x is effected by this  var threshold = 60; //if a pixels red component is less than this, return particle to it's original position  var amountRed = 25; //amount of red added to a pixel occupied by a particle  var amountGreen = 12; //amount of green added to a pixel occupied by a particle  var amountBlue = 1; //amount of blue added to a pixel occupied by a particle  var directionCount = 100; //number of random pre-calculated x and y directions    function renderParticles(){      //fill renderBounds area with a transparent black, and render a nearly black text      context.fillStyle = "#000000";      context.fillRect(renderBounds.x, renderBounds.y, renderBounds.width, renderBounds.height);      context.fillStyle = "#010000";      context.fillText(currentText, fontRect.x, fontRect.y);        var randomRed = amountRed -5 + Math.random()*10;      var randomGreen = amountGreen -2 + Math.random()*4;        var imageData = context.getImageData(renderBounds.x, renderBounds.y, renderBounds.width, renderBounds.height);      var data = imageData.data;      var rowWidth = imageData.width * 4;      var index, i, length = particles.length;      var d = Math.floor(Math.random()*30);      xWind += (-.5 + Math.random());//move randomly left or right      xWind = Math.min(xWind, 1.5);//clamp to a maximum wind      xWind = Math.max(xWind, -1.5);//clamp to a minimum wind      for(i=0; i<length; i+=4, d++ ){            particles[i] += (xDirections[d % directionCount] + xWind);          particles[i+1] += yDirections[d % directionCount];            index = Math.round(particles[i] - renderBounds.x) * 4 + Math.round(particles[i+1] - renderBounds.y) * rowWidth;            data[index] += randomRed;          data[index + 1] += randomGreen;          data[index + 2] += amountBlue;            //if pixels red component is below set threshold, return particle to orgin          if( data[index] < threshold){              particles[i] = particles[i+2];              particles[i+1] = particles[i+3];          }      }      context.putImageData(imageData, renderBounds.x, renderBounds.y);  }        var maxCharacters = 10;    function changeText(){      var textInput = document.getElementById("textInput");      if(textInput.value && textInput.text!=""){          if(textInput.value.length > maxCharacters){              alert("Sorry, there is only room for "+maxCharacters+" characters. Try a shorter name.");              return;          }          if(textInput.value.indexOf(" ")>-1){              alert("Sorry, no support for spaces right now :(");              return;          }          currentText = textInput.value;          clearTimeoutsAndIntervals();          animating = false;          setTimeout(commitResize, 100);      }  }    function changeSettings(){      clearTimeoutsAndIntervals();      animating = false;      setTimeout(commitResize, 100);  }    function setParticleNumberOptions(values){      var selector = document.getElementById("particlesSelect");      if(selector.options.length>0 && parseInt(selector.options[0].value) == values[0] ){          return;      }      while(selector.options.length){          selector.remove(selector.options.length-1);      }      for(var i=0;i <values.length; i++){          selector.options[i] = new Option(values[i], values[i], i==0, i==0);      }  }

View Code

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

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

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


发表评论

电子邮件地址不会被公开。 必填项已用*标注