> 웹 프론트엔드 > H5 튜토리얼 > 캔버스 API, 인기 있는 캔버스 기본 사항 (5)

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

黄舟
풀어 주다: 2017-02-25 11:50:21
원래의
1596명이 탐색했습니다.

이전 이슈는 모두 그리기 경로 그래픽에 관한 것이었습니다. 이 섹션에서는 캔버스에서 그림을 조작하는 방법에 대해 이야기하겠습니다. 그래픽은 아름다운 소녀를 그릴 수 없기 때문에(그리기 전문가는 이를 무시합니다), 어떻게 해야 할까요? 나는 아름다운 소녀들을 그리고 싶다? 따라오세요:

캔버스에 그림을 삽입하려면 다음 영웅이 필요합니다.
drawImage() 캔버스에 이미지, 캔버스 또는 비디오를 그립니다.
이 영웅은 다음을 수행할 수 있습니다. 무술에 있어서는 매우 강하다고 합니다. 고수 중의 고수라고 불릴 만큼 독특한 실력과 깊은 내면의 힘을 가지고 있는 그가 어떤 독특한 능력을 가지고 있는지 살펴보겠습니다.
치트 1:
drawImage(img ,x,y) 캔버스에 그림 배치
매개변수: img는 가져온 그림 개체를 나타내고, x, y는 가져온 좌표를 나타냅니다.
ps: 여기서 img는 그림의 경로가 아닌 이미지 개체를 나타냅니다. image , 이미지를 직접 인용할 수는 없지만 DOM을 운영하여 참조해야 함을 나타냅니다.
위 팁에서는 이미지의 특수성을 설명하는데 이미지를 어떻게 얻을 수 있을까요? 가장 간단한 것부터 먼저 해보자:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span>
</canvas>
<img src="2.jpg" alt="" id="img">
로그인 후 복사

페이지에 사진을 넣고(그때 밀크티 소녀, 아), 이 사진을 가져와서 캔버스에 올려 놓습니다

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10);
로그인 후 복사



캔버스 API, 인기 있는 캔버스 기본 사항 (5)

보세요, 캔버스 밖의 밀크티 소녀가 우리 캔버스에 왔습니다. 안타깝게도 현재의 밀크티 소녀는 더 이상 현재의 소녀가 아닙니다. 밀크티 소녀가 있습니다. 어떤 학생들은 '나는 단지 내 밀크티 소녀를 내 캔버스에 담고 싶은데(왜 내 밀크티 소녀인가) 그녀가 다른 곳에서 보여지는 것을 원하지 않는다'고 말할 것입니다. 똑똑한 학생들은 알아냈을 텐데, 그냥 밖에 사진을 숨겨두면 안 될까요? 그냥 숨겨도 괜찮나요?

으르르르


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

오른쪽 밀크티 소녀 없어졌는데 내 캔버스에만 밀크티 소녀가 좋은데 어, 이게 뭐야? 예, 페이지에 이 사진이 있으면 이 DOM 요소를 얻을 수 있다는 의미입니다. 사진이 표시되는지 여부는 중요하지 않습니다. p에 넣어서 숨기거나, 캔버스 태그에 넣으세요(캔버스를 지원하는 브라우저의 콘텐츠가 표시되지 않기 때문입니다). 또한 순수 js를 사용하여 사진을 추가할 수도 있습니다.

<img src="2.jpg" alt="" id="img" style="display:none;">
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

비밀 팁 2:

drawImage(img,x,y,w,h) 캔버스에 이미지를 배치하고 이미지의 너비와 높이를 지정합니다.

매개변수: img는 가져온 이미지 객체를 나타내고, x, y는 가져온 좌표를 나타내고, w, h는 지정된 이미지 크기를 나타냅니다.

일부 학생들은 이렇게 말할 것입니다. 밀크티걸은 좋은데 캔버스가 너무 작아요, 밀크티걸이 너무 크네요(얼마나 큰지), 그림이 너무 커서 기본적으로 캔버스에 다른 모양을 그리면 캔버스를 가득 채우지 않나요? 밀크티 소녀에게 불명예가 될까요? 그녀를 더 작게 만들 수 있나요? 하하, drawImage에는 크거나 작을 수 있는 능력이 있습니다. 믿을 수 없다면 여기를 보세요:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var aImg = new Image();
aImg.src = &#39;2.jpg&#39;;
ctx.onload = function(){
    ctx.drawImage(aImg,10,10,400,300);
}
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)
위의 밀크티 소녀를 보세요. 갑자기 작아졌습니다. 앗, 너무 작아서 잘 보이지 않습니다. 그리고 다른 나쁜 반 친구들은 보지 않고 밀크티 소녀만 보고 싶은데, 괜찮을까요? 물론 가능합니다

치트 팁 3
drawImage(img,sX,sY,sWidth,sHeight,x,y,width,height) 캔버스를 자르고 잘라낸 부분을 캔버스에 배치
매개변수: img는 가져온 그림 객체를 나타냅니다. sX, sY는 클리핑의 실제 좌표를 나타냅니다. sWidth, sHeight는 클리핑의 너비와 높이를 나타냅니다. x, y는 그림을 캔버스에 배치하는 좌표를 나타냅니다. width, height는 사용할 사진입니다.
위의 매개변수가 많지만 여전히 이해하기 쉽습니다. 밀크티 소녀를 자르는 방법을 살펴보겠습니다.

rree


캔버스 API, 인기 있는 캔버스 기본 사항 (5)
나리야, 밀크티 소녀는 왜 뚱뚱해진 걸까? 매개변수를 다시 살펴보면 이때 마지막 너비와 높이가 이전의 w, h와 다른 의미를 갖고 있음을 발견했습니다. 이제 자른 이미지가 자른 너비와 높이보다 더 큰 경우 표시해야 하는 크기를 나타냅니다. , 당겨집니다. 크롭된 너비와 높이보다 작으면 줄어듭니다. 자, 크롭된 크기와 동일한 크기로 조정하겠습니다.


var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oImg = document.getElementById("img");
ctx.drawImage(oImg,10,10,200,150);
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)
그렇습니다. 뒤에 있는 x와 y는 잘린 사진이 표시되는 위치를 나타냅니다. 가운데로 옮겨서 살펴보세요

ctx.drawImage(oImg,150,0,150,300,150,10,150,300);
로그인 후 복사

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

所以在使用裁剪功能的时候,要特别注意,图片的坐标和宽高和原来的意思有区别了

秘籍四

drawImage(video,x,y,w,h) 在画布上定位视频,并规定视频的宽高

参数:video表示引入是视频对象 ,x,y表示视频引入的坐标 ,w,h表示规定视频的大小

其实这里跟引入图片是一样的,只不过它是可以引入视频的,但是这里的引入只是视频的某一帧,所以,当我们直接引入时,是没有什么反应的:

<canvas width="500" height="400" id="canvas">
        <span>亲,您的浏览器不支持canvas,换个浏览器试试吧!</span>
    </canvas>
    <video id="video1" controls width="270">
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.mp4" type=&#39;video/mp4&#39;>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.ogg" type=&#39;video/ogg&#39;>
      <source src="http://www.w3school.com.cn/example/html5/mov_bbb.webm" type=&#39;video/webm&#39;>
    </video>
로그인 후 복사
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var oVideo = document.getElementById("video1");
ctx.drawImage(oVideo,10,10,270,135);
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

当视频设置为autoplay时:

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

可以看到,右侧视频在播放,左侧没有什么反应,那怎么来播放视频呢?我们可以加一个定时器,然后每隔20秒执行一次绘画,这样一帧一帧的执行,连续起来就是一个视频了,其实视频的原理也是如此:

var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var oImg = document.getElementById("img");
        var oVideo = document.getElementById("video1");
        var timer = setInterval(function(){
            ctx.drawImage(oVideo,10,10,270,135);
        },20)
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

不想让画布外的视频显示的方法跟图片是一样的,这里我就不细说了

除了drawImage具有裁剪功能外,还有一个方法可以裁剪——clip(),不同的是drawImage是裁剪图片,而clip只能裁剪图形,我们具体来看一下clip吧:

clip() 从原始画布中剪切任意形状和尺寸

ps:一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)。您也可以在使用 clip() 方法前通过使用 save() 方法对当前画布区域进行保存,并在以后的任意时间对其进行恢复(通过 restore() 方法)。

提示这里很重要,一定要看清楚,就好比是一张很大的油画布,现在我们用一个木框架子框一部分,然后就只能在这个框里画画了,框外面的就不能来画,恩,就是这个意思,当我们用restore()方法恢复画布是时候,就好比是把木框架子取掉了,这样就可以在别的地方画了,当然画好的这部分就不要动了
举个栗子:
不用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)
使用clip裁剪:

ctx.arc(200, 200, 80, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.clip();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.arc(150, 150, 100, (Math.PI/180)*0, (Math.PI/180)*360, false);
ctx.fill();
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

可以比较看出,后面画的圆只显示在裁剪的圆的范围中,其他的都不见了,再看一个例子:

ctx.fillRect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.fillRect(100,100,200,100);
로그인 후 복사

我们将圆改成实心的矩形,且是用的fillRect,而不是用fill,rect,结果是:

캔버스 API, 인기 있는 캔버스 기본 사항 (5)
只显示第一个矩形,第二个矩形貌似不见了,而我们分开写:

//不用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.fillRect(100,100,200,100);
로그인 후 복사
//使用clip裁剪
ctx.rect(50,50,200,100);
ctx.fill();
ctx.clip();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.fillRect(100,100,200,100);
로그인 후 복사
//第一个矩形不填充,只画路径
ctx.rect(50,50,200,100);
ctx.clip();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.fillRect(100,100,200,100);
로그인 후 복사
//将clip放在第二个矩形
ctx.rect(50,50,200,100);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = &#39;green&#39;;
ctx.rect(100,100,200,100);
ctx.clip();
ctx.fill();
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

上面的4张图分别代码上面的4段代码的效果,从这4组对比我们可以看出:
第一:裁剪的路径必须在被裁剪图形的前面申明,如果在后面申明,则会没有效果或只有第一个图形显示;
第二:如果前面的裁剪区域要是没有填充的话,显示的部分就要2图形相交的部分,但是绘图区域还是裁剪部分的区域

下面要讲的是像素操作,相对来说比较复杂,需要大家的强大大脑来脑补和理解,何为像素操作?我们说任何在屏幕上显示的图形,图片,画面等等都是由像素构成的,最好理解的就是户外大屏幕的画面了,因为户外大屏幕分辨率比较小,相比之下像素的颗粒就比较大,可以清晰的看到画面是又密密麻麻的像素来显示的,当户外大屏幕的屏幕有部分花了的话,会看到呈现的画面就会在花掉的部分显示成别的颜色,很明显,对于我们的电脑显示器也是一个原理!

那么像素是通过什么来获取的呢?我们来一一介绍:
getImageData(x,y,w,h) 拷贝画布指定矩形的像素数据
参数:x,y表示开始复制的左上角的坐标 w,h表示将要复制的区域大小
参数很好理解,就是在什么地方复制多大一个地方,而且它返回一个ImageData对象,ImageData对象里面包含了几个参数:
data:数组集合 width :对象的宽度 height:对象的高度
后面2个好理解,这个data集合到底是什么呢?我们来举个栗子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

我们画了一个100*100的实现矩形,然后获取它的像素,然后分别查看了他们代表的意思,可以看到一个很有意思的东西,就是100*100的矩形的像素点应该是10000个像素,为什么它的长度是40000,这个我们可以在data数组中可以看到端倪,一个像素点是由rgba构成的:

r : 0-255 黑-白

g : 0-255 黑-白

b : 0-255 黑-白

a : 0-255 透明-不透明

也就是说,一个像素是用这4个值组成的,那么10000个像素的长度自然就是40000了,而且对应的值在console中也能看到,好了,理解了这一点,那么就里像素操作不远了!
除了我们在已知的地方去获取像素外,我们能不能自己来创造像素区域呢?答案是肯定的:
createImageData(w,h) 表示创建一个规定尺寸的ImageData对象
createImageData(ImageData) 表示创建与指定的另一个 ImageData 对象尺寸相同的新 ImageData 对象(不会复制图像数据)
我们也来写一个例子:

var oImg = ctx.createImageData(100,100);
console.log(oImg);
console.log(oImg.data)
console.log(oImg.data.length)
로그인 후 복사



캔버스 API, 인기 있는 캔버스 기본 사항 (5)

恩,跟前面的是一样的,创建了一个ImageData对象,当然画布是没有任何的效果的,因为我们只是创建了一个对象,那么我们怎么将我们创建的对象放到画布上呢?那就要用到这个方法:
putImageData(imageData,x,y,dirtyX,dirtyY,dirtyWidth,dirtyHeight) 方法将图像数据(从指定的 ImageData 对象)放回画布上
参数:
imageData指创建或获取的imageData对象
x,y表示imageData对象的左上角坐标
dirtyX,dirtyY 表示在画布上放置图像的坐标,以像素计,可选
dirtyWidth,dirtyHeight 表示在画布上放置的图形大小,可选
我们也举2个例子:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
ctx.putImageData(oImg,100,100);
ctx.putImageData(oImg,100,0,10,10,50,50);
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

看,这么一对比,就知道这些参数是什么意思了,其中第二个我还得解释一下,如图小矩形,x,y依然是表示大的ImageData对象的起始坐标,dirtyX,dirtyY,dirtyWidth,dirtyHeight表示是相对于现在的x,y的起始坐标再来定义位置和大小,这么解释应该就明白了!
这就是操作像素的方法,看着很简单,也挺好理解,但是真正用起来,还是蛮费脑子的,我们先来看第一个小实例,改变像素的颜色:
实例效果,改变100*100的黑色矩形框中的第10行第10列的颜色,颜色为红色,先画个图分析一下:

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

从上面的console中也可以看出,像素点是从0开始的,如果上图就是矩形的像素点的分布(画的有点烂,将就看一下),第10行,也就是第11行,第10列也就是第11列,那么前十列的像素就是矩形的宽度*10,剩下的就是11个像素,二者相加就是所有的像素,然后每个像素用4个值表示,就是总和乘以4,好具体我们看代码:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
setXY(oImg,10,10,[255,0,0,255]);
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);
로그인 후 복사

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

看,(10,10)坐标点的颜色就变成了红色,一个点还是不太明显,如果是一条横向的或者的纵向的,就跟明显了:

ctx.fillRect(0,0,100,100);
//获取矩形框的像素
var oImg = ctx.getImageData(0,0,100,100);
for(var i=0;i<oImg.width;i++){
    setXY(oImg,i,10,[255,0,0,255]);
}
for(var i=0;i<oImg.height;i++){
    setXY(oImg,10,i,[255,0,0,255]);
}
//设置目标像素点的颜色
function setXY(obj,x,y,color){
    var w = obj.width;
    var h = obj.height;
    obj.data[4*(w*y+x)] = color[0];
    obj.data[4*(w*y+x)+1] = color[1];
    obj.data[4*(w*y+x)+2] = color[2];
    obj.data[4*(w*y+x)+3] = color[3];    
}
ctx.putImageData(oImg,100,100);
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

我们经常看到那种很炫酷的粒子文字,图形的效果,既然我们可以操作像素,如果我们只显示一部分的像素点,不就是粒子效果吗?看下面的例子:

ctx.fillStyle = &#39;red&#39;;
        ctx.arc(150,150,100,0,360*Math.PI/180,false);
        ctx.fill();
        //获取矩形框的像素
        var oImg = ctx.getImageData(50,50,200,200);
        ctx.clearRect(0,0,canvas.width,canvas.height);
        var w = oImg.width;
        var h = oImg.height;
        var arr = randomNum(w*h,w*h/10);
        var newImg = ctx.createImageData(oImg);
        for(var i=0;i<arr.length;i++){
            newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
            newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
            newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
            newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
        }
        ctx.putImageData(newImg,50,50);

        
        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i<iNow;i++){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }
로그인 후 복사

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

上面的例子表示,我只显示当前的十分之一的像素,具体效果看这里——粒子图形
像素操作不仅仅只能操作图形,图片我们一样可以操作,这样我们就能做出更多的效果,看看下面的例子,我们将图像换成图片,看看能不能做出粒子图片:

var aImg = new Image();
        aImg.src = &#39;3.jpg&#39;;
        
        //当图片加载完毕才能进行下面的操作
        aImg.onload = function(){
            draw(this);    
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);    
            //获取矩形框的像素
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            var arr = randomNum(w*h,w*h/2);
            var newImg = ctx.createImageData(oImg);
            for(var i=0;i<arr.length;i++){
                newImg.data[4*arr[i]] = oImg.data[4*arr[i]];
                newImg.data[4*arr[i]+1] = oImg.data[4*arr[i]+1];
                newImg.data[4*arr[i]+2] = oImg.data[4*arr[i]+2];
                newImg.data[4*arr[i]+3] = oImg.data[4*arr[i]+3];
            }
            ctx.putImageData(newImg,0,0);
        }

        //某区域的部分随机数
        function randomNum(iAll,iNow){
            var arr = [];
            var newArr = [];
            for(var i=1;i<=iAll;i++){
                arr.push(i);    
            }
            for(var i=0;i<iNow;i++){
                newArr.push(arr.splice(Math.random()*(arr.length),1));    
            }    
            return newArr;
        }
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

这里我用的是二分之一的像素点,十分之一太少了,看得不明显,由此我们可以知道,也是可以来操作图片的像素点的,具体效果看这里 —— 图片粒子化

既然我们可以操作图片,那可以做的事就太多了,先看看下面这个例子,图片反色(即将原图片的像素颜色用相反的颜色替代):

var aImg = new Image();
        aImg.src = &#39;1.jpg&#39;;
        aImg.onload = function(){
            draw(this);
            
        }
        
        function draw(obj){
            ctx.drawImage(obj,0,0,400,400);
            var oImg = ctx.getImageData(0,0,400,400);
            var w = oImg.width;
            var h = oImg.height;
            
            for(var i=0;i<h;i++){
                for(var j=0;j<w;j++){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(oImg,j,i,result);
                }    
            }
            ctx.putImageData(oImg,w,0);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

是不是很有意思,具体效果可以看这里—— canvas图片反色
用这个例子,我们还可以延伸一下,让它反色后,我们再加一个倒影,美女不明显,我们用山峰那张:

var aImg = new Image();
        aImg.src = &#39;3.jpg&#39;;
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height)
            
            for(var i=0;i<h;i++){
                for(var j=0;j<w;j++){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }
로그인 후 복사


캔버스 API, 인기 있는 캔버스 기본 사항 (5)

细心的同学一定能看出它的原理,没错,就是在设置像素的时候,将它的像素方向反向,即此处“h-i”,具体效果看这里——canvas图片反色倒影
我们还可以做一些延伸,我们可以通过像素的透明度的参数,给它设置投影渐变,我们来看看:

var aImg = new Image();
        aImg.src = &#39;3.jpg&#39;;
        aImg.onload = function(){
            draw(this);
            
        }
        function draw(obj){
            ctx.drawImage(obj,0,0,obj.width,obj.height);
            var oImg = ctx.getImageData(0,0,obj.width,obj.height);
            var w = oImg.width;
            var h = oImg.height;
            
            var newImg = ctx.createImageData(obj.width,obj.height);
            
            for(var i=0;i<h;i++){
                for(var j=0;j<w;j++){
                    var result = [];
                    var color = getXY(oImg,j,i);
                    result[0] = 255 - color[0];    
                    result[1] = 255 - color[1];    
                    result[2] = 255 - color[2];    
                    result[3] = 255*i/h;    
                    setXY(newImg,j,h-i,result);
                }    
            }
            ctx.putImageData(newImg,0,h);
        }
        
        function getXY(obj,x,y){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            var color = [];
            color[0] =     obj.data[4*(y*w+x)];
            color[1] =     obj.data[4*(y*w+x)+1];
            color[2] =     obj.data[4*(y*w+x)+2];
            color[3] =     obj.data[4*(y*w+x)+3];
            return color;
        }
        
        function setXY(obj,x,y,color){
            var w = obj.width;
            var h = obj.height;
            var d = obj.data;
            obj.data[4*(y*w+x)] = color[0];
            obj.data[4*(y*w+x)+1] = color[1];
            obj.data[4*(y*w+x)+2] = color[2];
            obj.data[4*(y*w+x)+3] = color[3];
        }
로그인 후 복사

캔버스 API, 인기 있는 캔버스 기본 사항 (5)

核心代码就一个地方,255*i/h 给透明度乘以一个百分比的值,从0-255,也是很巧妙啊,具体效果看这里——canvas图片反色投影渐变

总结一下吧:虽然像素操作的方法不多,但是其功能之强大,是很多人都要望其项背的,关键在于人的想象力和深入的理解,要理解这样一个概念,掌握了像素操作,就好比是掌握了物体的核心本质,你就是造物者,你想造出什么东西,全凭你的想法,这里只是展示了一个很低劣的效果,旨在给大家展示一下canvas像素操作的魅力,抛砖引玉而已,后期会单独发一下canvas的像素操作的实例给大家参考,这个东西实在是太重要了!

好了,弄了几天了,终于写完了,本来想多写一点的,想想,后面再扩展吧!谢谢大家!

 以上就是canvas API ,通俗的canvas基础知识(五) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!


관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿