红包照片四不像(二)——canvas基础

在前面一篇文章中,我们通过css的方式实现了红包照片的模糊效果和偷窥镜。
但是通过demo发现,效果并不是特别好,尤其是移动设备上的 动画性能实在无法接受。
也可以通过canvas来实现相同的效果,本篇先来了解一下canvas的使用。

一、canvas基础

1、canvas本质

a.标签;
b.画布;

2、基本使用

var canvas = document.getElementById('canvas_id'); //获取canvas
canvas.height = document.documentElement.clientWidth; //设置宽高
canvas.width = document.documentElement.clientHeight;
var context = canvas.getContext('2d'); //获取2d绘图context

context.beginPath();  
  ...... //绘图路径
context.closePath();

context.fillStyle = ‘red'; //填充样式,描边样式使用strokeStyle
context.fill(); // 填充绘图,描边绘图使用stroke()

3、基础API(路径)

context.moveTo(x,y) // 确定起点
context.lineTo(x,y) // 绘制线段
context.fillRect(x,y,width,height) // 填充矩形
context.strokeRect(x,y,width,height) // 描边矩形
// 绘制圆弧,参数包含圆心坐标/半径/起止弧度点/弧度行进方向
context.arc(x, y, radius, starAngle,endAngle, anticlockwise)

context.clearRect(x,y,width,height) //清除画布某矩形区域

// 贝塞尔曲线
context.quadraticCurveTo(qcpx,qcpy,qx,qy)
context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 

// 渐变,起始点以及偏移点点颜色
var lGradient = context.createLinearGradient(xStart,yStart,xEnd,yEnd) // 线性
var rGradient = context.createRadialGradient(xStart,yStart,radiusStart,xEnd,yEnd,radiusEnd) // 径向
*Gradient.addColorStop(offset,color)

context.translate(x,y) // 平移
context.scale(x,y) // 缩放
context.rotate(angle) // 旋转
// 备注:以上三个变化操作的不是绘图,而是坐标轴

context.globalCompositeOperation=type //图形组合
/*    type:
        source-over(默认值):在原有图形上绘制新图形
        destination-over:在原有图形下绘制新图形
        source-in:显示原有图形和新图形的交集,新图形在上,所以颜色为新图形的颜色
        destination-in:显示原有图形和新图形的交集,原有图形在上,所以颜色为原有图形的颜色
        source-out:只显示新图形非交集部分
        destination-out:只显示原有图形非交集部分
        source-atop:显示原有图形和交集部分,新图形在上,所以交集部分的颜色为新图形的颜色
        destination-atop:显示新图形和交集部分,新图形在下,所以交集部分的颜色为原有图形的颜色
        lighter:原有图形和新图形都显示,交集部分做颜色叠加
        xor:重叠部分不显示
        copy:只显示新图形
*/

// 阴影
context.shadowOffsetX = 10;
context.shadowOffsetY = 10;
context.shadowColor = 'rgba(100,100,100,0.5)';
context.shadowBlur = 1.5;

// 绘制文字
context.fillText(text,x,y)  
context.strokeText(text,x,y)

// 画笔画布状态暂存
context.save()
context.restore()

context.drawImage // 绘图——下面单独介绍

二、绘图api相关

1、api介绍

context.drawImage(image, x, y, w, h) // Image对象、起始坐标、绘制宽高(可省略)

context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh)// 将Image的sx、sy位置sw、sh大小的图像绘制再画布dx、dy位置dw、dh大小的地方

context.fillStyle = context.createPattern(image,type)
/*  type:   no-repeat:不平铺
          repeat-x:横方向平铺
          repeat-y:纵方向平铺
          repeat:全方向平铺   */

context.clip() // 设置绘制的封闭区域

// imagedata中每4个元素代表一个像素的rgba数据,对应图像从左到右从上到下的像素
var imagedata=context.getImageData(sx,sy,sw,sh)
context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight) 

2、上帝绘图模式

由于可以获取到图片每个像素的数据,包括rgba,可以通过改变任何像素的值为任何值来达到预期的效果。(just like the God)
那么我们究竟可以做些什么呢?
一般情况下,可以通过像素色彩的计算实现PS中一些比较简单的滤镜效果,例如灰度图片只需要对单个像素的rgb值做加权平均就可以了,红色图片只需要把每个像素的r值设置为255即可。
下面详细介绍几种简单的算法。

三、滤镜算法

1、灰度

// 一般采用加权平均值,权值可以任意选取,常用 0.3、0.59、0.11;
r = g = b = r * rWeight + g * gWeight + b * bWeight; 
// 也可以使用其他的一些技巧,例如MAX
r = g = b = Math.max(r, g, b); 

2、灰度加强

r =(2*g - b + r)* r / 255;
g =(2*b - g + r)* r / 255;
b =(2*b - g + r)* g / 255;
... //再做灰度处理

3、反色——底片效果

r = 255 - r;
g = 255 - g;
b = 255 - b;

4、黑白

var temp = r * rWeight + g * gWeight + b * bWeight; // 可以采用灰度中的多种方式
r = g = b = temp > 128 ? 255 : 0; // 这里的取值也可以灵活处理,达到不同的黑白灰的效果

5、斑驳

r = r > 128 ? 255 : 0;
g = g > 128 ? 255 : 0;
b = b > 128 ? 255 : 0;

6、怀旧

r = r * 0.393 + g * 0.769 + b * 0.189; 
g = r * 0.349 + g * 0.686 + b * 0.168; 
b = r * 0.272 + g * 0.534 + b * 0.131; 

7、色彩通道——纯色通道

// 纯色比较简单,包括一些单色通道和混合通道
r = 255; // 红色
r= g = 255; // 黄色(红+绿)
r = 0;// 反红色,有别于(绿+蓝)
// 这种方式比较灵活,可以通过调整rgb为任意常数值,来实现一些特别的效果

8、锐化

// rgb的值均加上当前位置的颜色值与四面八方颜色值的差为当前值
function getColor(color) {
      color[i][j] *= 10;
      for (var row = -1; row < 2; row++) {
            for (var col = -1; col < 2; col++) {
                  color[i][j] -= color[i + row][j + col];
            }
      }
}

9、马赛克

// 某个方块中所有像素的值取同一个位置的值
for (var i=0; i< Height; i++) {
    for (var j=0; j<Width; j++) {
        var iTemp = i - i % RADUIS;
        var jTemp = j - j % RADUIS;
        r[i * Width + j] =  r[iTemp * Width + jTemp];
        g[i * Width + j] =  g[iTemp * Width + jTemp];
        b[i * Width + j] =  b[iTemp * Width + jTemp];
   }
}

10、模糊

// 每个像素的值均取周围像素值的平均值
for (var i=0; i< Height; i++) {
    for (var j=0; j<Width; j++) {
        color[i * Width + j] =  getColor(i, j);
   }
}
function getColor(i, j) {
    var result = 0, count = 0;
    for (var m = i - RADUIS;m < i + RADUIS; m++) {
          if (m < 0) {               continue;        }
          for(var n = j - RADUIS; n < j + RADUIS; n++) {
              if (n < 0) {            continue;        }
              result += data[m * width + n];
              count++;
          }
      }
      return result/count;
}

11、浮雕

// 相邻点的差值做类似半灰度的处理
for (var i=0; i< Height; i++) {
    for (var j=0;j<Width;j++) {        
        r[i* Width + j] = r[(i* Width + j) + 1] - r[i* Width + j] + 128;
        g[i* Width + j] = g[(i* Width + j) + 1] - g[i* Width + j] +128;
        b[i* Width + j] = b[(i* Width + j) + 1] - b[i* Width + j] +128;
        ... //再做灰度处理(可能会有一些彩色的线条,可以通过灰度处理去掉)
     }
}

四、滤镜示例

Just Load:http://tkixp9.github.io/redbag/draw_image_as_god.html

五、canvas实现红包照片

TO BE CONTINUED...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容