【30分钟学完】canvas动画|游戏基本(extra1-1):美图我也行

媒介

本文是继续系列教程的extra1,主假如引见颜色体系在canvas中的运用。
本来是与extra1一同成文的,由于segmentfault稀里糊涂的字数限定bug只能支解放送了。

canvas支配像素

你假如以为canvas只是绘图东西,那接下来的操纵会推翻你的认知。canvas供应api能够猎取画布上任何一个像素,并能够自在的操纵他们。

猎取像素

直接接见像素的功用由canvas高低文中的ImageData对象供应,它供应了以下一组要领,都邑返回ImageData对象。

  • getImageData()接收x轴坐标、y轴坐标、宽度、高度四个参数,猎取画布上这个矩形地区的像素数据;
  • createImageData()可平空建立指定宽高的矩形地区,初始是黑色,也能够输入一个ImageData对象用于建立一个一样大小的地区,但注重不会复制像素数据
context.getImageData(x, y, width, height);
context.createImageData(width, height);
context.createImageData(anothorImageData);

猎取到的ImageData对象中data属性是一个一维数组,乍看乱糟糟的,但细看你会发明实在这就是RGBA的颜色数据,也就是数组中每一个四位就是一个像素的颜色数据,这里注重一下透明度A也是0~255,不是CSS里简化过的0~1

    • *

举个例子
如今假定在一个纯赤色地区取一块2*2的矩形,我们取得的像素数据是:

let pixels = [255, 0, 0, 255, 255, 0, 0, 255,
              255, 0, 0, 255, 255, 0, 0, 255]

他们与图象的对应关联是从左到右,从上到下,或许就像上面代码格式化如许,如图所示:

《【30分钟学完】canvas动画|游戏基本(extra1-1):美图我也行》

依据4对1的对应关联,我们很轻易就可以写出遍历的方法,offset就相当于指针,每次挪动4位,代码以下:

for (let offset = 0, len = pixels.length; offset < len; offset += 4) {
  r = pixels[offset];
  g = pixels[offset + 1];
  b = pixels[offset + 2];
  a = pixels[offset + 3];
}

当须要接见特定坐标的像素时,能够运用以下公式,个中xpos是像素点在该地区的x坐标;ypos是像素点在该地区的y坐标,imagedata.width是指地区横向有若干像素。

let offset = (xpos + ypos * imagedata.width) * 4;
let r = pixels[offset];
let g = pixels[offset + 1];
let b = pixels[offset + 2];
let a = pixels[offset + 3];

绘制像素

能够将修悛改的ImageData对象从新用高低文的putImageData()要领绘制到指定地区,该要领接收三个参数:ImageData对象、x轴坐标、y轴坐标。绘制指定的位置绘制ImageData对象的内容。直接看下面例子的中心代码。
先绘制铺满画布的色块,点击按钮触发change事宜处理器可转变颜色,历程见解释。
完全例子:演示反色变化

【PS】对js相识不深的朋侪能够会有疑问,遍历历程操纵的是pixels,imageData怎么会转变呢?

这是由于js中对象都是地点通报的特性,也就是pixels = imageData.data操纵只是将pixels变量的指向到imageData.data所指向的内存空间,所以操纵pixels就是操纵imageData.data。

window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  // 绘制色块,每一个色块宽10像素,高即是画布高,铺满画布
  for (let i = 0; i < canvas.width; i += 10) {
    context.fillStyle = (i % 20 === 0) ? '#f00' : ((i % 30 === 0) ? '#0f0' : '#00f');
    context.fillRect(i, 0, 10, canvas.height);
  }
};

function change() {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  // 猎取全部画布的ImageData对象
  const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
  // 掏出颜色数据
  const pixels = imageData.data;
  // 遍历颜色数据求每一个颜色的反色
  for (let offset = 0, len = pixels.length; offset < len; offset += 4) {
    pixels[offset] = 255 - pixels[offset];
    pixels[offset + 1] = 255 - pixels[offset + 1];
    pixels[offset + 2] = 255 - pixels[offset + 2];
    // 这里没有操纵透明度
  }
  // 将ImageData从新绘制到画布上
  context.putImageData(imageData, 0, 0);
}

更多风趣的例子

canvas壮大的像素操纵能够给我们带来更多的能够,或许你会想最先做一个网页版的美图东西了吧(笑)。
这里另有一些风趣的demo能够玩玩:

综合案例

有关颜色的番外部分到这里就基础完结了,末了有个综合题,会运用这些手艺。
将系列第二篇中的鼠标绘图东西改形成鼠标喷漆东西,这里发起本身着手实践一下。
下面例子基础思路就是取得画布像素数据,每当鼠标点下并挪动(实行onMouseMove)就随机转变鼠标四周肯定局限的像素点的颜色。
完全案例:鼠标喷漆东西

window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  // 取得全部画布地区的ImageData对象
  const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
  // 掏出像素数据
  const pixels = imageData.data;
  // 设定笔刷大小
  const brush_size = 25;
  // 设定笔刷密度
  const brush_density = 80;
  // 笔刷的颜色变量
  let brush_color;

  function onMouseMove() {
    // 依据设定的笔刷密度天生随机像素点
    for (let i = 0; i < brush_density; i++) {
      // 随机像素点角度相对于鼠标的角度
      const angle = Math.random() * Math.PI * 2;
      // 依据设定的笔刷大小,随机像素点以鼠标为圆心的半径
      const radius = Math.random() * brush_size;
      // 计算出像素点的x轴相对坐标
      const xpos = (mouse.x + Math.cos(angle) * radius) | 0;
      // 计算出像素点的y轴相对坐标
      const ypos = (mouse.y + Math.sin(angle) * radius) | 0;
      // 算出该像素点在pixels中的偏移量
      const offset = (xpos + ypos * imageData.width) * 4;
      // 对这个像素点的颜色数据举行操纵,将颜色分解成三基色
      pixels[offset] = brush_color >> 16 & 0xff;
      pixels[offset + 1] = brush_color >> 8 & 0xff;
      pixels[offset + 2] = brush_color & 0xff;
      pixels[offset + 3] = 255;
    }
    // 从新绘制地区
    context.putImageData(imageData, 0, 0);
  }
  canvas.addEventListener('mousedown', () => {
    // 随机一个颜色
    brush_color = utils.parseColor(Math.random() * 0xffffff, true);
    canvas.addEventListener('mousemove', onMouseMove, false);
  }, false);
  canvas.addEventListener('mouseup', () => {
    canvas.removeEventListener('mousemove', onMouseMove, false);
  }, false);
};
    原文作者:calimanco
    原文地址: https://segmentfault.com/a/1190000013971943
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞