js高级程序设计canvas

1.canvas的save()和restore()的区别

save()只是保存的绘图上下文的设置和变换,用来保存Canvas的状态,而不是保存绘图的上下文内容。

restore()用来恢复Canvas旋转、缩放等之后的状态,当和canvas.save( )一起使用时,恢复到canvas.save( )保存时的状态。

按照我自己的话说,就是假如我们画了一个圆,用save()保存,此时并没有状态的改变操作。然后我们进行一系列的状态变换,比如旋转,接着我们又画了一条线,此时的线是在画布旋转之后位置。此时我们调用restore()方法,则会恢复到save时的状态,即未旋转的状态,现在再画一条线,这条线就会处于画布未旋转时的位置。

参考链接http://www.jianshu.com/p/619618905432

2.绘制图像:drawImage()

这里可以有九个参数:image元素、源图像的x坐标、y坐标、宽、高、目标图像的x坐标、y坐标、宽、高

// 用法 ,现在在坐标10,10位置处画一个图像
const image = document.images[0];
context.drawImage(image, 10, 10); 

我们可以通过图像的九个参数,对图像做出不同位置的显示以及图像部分的显示。

// 现在画一个类似图像迁移的试图
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);

这样会得到两个图形,其中第二个图形由于是40, 60的宽高,所以只会显示一部分。

第一个擦参数还可以是canvas元素,这样就可以将一个画布绘制在当前的画布上,画布的结果可以通过toDataURL()方法取得,注意不能在跨域的环境下使用这个方法。

3.渐变

渐变主要是通过2D上下文进行创建和改变,渐变分为线性渐变和径向渐变,他们都会返回一个对象值。

  • 线性渐变:createLinearGradient(x1, y1, x2, y2)

  • 径向渐变:createRadialGradient(x1, y1, r1, x2, y2, r2)

    // 用法, 画一条起点10, 10 终点30, 30的线性渐变区域
    const linear = context.createLinearGradient(10, 10, 30, 30);
    // 渐变的颜色设置是从白到黑
    linear.addColorStop(0, "white");
    linear.addColorStop(1, "black");
    context.fillStyle = linear;
    context.fillRect(10, 10, 50, 50);
    
    径向渐变的区域使用方法相似,也会返回一个对象,再去调用addColorStop()方法,进行设置颜色的渐变
    
    // 这里使用的时候要注意坐标的变化,这里是根据画出的矩形做出的坐标的调整
    const radial = context.createRadialGradient(30, 30, 10, 30, 30, 10);
    
4.模式,createPattern()

模式其实就是绘制重复的图像,它会返回一个样式的值。它有两个参数,分别是img元素,video元素或者canvas元素,第二个参数是一个字符串和css的属性background-repeat相似,可以是repeat,repeat-x,repeat-y,no-repeat

// 用法
const img = document.images[0];
const imgRepeat = context.createPattern(img, "repeat");
context.fillStyle = imgRepeat;
// 在宽高指定的矩形区域内,进行显示重复的图片,而不是在起点为10, 10处开始重复图像
context.fillRect(10, 10, 50, 50);
5.使用图形原始数据

使用图形的原始数据就是想获得图像的宽高和rgba,通过调用getImageData(),指定四个参数(x, y, width, height),就可以获得元素数据,返回一个对象,属性值分别是宽和高以及raba组成的一个data数组

// 首先画一个画布
const draw = document.getElementById("draw");
// 判断画布元素是否支持canvas
if (draw.getContext) {
  // 取得画布2d上下文
  const context = draw.getContext("2d");
  // 取得图像
  const image = document.images[0];
  // 调用drawImage()方法在0, 0处绘制图像
  context.drawImage(image, 0, 0);
  // 取得图像的原始数据
  const getImgData = context.getImageData(0, 0, image.width, image.height);
  // 获取原始图形的宽高以及rgba的数组数据
  const imageWidth = getImgData.width;
  const imageHeight = getImgData.height;
  const imageRgbaArr = getImgData.data;
  let r, g, b, a, average
  // 获取数据的rgba的值
  imageRgbaArr.forEach((item, index) => {
  r = (index === 0) && item;
    g = (index === 1) && item;
    g = (index === 2) && item;
    a = (index === 3) && item;
    if (r && g && b && a) {
      average = (r + g + b) / 3;
      imageRgbaArr[0] = average;
      imageRgbaArr[1] = average;
      imageRgbaArr[2] = average;
    }
  })
}
// 调用putImageData()方法回填数据并在画板上展现出来
getImgData = imageRgbaArr;
context.putImageData(getImgData, 0, 0);

取得原始图像数据的时,图像并不能来自其他域,否则js会报错。

6.图像合成

图像合成分为两个全局属性:globalAlpha和globalCompositionOperation

// 用法,globalAlpha属性默认值是0,表示绘制的透明度,默认是不透明
context.globalAlpha = 0.5;
context.fillStyle = "red";
context.fillRect(10, 10, 30, 30);

// 用法,globalCompositionOperation,用来表示先后两次绘制图形的位置。默认值是"source-over",即后绘制的图形在先绘制图形的上方
context.fillStyle = "red";
context.fillRect(10, 10, 30, 30);
// 设置图形的合成位置,先绘制的图形在后绘制图形的上方
context.globalCompositionOperation = "destination-over";
context.fillStyle = "green";
context.fillRect(20, 20, 30, 30);

globalCompositionOperation它还有很多属性值,包括两个图形合成的时候的透明度的变换显示,可以继续在浏览器上测试,目前支持较好的有IE和firefox,在不同的浏览器上测试可能会有很大的差别

推荐阅读更多精彩内容