Canvas Ghost 魔法

1,891 阅读3分钟

说实话,我对 Canvas 真的不熟,没有在任何生产环境用过,除了偶尔自己写(抄)一些 Demo 。

但是通常面试的时候会问到,你要是回问,Canvas 是什么东西,场面就相当尴尬。所以建议你平时没事也可以练练手,至少掌握一些常用 API。今天想分享的是,使用 Canvas Ghost 来做两个神奇的 Demo 。

Canvas Ghost 是什么? Google 一下,貌似没有什么人这么称呼,但是隐约在哪里看过。不过这都不重要,我的意思是,通过镜像或者说肉眼看不见的复本来借用 Canvas 的 API,以达到真正目的。那么就管这个虚无缥缈的 Canvas 叫做 Canvas Ghost。 这么说不过分吧。

Demo1 - 不规则图形范围检测

假设有天,设计师给了你一张 png 图片,大部分内容是透明的。需求是,当用户鼠标滑到内容区域(非透明像素点)上的时候,要标记图片高亮。

没明白什么意思的话,看图吧。
效果图

效果图

当鼠标移入 png 图片非透明区域的时候,需要把图片的背景色置灰,你懂我意思吧?
那么就这个简单的需求,你会有什么解决方案? 获取图片上某个位置是否透明?JavaScript 没有这样的 Api 吧!但是 Canvas 有。Canvas 有个 getImageData 的接口,通过这个接口可以获取到 Canvas 上每一个像素点的像素值。这么一转换的话,问题是不是就很简单了?

看代码!

// 创建一个虚拟的 Canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');

// 对目标元素绑定事件
self.$ele.on('mouseenter', $.proxy(this._copyImageToCtx, this));
self.$ele.on('mousemove', $.proxy(this._onMouseMove, this));
self.$ele.on('mouseleave', $.proxy(this._removeImageFromCtx, this));

// onMouseMove  转换坐标,获取 Canvas Ghost 上相对于位置的色值
var mousePos = {
    x: event.pageX,
    y: event.pageY
}

var pixelPos = convertCoord(mousePos, self.offset);
var pixelColor = ctx.getImageData(pixelPos.x, pixelPos.y, 1, 1).data;

// pixelColor 是个数组,有四个值,分别对应 r,g,b,a
//
if (pixelColor[3] !== 0) {
    self.$ele.addClass(self.settings.hoveringClass);
} else {
    self.$ele.removeClass(self.settings.hoveringClass);
}

完整代码看github,大部分代码参考自shaperollover
代码量非常少,但是按这个套路还可以演化出很多不可思议的效果,留给聪明的读者你自己去思考。

Demo2 - 代理事件

我们知道 Canvas 就是一块画布,大部分操作就像画笔一样,在上边描绘内容。画上去的内容不像 Dom 结构,无法对某个图像绑定事件。这个 Demo 演示的是,通过 Canvas Ghost 代理来实现获取 event target 的效果。

核心代码:


for (var i = boxsLength - 1; i >= 0; i--) {
    var box = boxList[i];
    // 清除 ghost 画板
    ghostCtx.clearRect(0, 0, canvasWidth, canvasHeight);
    // 创建相同形状相同位置,黑色 box
    var fakeBox = new Box(box.x, box.y, box.width, box.height, 'black');
    fakeBox.drawOn(ghostCtx);
    // 使用 getImageData 获取对应点样式
    var pixelData = ghostCtx.getImageData(ox, oy, 1, 1).data;
    if (pixelData[3] !== 0) {
        // 记录选中元素
        box.isActive = true;
        draggingIndex = i;
        break;
    }
}

注意是在 Canvas 上的喔

注意是在 Canvas 上的喔

完整演示代码看github

说点什么

可能你跟我一样在实际工作中不会遇上这样的需求。但是有天突然需要这样的展示效果了,束手无策怎么办?认真想想!我们真的没做过吗?Canvas Ghost 说白了不就是加了层代码嘛? 代理模式我们都懂的!平时养成多思多想的习惯,而不只是为了应付面试的刷概念,那么应对这样的需求挥手即来的代码,不过是触类旁通的必然产物。与君共勉!

如需转载,请注明出处: w3ctrain.com/2016/12/19/… ,欢迎加入前端Q群(467969149)


本文对你有帮助?欢迎扫码加入前端学习小组微信群: