示例地址
https://liuxianl.com/2021/02/12/%E5%89%8D%E7%AB%AF/canvas/
1.
canvas标签中特殊属性只有width和height
通过document.getElementById(‘canvas的id’)来获取canvas元素
方法、属性 | 描述 |
---|
getContext() | 得到画布上下文,上下文有2个,2d 的上下文和3d的上下文 |
fillStyle | 设置颜色 |
fillRect() | 方法,绘制已填色的矩形,默认的填充颜色是黑色 |
2.
面向对象的画布动画
var can = document.getElementById("can")
var ctx = can.getContext("2d");
function Rect(x, y, w, h, color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color
}
Rect.prototype.update = function () {
this.x++;
}
Rect.prototype.render = function () {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
setInterval(() => {
ctx.clearRect(0, 0, can.width, can.height)
r1.update()
r1.render()
}, 5)
3.绘制、画线
方法 / 属性 | 描述 |
---|
fillStyle | 设置填充颜色 |
fillRect(x,y,width,height) | 方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。 |
strokeStyle | 设置边框颜色 |
strokeRect(x,y,width,height) | 方法绘制矩形边框。默认的填充颜色是黑色。 |
clearRect(x,y,width,height) | 清除画布内容 |
globalAlpha | 设置透明度 0-1 |
#3.1 绘制路径
ctx.beginPath()
ctx.moveTo(100,100)
ctx.lineTo(200,300);
ctx.lineTo(300,230);
ctx.lineTo(440,290);
ctx.lineTo(380,50);
ctx.closePath()
ctx.strokeStyle="#91d5ff"
ctx.stroke()
ctx.fill()
4.绘制圆弧
arc(x, y, radius, startAngle, endAngle, anticlockwise)
- x,y 为绘制圆弧所在圆上的圆心坐标。
- radius 为半径。
- startAngle 以及 endAngle 参数用弧度定义了开始以及结束的弧度。这些都是以 x 轴为基准。
- 参数 anticlockwise 为一个布尔值。为 true 时,是逆时针方向,否则顺时针方向。
注意:arc() 函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:弧度 =(Math.PI/180)* 角度。
ctx.beginPath();
ctx.arc(200,200,100,0,2*Math.PI,false)
ctx.stroke()
炫彩小球
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas{
border: 1px solid #000;
}
</style>
</head>
<body>
<canvas id="mycanvas" width="800" height="600"></canvas>
<script>
var can =document.getElementById("mycanvas");
var ctx =can.getContext("2d");
function Ball(x,y,r) {
this.x =x;
this.y =y;
this.r =r;
this.color =getRandomColor();
this.dx =parseInt(Math.random() *10) - 5;
this.dy =parseInt(Math.random() *10) - 5;
balArr.push(this)
}
Ball.prototype.update =function () {
this.x +=this.dx
this.y +=this.dy
this.r -=0.1
if (this.r < 0) {
this.remove()
}
}
Ball.prototype.remove =function () {
for (let index =0;index < balArr.length;index++) {
if (balArr[index] ==this) {
balArr.splice(index,1)
}
}
}
Ball.prototype.render =function () {
ctx.beginPath();
ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)
ctx.fillStyle =this.color
ctx.fill()
}
can.addEventListener("mousemove",function (event) {new Ball(event.offsetX,event.offsetY,Math.random() *13)
})
setInterval(() =>{
ctx.clearRect(0,0,can.width,can.height)
for (let index =0;index < balArr.length;index++) {
balArr[index].update()
if (balArr[index]) {
balArr[index].render()
}
}
},40)
var balArr =[]
function getRandomColor() {
var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"
var allTypeArr =allType.split(",");var color ="#"
for (let index =0;index < 6;index++) {
var random =parseInt(Math.random() *allTypeArr.length);
color +=allTypeArr[random]
}
return color
}
</script>
</body>
</html>
小球连线
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
canvas{
display: block;
}
</style>
</head>
<body>
<canvas id="can" width="800" height="600"></canvas>
<script>
var ballArr =[]
var can =document.getElementById("can");var ctx =can.getContext("2d");
can.width =document.documentElement.clientWidth
can.height =document.documentElement.clientHeight
function Ball(x,y,r) {this.x =x
this.y =y
this.r =r
this.color=getRandomColor()
this.count =0
this.dx =parseInt(Math.random() *10) - 5
this.dy =parseInt(Math.random() *10) - 5
ballArr.push(this)
this.index = ballArr.length -1
}
Ball.prototype.update =function () {
this.x +=this.dx
this.y +=this.dy
if (this.x <=this.r ||this.x >=can.width - this.r) {
this.dx =-this.dx
this.count++
this.color=getRandomColor()
}
if (this.y <=this.r ||this.y >=can.height - this.r) {
this.dy =-this.dy
this.count++
this.color=getRandomColor()
}
if (this.count >=3) {
this.remove()
}
}
Ball.prototype.remove =function () {
for (let index =0;index < ballArr.length;index++) {
if (ballArr[index] ==this) {
ballArr.splice(index,1)
}
}
}
Ball.prototype.render =function () {
ctx.beginPath();
ctx.globalAlpha =1
ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false)
ctx.fillStyle =this.color
ctx.fill()
for (let index = this.index + 1;index < ballArr.length;index++) {
if (Math.abs(ballArr[index].x - this.x) < 180 && Math.abs(ballArr[index].y - this.y) < 180) {
ctx.strokeStyle = getRandomColor()
ctx.beginPath();
ctx.globalAlpha =10 / Math.sqrt(Math.pow(ballArr[index].x - this.x,2) + Math.pow(ballArr[index].y - this.y,2))
ctx.moveTo(this.x,this.y)
ctx.lineTo(ballArr[index].x,ballArr[index].y)
ctx.closePath()
ctx.stroke()
}
}
}
can.addEventListener("click",function (event) {
for (let index =0;index < Math.ceil(Math.random() *20);index++) {
new Ball(event.offsetX,event.offsetY,Math.random() *10 + 10)
}
})
setInterval(function () {
ctx.clearRect(0,0,can.width,can.height)
for (let index =0;index < ballArr.length;index++) {
ballArr[index].update()
ballArr[index].render()
}
},25)
function getRandomColor() {
var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f"
var allTypeArr =allType.split(",");var color ="#"
for (let index =0;index < 6;index++) {
var random =parseInt(Math.random() *allTypeArr.length);
color +=allTypeArr[random]
}
return color
}
</script>
</body>
</html>
线型
方法 / 属性 | 描述 |
---|
lineCap | 线开头和结束的形状 |
lineJoin | 线交会时的形状,有三种值round,bevel,miter |
setLineDash | 设置虚线的样式 |
蚂蚁线
let canvas = document.getElementById("mycanvas");
let ctx = canvas.getContext('2d');
let offset = 0;
function draw() {
ctx.clearRect(0,0, canvas.width, canvas.height);
ctx.setLineDash([2, 3]);
ctx.lineDashOffset = -offset;
ctx.strokeRect(10,10, 100, 100);
}
function march() {
offset++;
if (offset > 16) {
offset = 0;
}
draw();
setTimeout(march, 20);
}
march();
渐变
方法 / 属性 | 描述 |
---|
font | 设置字体大小、字体等 |
textAlign | 根据坐标的对齐方式 |
fillText() | (文字,x1,y1) |
线型渐变
let line = ctx.createLinearGradient(100,150,300,160);
line.addColorStop(0, 'black');
line.addColorStop(0.5, 'red');
line.addColorStop(1, 'orange');
ctx.fillStyle = line;
ctx.fillRect(100,150,200,10);
镜像渐变
let gradient = ctx.createRadialGradient(200,300,100,200,300,0);
gradient.addColorStop(0,"white");
gradient.addColorStop(.2,"red");
gradient.addColorStop(.4,"orange");
gradient.addColorStop(.6,"green");
gradient.addColorStop(.8,"blue");
gradient.addColorStop(1,"purple");
ctx.fillStyle = gradient;
ctx.fillRect(100,200,200,200);
阴影
方法 / 属性 | 描述 |
---|
shadowOffsetX | X轴偏离像素 |
shadowOffsetY | Y轴偏离像素 |
shadowBlur | 模糊程度 |
shadowColor | 阴影颜色 |
使用图片
let image = new Image();
image.src = "imgs/test1.png";
image.onload = function(){
ctx.drawImage(image, 0, 0, 10, 10,10, 10, 50, 50);
}
- 前4个参数表示以图片为坐标的x,y,width,height
- 后4个参数表示以画布为坐标的x,y,width,height
资源管理器
https://liuxianl.com/demo/
https://liuxianl.com/2021/02/12/%E5%89%8D%E7%AB%AF/canvas/
进度1,2,3,4,5,6,7,8,9,10,11,12,13,14
1.
canvas标签中特殊属性只有width和height
通过document.getElementById('canvas的id')来获取canvas元素
2.
面向对象的画布动画
var can = document.getElementById("can")
var ctx = can.getContext("2d");
function Rect(x, y, w, h, color) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color
}
Rect.prototype.update = function () {
this.x++;
}
Rect.prototype.render = function () {
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
var r1 = new Rect(100, 100, 50, 50, "#91d5ff")
setInterval(() => {
ctx.clearRect(0, 0, can.width, can.height)
r1.update()
r1.render()
}, 5)
3.绘制、画线
方法 / 属性 描述
fillStyle 设置填充颜色
fillRect(x,y,width,height) 方法绘制 “已填色” 的矩形。默认的填充颜色是黑色。
strokeStyle 设置边框颜色
strokeRect(x,y,width,height) 方法绘制矩形边框。默认的填充颜色是黑色。
clearRect(x,y,width,height) 清除画布内容
globalAlpha 设置透明度 0-1
3.1 绘制路径
JAVASCRIPT
4.2 绘制圆弧
JAVASCRIPT
1 arc(x, y, radius, startAngle, endAngle, anticlockwise)
x,y 为绘制圆弧所在圆上的圆心坐标。
radius 为半径。
startAngle 以及 endAngle 参数用弧度定义了开始以及结束的弧度。这些都是以 x 轴为基准。
参数 anticlockwise 为一个布尔值。为 true 时,是逆时针方向,否则顺时针方向。
注意:arc() 函数中表示角的单位是弧度,不是角度。角度与弧度的 js 表达式:
弧度 =(Math.PI/180)* 角度。
JAVASCRIPT
1234567
炫彩小球
JAVASCRIPT
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> canvas{ border: 1px solid #000; } </style></head><body> <canvas id="mycanvas" width="800" height="600"></canvas> <script> var can =document.getElementById("mycanvas"); var ctx =can.getContext("2d"); function Ball(x,y,r) { this.x =x; this.y =y; this.r =r; this.color =getRandomColor(); this.dx =parseInt(Math.random() *10) - 5; this.dy =parseInt(Math.random() *10) - 5; balArr.push(this) } Ball.prototype.update =function () { this.x +=this.dx this.y +=this.dy this.r -=0.1 if (this.r < 0) { this.remove() } } Ball.prototype.remove =function () { for (let index =0;index < balArr.length;index++) { if (balArr[index] ==this) { balArr.splice(index,1) } } } Ball.prototype.render =function () { ctx.beginPath(); ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false) ctx.fillStyle =this.color ctx.fill() } can.addEventListener("mousemove",function (event) {new Ball(event.offsetX,event.offsetY,Math.random() *13) }) setInterval(() =>{ ctx.clearRect(0,0,can.width,can.height) for (let index =0;index < balArr.length;index++) { balArr[index].update() if (balArr[index]) { balArr[index].render() } } },40) var balArr =[] function getRandomColor() { var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f" var allTypeArr =allType.split(",");var color ="#" for (let index =0;index < 6;index++) { var random =parseInt(Math.random() *allTypeArr.length); color +=allTypeArr[random] } return color } </script></body></html>
小球连线
JAVASCRIPT
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; } canvas{ display: block; } </style></head><body> <canvas id="can" width="800" height="600"></canvas> <script> var ballArr =[] var can =document.getElementById("can");var ctx =can.getContext("2d"); can.width =document.documentElement.clientWidth can.height =document.documentElement.clientHeight function Ball(x,y,r) {this.x =x this.y =y this.r =r this.color=getRandomColor() this.count =0 this.dx =parseInt(Math.random() *10) - 5 this.dy =parseInt(Math.random() *10) - 5 ballArr.push(this) this.index = ballArr.length -1 } Ball.prototype.update =function () { this.x +=this.dx this.y +=this.dy if (this.x <=this.r ||this.x >=can.width - this.r) { this.dx =-this.dx this.count++ this.color=getRandomColor() } if (this.y <=this.r ||this.y >=can.height - this.r) { this.dy =-this.dy this.count++ this.color=getRandomColor() } if (this.count >=3) { this.remove() } } Ball.prototype.remove =function () { for (let index =0;index < ballArr.length;index++) { if (ballArr[index] ==this) { ballArr.splice(index,1) } } } Ball.prototype.render =function () { ctx.beginPath(); ctx.globalAlpha =1 ctx.arc(this.x,this.y,this.r,0,2 *Math.PI,false) ctx.fillStyle =this.color ctx.fill() for (let index = this.index + 1;index < ballArr.length;index++) { if (Math.abs(ballArr[index].x - this.x) < 180 && Math.abs(ballArr[index].y - this.y) < 180) { ctx.strokeStyle = getRandomColor() ctx.beginPath(); ctx.globalAlpha =10 / Math.sqrt(Math.pow(ballArr[index].x - this.x,2) + Math.pow(ballArr[index].y - this.y,2)) ctx.moveTo(this.x,this.y) ctx.lineTo(ballArr[index].x,ballArr[index].y) ctx.closePath() ctx.stroke() } } } can.addEventListener("click",function (event) { for (let index =0;index < Math.ceil(Math.random() *20);index++) { new Ball(event.offsetX,event.offsetY,Math.random() *10 + 10) } }) setInterval(function () { ctx.clearRect(0,0,can.width,can.height) for (let index =0;index < ballArr.length;index++) { ballArr[index].update() ballArr[index].render() } },25) function getRandomColor() { var allType ="0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f" var allTypeArr =allType.split(",");var color ="#" for (let index =0;index < 6;index++) { var random =parseInt(Math.random() *allTypeArr.length); color +=allTypeArr[random] } return color } </script></body></html>
5.线型
方法 / 属性 描述
lineCap 线开头和结束的形状
lineJoin 线交会时的形状,有三种值round,bevel,miter
setLineDash 设置虚线的样式
5.1 蚂蚁线
JS
let canvas = document.getElementById("mycanvas"); let ctx = canvas.getContext('2d'); let offset = 0; function draw() { ctx.clearRect(0,0, canvas.width, canvas.height); ctx.setLineDash([2, 3]); ctx.lineDashOffset = -offset; ctx.strokeRect(10,10, 100, 100); } function march() { offset++; if (offset > 16) { offset = 0; } draw(); setTimeout(march, 20); } march();
5.渐变
方法 / 属性 描述
font 设置字体大小、字体等
textAlign 根据坐标的对齐方式
fillText() (文字,x1,y1)
线型渐变
let line = ctx.createLinearGradient(100,150,300,160);
line.addColorStop(0, 'black');
line.addColorStop(0.5, 'red');
line.addColorStop(1, 'orange');
ctx.fillStyle = line;
ctx.fillRect(100,150,200,10);
镜像渐变
let gradient = ctx.createRadialGradient(200,300,100,200,300,0);
gradient.addColorStop(0,"white");
gradient.addColorStop(.2,"red");
gradient.addColorStop(.4,"orange");
gradient.addColorStop(.6,"green");
gradient.addColorStop(.8,"blue");
gradient.addColorStop(1,"purple");
ctx.fillStyle = gradient;
ctx.fillRect(100,200,200,200);
6.阴影
方法 / 属性 描述
shadowOffsetX X轴偏离像素
shadowOffsetY Y轴偏离像素
shadowBlur 模糊程度
shadowColor 阴影颜色
7.使用图片
let image = new Image();
image.src = "imgs/test1.png";
image.onload = function(){
ctx.drawImage(image, 0, 0, 10, 10,10, 10, 50, 50);
}
前4个参数表示以图片为坐标的x,y,width,height
后4个参数表示以画布为坐标的x,y,width,height
8.资源管理器
<canvas id="mycanvas" width="600" height="400"></canvas>
<script>
function Game(){
this.dom = document.querySelector("canvas");
this.ctx = this.dom.getContext("2d");
let image = new Image();
this.R = {
'test1': "./imgs/test1.png",
'test2': "./imgs/test2.png",
'test3': "./imgs/test3.png",
'test4': "./imgs/test4.png",
'test5': "./imgs/test5.png",
}
let allAmount = Object.keys(this.R).length;
let count = 0;
for(k in this.R){
let src = this.R[k];
this.R[k] = new Image();
this.R[k].src = src;
let self = this;
this.R[k].onload = function(){
count++;
self.ctx.clearRect(0,0,600,400);
self.ctx.font = "16px Arial";
self.ctx.fillText("图片已加载:"+count+"/"+allAmount,10,50);
if(count == allAmount){
self.start();
}
}
}
}
Game.prototype.start = function(){
this.ctx.drawImage(this.R["test1"],200,200,100,100);
}
new Game();
</script>
9.变形
属性/方法
translate 和css的translate一样,空间平移
rotate 参数为旋转角度
scale 缩放(宽度缩放比,高度缩放比)>0 0~1为缩小,>1为放大
transform(a, b, c, d, e, f) a (m11)水平方向的缩放b(m12)竖直方向的倾斜偏移c(m21)水平方向的倾斜偏移d(m22)竖直方向的缩放e(dx)水平方向的移动f(dy)竖直方向的移动
10.滚动的车轮案例
<canvas id="mycanvas" width="1200" height="500"></canvas>
<script>
var canvs = document.getElementById("mycanvas");
var ctx = canvs.getContext('2d');
let img = new Image();
img.src = "imgs/车轮.png";
img.onload = function(){
let deg = 0;
let x = 200;
setInterval(function(){
ctx.clearRect(0, 0, canvs.width, canvs.height);
x+=2;
deg += 0.08;
ctx.save();
ctx.translate(x, 200);
ctx.rotate(deg);
ctx.drawImage(img, -200/2, -200/2);
ctx.restore();
},50);
}
</script>
11.合成
属性/方法 描述
source-in 取重合的部分
source-over 之后的压盖前面的
source-out 取不重合的部分
source-atop 取之前的部分+重合的部分
destination-in 之前的在上层,取重合的部分
destination-atop 重合部分之前的在上层+之后的画布
destination-over 之后的将被压盖
lighter 重合的部分颜色会累加
copy 只显示之后的部分
xor 重合部分为透明
multiply 重合部分像素乘以底层像素
screen 重合部分像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。
overlay 重合部分multiply和screen的结合,原本暗的地方更暗,原本亮的地方更亮。
darken 保留两个图层中最暗的像素。
lighten 保留两个图层中最亮的像素。
color-dodge 将底层除以顶层的反置。
color-burn 将底层除以顶层的反置。
hard-light 屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。
soft-light 用顶层减去底层或者相反来得到一个正值。
difference 一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。
exclusion 和difference相似,但对比度较低。
hue 保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。
saturation 保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma)
color 保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma)
luminosity 保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma)
ctx.globalCompositeOperation = "luminosity";
12.刮刮乐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
border: 1px solid #000;
width: 400px;
height: 120px;
font-size: 40px;
line-height: 120px;
text-align: center;
position: relative;
color: red;
-webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none;
}
#canvas1{
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div>
特等奖
<canvas width="400" height="120" id="canvas1"></canvas>
</div>
<script>
let canvas1 = document.getElementById("canvas1");
let ctx1 = canvas1.getContext('2d');
ctx1.fillStyle = "grey";
ctx1.fillRect(0,0,400,120);
ctx1.globalCompositeOperation = "destination-out";
canvas1.onmousedown = function(e){
canvas1.onmousemove = function(event){
ctx1.beginPath();
ctx1.arc(event.offsetX,event.offsetY,10,0,7,false);
ctx1.fill();
}
}
</script>
</body>
</html>
变形
属性/方法 | |
---|
translate | 和css的translate一样,空间平移 |
rotate | 参数为旋转角度 |
scale | 缩放(宽度缩放比,高度缩放比)>0 ,0~1为缩小,>1为放大 |
transform(a, b, c, d, e, f) | a (m11)水平方向的缩放,b(m12)竖直方向的倾斜偏移,c(m21)水平方向的倾斜偏移,d(m22)竖直方向的缩放,e(dx)水平方向的移动,f(dy)竖直方向的移动 |
滚动的车轮案例
<canvas id="mycanvas" width="1200" height="500"></canvas>
<script>
var canvs = document.getElementById("mycanvas");
var ctx = canvs.getContext('2d');
let img = new Image();
img.src = "imgs/车轮.png";
img.onload = function(){
let deg = 0;
let x = 200;
setInterval(function(){
ctx.clearRect(0, 0, canvs.width, canvs.height);
x+=2;
deg += 0.08;
ctx.save();
ctx.translate(x, 200);
ctx.rotate(deg);
ctx.drawImage(img, -200/2, -200/2);
ctx.restore();
},50);
}
</script>
合成
属性/方法 | 描述 |
---|
source-in | 取重合的部分 |
source-over | 之后的压盖前面的 |
source-out | 取不重合的部分 |
source-atop | 取之前的部分+重合的部分 |
destination-in | 之前的在上层,取重合的部分 |
destination-atop | 重合部分之前的在上层+之后的画布 |
destination-over | 之后的将被压盖 |
lighter | 重合的部分颜色会累加 |
copy | 只显示之后的部分 |
xor | 重合部分为透明 |
multiply | 重合部分像素乘以底层像素 |
screen | 重合部分像素被倒转,相乘,再倒转,结果是一幅更明亮的图片。 |
overlay | 重合部分multiply和screen的结合,原本暗的地方更暗,原本亮的地方更亮。 |
darken | 保留两个图层中最暗的像素。 |
lighten | 保留两个图层中最亮的像素。 |
color-dodge | 将底层除以顶层的反置。 |
color-burn | 将底层除以顶层的反置。 |
hard-light | 屏幕相乘(A combination of multiply and screen)类似于叠加,但上下图层互换了。 |
soft-light | 用顶层减去底层或者相反来得到一个正值 |
difference | 一个柔和版本的强光(hard-light)。纯黑或纯白不会导致纯黑或纯白。 |
exclusion | 和difference相似,但对比度较低。 |
hue | 保留了底层的亮度(luma)和色度(chroma),同时采用了顶层的色调(hue)。 |
saturation | 保留底层的亮度(luma)和色调(hue),同时采用顶层的色度(chroma) |
color | 保留了底层的亮度(luma),同时采用了顶层的色调(hue)和色度(chroma) |
luminosity | 保持底层的色调(hue)和色度(chroma),同时采用顶层的亮度(luma) |
ctx.globalCompositeOperation = "luminosity";
刮刮乐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
border: 1px solid #000;
width: 400px;
height: 120px;
font-size: 40px;
line-height: 120px;
text-align: center;
position: relative;
color: red;
-webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; user-select:none;
}
#canvas1{
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div>
特等奖
<canvas width="400" height="120" id="canvas1"></canvas>
</div>
<script>
let canvas1 = document.getElementById("canvas1");
let ctx1 = canvas1.getContext('2d');
ctx1.fillStyle = "grey";
ctx1.fillRect(0,0,400,120);
ctx1.globalCompositeOperation = "destination-out";
canvas1.onmousedown = function(e){
canvas1.onmousemove = function(event){
ctx1.beginPath();
ctx1.arc(event.offsetX,event.offsetY,10,0,7,false);
ctx1.fill();
}
}
</script>
</body>
</html>