이 글은 캔버스 API 시리즈의 시작이자 끝입니다. 이 글 이후에는 모든 캔버스 속성과 메서드가 완료됩니다. 아, 가장 일반적으로 사용되는 속성과 메서드도 있습니다. 여러 가지 이유로 인해 이후 단계에서는 더 실용적인 캔버스 예제를 작성하는 데 중점을 두겠습니다. 더 이상 고민하지 말고 나머지 속성과 메서드를 살펴보겠습니다.
1.createPattern
createPattern(image,"repeat|repeat-x|repeat-y|no-repeat") 지정된 요소를 지정된 방향으로 반복합니다
매개변수: image는 실제 그림, 캔버스를 나타냅니다. 아니면 비디오 객체의 두 번째 매개변수가 반복을 나타내는 방식
다음 매개변수를 보면 CSS의 배경 반복을 생각하기 쉽습니다. 첫 번째 매개변수에 대해 말씀드리고 싶은 것이 있습니다. 참조된 이미지가 아니라 그림 개체입니다. 여기서는
var aImg = new Image(); aImg.src = '4.jpg'; aImg.onload = function(){ draw(this); } function draw(obj){ //这里为了演示方便,把其他的先注释 //var bg = ctx.createPattern(obj,"repeat"); //var bg = ctx.createPattern(obj,"repeat-x"); //var bg = ctx.createPattern(obj,"repeat-y"); var bg = ctx.createPattern(obj,"no-repeat"); ctx.fillStyle = bg; ctx.fillRect(0,0,400,400); }
뭐 효과는 CSS의 background-repeat와 같으니 이해하기 쉽겠지만, 그런데 캔버스에는 배경 위치가 없습니다. 음, 이 효과는 이렇습니다. 말할 것도 없습니다!
특정 효과는 여기를 참조하세요 - 캔버스 배경 반복
2. gloableCompositeOperation
gloableCompositeOperation() 기존 이미지에 새 이미지를 그리는 방법을 설정하거나 반환합니다.
매개변수:
source-over 기본적으로 원본 이미지가 대상 이미지 위에 표시됩니다.
source-atop 대상 이미지 위에 소스 이미지를 표시합니다. 대상 이미지 외부에 있는 소스 이미지 부분은 보이지 않습니다.
source-in 대상 이미지에 원본 이미지를 표시합니다. 대상 이미지 내의 소스 이미지 부분만 투명하게 표시됩니다.
source-out 대상 이미지 외에 소스 이미지도 표시합니다. 원본 이미지에서 대상 이미지 이외의 부분만 표시되고 대상 이미지는 투명해집니다.
destination-over 원본 이미지 위에 대상 이미지를 표시합니다.
destination-atop 원본 이미지 위에 대상 이미지를 표시합니다. 원본 이미지 외부의 대상 이미지 부분은 표시되지 않습니다.
destination-in 소스 이미지 내에 대상 이미지를 표시합니다. 소스 이미지 내의 대상 이미지 부분만 투명하게 표시됩니다.
destination-out 원본 이미지 외부에 대상 이미지를 표시합니다. 소스 이미지 외부의 대상 이미지 부분만 투명하게 표시됩니다.
lighter 원본 이미지 + 대상 이미지를 표시합니다. 즉, 교차하는 그래픽을 연속적으로 채워 밝기를 높입니다.
copy 원본 이미지를 표시합니다. 대상 이미지 무시, 즉 원본 이미지만 표시
xor XOR 연산을 사용하여 원본 이미지와 대상 이미지 결합, 즉 교차 부분이 투명
곱하기 원본 이미지의 픽셀과 대상 이미지의 픽셀을 곱합니다
화면
오버레이
어둡게 그래픽의 교차 부분 심화 연속적으로 채워져 밝기가 감소합니다
lighten Bright 추가, 그래픽의 교차 부분을 연속적으로 채워 밝기를 높입니다
color-dodge 하단 레이어를 상단 레이어로 조정합니다. , 원본 이미지 위의 대상 이미지 조정
color-burn 하단 레이어를 상단 레이어로 조정한 다음 반전
하드라이트를 켜고 하단 레이어를 상단 레이어로 조정하고, 그런 다음 화면
소프트 라이트
차이
제외
색조
채도
에 효과를 곱합니다. color
luminosity
일반적으로 사용되는 일부 매개변수의 의미는 영어가 부족하여 설명하기 쉽지 않습니다. 더 나은 영어, 여기에서 gloableCompositeOperation 매개변수에 대한 설명을 살펴보세요. 더 명확하게 번역할 수 있다면 번역의 의미를 알려주시기 바랍니다. 정말 감사합니다. 하지만 참고하실 수 있도록 후속 실행 결과를 알려드리겠습니다!
먼저 일반적으로 사용되는 매개변수를 살펴보겠습니다. 처음 8개는 이해하기 쉽고 그 반대입니다. 먼저 대상 그래픽이 무엇인지 이해해야 합니다. 소스 그래픽이란 무엇입니까?
대상 이미지 = 캔버스에 배치한 그림, 원본 이미지 = 캔버스에 배치하려는 그림. 이것이 공식적인 설명이 이해되지 않으면 이렇게 이해할 수 있습니다. 즉, 먼저 그려진 이미지가 대상 그래픽이고 나중에 그려진 이미지가 소스 이미지입니다. 예:
//目标图像 ctx.fillStyle="red"; ctx.fillRect(20,20,75,50); ctx.globalCompositeOperation="source-over"; //源图像 ctx.fillStyle="blue"; ctx.fillRect(50,50,75,50);
물론, 이 gloableCompositeOperation의 위치는 고정되어 있지 않으며, 대상 이미지 앞에 배치할 수도 있고, 대상 이미지 뒤에 배치할 수도 있습니다. 하지만 원본 이미지 뒤에 배치할 수는 없습니다(알다시피). 매개변수의 의미를 이해하기 쉽지 않다면 아래 그림을 보고 어떻게 보이는지 확인하세요.
var arr = ['source-over','source-atop','source-in','source-out','destination-over','destination-atop','destination-in','destination-out','lighter','copy','xor','multiply','screen','overlay','darken','lighten','color-dodge','color-burn','hard-light','soft-light','difference','exclusion','hue','saturation','color','luminosity']; for(var i=0;i<arr.length;i++){ document.write("<p id='p_" + i + "' style='float:left;'>" + arr[i] + ":<br>"); var canvas = document.createElement("canvas"); canvas.width = 120; canvas.height = 100; canvas.style.border = "1px solid #000"; canvas.style.marginRight = '10px'; document.getElementById("p_" + i).appendChild(canvas); var ctx = canvas.getContext("2d"); ctx.fillStyle="red"; ctx.fillRect(10,10,50,50); ctx.globalCompositeOperation=arr[i]; ctx.beginPath(); ctx.fillStyle="green"; ctx.fillRect(30,30,50,50); ctx.fill(); document.write("</p>"); }
红与绿
红与蓝
具体效果你也可以看这里 —— canvas图形组合模式
里面的代码我故意把canvas的代码留在上面,方便你们查看,不知道你看到这些参数有什么感想,我的第一感觉就是有些熟悉比clip好用,也让我第一时间想到了这一个效果:
ctx.fillStyle="red"; ctx.arc(150,150,100,0,360*Math.PI/180,false); ctx.fill(); ctx.globalCompositeOperation="xor"; ctx.beginPath(); ctx.arc(150,150,80,0,360*Math.PI/180,false); ctx.fill();
如果配合前面的扇形方法,很容易做一个圆形进度条什么的,当然,还有很多属性可以有大的作用,比如说裁切一个图形,发挥的发达的大脑吧,这里我就不演示了
3、setLineDash
setLineDash(arr) 在画布上画一条虚线
参数:arr 表示的是一个数组集合,里面的参数可以有多个,这里面的参数很有意思,举个栗子说明:
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10,20]); ctx.stroke();
对比代码看图,如果有2个参数,则第一个参数表示虚线的线宽,第二个参数表示虚线的线与线的距离,后面一直循环
如果是3个参数呢?
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10,20,30]); ctx.stroke();
此时会这样,第一条线长为10,然后间距为20,第2条线长为30,然后间距为10,第3条线长20,然后间距为30,到处为一个循环,后面重复
那么4个参数就好理解了,
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10,20,30,40]); ctx.stroke();
规律和上面的一样,只是循环的长度要长一些,更多参数的规则也是这样的,那么一个参数是否有效呢
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10]); ctx.stroke();
显然是有效的,此时线宽为10,间距为10,这就是华丽的分割线的做法
它还有一个兄弟用法,这个是设置虚线,那么就会有一个获取虚线
getLineDash() 获取当前虚线的样式
它没有参数,它得到的结果就是设置虚线的线宽数组arr,我们看一下怎么用:
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10]); var txt = ctx.getLineDash(); ctx.stroke(); ctx.fillStyle = 'red'; ctx.font = "30px Arial"; ctx.fillText(txt,180,140);
ctx.beginPath(); ctx.moveTo(0,100); ctx.lineTo(400, 100); ctx.setLineDash([10,20]); var txt = ctx.getLineDash(); ctx.stroke(); ctx.fillStyle = 'red'; ctx.font = "30px Arial"; ctx.fillText(txt,180,140);
从这两组图可以看出,当只有一个参数数,会默认为2个一样的参数
4、isPointInPath
isPointInPath(x,y) 指定点是否在路径区域中,如果在则返回true,不在则返回false
参数: x,y表示指定的坐标点
举个栗子:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.fillStyle = 'red'; ctx.rect(50,50,100,100); ctx.fill(); canvas.onclick = function(ev){ var ev = ev || event; ctx.clearRect(200,0,200,200); var l = ev.clientX - canvas.offsetLeft; var t = ev.clientY - canvas.offsetTop; if(ctx.isPointInPath(l,t)){ ctx.font = "40px Arial"; ctx.fillText((l+','+t),200,120); } }
看看这个gif图,当点击红色区域时,我将坐标打印出来,如果点击的地方不在红色区域,则不显示坐标,具体效果看这里 —— canvas判断是否在路径区域
这里有一点需要注意,就是在绘制矩形时,不能用fillRect或strokeRect,为什么呢?因为这里判断是是否在指定的路径中,而fillRect或strokeRect此时已经不是路径了,而是变成了填充过的图形,所以这里必须先用Rect()定义一下路径,再填充,这样才能回去到指定图形的路径,此点须知!
还有一个方法:
isPointInStroke(x,y) 指定点是否在路径中,如果在则返回true,不在则返回false
此方法跟上面的方法很相似,不同点在于,isPointInPath是在一个区域中,不管是用fill还是stroke,但是isPointInStroke只能用stroke填充,且指定的区域是在线框上,看下面的例子:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.strokeStyle = 'red'; ctx.lineWidth = 5; ctx.rect(50,50,100,100); ctx.stroke(); canvas.onclick = function(ev){ var ev = ev || event; ctx.clearRect(200,0,200,200); var l = ev.clientX - canvas.offsetLeft; var t = ev.clientY - canvas.offsetTop; if(ctx.isPointInStroke(l,t)){ ctx.font = "40px Arial"; ctx.fillText((l+','+t),200,120); } }
从这个gif中可以看出端倪来,只有点到线框才会触发,具体效果看这里 —— canvas 判断是否在线框中
这2个方法的基本用法就是这样,但是会有一个问题,就是目前只有一个图形在上面,如果有2个图形在上面,而且分别的方法不一样,比如说,一个是区域路径,一个是线框路径,分别点击他们,弹出不同的值,我们看行不行:
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.strokeStyle = 'red'; ctx.lineWidth = 5; ctx.rect(50,50,100,100); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = 'green'; ctx.rect(200,50,100,100); ctx.fill(); ctx.closePath(); canvas.onclick = function(ev){ var ev = ev || event; var l = ev.clientX - canvas.offsetLeft; var t = ev.clientY - canvas.offsetTop; if(ctx.isPointInStroke(l,t)){ console.log('线框路径'); } } canvas.onclick = function(ev){ var ev = ev || event; var l = ev.clientX - canvas.offsetLeft; var t = ev.clientY - canvas.offsetTop; if(ctx.isPointInPath(l,t)){ console.log('区域路径'); } }
看看console里面的提示,当点击区域路径的时候,触发了操作,但是点击线框路径时,无论我怎么点击,都无济于事,这是为什么呢?把2图形的执行顺序颠倒一下,发现效果也相反了,说明谁最后绘制就执行谁,其实这也是可以理解的,因为此时的ctx指的是当前的路径,它不能分当前路径一,路径二什么的,如果要实现多个图形执行不同的事件,又改如何做呢?由于实现方法有点复杂,就在这里留一个思考题?你们先思考一下,该怎么弄?我会到后期单独写一篇文章,专门来说这个的解决方案,供大家参考!
恩,到处所有该讲的canvas API就全部讲完了,看了这一系列的文章,不知道你是否对canvas有了那么一点点的感觉,是否canvas已经不那么神秘了,如果你嘴上不说,心里觉得,恩,好像有点感觉了,那我的目的就达到了,要是你还能写一些效果,那恭喜你,距离大神你有近了一步,如果有时间,有能力,我希望能多写一下有点深度的canvas实例给大家参考,但愿能对大家有帮助!
以上就是canvas API ,通俗的canvas基础知识(六) 的内容,更多相关内容请关注PHP中文网(www.php.cn)!