Canvas

Canvas

1.概述

Canvas是HTML5中非常重要的一個(gè)更新亮點(diǎn),畫布,替代Flash的!制作動(dòng)畫、制作游戲。渲染效率非常的高,瀏覽器不需要安裝任何的插件就可以渲染這個(gè)動(dòng)畫。而Flash需要安裝Flash Player這個(gè)插件才行。

Canvas適合動(dòng)態(tài)圖形繪制。小的動(dòng)態(tài)效果也可以使用過渡或動(dòng)畫屬性animation。

echarts圖表使用Canvas繪制,https://echarts.apache.org/zh/index.html

1.1. Hello World

canvas是一個(gè)標(biāo)簽,有一個(gè)默認(rèn)的寬高,此時(shí)注意,如果我們要設(shè)置寬度、高度,必須設(shè)置在HTML標(biāo)簽上面,而不能設(shè)置在CSS上。

注意:

  1. canvas本身布具有繪畫功能, 只是一個(gè)畫布標(biāo)簽, 但是H5提供給js的API具有繪畫功能
2.  IE9一下不兼容
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <canvas id="canvas" width="500" height="500">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    //繪制矩形路徑
    ctx.rect(50, 50, 50, 50);//距離畫布左上角50 50  寬高50 50,只是路徑看不到效果
    //描邊
    ctx.stroke();
    //填充
    // ctx.fill()
  </script>

2. 涉及的API

2.1 getContext()

get表示得到,context是上下文的意思。

canvas起初是空白的。為了展示,首先腳本需要找到渲染上下文,然后在它的上面繪制。<canvas> 元素有一個(gè)做 getContext() 的方法,這個(gè)方法是用來獲得渲染上下文和它的繪畫功能。getContext()只有一個(gè)參數(shù),上下文的格式。

// 首先獲取canvas 標(biāo)簽的dom對象
var mycanvas = document.querySelector("canvas");

// 獲取上下文對象() 參數(shù)是2d繪圖
var ctx = canvas.getContext('2d');

ctx對象,非常重要所有的繪制都是ctx的方法。canvas就是畫布,功能就是生產(chǎn)畫筆,

剩下所有的繪制都是有這支畫筆ctx對象的屬性來操作

//也就是說所有的繪制API都是ctx的事情,而不是canvas對象
ctx.fillStyle = "blue";
ctx.arc(300,300,100,0,Math.PI * 2,true);
ctx.fill();

2.2 繪制圓形 arc()

繪制圓形 arc(x,y,r,start, end, bol)

bol,是布爾值, 跟繪制圓弧有關(guān)

ctx.arc(300,300,100,0,Math.PI * 2,true);
<style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="500" height="500">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    console.log(ctx);
    //繪制一個(gè)圓
    ctx.arc(200, 200, 100, 0, Math.PI * 2, true);//繪制圓的路徑,圓心位置 圓心位置 半徑 起始為0 終止為Math.PI*2 順時(shí)針繪制
    //描邊后才可以看到邊,之前只是路徑
    ctx.strokeStyle = 'blue';//改變描邊顏色
    ctx.stroke();
    //改變填充顏色,填充之前定義填充顏色
    ctx.fillStyle = 'red';
    ctx.fill()//填充
  </script>
2.3 繪制矩形 rect()

繪制矩形 rect(x,y,w,h)

ctx.rect(200, 200, 100, 100);
 <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    //繪制矩形路徑
    ctx.rect(50, 50, 50, 50);//距離畫布左上角50 50  寬高50 50,只是路徑看不到效果
    //描邊
    ctx.stroke();
    //填充
    // ctx.fill()
  </script>
2.4 stroke()筆觸

繪制線條

ctx.stroke()
2.5 fill() 填充
ctx.fill()
2.6 可以合在一起寫
  1. strokeRect(x,y,w,h)

  2. fillRect(x,y,w,h)

    參數(shù):

    x,y 為起點(diǎn)的x,y坐標(biāo)

    w,h 為要繪制矩形的寬高

注意沒有strokeArc 和 fillArc 的寫法

    ctx.strokeRect(100,100,200,100)//通過描邊直接把矩形繪制出來
    ctx.fillRect(200,300,200,100)//填充的時(shí)候直接繪制一個(gè)矩形
2.7 清除 clearRect()

清除clearRect(x,y,w,h)

ctx.clearRect(250, 250, 30, 30);
ctx.clearRect(300,300,100,100)

清除在繪制有先后屬性之分

3. 筆觸和填充

Canvas中能夠產(chǎn)生顏色的是兩個(gè)東西,一個(gè)叫做筆觸(也叫做描邊),一個(gè)叫做填充。

3.1. 筆觸(描邊) strokeRect(x,y,w,h)

參數(shù),x,y 左上角起點(diǎn)坐標(biāo),w,h為繪制矩形的寬高

3.1.1 筆觸的使用:
//筆觸
ctx.strokeRect(100,100,300,40);

你會(huì)發(fā)現(xiàn)只有描邊沒有填充色

而我們剛學(xué)的 fillRect() API繪制的矩形是有填充色的

3.1.2 設(shè)置筆觸的顏色
// 設(shè)置筆觸顏色
ctx.strokeStyle = 'red';
// ctx.strokeStyle = 'hsl(250,50%,50%)'
// 繪制筆觸矩形
ctx.strokeRect(100,100,300,50);

此時(shí)你就會(huì)發(fā)現(xiàn)你繪制的是一個(gè)沒有填充色,只有紅色邊框的矩形

3.1.3 繪制筆觸的寬度
ctx.lineWidth = 20;   // 設(shè)置筆觸的寬為20
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    console.log(ctx);
    //繪制一個(gè)圓
    ctx.arc(200, 200, 100, 0, Math.PI * 2, true);//繪制圓的路徑,圓心位置 圓心位置 半徑 起始為0 終止為Math.PI*2 順時(shí)針繪制
    //描邊后才可以看到邊,之前只是路徑
    ctx.strokeStyle = 'blue';//改變描邊顏色
    ctx.lineWidth =20;
    ctx.stroke();

3.1.4 筆觸繪制線段

劃線之前你的先告訴瀏覽器怎么畫

moveTo() 繪制開始位置 lineTo() 畫筆移動(dòng)的下一個(gè)位置

ctx.moveTo(100,100);    //將畫筆移動(dòng)到一個(gè)位置(先移動(dòng)到開始點(diǎn)的位置)
ctx.lineTo(300,300);    //用畫筆畫,此時(shí)是抽象的一個(gè)線,沒有顯示在畫布上(下一個(gè)點(diǎn)的位置)
ctx.stroke();           //劃線(告訴瀏覽器,我說完了,你畫吧)

我們可以多次使用lineTo:

告訴瀏覽器下一個(gè)點(diǎn)的位置,來繪制相鄰點(diǎn)之間的線段

ctx.moveTo(100,100);    // 將畫筆移動(dòng)到一個(gè)位置
ctx.lineTo(300,300);    // 準(zhǔn)備繪制從開始點(diǎn)到這個(gè)點(diǎn)的線,

ctx.lineTo(300,200);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,
ctx.lineTo(430,180);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,

ctx.stroke();           // 正式開始劃線 
<body>
  <canvas id="canvas" width="500" height="500">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth = 20;//筆觸寬度
    ctx.strokeStyle='red';
    //繪制線段
    //筆尖不在畫布上moveTo
    ctx.moveTo(100, 100)
    //筆尖落在畫布上lineTo繪制路徑
    ctx.lineTo(200, 200)
    ctx.lineTo(200, 300)
    ctx.lineTo(400, 300)
    //筆觸填充
    ctx.stroke()//繪制
  </script>
</body>
3.1.5 閉合路徑

而且我們還可以使用closePath() ,來閉合路徑

就是瀏覽器會(huì)自動(dòng)的在開始點(diǎn)moveTo的點(diǎn)和最后一個(gè)lineTo的結(jié)束點(diǎn)之間繪制一條線

ctx.beginPath();        // 開始準(zhǔn)備畫線
ctx.moveTo(100,100);    // 將畫筆移動(dòng)到一個(gè)位置
ctx.lineTo(300,300);    // 準(zhǔn)備繪制從開始點(diǎn)到這個(gè)點(diǎn)的線,
ctx.lineTo(300,200);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,
ctx.lineTo(430,180);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,

ctx.closePath();        // 閉合路徑(加上就閉合了)

ctx.stroke();           // 正式開始劃線 

繪制新的線段

<body>
  <canvas id="canvas" width="500" height="500">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth = 20;//筆觸寬度
    ctx.strokeStyle = 'red';
    //繪制線段
    //筆尖不在畫布上moveTo
    ctx.moveTo(100, 100)
    //筆尖落在畫布上lineTo繪制路徑
    ctx.lineTo(200, 200)
    //筆觸填充
    ctx.stroke()//繪制
    ctx.moveTo(300, 200)//繪制新的線條
    ctx.lineTo(200, 300)
    ctx.stroke()
  </script>
</body>
3.1.6 繪制新的線條開始(開始新的路徑)

可以使用beginPath() 表示開始一個(gè)新的路徑

ctx.beginPath()
ctx.moveTo(50, 50);
ctx.lineTo(300, 300);
ctx.stroke()

ctx.beginPath()
ctx.lineTo(300, 200);
ctx.lineTo(430, 180);
ctx.stroke()

<body>
  <canvas id="canvas" width="500" height="500">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    //僅僅獲取畫布對象
    let mycanvas = document.getElementById('canvas');
    //通過畫布對象獲取上下文對象(畫筆對象)
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth = 20;//筆觸寬度
    ctx.strokeStyle = 'red';   
    ctx.beginPath()//開始一個(gè)新路徑beginPath() 一段路徑
    ctx.moveTo(100, 100)  
    ctx.lineTo(200, 200)   
    ctx.stroke()
    ctx.beginPath()//開始一個(gè)新路徑beginPath() 一段路徑
    ctx.moveTo(300, 200)
    ctx.lineTo(400, 300)
    ctx.stroke()
  </script>
</body>

可以使用lineWidth屬性設(shè)置線的寬度

ctx.beginPath();        
ctx.moveTo(100,100);    
ctx.lineTo(300,300);    
ctx.lineTo(300,200);    
ctx.lineTo(430,180);    

ctx.strokeStyle = 'red';// 繪制描邊的顏色
ctx.closePath();        // 閉合路徑
ctx.lineWidth = '10';   // 繪制線的寬度
ctx.stroke();   

ctx.filStyle = 'skyblue';// 繪制填充顏色
ctx.fill();             // 繪制填充色  
3.1.7 繪制線條的轉(zhuǎn)角

lineJoin : 邊界連接點(diǎn)樣式,要在畫ctx.stroke()之前設(shè)置轉(zhuǎn)角

  1. miter(默認(rèn)值),
  2. round(圓角),
  3. bevel(平角)
ctx.moveTo(50, 50);
ctx.lineTo(300, 300);

ctx.lineTo(300, 200);
ctx.lineTo(430, 180);
ctx.closePath()
ctx.strokeStyle = 'red';
ctx.lineWidth = 20;
ctx.lineJoin = 'round'
ctx.stroke()
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.beginPath();
    ctx.moveTo(100, 100);
    ctx.lineTo(300, 300);
    ctx.lineTo(300, 200);
    ctx.lineTo(430, 180);
    ctx.strokeStyle = 'red';
    ctx.closePath();
    ctx.lineWidth = '10';
    ctx.lineJoin = 'round'//線條轉(zhuǎn)角 
    ctx.stroke();
  </script>
</body>
3.1.8 端點(diǎn)樣式

lineCap: 端點(diǎn)樣式

  1. butt(默認(rèn)值),
  2. round(圓角) (寬度左右兩邊分別多出線高的一半)
  3. square(寬度左右兩邊分別多出線高的一半)
ctx.moveTo(50, 50);
ctx.lineTo(300, 300);
ctx.strokeStyle = 'red';
ctx.lineWidth = 50;
ctx.lineCap = 'round'
ctx.stroke()
    ctx.beginPath();
    ctx.moveTo(490, 100);
    ctx.lineTo(490, 350);
    ctx.strokeStyle = 'blue';
    ctx.lineCap = 'butt'//默認(rèn)
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(450, 100);
    ctx.lineTo(450, 350);
    ctx.strokeStyle = 'blue';
    ctx.lineCap = 'round'//圓角,線段寬度左右兩端分別多出線高的一半
    ctx.stroke();

    ctx.beginPath();
    ctx.moveTo(410, 100);
    ctx.lineTo(410, 350);
    ctx.strokeStyle = 'blue';
    ctx.lineCap = 'square'//平角,線段寬度左右兩端分別多出線高的一半
    ctx.stroke();   
3.2. 填充 fill()

還可以是用fill()給閉合路徑后的閉合區(qū)域填充顏色

ctx.beginPath();        // 開始準(zhǔn)備畫線
ctx.moveTo(100,100);    // 將畫筆移動(dòng)到一個(gè)位置
ctx.lineTo(300,300);    // 準(zhǔn)備繪制從開始點(diǎn)到這個(gè)點(diǎn)的線,
ctx.lineTo(300,200);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,
ctx.lineTo(430,180);    // 準(zhǔn)備繪制從上一個(gè)點(diǎn)到這個(gè)點(diǎn)的線,
ctx.closePath();        // 閉合路徑
ctx.stroke();           // 正式開始劃線 

ctx.fill();             // 繪制填充色
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.fillStyle = 'red';
    ctx.lineWidth = 10;

    ctx.moveTo(200, 200);
    ctx.lineTo(200, 400);
    ctx.lineTo(400, 400);
    ctx.lineTo(400, 200);
    // ctx.closePath()閉合路徑的方法之一  筆觸
    // ctx.stroke();
    ctx.fill()//使用填充會(huì)自動(dòng)閉合路徑
  </script>
</body>
3.2.1 繪制填充顏色 fillStyle

strokeStyle 屬性修改描邊顏色

fillStyle 屬性修改填充顏色

ctx.beginPath();        
ctx.moveTo(100,100);    
ctx.lineTo(300,300);    
ctx.lineTo(300,200);    
ctx.lineTo(430,180);    

ctx.strokeStyle = 'red';// 繪制描邊的顏色
ctx.closePath();        // 閉合路徑
ctx.stroke();   

ctx.filStyle = 'skyblue';// 繪制填充顏色
ctx.fill();             // 繪制填充色  

4.弧與圓形

1.1. 繪制弧度及圓形的公式
ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise)
參數(shù)
  1. x,y為圓心的坐標(biāo)
  2. radius 為圓形的半徑
  3. startAngle 為弧度的起始位置,0是正x軸的
  4. endAngle 為弧度的終點(diǎn)位置,
  5. anticlockwise 布爾值,true為逆時(shí)針繪制,false為順時(shí)針繪制
注意

canvas中的度數(shù)都是弧度制

弧和圓形也是筆觸(描邊),所以也需要以beginPath()開始

var ctx = mycanvas.getContext('2d');

ctx.beginPath();
ctx.arc(150,150,100,0,2*Math.PI,false);

ctx.arc(200,200,100,0,2,false);

ctx.arc(150,150,100,2,2,false);
ctx.fill();

ctx.beginPath();
ctx.arc(150,150,100,2,0,true);
ctx.strokeStyle= 'red';
ctx.lineWidth = 2;
ctx.stroke();
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');

    ctx.fillStyle = 'red';
    ctx.lineWidth = 10;

    ctx.beginPath();
    ctx.arc(250, 250, 100, 0, Math.PI * 0.5, false);
    ctx.stroke()

    ctx.beginPath();
    ctx.arc(450, 450, 100, Math.PI * 1.5, Math.PI * 0.5, false);
    ctx.stroke()
  </script>
</body>

5. 繪制曲線

5.1. 繪制弧度曲線

arcTo(x1,y1,x2,y2,r)
x1,y1 坐標(biāo)一 x2,y2坐標(biāo)二 r圓弧半徑

ctx.moveTo(100, 300)
ctx.arcTo(100, 100, 200, 100, 50)
ctx.stroke()
 <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.beginPath();
    ctx.lineWidth = 10;
    ctx.strokeStyle = 'red';
    ctx.moveTo(100, 300);
    ctx.arcTo(100, 100, 200, 100, 50);//弧線
    ctx.stroke()

    ctx.beginPath();
    ctx.moveTo(150, 200);
    ctx.arcTo(150, 100, 200, 100, 400);
    ctx.stroke()
  </script>
</body>
5.2. 繪制貝塞爾曲線
繪制公式
ctx.quadraticCurveTo(cp1x,cp1y,x,y)
參數(shù)
  1. cp1x, cp1y 為貝塞爾曲線的控制點(diǎn)
  2. x,y 為繪制曲線的終點(diǎn)
ctx.beginPath()
ctx.moveTo(100,100);
ctx.quadraticCurveTo(200,100,200,200)
ctx.stroke();
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.beginPath();
    ctx.lineWidth = 10;
    ctx.strokeStyle = 'red';
    ctx.moveTo(100,100);//起點(diǎn)
    //ctx.lineTo(300,100)//終點(diǎn)
    ctx.quadraticCurveTo(150,400,300,100)//一次貝塞爾曲線,貝塞爾控制點(diǎn)(150,400),終點(diǎn)
    ctx.stroke()
5.3. 繪制二次貝塞爾曲線
繪制公式
ctx.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)
參數(shù)
  1. cp1x, cp1y 為貝塞爾曲線的第一個(gè)控制點(diǎn)
  2. cp2x, cp3y 為貝塞爾曲線的第二個(gè)控制點(diǎn)
  3. x,y 為繪制曲線的終點(diǎn)
ctx.beginPath()
ctx.moveTo(100,100);
ctx.bezierCurveTo(200,120,50,150,200,200);
ctx.stroke();
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.beginPath();
    ctx.lineWidth = 10;
    ctx.strokeStyle = 'red';
    ctx.moveTo(100,100);//起點(diǎn)
    // ctx.bezierCurveTo(150,100,300,100,500,100)點(diǎn)都在一條線上的貝塞爾曲線
  
    ctx.bezierCurveTo(150,300,300,-50,500,100)//貝塞爾端點(diǎn)一  貝塞爾端點(diǎn)二 終點(diǎn)
    ctx.stroke()   
  </script>

6. canvas變換

6.1. translate(x,y)

坐標(biāo)基準(zhǔn)點(diǎn)偏移 : 從起始點(diǎn)為基準(zhǔn),移動(dòng)到當(dāng)前位置

ctx.translate(100, 100)ctx.arc(100, 100, 50, 0, Math.PI * 2, true)ctx.strokeStyle = 'red';ctx.lineWidth = 5;ctx.stroke()
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth=10;
    ctx.strokeStyle='red';
    
    ctx.translate(100,100);//可以理解為偏移基準(zhǔn)點(diǎn)
    ctx.arc(100, 100,50,0,Math.PI*2,true)//元素位置通過基準(zhǔn)點(diǎn)與參考點(diǎn)配合確定,調(diào)誰都可以
    ctx.stroke();
  </script>
</body>
6.2.rotate(弧度):

旋轉(zhuǎn) 弧度公式 :角度*PI/180

ctx.rotate(Math.PI / 180 * 30)
ctx.rect(200, 200, 100, 100)
ctx.strokeStyle = 'red';
ctx.lineWidth = 5;

ctx.stroke()
 let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth=10;
    ctx.strokeStyle='red';
    ctx.translate(100,100)//基準(zhǔn)點(diǎn)
        ctx.rotate(Math.PI/180 *80);//旋轉(zhuǎn),弧度值轉(zhuǎn)成角度值
    ctx.strokeRect(0,0,100,100)//參考點(diǎn)在自己中心位置
    ctx.strokeRect(-50,-50,100,100)//參考點(diǎn)在自己中心位置

6.3. scale(wb,hb)

縮放比例(縮放canvas繪制的圖片)

ctx.scale(1.5, 1.5)
ctx.rect(200, 200, 100, 100)
ctx.strokeStyle = 'red';
ctx.lineWidth = 5;

ctx.stroke()

這里將寬、高、圓心坐標(biāo)等比縮放

  let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.lineWidth=10;
    ctx.strokeStyle='red';
    ctx.scale(1,0.5);//縮放  基準(zhǔn)點(diǎn) 寬 高 線寬都等比例縮放
    ctx.strokeRect(200,200,50,100)

示例:

var can = document.getElementById("canvas");
ctx = can.getContext("2d");

ctx.beginPath();
ctx.translate(160,30);
ctx.fillStyle = "#00ff00";
ctx.fillRect(0,0,100,50);

for (var i=0;i<50 ;i++ ){
    ctx.translate(25,25);
    ctx.scale(0.9,0.9);//縮放,針對后面要繪制的圖形進(jìn)行縮放(在前面繪制的那個(gè)圖形的基礎(chǔ)上進(jìn)行縮放)
    ctx.rotate(Math.PI/10);
    ctx.fillRect(0,0,100,50);
}

7. 保存與恢復(fù)路徑

7.1. 保存路徑 save()

保存之前的路徑狀態(tài)

7.2.恢復(fù)路徑 restore()
ctx.save()
ctx.scale(3, 2)
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 20)
ctx.restore()


ctx.beginPath()
ctx.fillRect(0, 50, 100, 20)

會(huì)封閉一個(gè)獨(dú)立路徑 不會(huì)對外邊的區(qū)域產(chǎn)生影響

  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      margin: 50px auto;
      background-color: #fff;
    }
  </style>
</head>

<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let mycanvas = document.getElementById('canvas');
    let ctx = mycanvas.getContext('2d');
    ctx.strokeStyle = 'blue';
    ctx.beginPath();
    ctx.save()//保存之前的的路徑狀態(tài)
    ctx.strokeStyle = 'red';
    ctx.lineWidth = 10;

    ctx.moveTo(100, 100);
    ctx.lineTo(300, 100);
    ctx.stroke()
    ctx.beginPath()
    ctx.restore() //恢復(fù)之前保存的路徑狀態(tài)
    ctx.moveTo(100, 200);
    ctx.lineTo(300, 200);
    ctx.stroke()
  </script>

8 繪制圖片

8.1. 繪制圖片
8.1.1 創(chuàng)建圖片對象,獲取圖片

圖片預(yù)加載,獲取圖片文件

const img = new Image();
img.src = '../1.jpg'
8.1.2 onload事件,當(dāng)圖片加載完成執(zhí)行繪制
img.onload = function(){}
8.1.3 圖片加載完成后將圖片繪制在畫布上

ctx.drawImage(image, dx, dy, dWidth, dHeight);

繪制圖片(圖片對象,畫布坐標(biāo)x,畫布坐標(biāo)y,繪制顯示圖片寬度,繪制顯示圖片高度)

const img = new Image();
img.src = '../1.jpg';
img.onload = function () {
    ctx.drawImage(this, 0, 0, 100, 300)
}
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let img = new Image();//創(chuàng)建圖片對象
    img.src = './imgs/11.jpg';
    img.onload = function () {//加載就會(huì)觸發(fā)onload事件
      ctx.drawImage(this, 20, 20, 300, 300);//畫圖片
    }
  </script>
</body>
8.1.4 切圖

ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

參數(shù):

  1. image 繪制到上下文的元素

  2. sx 可選

    需要繪制到目標(biāo)上下文中的,image的矩形(裁剪)選擇框的左上角 X 軸坐標(biāo)。

  3. sy 可選

    需要繪制到目標(biāo)上下文中的,image的矩形(裁剪)選擇框的左上角 Y 軸坐標(biāo)。

  4. sWidth 可選

    需要繪制到目標(biāo)上下文中的,image的矩形(裁剪)選擇框的寬度。

  5. sHeight 可選

    需要繪制到目標(biāo)上下文中的,image的矩形(裁剪)選擇框的高度。

  6. dx

    image的左上角在目標(biāo)canvas上 X 軸坐標(biāo)。

  7. dy

    image的左上角在目標(biāo)canvas上 Y 軸坐標(biāo)。

  8. dWidth 可選

    image在目標(biāo)canvas上繪制的寬度。

  9. dHeight 可選

    image在目標(biāo)canvas上繪制的高度。 允許對繪制的image進(jìn)行縮放。

const img = new Image();
img.src = '../1.jpg';
img.onload = function () {
    ctx.drawImage(this, 50, 50, 500, 500, 100, 100, 100, 100)
}
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let img = new Image();//創(chuàng)建圖片對象
    img.src = './imgs/11.jpg';
    img.onload = function () {//加載就會(huì)觸發(fā)onload事件
      ctx.drawImage(this, 20, 20, 300, 300);//畫圖片
      ctx.drawImage(this, 50, 50, 100, 100, 20, 350, 300, 300);//可以做放大鏡
    }
  </script>
</body>
  <style>
    * {
      margin: 0;
      padding: 0;
    }

    body {
      background-color: #f3f3f3;
    }

    #canvas {
      /*canvas雖然默認(rèn)寬高300X150,但它是個(gè)行元素inline*/
      display: block;
      /*變塊才能居中*/
      background-color: #fff;
    }
  </style>
</head>
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let img = new Image();//創(chuàng)建圖片對象
    img.src = './imgs/11.jpg';
    img.onload = function () {//加載就會(huì)觸發(fā)onload事件
      ctx.drawImage(this, 20, 20, 300, 300);//畫圖片
      canvas.onmousemove = function (e) {
        console.log(e);
        let sX = e.clientX - 50;
        let sY = e.clientY - 50;
        ctx.drawImage(img, sX, sY, 100, 100, 20, 350, 300, 300);
      }
    }
  </script>
</body>
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let img = new Image();//創(chuàng)建圖片對象
    img.src = './imgs/11.jpg';
    img.onload = function () {//圖片加載就會(huì)觸發(fā)onload事件
      //創(chuàng)建背景圖片填充資源
      let bg = ctx.createPattern(this, 'repeat')
      ctx.fillStyle = bg;//填充背景資源
      ctx.fillRect(0, 0, 500, 500)//填充一個(gè)矩形
    }
  </script>
</body>
8.2. 填充背景
8.2.1 createPattern(img,平鋪方式)

參數(shù): 平鋪方式:repeat,repeat-x,repeat-y,no-repeat

const img = new Image();
img.src = '../1.jpg';
img.onload = function () {
    const bg = ctx.createPattern(img, 'no-repeat');
    ctx.fillStyle = bg;
    ctx.fillRect(100, 100, 300, 200)
}
8.3. 顏色漸變
8.3.1 線性漸變:createLinearGradient(x1,y1,x2,y2)
x1,y1起始坐標(biāo)點(diǎn)

x2,y2結(jié)束坐標(biāo)點(diǎn)
8.3.2 徑向漸變:createRadialGradient(x1,y1,r1,x2,y2,r2)
x1,y1,r1內(nèi)圓坐標(biāo)及半徑

x2,y2,r2外圓坐標(biāo)及半徑
8.3.3 addColorStop(位置,顏色)
位置:漸變點(diǎn)  0-1之間 可多個(gè)

例子,

線性漸變

let color = ctx.createLinearGradient(0, 0, 500, 500);
color.addColorStop(0, 'pink');
color.addColorStop(0.5, 'yellow')
color.addColorStop(1, 'deeppink')

ctx.fillStyle = color;
ctx.fillRect(0, 0, 500, 500)
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let color = ctx.createLinearGradient(0, 0, 500, 500)//漸變顏色對象
    color.addColorStop(0, 'red')//添加顏色
    color.addColorStop(.5, 'yellow')
    color.addColorStop(1, 'blue')
    ctx.fillStyle = color;//用漸變顏色填充
    ctx.fillRect(0, 0, 500, 500)
  </script>
</body>

徑向漸變

let color = ctx.createRadialGradient(200, 200, 100, 200, 200, 200);
color.addColorStop(0, 'pink');
color.addColorStop(0.5, 'yellow')
color.addColorStop(1, 'deeppink')

ctx.fillStyle = color;
ctx.fillRect(0, 0, 500, 500)
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    //加載圖片
    let color = ctx.createRadialGradient(200,200,50,200,200,300)//漸變顏色對象
    color.addColorStop(0, 'red')//添加顏色
    color.addColorStop(.5, 'yellow')
    color.addColorStop(1, 'blue')
    ctx.fillStyle = color;//用漸變顏色填充
    // ctx.fillRect(0, 0, 500, 500)
    ctx.fillRect(0, 0, 100, 100)
  </script>
</body>

9.繪制文本

9.1. 繪制文本
  1. strokeText(文本,x,y); 繪制空心文本(描邊文字)
  2. fillText(文本,x,y); 繪制實(shí)心文本(填充文字)
  3. font = "font-size font-family" 注:尺寸 字體缺一不可
  4. textAlign = "";文本左右對齊方式 (參考文字坐標(biāo)點(diǎn)對齊)
    start center end left right
  5. textBaseline文本上下對齊方式
    alphabetic 默認(rèn)。文本基線是普通的字母基線。
    top 文本基線是 em 方框的頂端。。
    hanging 文本基線是懸掛基線。
    middle 文本基線是 em 方框的正中。
    ideographic 文本基線是表意基線。
    bottom 文本基線是 em 方框的底端。
let str = 'wuwei'
ctx.font = '50px 宋體'
ctx.textAlign = 'center'
ctx.textBaseline = 'top'
ctx.strokeText(str, 100, 100)
ctx.fillText(str, 100, 200)
9.2. 繪制陰影
  1. shadowOffsetX,shadowOffsetY x軸、y軸偏移
  2. shadowBlur 陰影模糊度
  3. shadowColor 陰影顏色
    默認(rèn)顏色:rgba(0,0,0,0)
ctx.shadowOffsetX = '10'
ctx.shadowOffsetY = '10'
ctx.shadowBlur = '3'
ctx.shadowColor = 'red'

案例:

body {
    background-color: #000;
}
canvas {
    display: block;
    margin: 100px auto 0;
    border: 1px solid skyblue;
    background-color: #fff;
}
.box{
    width: 360px;
    margin: 10px auto;
}
input{
    width: 50px;
    height: 20px;
    text-align: center;
}
<canvas width="500" height="500"></canvas>
<div class="box">
    <input type="color" id='colorList'>
    <button id='color'>隨機(jī)顏色</button>
    <input type="text" value='2px' id='storke'>
    <button id='add'>筆觸增加</button>
    <button id='reduce'>筆觸減小</button>
    <button id="clear">清屏</button>
</div>
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');

var strokeColor = '#000000';
var lineWidth = 2;

colorList.onchange = function () {
    strokeColor = colorList.value;
}

color.onclick = function () {
    strokeColor = '#' + Math.random().toString(16).slice(2, 8);
    colorList.value = strokeColor;
}
add.onclick = function () {
    if (lineWidth >= 10) return;
    lineWidth += 2;
    storke.value = lineWidth + 'px'

}
reduce.onclick = function () {
    if (lineWidth <= 2) return;
    lineWidth -= 2;
    storke.value = lineWidth + 'px'
}



canvas.onmousedown = function (ev) {
    ev = ev || window.event;
    var This = this;
    var x = ev.clientX - this.offsetLeft;
    var y = ev.clientY - this.offsetTop;
    ctx.strokeStyle = strokeColor;
    ctx.lineWidth = lineWidth;
    ctx.beginPath();
    ctx.moveTo(x, y);
    document.onmousemove = function (ev) {
        ev = ev || window.event;
        var x = ev.clientX - This.offsetLeft;
        var y = ev.clientY - This.offsetTop;
        ctx.lineTo(x, y);
        ctx.stroke();

    }
    document.onmouseup = function () {
        this.onmousemove = null;
        this.onmouseup = null
    }
}
clear.onclick = function () {
    console.log(1)
    ctx.clearRect(0, 0, 500, 500)

}
<body>
  <canvas id="canvas" width="700" height="600">你的瀏覽器不支持canvas,請升級</canvas>
  <script>
    let canvas = document.getElementById('canvas');
    let ctx = canvas.getContext('2d');
    let str = 'hello world';
    ctx.font = '50px 微軟雅黑'
    ctx.textAlign = 'left'
    ctx.textBaseline = 'top'
    ctx.shadowOffsetX = '10'//水平偏移
    ctx.shadowOffsetY = '10'//垂直偏移
    ctx.shadowBlur = '3'//模糊
    ctx.shadowColor = 'red'//顏色
    ctx.strokeText(str, 50, 200)//空心文字

    let str2 = '你好呀';
    ctx.font = '50px 微軟雅黑'
    ctx.textAlign = 'left'
    ctx.textBaseline = 'middle'
    ctx.fillText(str2, 400, 200)//實(shí)心文字
  </script>
</body>

10.API使用總結(jié)

10.1. canvas標(biāo)簽
<canvas width="" height="" id="">
    您的瀏覽器不支持canvas,請更換瀏覽器!
</canvas>

默認(rèn)寬度300px,默認(rèn)高度 150px

10.2. canvas繪圖環(huán)境設(shè)置
getContext("2d"); 目前支持2d繪圖環(huán)境
10.3. 繪圖路徑:
  1. beginPath() :開始路徑
  2. closePath():閉合路徑
  3. moveTo(x,y):將觸筆移動(dòng)到x,y點(diǎn)
  4. lineTo(x,y):繪制到x,y點(diǎn)
  5. stroke(): 觸筆方法 畫線 默認(rèn)為黑色
  6. fill():填充方法
  7. rect(x,y,w,h):矩形路徑
  8. save():保存路徑
  9. restore():恢復(fù)路徑
10.4. 繪制矩形:
  1. fillRect(x,y,w,h) 填充實(shí)心矩形
  2. strokeRect(x,y,w,h) 繪制空心矩形
  3. clearRect(x,y,w,h) 清除矩形選區(qū)
10.5. 設(shè)置繪圖樣式:
  1. fillStyle: 填充顏色
  2. strokeStyle: 觸筆顏色
  3. lineWidth: 觸筆寬度(線寬)
10.6. 圖形邊界樣式:
  1. lineJoin : 邊界連接點(diǎn)樣式
    miter(默認(rèn)值),round(圓角),bevel(斜角)
  2. lineCap: 端點(diǎn)樣式
    butt(默認(rèn)值),round(圓角),square(高度多出線寬一半)
10.7. 繪制圓形:
  1. arc(x,y,r,0,360,false)
    x,y 圓心坐標(biāo)位置
    r 圓半徑
    0,360 從0度到360度 繪制一個(gè)圓形(用弧度公式)
    true/false 逆時(shí)針/順時(shí)針繪圖
10.8. 繪制曲線
  1. arcTo(x1,y1,x2,y2,r)
    x1,y1 坐標(biāo)一 x2,y2坐標(biāo)二 r圓弧半斤
  2. quadraticCurveTo(dx,dy,x1,y1)
    貝塞爾曲線:dx,dy控制點(diǎn) x1,y1結(jié)束坐標(biāo)
  3. bezierCurveTo(dx1,dy1,dx2,dy2,x1,y1)
    貝塞爾曲線:dx1,dy1 控制點(diǎn)一 dx2,dy2控制點(diǎn)二
    x1,y1結(jié)束坐標(biāo)
10.9. canvas變換
  1. translate(x,y)
    坐標(biāo)基準(zhǔn)點(diǎn)偏移 : 從起始點(diǎn)為基準(zhǔn),移動(dòng)到當(dāng)前位置
  2. rotate(弧度): 旋轉(zhuǎn) 弧度公式 :角度*PI/180
  3. scale(wb,hb)縮放比例(縮放canvas繪制的圖片)
10.10. 繪制圖片
  1. 圖片預(yù)加載,獲取圖片文件
  2. onload事件,監(jiān)聽圖片是否加載完畢,如果加載完畢執(zhí)行第三步
  3. drawImage(img,x,y,w,h);繪制圖片(圖片,坐標(biāo)x,坐標(biāo)y,寬度,高度)
10.11.設(shè)置背景
  1. createPattern(img,平鋪方式)
    平鋪方式:repeat,repeat-x,repeat-y,no-repeat
10.12. 顏色漸變
  1. 線性漸變:createLinearGradient(x1,y1,x2,y2)
    x1,y1起始坐標(biāo)點(diǎn)
    x2,y2結(jié)束坐標(biāo)點(diǎn)
  2. 徑向漸變:createRadialGradient(x1,y1,r1,x2,y2,r2)
    x1,y1,r1內(nèi)圓坐標(biāo)及半徑
    x2,y2,r2外圓坐標(biāo)及半徑
  3. addColorStop(位置,顏色)
    位置:漸變點(diǎn) 0-1之間 可多個(gè)
10.13. 繪制文本
  1. strokeText(文本,x,y); 繪制空心文本
  2. fillText(文本,x,y); 繪制實(shí)心文本
  3. font = "font-size font-family" 注:尺寸 字體缺一不可
  4. textAlign = "";文本左右對齊方式
    start center end left right
  5. textBaseline文本上下對齊方式
    alphabetic 默認(rèn)。文本基線是普通的字母基線。
    top 文本基線是 em 方框的頂端。。
    hanging 文本基線是懸掛基線。
    middle 文本基線是 em 方框的正中。
    ideographic 文本基線是表意基線。
    bottom 文本基線是 em 方框的底端。
10.14. 陰影
  1. shadowOffsetX,shadowOffsetY x軸、y軸偏移
  2. shadowBlur 陰影模糊度
  3. shadowColor 陰影顏色
  4. 默認(rèn)顏色:rgba(0,0,0,0)
畫板例子
<!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>
    body {
      background-color: #000;
    }

    canvas {
      display: block;
      margin: 10px auto 0;
      border: 1px solid skyblue;
      background-color: #fff;
    }

    .box {
      width: 500px;
      margin: 10px auto;
    }

    input {
      width: 50px;
      height: 20px;
      text-align: center;
    }
  </style>
</head>
<body>
  <canvas width="600" height="400"></canvas>
  <div class="box">
    <input type="color" id='colorList'>
    <!--type類型為color表示顏色選擇器 -->
    <button id='color'>隨機(jī)顏色</button>
    <input type="text" value='2px' id='storke' disabled> <!-- input 的阻止頁面上手動(dòng)編輯 disabled -->

    <button id='add'>筆觸增加</button>
    <button id='reduce'>筆觸減小</button>
    <button id="clear">清屏</button>
  </div>
  <script>
    //獲取canvas
    let canvas = document.getElementsByTagName('canvas')[0];
    // 獲取上下文對象(畫筆)
    let ctx = canvas.getContext('2d');
    //信號量 定義初始畫筆的顏色和大小
    let strokeColor = '#000000';//筆觸顏色信號量
    let lineWidth = 2;//筆觸大小信號量
    //清屏
    clear.onclock = function () {
      ctx.clearRECT(0, 0, 600, 400)
    }
    // 顏色選擇
    colorList.onchange = function () {
      strokeColor = this.value;
    }
    //隨機(jī)顏色
    color.onclick = function () {
      strokeColor = '#' + Math.random().toString(16).substr(2, 6);
      colorList.value = strokeColor//滑條顏色與隨機(jī)顏色保持一致
    }
    //加減筆觸
    add.onclick = function () {
      lineWidth += 2;      //畫筆值與頁面顯示保持一致
      storke.value = lineWidth + 'px';
    }
    reduce.onclick = function () {
      lineWidth -= 2;
      storke.value = lineWidth + 'px';
    }
    //繪制
    canvas.onmousedown = function (ev) {
      ev = ev || window.event//事件對象做兼容
      //獲取鼠標(biāo)按下時(shí)距離畫布左上端點(diǎn)的距離 x 有
      let x = ev.clientX - this.offsetLeft;//事件對象距離瀏覽器左邊的距離減去canvas距離瀏覽器左邊的距離
      let y = ev.clientY - this.offsetTop;
      //繪制
      ctx.strokeStyle = strokeColor;
      ctx.lineWidth = lineWidth;
      //開啟新路徑
      ctx.beginPath();
      ctx.moveTo(x, y);//鼠標(biāo)按下 繪制的坐標(biāo)就移動(dòng)到x y位置

      document.onmousemove = function (ev) {
        //使用外部this方法一 let This = this;定義一個(gè)大This,將外部this傳給里面的This
        //使用外部this方法二 .bind(this)
        //使用外部this方法三 箭頭函數(shù) (ev)=>{} 箭頭函數(shù)沒有this,只能向上找this
        ev = ev || window.event;
        let x = ev.clientX - this.offsetLeft;
        let y = ev.clientY - this.offsetTop;
        ctx.lineTo(x, y);
        ctx.stroke();
      }.bind(this)
      //現(xiàn)在的線段是由鼠標(biāo)拖出來的
      document.onmouseup = function () {//清理事件。鼠標(biāo)抬起說明畫完了,清理默認(rèn)事件.onmousedown事件是入口不清理
        this.onmousemove = null;
        this.onmouseup = null;
      }
    }
  </script>
</body>

</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容