この記事では、キャンバスの globalCompositeOperation 属性について詳しく説明し、コード例を通じてこの属性の魔法の効果を確認します。一定の参考値があるので、困っている友達が参考になれば幸いです。
説明
キャンバスの globalCompositeOperation プロパティについて最初に知るのは、スクラッチカードのエフェクトを実装する際、ネットで見つけてすぐに終わらせてしまったのですが、今回改めて理解を深めたいと思い勉強してみました。
まず、canvas の globalCompositeOperation 属性と、それが具体的に何をするのかを見てみましょう。
Definition
globalCompositeOperation プロパティは、ソース (新しい) イメージをターゲット (既存) イメージに描画する方法を設定または返します。画像。
ソース画像 = キャンバスに配置する予定の描画。
ターゲット画像 = キャンバス上に配置した描画。
このプロパティは、新しい図形を描画するときに適用される合成操作のタイプを設定するために使用されます。たとえば、青い四角形の上に赤い円を描いた場合、赤が上に表示されるか、青が表示されますか? 色を上に表示する、重なっている部分を表示するかどうか、重なっていない部分をどのように表示するか、その他の状況に直面したときは、globalCompositeOperation
属性の出番です。有効になります。
デフォルト値では、すべて表示され、新しく描画されたグラフィックスが元のグラフィックスを上書きします。
使用法
デフォルト値: source-over
構文: context.globalCompositeOperation=" source-in";
表内の青い四角形はターゲット イメージ、赤い円はソース イメージです。
#属性値 | 説明 | 効果 |
#ソースオーバー# # ####デフォルト。ソース画像を宛先画像の上に表示します。
|
|
#source-atop
| ソース画像を宛先画像の上に表示します。ターゲット イメージの外側にあるソース イメージの部分は表示されません。
|
| #source-in
ターゲット画像内にソース画像を表示します。宛先イメージ内のソース イメージの部分のみが表示され、宛先イメージは透明になります。 |
|
#source-out |
ターゲット イメージに加えてソース イメージを表示します。ソース画像のうちターゲット画像以外の部分のみが表示され、ターゲット画像は透明になります。
|
| #destination-over | ソース画像の上に宛先画像を表示します。 |
| destination-atop | ソース画像の上に宛先画像を表示します。ソース画像の外側にあるターゲット画像の部分は表示されません。 |
#destination-in |
ソース イメージ内にデスティネーション イメージを表示します。ソース イメージ内のターゲット イメージの部分のみが表示され、ソース イメージは透明になります。 |
|
#destination-out | ソース イメージの外側にデスティネーション イメージを表示します。ソース イメージの外側のターゲット イメージの部分のみが表示され、ソース イメージは透明になります。 |
|
#lighter
ソース画像ターゲット画像を表示します。 |
|
| #copy
ソース画像を表示します。対象画像は無視してください。 |
|
#xor |
XOR 演算を使用してソース画像と宛先画像を結合します。
|
|
さて、水滴の拡散の効果を実感してみましょう:
https://codepen.io/FEWY/pen/oPxbmj
レンダリング
実装のアイデア
まずキャンバスに白黒の絵を描き、次に背景をカラーの絵に設定します。 、マウスをクリックすると、キャンバスの globalCompositeOperation 属性値を destination-out に設定し、キャンバス内のマウスの座標に応じて徐々に増加する不規則な形状を使用します。白黒写真を消去し、ゆっくりと色付きの背景を表示します。
つまり、3 枚の写真が必要です。
白黒写真
カラー付きの写真写真
#不規則な形の写真
コード <!doctype html>
<html>
<head>
<meta charset="UTF-8">
<style>
canvas {
/* 设置鼠标的光标是一张图片, 16和22 分别表示热点的X坐标和Y坐标 */
/* https://developer.mozilla.org/zh-CN/docs/Web/CSS/cursor/url */
cursor: url('https://www.kkkk1000.com/images/globalCompositeOperation/mouse.png') 16 22, auto;
}
</style>
</head>
<body>
<canvas id="canvas" width="400px" height="250px"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
// 保存图片路径的数组
var urlArr = ["https://www.kkkk1000.com/images/globalCompositeOperation/bg2.png", "https://www.kkkk1000.com/images/globalCompositeOperation/clear.png"];
// imgArr 保存加载后的图片的数组,imgArr中保存的是真实的图片
// loadImg 函数用来加载 urlArr 中所有的图片
// 并返回一个保存所有图片的数组
var imgArr = loadImg(urlArr);
// flag 用来限制 点击事件,一张图片只会产生一次效果
var flag = false;
function loadImg(urlArr) {
var index = 0;
var res = [];
// 每次给 load 函数传入一个图片路径,来加载图片
load(urlArr[index]);
function load(url) {
// 如果 index 等于 urlArr.length,
// 表示加载完 全部图片了,就结束 load函数
if (index == urlArr.length) {
// 加载完全部图片,调用 init 函数
init();
return;
}
var img = new Image();
img.src = url;
// 不管当前图片是否加载成功,都要加载下一张图片
img.onload = next;
img.onerror = function () {
console.log(res[index] + "加载失败");
next();
}
// next 用来加载下一张图片
function next() {
// 把加载后的图片,保存到 res 中
res[index] = img;
load(urlArr[++index])
}
}
// 最后返回保存所有真实图片的数组
return res;
}
function init() {
// 先在canvas上画黑白的图片,然后再设置背景是彩色的图片
// 避免先显示出彩色图片,再显示出黑白的图片
context.globalCompositeOperation = "source-over";
context.drawImage(imgArr[0], 0, 0, 400, 250);
canvas.style.background = 'url(https://www.kkkk1000.com/images/globalCompositeOperation/bg.jpg)';
canvas.style.backgroundSize = "100% 100%";
// flag 是 true 时,鼠标点击才有水滴扩散的效果
flag = true;
// canvas 绑定点击事件,点击时产生水滴扩散效果
canvas.onclick = diffusion;
}
// width 表示 不规则形状的图片的尺寸
var width = 0;
// speed 表示扩散效果的速度
var speed = 8;
// diffusion 函数根据鼠标坐标,产生效果
function diffusion (e) {
if (flag) {
flag = false;
context.globalCompositeOperation = "destination-out";
window.requestAnimationFrame(draw);
// 根据鼠标坐标,画扩散效果
function draw() {
// 这里不一定需要是 1800 ,但必须是一个足够大的数,可以扩散出整张背景图
if (width > 1800) {
flag = true;
return;
}
width += speed;
// 获取鼠标相对于 canvas 的坐标
var x = e.layerX;
var y = e.layerY;
// 画不规则形状的图片,逐渐增大图片尺寸
context.drawImage(imgArr[1], x - (width / 2), y - (width / 2), width, width);
window.requestAnimationFrame(draw);
}
}
}
</script>
</body>
</html> ログイン後にコピー スクラッチカードの効果を実感してみよう
レンダリング
## という考え方スクラッチ カード効果の実装:
最初にキャンバス上にグレーのレイヤーを描画し、次にキャンバスの背景画像を設定し、globalCompositeOperation 属性値を設定します。キャンバスの destination -out をクリックして移動すると、移動点の座標に応じて灰色が消去されます。一部を消去すると、自動的にすべての灰色が消去され、背景が消去されます。表示される。 スクラッチカードのエフェクトと水滴の拡散エフェクトは最初はほぼ同じですが、水滴の拡散エフェクトは不規則な形状の絵を使用して白黒の絵を鮮明にするのに対し、スクラッチカードのエフェクトは上の灰色をより太い線を描いて消します。 主な違いは、スクラッチ カードの効果では、最後にすべてのグレーを自動的に消去する必要があることです。方法は 2 つあります。
1 つ目
キャンバスの getImageData メソッドを使用して、キャンバス上のピクセル情報を取得します。返されるオブジェクトのデータ属性このメソッドは RGBA 順にデータを格納した 1 次元配列です データは 0 から 255 までの整数で表されます 詳細は Canvas の ピクセル操作 を参照してください。 この方法を使用して、どれだけ消去されたかを確認します。つまり、変数を使用して、RGBA 値が 0 であるピクセル数を記録します。変数の値が特定の値を超えると、すべてのグレーが消去されます。 コードは次のとおりです:
https://codepen.io/FEWY/pen/BOjmyg
2 番目のタイプ どれだけ動いたか見てください。マウスを動かすと変数が増加し、この変数が一定の値を超えると、灰色がすべて消去されます。
コードはここにあります
https://codepen.io/FEWY/pen/eLJeNv
注:
##getImageData を使用する最初の方法にはクロスドメインの問題がありますが、この効果では画像がキャンバスに描画されず、キャンバスの background が画像に設定されるためです。まだ影響はありませんが、キャンバスに他の絵が描かれている場合は、クロスドメインの問題に対処する必要がある可能性があります。 getImageData を使用してキャンバス上のピクセル情報を取得すると、スクラッチ カード上のグレーの領域に基づいてグレーをすべて消去するタイミングを決定できるため、より柔軟になります。 2 番目の方法には、クロスドメインの問題はありませんが、スクラッチ カードのグレー領域に基づいてすべてのグレーを消去する最終タイミングを制御できません。 概要
この記事の効果は、主に globalCompositeOperation属性値が destination-out であり、値が他の値である場合に使用することです。 , さまざまな効果も出せるので、想像力を働かせて他の値も試してみると新たな発見があるかもしれません。 プログラミング関連の知識について詳しくは、プログラミング入門 をご覧ください。 !
|
以上がキャンバスの globalCompositeOperation 属性を理解します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。