ホームページ > 記事 > ウェブフロントエンド > Canvas API、一般的な Canvas の基本 (6)
この記事はキャンバス API シリーズの始まりであり、終わりです。この記事を終えると、これらは最も一般的に使用されるはずですが、いくつかの珍しいプロパティとメソッドもあります。理由については説明しません。キャンバスのより実践的な例を書くことに重点を置きます。よく言われるように、これ以上の説明は必要ありません。では、残りのプロパティとメソッドを見てみましょう。
1. createPattern
createPattern(image,"repeat|repeat-x|repeat-y|no-repeat") 指定された要素を指定された方向に繰り返します
パラメータ: 画像は実際の画像、キャンバス、またはビデオオブジェクトを参照します。繰り返しの方法を表します
以下のパラメータを見ると、CSS の background-repeat について考えるのが簡単です。これは、参照される画像アドレスではなく、背景とは異なります。ここで、これらの繰り返しメソッドのパフォーマンスをそれぞれ見てみましょう。 css なのでわかりやすいですが、canvas には背景位置がありません。まあ、この効果はこんな感じです、言うことはありません!
ここで具体的な効果を参照してください - キャンバスの背景の繰り返し
2. gloableCompositeOperation
gloableCompositeOperation() 新しい画像を既存の画像に描画する方法を設定または返します
パラメータ:
source-over デフォルトでは、ソース画像が表示されますターゲット画像。
source-atop ソース画像をターゲット画像の上に表示します。ターゲット イメージの外側にあるソース イメージの部分は表示されません。
source-in ターゲット画像内にソース画像を表示します。宛先イメージ内のソース イメージの部分のみが表示されます。宛先イメージは透明です。
source-out ターゲット画像の外側にソース画像を表示します。ソース画像のうちターゲット画像以外の部分のみが表示され、ターゲット画像は透明になります。
destination-over ソース画像の上に宛先画像を表示します。
destination-atop ソース画像の上に宛先画像を表示します。ソース画像の外側にあるターゲット画像の部分は表示されません。
destination-in ソース画像内に宛先画像を表示します。ソース イメージ内のターゲット イメージの部分のみが表示されます。ソース イメージは透明です。
destination-out ソース画像の外側に宛先画像を表示します。ソース イメージの外側のターゲット イメージの部分のみが表示されます。ソース イメージは透明です。
lighter ソース画像 + ターゲット画像を表示します。つまり、交差するグラフィックスが連続して塗りつぶされて明るさが増します。
copy ソース画像を表示します。ターゲット画像を無視する、つまりソース画像のみを表示します
xor XOR演算を使用してソース画像とターゲット画像を結合します、つまり交差部分は透明になります
一般的に使用されない:
ソースのピクセルを乗算します画像は対象画像のピクセルを掛け合わせます
スクリーン
オーバーレイ
darken 暗くし、交差する部分を次々と塗りつぶして明るさを下げます
lighten 明るくし、交差する部分を次々に塗りつぶして明るさを増やします
color-dodge 下のレイヤーを上のレイヤーに合わせて調整します。つまり、ターゲット画像をソース画像に合わせます。 上の
color-burn 下のレイヤーを上のレイヤーに合わせて調整し、反転します。
hard-light 下のレイヤーを調整します
ソフトライト
差分
除外
色相
彩度
色
明度
英語が下手なため、よく使用されるパラメータの意味は次のとおりです。説明するのは簡単ではありませんが、誤解を招かないように、ここでの gloableCompositeOperation パラメータの説明をご覧ください。もっと分かりやすく翻訳していただければ幸いです。翻訳の意味はどうもありがとうございます。ただし、参考までにその後の走行結果を載せておきます!
最初によく使用されるパラメータを見てみましょう。最初に、ターゲット グラフィックが何であるかを理解する必要があります。ソースグラフィックとは何ですか?
宛先画像 = キャンバスに配置した描画; ソース画像 = キャンバスに配置する予定の描画。これが公式の説明です。この説明がわからない場合は、次のように理解できます。つまり、最初に描画された画像がターゲット グラフィックで、後で描画された画像がソース画像です。たとえば、次のようになります。
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); }
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)!