奥门新浦京官方网站基于HTML5 Canvas的线性区域图表教程

本文由码农网 –
小峰原创,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

之前我们看到过很多用jQuery实现的网页图表,有些还是比较实用的。今天我们来介绍一款基于HTML5
Canvas的线性区域图表应用,这个图表应用允许你使用多组数据来同时展示,并且将数据结果以线性图的形式展现,各个数据之间形成的区域用不同的颜色表示,具体可以看下面的DEMO演示。

这是一个很酷的HTML5
Canvas动画,它将模拟的是我们现实生活中烟花绽放的动画特效,效果非常逼真,但是毕竟是电脑模拟,带女朋友看就算了,效果还是差了点,呵呵。这个HTML5
Canvas动画有一点比较出色,就是其性能,Chrome上基本没有卡的感觉,就算你放出很多烟花也一样。

在今天的HTML教程里,我们要学习一下如何使用HTML5
Canvas实现一个超酷而又简单的网络画板功能。在这个教程中,我们可以选择笔刷的类型、笔刷的大小以及笔刷的颜色,当然作为画板还需要很多功能,这里只是最基本的绘制功能,大家可以自己实现类似矩形、椭圆等复杂元素的绘制。

奥门新浦京官方网站 1

奥门新浦京官方网站 2

奥门新浦京官方网站 3

你也可以在这里查看在线演示

你可以在这里看在线演示

你也可以再这里查看DEMO演示

下面我们来简单介绍一下实现这款HTML5图表的过程以及源代码。

下面我们来简单分析一下实现这款HTML5烟花特效的过程及代码,主要由HTML代码、CSS代码以及Javascript代码组成,当然javascript代码是最重要的。

下面我们来简单地分析一下实现这个HTML5网页画板的原理及代码,代码由HTML以及Javascript组成,主要还是Javascript代码。

HTML代码:

<canvas id="cvs" width="600" height="250">[No canvas support]</canvas>

简单的一个canvas标签,我们的图表就是在canvas上绘制而成的。

由于这款图表是基于RGraph的,所以我们还要引用RGraph的相关js脚本以及jquery类库:

<script src="../libraries/RGraph.common.core.js" ></script>  <script src="../libraries/RGraph.common.effects.js" ></script>  <script src="../libraries/RGraph.common.dynamic.js" ></script>  <script src="../libraries/RGraph.common.tooltips.js" ></script>  <script src="../libraries/RGraph.drawing.poly.js" ></script>  <script src="../libraries/RGraph.line.js" ></script>  <script src="../libraries/jquery.min.js" ></script>

HTML代码:

<div id=”gui”></div>
<div id=”canvas-container”>
<div id=”mountains2″></div>
<div id=”mountains1″></div>
<div id=”skyline”></div>
</div>

HTML的结构非常简单,即构造了一个canvas容器,我们会利用JS在这个容器中生成一个Canvas对象。看最后的JS代码你就会知道了。

HTML代码:

<div style="width:530px;margin:10px auto">
    <div id="canvasDiv"></div>
</div>

HTML代码非常简单,仅仅是构造了一个canvas容器,我们的画板就在这个地方生成。

最后是Javascript代码:

var d1  = [];              var d2  = [];              var val = 47;                            // Create the data              for (var i=0; i<100; i+=1) d1[i] = RGraph.random(45,55);              for (var i=0; i<100; i+=1) d2[i] = RGraph.random(25,35);                          var line = new RGraph.Line('cvs', d1, d2)                  .Set('background.grid.autofit.numhlines', 10)                  .Set('hmargin', 10)                  .Set('filled', true)                  .Set('fillstyle', 'red')                  .Set('filled.range', true)                  .Set('filled.range.threshold',40)                  .Set('filled.range.threshold.colors', ['rgba(255,0,0,0.5)', 'rgba(0,0,255,0.5)'])                  .Set('labels',['Q1','Q2','Q3','Q4'])                  .Set('colors', ['gray', 'gray'])                  .Set('numxticks', 8)                  .Set('linewidth', 1)                  .Set('ymax', 60)              RGraph.Effects.Line.jQuery.Trace(line);                            var coords = []              for (var i=0; i<(line.coords.length/2); i+=1) {                  coords.push(line.coords[i])              }              for (var i=(line.coords.length - 1); i>=(line.coords.length/2); i-=1) {                  coords.push(line.coords[i])              }                var poly = new RGraph.Drawing.Poly('cvs', coords)                  .Set('fillstyle', 'rgba(0,0,0,0)')                  .Set('strokestyle', 'rgba(0,0,0,0)')                  .Set('tooltips', ['The range chart'])                  .Set('highlight.fill', 'rgba(255,255,255,0.3)')                  .Draw();

主要是初始化一些数据,RGraph是一款很不错的HTML5图表框架,更多的RGraph例子我们今后会继续讲解。源代码下载>>


CSS代码:

#canvas-container {
    background: #000 url(bg.jpg);
  height: 400px;
    left: 50%;
    margin: -200px 0 0 -300px;
    position: absolute;
    top: 50%;
  width: 600px;
    z-index: 2;
}

canvas {
    cursor: crosshair;
    display: block;
    position: relative;
    z-index: 3;
}

canvas:active {
    cursor: crosshair;
}

#skyline {
    background: url(skyline.png) repeat-x 50% 0;
    bottom: 0;
    height: 135px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1;    
}

#mountains1 {
    background: url(mountains1.png) repeat-x 40% 0;
    bottom: 0;
    height: 200px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1;    
}

#mountains2 {
    background: url(mountains2.png) repeat-x 30% 0;
    bottom: 0;
    height: 250px;
    left: 0;
    position: absolute;
    width: 100%;
    z-index: 1;    
}

#gui {
    right: 0;
    position: fixed;
    top: 0;
    z-index: 3;
}

CSS代码没什么特别,主要也就定义一下背景色和边框之类的。

接下来是最重要的Javascript代码。

Javascript代码:

首先我们通过一组变量来定义画板的样式,以及一些数据的初始化:

var canvas;
var context;
var canvasWidth = 490;
var canvasHeight = 220;
var padding = 25;
var lineWidth = 8;
var colorPurple = "#cb3594";
var colorGreen = "#659b41";
var colorYellow = "#ffcf33";
var colorBrown = "#986928";
var outlineImage = new Image();
var crayonImage = new Image();
var markerImage = new Image();
var eraserImage = new Image();
var crayonBackgroundImage = new Image();
var markerBackgroundImage = new Image();
var eraserBackgroundImage = new Image();
var crayonTextureImage = new Image();
var clickX = new Array();
var clickY = new Array();
var clickColor = new Array();
var clickTool = new Array();
var clickSize = new Array();
var clickDrag = new Array();
var paint = false;
var curColor = colorPurple;
var curTool = "crayon";
var curSize = "normal";
var mediumStartX = 18;
var mediumStartY = 19;
var mediumImageWidth = 93;
var mediumImageHeight = 46;
var drawingAreaX = 111;
var drawingAreaY = 11;
var drawingAreaWidth = 267;
var drawingAreaHeight = 200;
var toolHotspotStartY = 23;
var toolHotspotHeight = 38;
var sizeHotspotStartY = 157;
var sizeHotspotHeight = 36;
var sizeHotspotWidthObject = new Object();
sizeHotspotWidthObject.huge = 39;
sizeHotspotWidthObject.large = 25;
sizeHotspotWidthObject.normal = 18;
sizeHotspotWidthObject.small = 16;
var totalLoadResources = 8;
var curLoadResNum = 0;

接下来开始准备画布,也就是初始化Canvas对象:

function prepareCanvas()
{
    // Create the canvas (Neccessary for IE because it doesn't know what a canvas element is)
    var canvasDiv = document.getElementById('canvasDiv');
    canvas = document.createElement('canvas');
    canvas.setAttribute('width', canvasWidth);
    canvas.setAttribute('height', canvasHeight);
    canvas.setAttribute('id', 'canvas');
    canvasDiv.appendChild(canvas);
    if(typeof G_vmlCanvasManager != 'undefined') {
        canvas = G_vmlCanvasManager.initElement(canvas);
    }
    context = canvas.getContext("2d"); // Grab the 2d canvas context
    // Note: The above code is a workaround for IE 8 and lower. Otherwise we could have used:
    //     context = document.getElementById('canvas').getContext("2d");

    // Load images
    // -----------
    crayonImage.onload = function() { resourceLoaded(); 
    };
    crayonImage.src = "images/crayon-outline.png";
    //context.drawImage(crayonImage, 0, 0, 100, 100);

    markerImage.onload = function() { resourceLoaded(); 
    };
    markerImage.src = "images/marker-outline.png";

    eraserImage.onload = function() { resourceLoaded(); 
    };
    eraserImage.src = "images/eraser-outline.png";    

    crayonBackgroundImage.onload = function() { resourceLoaded(); 
    };
    crayonBackgroundImage.src = "images/crayon-background.png";

    markerBackgroundImage.onload = function() { resourceLoaded(); 
    };
    markerBackgroundImage.src = "images/marker-background.png";

    eraserBackgroundImage.onload = function() { resourceLoaded(); 
    };
    eraserBackgroundImage.src = "images/eraser-background.png";

    crayonTextureImage.onload = function() { resourceLoaded(); 
    };
    crayonTextureImage.src = "images/crayon-texture.png";

    outlineImage.onload = function() { resourceLoaded(); 
    };
    outlineImage.src = "images/watermelon-duck-outline.png";

    // Add mouse events
    // ----------------
    $('#canvas').mousedown(function(e)
    {
        // Mouse down location
        var mouseX = e.pageX - this.offsetLeft;
        var mouseY = e.pageY - this.offsetTop;

        if(mouseX < drawingAreaX) // Left of the drawing area
        {
            if(mouseX > mediumStartX)
            {
                if(mouseY > mediumStartY && mouseY < mediumStartY + mediumImageHeight){
                    curColor = colorPurple;
                }else if(mouseY > mediumStartY + mediumImageHeight && mouseY < mediumStartY + mediumImageHeight * 2){
                    curColor = colorGreen;
                }else if(mouseY > mediumStartY + mediumImageHeight * 2 && mouseY < mediumStartY + mediumImageHeight * 3){
                    curColor = colorYellow;
                }else if(mouseY > mediumStartY + mediumImageHeight * 3 && mouseY < mediumStartY + mediumImageHeight * 4){
                    curColor = colorBrown;
                }
            }
        }
        else if(mouseX > drawingAreaX + drawingAreaWidth) // Right of the drawing area
        {
            if(mouseY > toolHotspotStartY)
            {
                if(mouseY > sizeHotspotStartY)
                {
                    var sizeHotspotStartX = drawingAreaX + drawingAreaWidth;
                    if(mouseY < sizeHotspotStartY + sizeHotspotHeight && mouseX > sizeHotspotStartX)
                    {
                        if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.huge){
                            curSize = "huge";
                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
                            curSize = "large";
                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
                            curSize = "normal";
                        }else if(mouseX < sizeHotspotStartX + sizeHotspotWidthObject.small + sizeHotspotWidthObject.normal + sizeHotspotWidthObject.large + sizeHotspotWidthObject.huge){
                            curSize = "small";                        
                        }
                    }
                }
                else
                {
                    if(mouseY < toolHotspotStartY + toolHotspotHeight){
                        curTool = "crayon";
                    }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 2){
                        curTool = "marker";
                    }else if(mouseY < toolHotspotStartY + toolHotspotHeight * 3){
                        curTool = "eraser";
                    }
                }
            }
        }
        else if(mouseY > drawingAreaY && mouseY < drawingAreaY + drawingAreaHeight)
        {
            // Mouse click location on drawing area
        }
        paint = true;
        addClick(mouseX, mouseY, false);
        redraw();
    });

    $('#canvas').mousemove(function(e){
        if(paint==true){
            addClick(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true);
            redraw();
        }
    });

    $('#canvas').mouseup(function(e){
        paint = false;
          redraw();
    });

    $('#canvas').mouseleave(function(e){
        paint = false;
    });
}

看起来很复杂,前面主要是初始化canvas的背景图片,后面主要是初始化画笔事件,像click、mouseup、mouseleave等鼠标事件。

下面是draw的主要方法:

function redraw()
{
    // Make sure required resources are loaded before redrawing
    if(curLoadResNum < totalLoadResources){ return; }

    clearCanvas();

    var locX;
    var locY;
    if(curTool == "crayon")
    {
        // Draw the crayon tool background
        context.drawImage(crayonBackgroundImage, 0, 0, canvasWidth, canvasHeight);

        // Purple
        locX = (curColor == colorPurple) ? 18 : 52;
        locY = 19;

        context.beginPath();
        context.moveTo(locX + 41, locY + 11);
        context.lineTo(locX + 41, locY + 35);
        context.lineTo(locX + 29, locY + 35);
        context.lineTo(locX + 29, locY + 33);
        context.lineTo(locX + 11, locY + 27);
        context.lineTo(locX + 11, locY + 19);
        context.lineTo(locX + 29, locY + 13);
        context.lineTo(locX + 29, locY + 11);
        context.lineTo(locX + 41, locY + 11);
        context.closePath();
        context.fillStyle = colorPurple;
        context.fill();    

        if(curColor == colorPurple){
            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Green
        locX = (curColor == colorGreen) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 41, locY + 11);
        context.lineTo(locX + 41, locY + 35);
        context.lineTo(locX + 29, locY + 35);
        context.lineTo(locX + 29, locY + 33);
        context.lineTo(locX + 11, locY + 27);
        context.lineTo(locX + 11, locY + 19);
        context.lineTo(locX + 29, locY + 13);
        context.lineTo(locX + 29, locY + 11);
        context.lineTo(locX + 41, locY + 11);
        context.closePath();
        context.fillStyle = colorGreen;
        context.fill();    

        if(curColor == colorGreen){
            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Yellow
        locX = (curColor == colorYellow) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 41, locY + 11);
        context.lineTo(locX + 41, locY + 35);
        context.lineTo(locX + 29, locY + 35);
        context.lineTo(locX + 29, locY + 33);
        context.lineTo(locX + 11, locY + 27);
        context.lineTo(locX + 11, locY + 19);
        context.lineTo(locX + 29, locY + 13);
        context.lineTo(locX + 29, locY + 11);
        context.lineTo(locX + 41, locY + 11);
        context.closePath();
        context.fillStyle = colorYellow;
        context.fill();    

        if(curColor == colorYellow){
            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Yellow
        locX = (curColor == colorBrown) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 41, locY + 11);
        context.lineTo(locX + 41, locY + 35);
        context.lineTo(locX + 29, locY + 35);
        context.lineTo(locX + 29, locY + 33);
        context.lineTo(locX + 11, locY + 27);
        context.lineTo(locX + 11, locY + 19);
        context.lineTo(locX + 29, locY + 13);
        context.lineTo(locX + 29, locY + 11);
        context.lineTo(locX + 41, locY + 11);
        context.closePath();
        context.fillStyle = colorBrown;
        context.fill();    

        if(curColor == colorBrown){
            context.drawImage(crayonImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(crayonImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }
    }
    else if(curTool == "marker")
    {
        // Draw the marker tool background
        context.drawImage(markerBackgroundImage, 0, 0, canvasWidth, canvasHeight);

        // Purple
        locX = (curColor == colorPurple) ? 18 : 52;
        locY = 19;

        context.beginPath();
        context.moveTo(locX + 10, locY + 24);
        context.lineTo(locX + 10, locY + 24);
        context.lineTo(locX + 22, locY + 16);
        context.lineTo(locX + 22, locY + 31);
        context.closePath();
        context.fillStyle = colorPurple;
        context.fill();    

        if(curColor == colorPurple){
            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Green
        locX = (curColor == colorGreen) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 10, locY + 24);
        context.lineTo(locX + 10, locY + 24);
        context.lineTo(locX + 22, locY + 16);
        context.lineTo(locX + 22, locY + 31);
        context.closePath();
        context.fillStyle = colorGreen;
        context.fill();    

        if(curColor == colorGreen){
            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Yellow
        locX = (curColor == colorYellow) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 10, locY + 24);
        context.lineTo(locX + 10, locY + 24);
        context.lineTo(locX + 22, locY + 16);
        context.lineTo(locX + 22, locY + 31);
        context.closePath();
        context.fillStyle = colorYellow;
        context.fill();    

        if(curColor == colorYellow){
            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }

        // Yellow
        locX = (curColor == colorBrown) ? 18 : 52;
        locY += 46;

        context.beginPath();
        context.moveTo(locX + 10, locY + 24);
        context.lineTo(locX + 10, locY + 24);
        context.lineTo(locX + 22, locY + 16);
        context.lineTo(locX + 22, locY + 31);
        context.closePath();
        context.fillStyle = colorBrown;
        context.fill();    

        if(curColor == colorBrown){
            context.drawImage(markerImage, locX, locY, mediumImageWidth, mediumImageHeight);
        }else{
            context.drawImage(markerImage, 0, 0, 59, mediumImageHeight, locX, locY, 59, mediumImageHeight);
        }
    }
    else if(curTool == "eraser")
    {
        context.drawImage(eraserBackgroundImage, 0, 0, canvasWidth, canvasHeight);
        context.drawImage(eraserImage, 18, 19, mediumImageWidth, mediumImageHeight);    
    }else{
        alert("Error: Current Tool is undefined");
    }

    if(curSize == "small"){
        locX = 467;
    }else if(curSize == "normal"){
        locX = 450;
    }else if(curSize == "large"){
        locX = 428;
    }else if(curSize == "huge"){
        locX = 399;
    }
    locY = 189;
    context.beginPath();
    context.rect(locX, locY, 2, 12);
    context.closePath();
    context.fillStyle = '#333333';
    context.fill();    

    // Keep the drawing in the drawing area
    context.save();
    context.beginPath();
    context.rect(drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
    context.clip();

    var radius;
    var i = 0;
    for(; i < clickX.length; i++)
    {        
        if(clickSize[i] == "small"){
            radius = 2;
        }else if(clickSize[i] == "normal"){
            radius = 5;
        }else if(clickSize[i] == "large"){
            radius = 10;
        }else if(clickSize[i] == "huge"){
            radius = 20;
        }else{
            alert("Error: Radius is zero for click " + i);
            radius = 0;    
        }

        context.beginPath();
        if(clickDrag[i] && i){
            context.moveTo(clickX[i-1], clickY[i-1]);
        }else{
            context.moveTo(clickX[i], clickY[i]);
        }
        context.lineTo(clickX[i], clickY[i]);
        context.closePath();

        if(clickTool[i] == "eraser"){
            //context.globalCompositeOperation = "destination-out"; // To erase instead of draw over with white
            context.strokeStyle = 'white';
        }else{
            //context.globalCompositeOperation = "source-over";    // To erase instead of draw over with white
            context.strokeStyle = clickColor[i];
        }
        context.lineJoin = "round";
        context.lineWidth = radius;
        context.stroke();

    }
    //context.globalCompositeOperation = "source-over";// To erase instead of draw over with white
    context.restore();

    // Overlay a crayon texture (if the current tool is crayon)
    if(curTool == "crayon"){
        context.globalAlpha = 0.4; // No IE support
        context.drawImage(crayonTextureImage, 0, 0, canvasWidth, canvasHeight);
    }
    context.globalAlpha = 1; // No IE support

    // Draw the outline image
    context.drawImage(outlineImage, drawingAreaX, drawingAreaY, drawingAreaWidth, drawingAreaHeight);
}

其实HTML5说白了还是需要很多Javascript支持,不过Canvas非常不错,可以让你在上面自由地绘制图形和动画。这款基于HTML5
Canvas的网页画板就是一个很好的例子。源代码下载>>

Javascript代码:

self.init = function(){    
    self.dt = 0;
        self.oldTime = Date.now();
        self.canvas = document.createElement('canvas');                
        self.canvasContainer = $('#canvas-container');

        var canvasContainerDisabled = document.getElementById('canvas-container');
        self.canvas.onselectstart = function() {
            return false;
        };

        self.canvas.width = self.cw = 600;
        self.canvas.height = self.ch = 400;    

        self.particles = [];    
        self.partCount = 30;
        self.fireworks = [];    
        self.mx = self.cw/2;
        self.my = self.ch/2;
        self.currentHue = 170;
        self.partSpeed = 5;
        self.partSpeedVariance = 10;
        self.partWind = 50;
        self.partFriction = 5;
        self.partGravity = 1;
        self.hueMin = 150;
        self.hueMax = 200;
        self.fworkSpeed = 2;
        self.fworkAccel = 4;
        self.hueVariance = 30;
        self.flickerDensity = 20;
        self.showShockwave = false;
        self.showTarget = true;
        self.clearAlpha = 25;

        self.canvasContainer.append(self.canvas);
        self.ctx = self.canvas.getContext('2d');
        self.ctx.lineCap = 'round';
        self.ctx.lineJoin = 'round';
        self.lineWidth = 1;
        self.bindEvents();            
        self.canvasLoop();

        self.canvas.onselectstart = function() {
            return false;
        };

    };

这段JS代码主要是往canvas容器中构造一个Canvas对象,并且对这个canvas对象的外观以及动画属性作了初始化。

var Particle = function(x, y, hue){
        this.x = x;
        this.y = y;
        this.coordLast = [
            {x: x, y: y},
            {x: x, y: y},
            {x: x, y: y}
        ];
        this.angle = rand(0, 360);
        this.speed = rand(((self.partSpeed - self.partSpeedVariance) <= 0) ? 1 : self.partSpeed - self.partSpeedVariance, (self.partSpeed + self.partSpeedVariance));
        this.friction = 1 - self.partFriction/100;
        this.gravity = self.partGravity/2;
        this.hue = rand(hue-self.hueVariance, hue+self.hueVariance);
        this.brightness = rand(50, 80);
        this.alpha = rand(40,100)/100;
        this.decay = rand(10, 50)/1000;
        this.wind = (rand(0, self.partWind) - (self.partWind/2))/25;
        this.lineWidth = self.lineWidth;
    };

    Particle.prototype.update = function(index){
        var radians = this.angle * Math.PI / 180;
        var vx = Math.cos(radians) * this.speed;
        var vy = Math.sin(radians) * this.speed + this.gravity;
        this.speed *= this.friction;

        this.coordLast[2].x = this.coordLast[1].x;
        this.coordLast[2].y = this.coordLast[1].y;
        this.coordLast[1].x = this.coordLast[0].x;
        this.coordLast[1].y = this.coordLast[0].y;
        this.coordLast[0].x = this.x;
        this.coordLast[0].y = this.y;

        this.x += vx * self.dt;
        this.y += vy * self.dt;

        this.angle += this.wind;                
        this.alpha -= this.decay;

        if(!hitTest(0,0,self.cw,self.ch,this.x-this.radius, this.y-this.radius, this.radius*2, this.radius*2) || this.alpha < .05){                    
            self.particles.splice(index, 1);    
        }            
    };

    Particle.prototype.draw = function(){
        var coordRand = (rand(1,3)-1);
        self.ctx.beginPath();                                
        self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
        self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
        self.ctx.closePath();                
        self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
        self.ctx.stroke();                

        if(self.flickerDensity > 0){
            var inverseDensity = 50 - self.flickerDensity;                    
            if(rand(0, inverseDensity) === inverseDensity){
                self.ctx.beginPath();
                self.ctx.arc(Math.round(this.x), Math.round(this.y), rand(this.lineWidth,this.lineWidth+3)/2, 0, Math.PI*2, false)
                self.ctx.closePath();
                var randAlpha = rand(50,100)/100;
                self.ctx.fillStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+randAlpha+')';
                self.ctx.fill();
            }    
        }
    };

这段JS代码的功能是实现烟花爆炸后的小颗粒的绘制,从draw方法中可以看出,创建几个随机点,烟花颗粒即可在这个范围的随机点中散落。

var Firework = function(startX, startY, targetX, targetY){
        this.x = startX;
        this.y = startY;
        this.startX = startX;
        this.startY = startY;
        this.hitX = false;
        this.hitY = false;
        this.coordLast = [
            {x: startX, y: startY},
            {x: startX, y: startY},
            {x: startX, y: startY}
        ];
        this.targetX = targetX;
        this.targetY = targetY;
        this.speed = self.fworkSpeed;
        this.angle = Math.atan2(targetY - startY, targetX - startX);
        this.shockwaveAngle = Math.atan2(targetY - startY, targetX - startX)+(90*(Math.PI/180));
        this.acceleration = self.fworkAccel/100;
        this.hue = self.currentHue;
        this.brightness = rand(50, 80);
        this.alpha = rand(50,100)/100;
        this.lineWidth = self.lineWidth;
        this.targetRadius = 1;
    };

    Firework.prototype.update = function(index){
        self.ctx.lineWidth = this.lineWidth;

        vx = Math.cos(this.angle) * this.speed,
        vy = Math.sin(this.angle) * this.speed;
        this.speed *= 1 + this.acceleration;                
        this.coordLast[2].x = this.coordLast[1].x;
        this.coordLast[2].y = this.coordLast[1].y;
        this.coordLast[1].x = this.coordLast[0].x;
        this.coordLast[1].y = this.coordLast[0].y;
        this.coordLast[0].x = this.x;
        this.coordLast[0].y = this.y;

        if(self.showTarget){
            if(this.targetRadius < 8){
                this.targetRadius += .25 * self.dt;
            } else {
                this.targetRadius = 1 * self.dt;    
            }
        }

        if(this.startX >= this.targetX){
            if(this.x + vx <= this.targetX){
                this.x = this.targetX;
                this.hitX = true;
            } else {
                this.x += vx * self.dt;
            }
        } else {
            if(this.x + vx >= this.targetX){
                this.x = this.targetX;
                this.hitX = true;
            } else {
                this.x += vx * self.dt;
            }
        }

        if(this.startY >= this.targetY){
            if(this.y + vy <= this.targetY){
                this.y = this.targetY;
                this.hitY = true;
            } else {
                this.y += vy * self.dt;
            }
        } else {
            if(this.y + vy >= this.targetY){
                this.y = this.targetY;
                this.hitY = true;
            } else {
                this.y += vy * self.dt;
            }
        }                

        if(this.hitX && this.hitY){
            var randExplosion = rand(0, 9);
            self.createParticles(this.targetX, this.targetY, this.hue);
            self.fireworks.splice(index, 1);                    
        }
    };

    Firework.prototype.draw = function(){
        self.ctx.lineWidth = this.lineWidth;

        var coordRand = (rand(1,3)-1);                    
        self.ctx.beginPath();                            
        self.ctx.moveTo(Math.round(this.coordLast[coordRand].x), Math.round(this.coordLast[coordRand].y));
        self.ctx.lineTo(Math.round(this.x), Math.round(this.y));
        self.ctx.closePath();
        self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+this.alpha+')';
        self.ctx.stroke();    

        if(self.showTarget){
            self.ctx.save();
            self.ctx.beginPath();
            self.ctx.arc(Math.round(this.targetX), Math.round(this.targetY), this.targetRadius, 0, Math.PI*2, false)
            self.ctx.closePath();
            self.ctx.lineWidth = 1;
            self.ctx.stroke();
            self.ctx.restore();
        }

        if(self.showShockwave){
            self.ctx.save();
            self.ctx.translate(Math.round(this.x), Math.round(this.y));
            self.ctx.rotate(this.shockwaveAngle);
            self.ctx.beginPath();
            self.ctx.arc(0, 0, 1*(this.speed/5), 0, Math.PI, true);
            self.ctx.strokeStyle = 'hsla('+this.hue+', 100%, '+this.brightness+'%, '+rand(25, 60)/100+')';
            self.ctx.lineWidth = this.lineWidth;
            self.ctx.stroke();
            self.ctx.restore();
        }                                 
    };

这段JS代码是创建烟花实例的,我们也可以从draw方法中看出,当我们鼠标点击画布中的某点时,烟花发射的目的地就在那个点上。

这款HTML5
Canvas烟花效果的核心代码就是这样,全部的代码还请各位下载源代码研究。源代码下载>>

发表评论

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