粤虎 發表於 2021-5-12 16:59:00

html5基础---canvas

<h3 id="1-canvas简介">1. canvas简介</h3>
<p>​        <code>&lt;canvas&gt;</code> 是 HTML5 新增的元素,可用于通过使用JavaScript中的脚本来绘制图形</p>
<p>​        <strong>· 使用<code>&lt;canvas&gt;</code>标签时,建议要成对出现,不要使用闭合的形式。</strong></p>
<p>​        <strong>· canvas元素默认具有高宽</strong></p>
<pre><code class="language-css">        width: 300px
        height: 150px
</code></pre>
<hr>
<h3 id="2-替换内容">2. 替换内容</h3>
<p>​        由于某些较老的浏览器(尤其是IE9之前的IE浏览器)<strong>不支持</strong>HTML元素<code>&lt;canvas&gt;</code>,但在这些浏览器上你应该要给用户展示些替代内容。这非常简单:我们只需要在<code>&lt;canvas&gt;</code><strong>标签内部</strong>提供替换内容就可以。<br>
​        <strong>·</strong> 支持<code>&lt;canvas&gt;</code>的浏览器将会忽略在容器中包含的内容,并且只是正常渲染canvas。<br>
​        <strong>·</strong> 不支持<code>&lt;canvas&gt;</code>的浏览器会显示代替内容。</p>
<hr>
<h3 id="3-canvas的宽和高属性">3. canvas的宽和高属性</h3>
<p>​        <strong>·</strong> html属性设置width、height时只影响画布本身不影画布内容。**★推荐使用 **<br>
​        <strong>·</strong> css属性设置width、height时不但会影响画布本身的高宽,还会使画布中的内容等比例缩放(缩放参照于画布默认的尺寸)。</p>
<hr>
<h3 id="4-渲染上下文">4. 渲染上下文</h3>
<p>​        <strong>· getContext() ,这个方法是用来获得渲染上下文和它的绘画功能。</strong></p>
<pre><code class="language-js">var canvas = document.getElementById('canvas');
if (canvas.getContext){
    var ctx = canvas.getContext('2d');
}
</code></pre>
<hr>
<h3 id="5-绘制矩形">5. 绘制矩形</h3>
<p>​        <strong>canvas只支持一种原生的图形绘制:矩形。所有其他的图形的绘制都至少需要生成一条路径。</strong></p>
<h5 id="-三个方法">· 三个方法:</h5>
<pre><code class="language-js">        // 绘制一个填充的矩形(填充色默认为黑色)
        fillRect(x, y, width, height)
        // 绘制一个矩形的边框(默认边框为:一像素实心黑色)
        strokeRect(x, y, width, height)
        // 清除指定矩形区域,让清除部分完全透明。       
        clearRect(x, y, width, height)

        // x、y不带单位
        // x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。
        // width和height设置矩形的尺寸。(存在边框的话,边框会在width上占据一个边框的宽度,height同理)
</code></pre>
<p>​                <strong>strokeRect时,边框像素渲染问题</strong><br>
​                        按理渲染出的边框应该是1px的,canvas在渲染矩形边框时,边框宽度是平均分在偏移位置的两侧。<br>
​                        <code>context.strokeRect(10,10,50,50)</code><br>
​                                边框会渲染在10.5 和 9.5之间,浏览器不支持小数的像素,自动取整,边框会渲染在9到11之间。<br>
​                        <code>context.strokeRect(10.5,10.5,50,50)</code>   边框会渲染在10到11之间    <strong>★★ 推荐使用</strong></p>
<h5 id="-添加样式和颜色">· 添加样式和颜色</h5>
<pre><code class="language-js">        // 同步渲染,必须在绘画之前定义,而且后面定义的样式会覆盖到前面声明的样式上面。
        // 用法与上述三个方法相同

        fillStyle: 设置图形的填充颜色。
        strokeStyle: 设置图形轮廓的颜色。
                默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000)
        lineWidth: 这个属性设置当前绘线的粗细。属性值必须为正数。
                描述线段宽度的数字。 0、 负数、 Infinity 和 NaN 会被忽略。
                默认值是1.0。
    lineJoin: 设定线条与线条间接合处的样式(默认是 miter)
      round : 圆角
      bevel : 斜角
      miter : 直角
</code></pre>
<hr>
<h3 id="6-绘制路径">6. 绘制路径</h3>
<h5 id="-步骤">· 步骤</h5>
<pre><code>1.首先,你需要创建路径起始点。
2.然后你使用画图命令去画出路径。
3.之后你把路径封闭。
4.一旦路径生成,你就能通过描边或填充路径区域来渲染图形。
</code></pre>
<h5 id="-api">· API</h5>
<pre><code class="language-js">beginPath()--&gt; 清空路径容器
        新建一条路径,生成之后,图形绘制命令被指向到路径上准备生成路径。

moveTo(x, y)--&gt; 抬笔
        将笔触移动到指定的坐标x以及y上
        当canvas初始化或者beginPath()调用后,你通常会使用moveTo()函数设置起点
       
lineTo(x, y)--&gt; 移动笔
        将笔触移动到指定的坐标x以及y上
        绘制一条从当前位置到指定x以及y位置的直线。

closePath()--&gt; 闭合路径
        闭合路径之后图形绘制命令又重新指向到上下文中。
                闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。
        如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做
                当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。
        但是调用stroke()时不会自动闭合
       
stroke() --&gt; 绘制线框
        通过线条来绘制图形轮廓。
        不会自动调用closePath()
       
fill()--&gt; 填充
        通过填充路径的内容区域生成实心的图形。
        自动调用closePath()
       
rect(x, y, width, height)--&gt; 矩形路径
    绘制一个左上角坐标为(x,y),宽高为width以及height的矩形。
    当该方法执行的时候,moveTo()方法自动设置坐标参数(0,0)。
    也就是说,当前笔触自动重置会默认坐标
    ctx.fillRect() = ctx.rect() + ctx.fill()
   
lineCap--&gt; 线段末端的属性
        有3个可能的值,分别是:
                butt:线段末端以方形结束。
                round :线段末端以圆形结束,即线段两端增加半圆。
                square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。
        默认值是 butt。

lineJoin--&gt; 当两条线交汇时,设置或返回所创建边角的类型
        有3个可能的值,分别是:
                bevel:创建斜角。
                round :创建圆角。
                miter:默认。创建尖角。
   
save--&gt; 保存全部状态
        保存到栈中的绘制状态有下面部分组成:
      当前的变换矩阵。
      当前的剪切区域。
      当前的虚线列表.
      样式等属性当前的值: strokeStyle, fillStyle,lineWidth, lineCap, lineJoin..
      
restore --&gt; 在绘图状态栈中弹出顶端的状态
        将canvas恢复到最近的保存状态的方法。如果没有保存状态,此方法不做任何改变。

   
// 示例   
var canvas = document.getElementById("#canvas");
if(canvas.getContext){
    var ctx = canvas.getContext("2d");
                               
    ctx.strokeStyle="deeppink";
    ctx.fillStyle="green"
    ctx.lineWidth=4;

    ctx.moveTo(100,100);
    ctx.lineTo(100,200);
    ctx.lineTo(200,200);
    ctx.closePath();
    ctx.stroke();


    //清空路径容器
    ctx.beginPath();
    ctx.moveTo(200,200);
    ctx.lineTo(200,300);
    ctx.lineTo(300,300);
    //fill方法会自动合并路径
    ctx.fill();
}
</code></pre>
<h5 id="-三个容器">· 三个容器</h5>
<pre><code class="language-js">/*
        1.路径容器
                每次调用路径api时,都会往路径容器里做登记
                调用beginPath时,清空整个路径容器
        2.样式容器
                每次调用样式api时,都会往样式容器里做登记
                调用save时候,将样式容器里的状态压入样式栈
                调用restor时候,将样式栈的栈顶状态弹出到样式样式容器里,进行覆盖
        3.样式栈
                调用save时候,将样式容器里的状态压入样式栈
                调用restor时候,将样式栈的栈顶状态弹出到样式样式容器里,进行覆盖
*/


    // 基本模板
    var ctx = canvas.getContext("2d");

    ctx.save();
    //关于样式的设置
    //saverestore成对出现
    ctx.beginPath();
    //关于路径
    ctx.restore();

    ctx.save();
    //关于样式的设置
    ctx.beginPath();
    //关于路径

    ctx.fill();
    ctx.restore();
</code></pre>
<h5 id="-签名练习">· 签名练习</h5>
<pre><code class="language-js">var canvas =document.getElementById("test");
if(canvas.getContext){
    var ctx = canvas.getContext("2d");
}

canvas.onmousedown=function(ev){
    ev = ev || window.event;
    // 全局捕获
    if(canvas.setCapture){
      canvas.setCapture();
    }
    ctx.beginPath();
    ctx.moveTo(ev.clientX -canvas.offsetLeft,ev.clientY -canvas.offsetTop);
    document.onmousemove=function(ev){
      // save、restore需要放在回调函数内部
      ctx.save();
      ctx.strokeStyle="pink";
      ev = ev || event;
      ctx.lineTo(ev.clientX -canvas.offsetLeft,ev.clientY -canvas.offsetTop);
      ctx.stroke();
      ctx.restore();
    }
    document.onmouseup=function(){
      document.onmousemove=document.onmouseup=null;
      // 释放全局捕获
      if(document.releaseCapture){
            document.releaseCapture();
      }
    }
    return false;
}
</code></pre>
<hr>
<h3 id="7-绘制曲线">7. 绘制曲线</h3>
<h5 id="-圆形">· 圆形</h5>
<pre><code class="language-js">arc(x, y, radius, startAngle, endAngle, anticlockwise) //角度单位为弧度/*         画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。        ture:逆时针        false:顺时针 */arcTo(x1, y1, x2, y2, radius)/*        根据moveTo起始点和(x1,y1),(x2,y2)两个控制点组成的角,找出与半径radius的圆相切的圆弧,然后与起始点相连。        肯定会从(x1 y1)但不一定经过(x2 y2);(x2 y2)只是控制一个方向*/
</code></pre>
<h5 id="-二次贝塞尔">· 二次贝塞尔</h5>
<pre><code class="language-js">quadraticCurveTo(cp1x, cp1y, x, y)/*        绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。        起始点为moveto时指定的点*/
</code></pre>
<h5 id="-三次贝塞尔">· 三次贝塞尔</h5>
<pre><code class="language-js">bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)/*        绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。        起始点为moveto时指定的点*/
</code></pre>
<p>​                                                                                                        <strong>贝塞尔曲线必过起始点和终点</strong></p>
<hr>
<h3 id="8-变换">8. 变换</h3>
<h5 id="-api-1">· API</h5>
<pre><code class="language-js">translate(x, y)/*        我们先介绍 translate 方法,它用来移动 canvas的原点到一个不同的位置。        translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量。        在canvas中translate是累加的。*/rotate(angle)/*        这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。        旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法。        在canvas中rotate是累加的。*/        scale(x, y)/* * 缩放一般我们用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。 *        scale 方法接受两个参数。x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。        值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。        在canvas中scale是累称的。*/
</code></pre>
<h5 id="-示例">· 示例</h5>
<pre><code class="language-js">var flag =0;var scale = 0;var flagScale = 0;var canvas = document.querySelector("#test");if(canvas.getContext){    var ctx = canvas.getContext("2d");    setInterval(function(){      flag++;      ctx.clearRect(0,0,canvas.width,canvas.height);      ctx.save();      ctx.translate(150,150);      ctx.rotate(flag*Math.PI/180);      if(scale==100){            flagScale=-1;      }else if(scale==0){            flagScale=1;      }      scale+=flagScale;      ctx.scale(scale/50,scale/50);      ctx.beginPath();      ctx.fillRect(-50,-50,100,100);      ctx.restore();    },10)}
</code></pre>
<hr>
<h3 id="9-使用图片">9. 使用图片</h3>
<h5 id="-引入图片">· 引入图片</h5>
<pre><code class="language-js">/*         1.canvas操作图片时,必须要等图片加载完才能操作                2.drawImage(image, x, y, width, height)        其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。        这个方法多了2个参数:width 和 height,这两个参数用来控制 当像canvas画入时应该缩放的大小*/var ctx = canvas.getContext("2d");                                var img = new Image();img.src="tg.png";img.onload=function(){    draw();}function draw(){    ctx.drawImage(img,0,0,img.width,img.height)}
</code></pre>
<h5 id="-设置背景">· 设置背景</h5>
<pre><code class="language-js">/*         在canvas中设置背景(需要image对象)                createPattern(image, repetition)                image:图像源                repetition:                        "repeat"                         "repeat-x"                         "repeat-y"                         "no-repeat" */function draw(){    var pattern = ctx.createPattern(img,"no-repeat")    ctx.fillStyle=pattern;    ctx.fillRect(0,0,300,300);}
</code></pre>
<h5 id="-渐变">· 渐变</h5>
<h6 id="1线性渐变">1.线性渐变</h6>
<p>​                        createLinearGradient(x1, y1, x2, y2)<br>
​                                表示渐变的起点 (x1,y1) 与终点 (x2,y2)</p>
<h6 id="2径向渐变">2.径向渐变</h6>
<p>​                        createRadialGradient(x1, y1, r1, x2, y2, r2)<br>
​                                前三个参数则定义另一个以(x1,y1) 为原点,半径为 r1 的圆,<br>
​                                后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆。</p>
<p>​                <strong>gradient.addColorStop(position, color)</strong></p>
<p>​                                gradient :createLinearGradient的返回值<br>
​                                addColorStop 方法接受 2 个参数,<br>
​                                        position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。<br>
​                                        例如,0.5 表示颜色会出现在正中间。<br>
​                                        color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)</p>
<hr>
<h3 id="10-绘制文本">10. 绘制文本</h3>
<h5 id="--绘制">·绘制</h5>
<p>​                canvas 提供了两种方法来渲染文本:<br>
​                        <code>fillText(text, x, y)</code><br>
​                                在指定的(x,y)位置填充指定的文本<br>
​                        <code>strokeText(text, x, y)</code><br>
​                                在指定的(x,y)位置绘制文本边框</p>
<h5 id="-文本样式">· 文本样式</h5>
<p>​                <strong>font</strong><br>
​              当前我们用来绘制文本的样式,这个字符串使用和 CSS font 属性相同的语法。<br>
​              默认的字体是 10px sans-serif。<br>
​              font属性在指定时,必须要有大小和字体 缺一不可。<br>
<strong>textAlign</strong><br>
​                        文本对齐选项。可选的值包括: <code>left,right,center </code>。<br>
​                        这里的textAlign="center"比较特殊。textAlign的值为center时候<br>
​                                文本的居中是基于你在fillText的时候所给的x的值,<br>
​                                也就是说文本一半在x的左边,一半在x的右边</p>
<p>​                <strong>textBaseline</strong><br>
​                        描述绘制文本时,当前文本基线的属性。可选的值包括: <code>top,middle,bottom </code>。</p>
<h5 id="-measuretext">· measureText</h5>
<p>​                measureText() 方法返回一个 TextMetrics 对象,包含关于文本尺寸的信息(例如文本的宽度)。</p>
<h5 id="-文本水平垂直居中">· 文本水平垂直居中</h5>
<pre><code class="language-js">window.onload = function(){        var oC =document.getElementById('c1');        var oGC = oC.getContext('2d');        oGC.font = '60px impact';        oGC.textBaseline = 'middle';//middle bottom        var w = oGC.measureText('尚硅谷').width;        oGC.fillText('尚硅谷',(oC.width - w)/2 , (oC.height - 60)/2);};
</code></pre>
<h5 id="-阴影文本阴影盒模型阴影">· 阴影(文本阴影&amp;盒模型阴影)</h5>
<p>​                <code>shadowOffsetX | shadowOffsetY </code><br>
​                        shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们默认都为 0。<br>
​                <code>shadowBlur</code><br>
​                        shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默                认为 0。<br>
​                <code>shadowColor </code>(必需项)<br>
​                        shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。</p>
<hr>
<h3 id="11-像素操作">11. 像素操作</h3>
<h5 id="-获取像素数据">· 获取像素数据</h5>
<p>​                <code>getImageData()</code>:获得一个包含画布场景像素数据的ImageData对像,它代表了画布区域的对象数据。</p>
<pre><code class="language-js">        ctx.getImageData(sx, sy, sw, sh)/*        sx:将要被提取的图像数据矩形区域的左上角 x 坐标。        sy:将要被提取的图像数据矩形区域的左上角 y 坐标。        sw:将要被提取的图像数据矩形区域的宽度。        sh:将要被提取的图像数据矩形区域的高度。*/
</code></pre>
<p>​                <strong>ImageData对象</strong><br>
​                <code>ImageData</code>对象中存储着canvas对象真实的像素数据,它包含以下几个只读属性:<br>
​                        <code>width</code>: 图片宽度,单位是像素<br>
​                        <code>height</code>: 图片高度,单位是像素<br>
​                        <code>data</code>: Uint8ClampedArray类型的一维数组,<br>
​                                包含着RGBA格式的整型数据,范围在0至255之间(包括255)<br>
​                                        R:0 --&gt; 255(黑色到白色)<br>
​                                        G:0 --&gt; 255(黑色到白色)<br>
​                                        B:0 --&gt; 255(黑色到白色)<br>
​                                        A:0 --&gt; 255(透明到不透明)</p>
<h5 id="-写入像素数据">· 写入像素数据</h5>
<p>​                <code>putImageData()</code>方法去对场景进行像素数据的写入。<br>
​                <code>putImageData(myImageData, dx, dy)</code><br>
​                        dx和dy参数表示你希望在场景内左上角绘制的像素数据所得到的设备坐标<br>
​</p>
<h5 id="-创建imagedata对象">· 创建ImageData对象</h5>
<p>​                <code>ctx.createImageData(width, height)</code><br>
​                        width : ImageData 新对象的宽度。<br>
​                        height: ImageData 新对象的高度。<br>
​                        <strong>默认创建出来的是透明的</strong></p>
<h5 id="-操作单个像素行与列">· 操作单个像素(行与列)</h5>
<pre><code class="language-js">// 调用var color = getPxInfo(imgdata,50,50);for(var i=0;i&lt;imgdata.width;i++){    setPxInfo(imgdata,30,i,);}function getPxInfo(imgdata,x,y){    var color = [];    var data = imgdata.data;    var w = imgdata.width;    var h = imgdata.height;    //(x,y)y*w+x    //r    color=data[(y*w+x)*4];    //g    color=data[(y*w+x)*4+1];    //b    color=data[(y*w+x)*4+2];    //a    color=data[(y*w+x)*4+3];    return color;}function setPxInfo(imgdata,x,y,color){    var data = imgdata.data;    var w = imgdata.width;    var h = imgdata.height;    //(x,y)y*w+x   x:多少列y:多少行    //r    data[(y*w+x)*4]=color;    //g    data[(y*w+x)*4+1]=color;    //b    data[(y*w+x)*4+2]=color;    //a    data[(y*w+x)*4+3]=color;}
</code></pre>
<h5 id="-马赛克">· 马赛克</h5>
<pre><code class="language-js">function draw(){    ctx.drawImage(img,0,0);    var oldImgdata = ctx.getImageData(0,0,img.width,img.height);    var newImgdata = ctx.createImageData(img.width,img.height);   /*   * 马赛克   *      1.选取一个马赛克矩形      2.从马赛克矩形中随机抽出一个像素点的信息(rgba)      3.将整个马赛克矩形中的像素点信息统一调成随机抽出的那个    */      //选取一个马赛克矩形    var size = 5;    for(var i=0;i&lt;oldImgdata.width/size;i++){            for(var j=0;j&lt;oldImgdata.height/size;j++){                    //(i,j)每一个马赛克矩形的坐标                    //(0,0):(0,0)(4,4);   //(1,0): (5,0) (9,4)                    //(0,1):(0,5)(4,9)                  //(1,1): (5,5) (9,9)                    //Math.random()                    //从马赛克矩形中随机抽出一个像素点的信息(rgba)                    var color = getPxInfo(oldImgdata,i*size+Math.floor(Math.random()*size),j*size+Math.floor(Math.random()*size));                    //将整个马赛克矩形中的像素点信息统一调成随机抽出的那个                    for(var a=0;a&lt;size;a++){                            for(var b=0;b&lt;size;b++){                                    setPxInfo(newImgdata,i*size+a,j*size+b,color)                                  }                    }            }    }    ctx.clearRect(0,0,oc.width,oc.height);    ctx.putImageData(newImgdata,0,0);}
</code></pre>
<hr>
<h3 id="12-合成">12. 合成</h3>
<h5 id="-全局透明度的设置">· 全局透明度的设置</h5>
<p>​                <code>globalAlpha = value</code><br>
​                        <strong>·</strong> 这个属性影响到 canvas 里所有图形的透明度,<br>
​                        <strong>·</strong> 有效的值范围是 0.0 (完全透明)到 1.0(完全不透明)<br>
​                        <strong>·</strong> 默认是 1.0</p>
<h5 id="-覆盖合成">· 覆盖合成</h5>
<p>​                <code>source</code>: 新的图像(源)<br>
​                <code>destination</code>: 已经绘制过的图形(目标)</p>
<p>​                <code>globalCompositeOperation</code><br>
​                        <strong>·</strong> source-over(默认值): 源在上面,新的图像层级比较高<br>
​                        <strong>·</strong> source-in: 只留下源与目标的重叠部分(源的那一部分)<br>
​                        <strong>·</strong> source-out: 只留下源超过目标的部分<br>
​                        <strong>·</strong> source-atop: 砍掉源溢出的部分</p>
<p>​                        <strong>·</strong> destination-over: 目标在上面,旧的图像层级比较高<br>
​                        <strong>·</strong> destination-in: 只留下源与目标的重叠部分(目标的那一部分)<br>
​                        <strong>·</strong> destination-out: 只留下目标超过源的部分<br>
​                        <strong>·</strong> destination-atop: 砍掉目标溢出的部分</p>
<hr>
<h3 id="13-其他">13. 其他</h3>
<h5 id="-将画布导出为图像">· 将画布导出为图像</h5>
<p>​                <code>toDataURL </code> (注意是canvas元素接口上的方法)</p>
<h5 id="-事件操作">· 事件操作</h5>
<p>​                <code>ctx.isPointInPath(x, y)</code><br>
​                        判断在当前路径中是否包含检测点<br>
​                                x:检测点的X坐标<br>
​                                y:检测点的Y坐标</p>
<p>​                <code>ctx.isPointInPath(path, x, y, fillRule)</code></p>
<p>​                        <code>fillRule</code></p>
<p>​                                用来决定点在路径内还是在路径外的算法。<br>
​                                允许的值:</p>
<p>​                                <code>nonzero</code>: 非零环绕规则 ,默认的规则。</p>
<p>​                                <code>evenodd</code>: 奇偶环绕原则 。</p>
<p>​                        <code>path</code></p>
<p>​                                <code>                        Path2D</code>应用的路径。</p><br><br>
来源:https://www.cnblogs.com/GisNicer/p/14760608.html
頁: [1]
查看完整版本: html5基础---canvas