OurJS


OurJS-我们的JS, 我们的技术-IT文摘; 专注JS相关领域;
我们热爱编程, 我们热爱技术;我们是高大上, 有品味的码农;

欢迎您订阅我们的技术周刊


我们会向您分享我们精心收集整理的,最新的行业资讯,技术动态,外文翻译,热点文章;
我们使用第三方邮件列表向您推送,我们不保存您的任何个人资料,注重您的隐私,您可以随时退订,

欢迎分享您的观点,经验,技巧,心得

让我们一起找寻程序员的快乐,探索技术, 发现IT人生的乐趣;


本网站使用缓存技术每次加载仅需很小流量, 可在手机中流畅浏览;
如果您发现任何BUG,请即时告知我们: ourjs(at)ourjs.com

创造canvas的艺术


分享到
分类 编程技巧   关键字 Html5   发布 1518409521  1409578158655
注意 转载须保留原文链接,译文链接,作者译者等信息。  
知道<canvas>吗?如果你愿意,将你的注意力集中在这个web文档的顶部。我的网站的头部区域包括一系列的“北极光”动画,是用HTML5′新的JavaScript渲染引擎<canvas>生成的。点击页面任何地方产生新的亮光,每个亮光都带着随机颜色和改变网站头部外观的轨迹,这条轨迹慢慢移动穿过整个页面。

如果你不熟悉<canvas>,学习他的最好方法是去看一个简单的例子。下面的HTML和JavaScript将在<canvas>域内生成一个橙色的矩形区域。

<canvas id="example1" width="400" height="300"></canvas>


// get the canvas
var canvas = document.getElementById('example1');
// get the "2d" context
var context = canvas.getContext('2d');
// change fill style to orange
context.fillStyle = '#ff7700';
// draw an orange rectangle
context.fillRect(0, 0, 400, 300);

你总是通过找到web文档中的元素,然后选择“context”开始canvas绘画。在本例中, context是2 d, 因为我们想用canvas画二维形状。选择一个context之后,canvas API包含了很多有用的绘图功能,如填充样式,形状,中空,阴影,和大量的其他特性,允许我们给图片做出奇特的改变。我们的编写的脚本的结果看起来是这样的


<canvas>的伟大之处就是它是一个JavaScript  API,这意味着我们可以利用所有的JavaScript变量,事件,循环等等的特点。让我们应用我们的脚本使用一个简单的JavaScript循环在我们的canvas区域创建一个网格的小区域。

<canvas id="example2" width="400" height="300"></canvas>

// get the canvas and context
var canvas = document.getElementById('example2');
var context = canvas.getContext('2d');
// orange fill style
context.fillStyle = '#ff7700';
// create squares in a loop
for(var x = 0; x < canvas.width; x += 25){
  for(var y = 0; y < canvas.height; y += 25){
    context.fillRect(x, y, 20, 20);
  }
}

短短几行JavaScript, 在我们的canvas区域能够产生192个方块。在我看来,这是<canvas>的真正价值。它允许我们利用web浏览器的处理能力来生成数学几何和图纸。再加上一点工作和大量的创造力,我们甚至可以利用这种力量的实现艺术效果


动画


在我们继续这个话题之前,我们需要了解如何使用<canvas>创建一个动画。这是一个有点更难做的事情。首先,请理解,以阻碍web浏览器性能的方式使用canvas API是很容易的。在canvas上绘画是需要处理器密集型的工作,特别是如果你不断更新动画之类的图纸。缓解任何性能问题,我将使用一个新功能叫做requestAnimationFrame,允许我们的web浏览器来决定更新canvas的频率, 同时在我们的web文档保持最佳性能。这不是在所有浏览器都可用的, 但幸运的是保罗爱尔兰曾写过一个出色的poly-fill将此功能添加到旧版本的web浏览器。他在他的博客写下了这个脚本和web浏览器这个的特性。
为了简便起见,我不打算在我的代码示例中包含保罗的脚本,但是你应该在自己的代码中使用它。使用requestAnimationFrame,我们可以在我们的脚本中创建一个基本的“动画循环”。它看上去是这样的

<canvas id="example3" width="400" height="300"></canvas>

// get the canvas
var canvas = document.getElementById('example3');
var context = canvas.getContext('2d');
context.fillStyle = '#ff7700';
var time = false;
// box position
var x = -100;
// animation loop
var loop = function(){
  // get time since last frame
  var now = new Date().getTime();
  var d = now - (time || now);
  time = now; 
  // clear previously drawn rectangles
  context.clearRect(0, 0, canvas.width, canvas.height);
  // draw new rectangle
  context.fillRect(x, 100, 100, 100);
  // advance horizontal position
  x += 0.1 * d;
  // reset horizontal position
  if(x > canvas.width){
    x = -100;
  }  
  // request next frame
  requestAnimationFrame(loop);
};
// first frame
loop();

当在canvas元素中使用动画, 所有绘画应由一个可重复的函数完成。在我们的示例中,我们使用loop()函数在我们的canvas上画一个正方形。requestAnimationFrame函数基于可用的处理能力告诉浏览器时自动选择什么时候绘制下一个框架,结果是我们的loop()函数一遍又一遍的运行, 从左到右推进我们的橙色盒子前进。请注意,我们使用d变量(delta)来确定帧之间的时间,以毫秒为单位。这是使我们的动画速度正常的一个重要的增加项。没有它,我们的动画在有好一点的处理器的计算机上会跑的更快,几年后当电脑获得更多的处理能力,我们的动画可以跑的更快之快,以至于混淆或误导用户。使用delta变量,我们可以每毫秒指定一个速度。在我们的示例中, 方块的位置每毫秒前进0.1 * d,或0.1像素,转化后即为每秒100像素。无论您的处理器的速度是多少, 动画总是花同样多的时间完成。

艺术元素


既然我们了解canvas元素以及如何使用它创建动画,我们可以在这些基础上加上一些艺术创造力来创造更有意思的东西。在下一个示例中,我们将在canvas元素中随机生成彩色圆圈并且和给他们随机轨迹。通过使用渐变画圆圈而不是纯色,我们的“北极光”脚本变得生动起来。


<canvas id="example4" width="400" height="300" style="background-color: #0e74a2;"></canvas>


// get the canvas
var canvas = document.getElementById('example4');
var context = canvas.getContext('2d');
var time = false;
// create an empty array of "circles"
var circles = [];
// animation loop
var loop = function(){
  // get time since last frame
  var now = new Date().getTime();
  var d = now - (time || now);
  time = now;
  // clear the canvas
  context.clearRect(0, 0, canvas.width, canvas.height);
  // draw circles
  for(var i = 0; i < circles.length; i++){
    circles[i].update(d);
    circles[i].draw();
  }
  // request next frame
  requestAnimationFrame(loop);
};
// circle object
var circle = function(options){
  // configuration
  var circle = this;
  circle.settings = {
    x: 0,
    y: 0,
    radius: 20,
    orientation: 0,
    vector: { x: 0, y: 0 },
    speed: 1,
    color: { red: 0, green: 0, blue: 0, alpha: 1 }
  };
  // merge options into settings
  var newsettings = {};
  for(var attrname in circle.settings){ newsettings[attrname] = circle.settings[attrname]; }
  for(var attrname in options){ newsettings[attrname] = options[attrname]; }
  circle.settings = newsettings;
  // update circle
  circle.update = function(d){
    // update position
    circle.settings.x += circle.settings.vector.x * circle.settings.speed * d;
    circle.settings.y += circle.settings.vector.y * circle.settings.speed * d;
    // bounce
    if(circle.settings.x < 0 && circle.settings.vector.x < 0 || circle.settings.x > canvas.width && circle.settings.vector.x > 0){
      circle.settings.vector.x = circle.settings.vector.x * -1;
    }
    if(circle.settings.y < 0 && circle.settings.vector.y < 0 || circle.settings.y > canvas.height && circle.settings.vector.y > 0){
      circle.settings.vector.y = circle.settings.vector.y * -1;
    }
  };
  // draw circle
  circle.draw = function(){
    // gradient fill
    var gradient = context.createRadialGradient(circle.settings.x, circle.settings.y, circle.settings.radius / 10, circle.settings.x, circle.settings.y, circle.settings.radius);
    gradient.addColorStop(0, 'rgba(' + circle.settings.color.red + ', ' + circle.settings.color.green + ', ' + circle.settings.color.blue + ', ' + circle.settings.color.alpha + ')');
    gradient.addColorStop(1, 'rgba(' + circle.settings.color.red + ', ' + circle.settings.color.green + ', ' + circle.settings.color.blue + ', ' + circle.settings.color.alpha / 50 + ')');
    context.fillStyle = gradient; 
    // draw
    context.beginPath();
    context.arc(circle.settings.x, circle.settings.y, circle.settings.radius, 0, 2 * Math.PI, false);
    context.fill(); 
  };
};
// create new circles
var newcircles = function(){
  // remove old circles
  circles = [];
  
  // create 5 new circles
  for(var i = 0; i < 5; i++){
    // create a new circle
    var newcircle = new circle({
      x: Math.floor(Math.random() * canvas.width),
      y: Math.floor(Math.random() * canvas.height),
      radius: Math.floor(Math.random() * canvas.width),
      orientation: Math.floor(Math.random() * 360),
      vector: {
        x: Math.random() / 40,
        y: Math.random() / 40
      },
      speed: Math.random(),
      color: {
        red: 100 + Math.floor(Math.random() * 155),
        green: 100 + Math.floor(Math.random() * 155),
        blue: 100 + Math.floor(Math.random() * 155),
        alpha: 0.1 + Math.random()
      }
    });
    
    // add new circle to circles array
    circles.push(newcircle);   
  }
};
// generate new circles
window.addEventListener('click', newcircles, false);
window.addEventListener('touchend', newcircles, false);
newcircles();
// first frame
loop();

在这个窗口每次单击,新的随机圆圈将会出现。试一试,在线DEMO。
我们才刚刚开始理解和利用<canvas>的力量。我渴望了解这个行业如何采用它以及SVG等技术构建惊奇和艺术的web内容。在我的下一篇文章中,我将展示如何采用此代码使用键盘快捷键和动画来创建一个简单的基于canvas的游戏,让你可以在web浏览器中玩这种游戏。


原文地址: 点此
社区评论 ( Beta版 )
OnceDoc 您自己的企业内容管理系统——文档、流程、知识库、报表、网盘All In One

访问404页面,寻找丢失儿童
 热门文章 - 分享最多
  1. OurJS-免费开源的博客引擎,论坛系统,网站模板和轻量级的CMS
  2. JavaScript构建(编绎)系统大比拼:Grunt vs. Gulp vs. NPM
  3. JavaScript中的继承,构造函数以及new关键字的作用
  4. CSS的力量:用一个DIV画图
  5. 微软Azure云推出基于JSON的NoSQL数据库DocumentDB
  6. 前置逗号是不好的JavaScript代码书写习惯吗?
  7. 内存管理技巧:如何避免JavaScript的内存泄露
  8. 有可能将CSS应用到一个字符的一半吗?
  9. fibjs 比 nodejs 快五倍
  10. 为JavaScript设计一个指数操作(运算)符
  11. AirJD-简单好用的免费建站工具

 相关阅读 - 编程技巧
  1. 有可能将CSS应用到一个字符的一半吗?
  2. Express.JS指南
  3. 在JavaScript中判断整型的N种方法
  4. 你应该使用HTML5的header和footer标签吗?
  5. 功夫:HTML和CSS?
  6. Linux命令及Linux终端的20个趣事
  7. 在NodeJS中启用ECMAScript 6
  8. 如何提高NODE.js中SSL服务的性能
  9. 极快的node.js:来自领英(LinkedIn)移动的10个性能技巧
  10. 在JavaScript里写类层次结构?别那么做!

 关键字 - Html5
  1. 用纯CSS实现的箭头
  2. HTML5的TCP和UDP Web Socket API草案定稿
  3. 传统广告与H5广告的差别在哪里?
  4. WeMall微信商城源码插件代金券部分代码
  5. WeMall微信商城源码插件会员卡代码详情
  6. WeMall微信商城源码插件大转盘代码详情
  7. 你应该使用HTML5的header和footer标签吗?
  8. 5个实用Web界面设计工具 | 附开发案例
  9. 从PDF转换到HTML5的三种方法,你用过吗?
  10. 分享5个主流的HTML5开发工具

 欢迎订阅 - 技术周刊

我们热爱编程, 我们热爱技术; 我们是高端, 大气, 上档次, 有品味, 时刻需要和国际接轨的码农; 欢迎您订阅我们的技术周刊; 您只需要在右上角输入您的邮箱即可; 我们注重您的隐私,您可以随时退订.
加入我们吧! 让我们一起找寻码农的快乐,探索技术, 发现IT人生的乐趣;


 关注我们

我们的微信公众号: ourjs-com
打开微信扫一扫即可关注我们:
IT文摘-程序员(码农)技术周刊

ourjs官方微信号