HTML5로 놀면서 배우기 (6) - 오토봇과 변환에 대한 자세한 소개

黄舟
풀어 주다: 2017-03-29 15:07:21
원래의
1620명이 탐색했습니다.

1. 국가와 그 보존 및 복원

이 섹션을 시작하기 전에 먼저 국가가 무엇인지, 국가의 보존과 복원이 무엇인지 이해해야 합니다. MFC 프로그래밍을 해본 사람들은 종종 다음과 같은 코드를 접하게 됩니다.

pOldPen=pDC->SelectObject(pNewPen)

새 브러시 개체를 선택할 때 항상 저장해야 합니다. 오래된 브러시 개체를 라이브로 실행하는 이유는 무엇입니까? 새 브러시 개체는 임시 용도로만 사용되므로 원래 브러시 구성을 복원하려는 경우 이전 구성을 미리 저장하지 않으면 이러한 구성이 손실되며 복원할 방법이 없습니다.

HTML5 드로잉에서 특정 시점의 상태는 현재 시점의 컨텍스트 개체의 일련의 속성에 대한 구성 값입니다. 그러나 브러시의 상태를 결정하는 속성은 상대적으로 적습니다. 색상, 두께, 선 유형 등이며 다음을 포함하여 컨텍스트 상태를 결정하는 많은 속성이 있습니다.

1. 현재 컨텍스트 개체의 이동, 회전 및 크기 조정 구성

2. 현재 컨텍스트 객체의 lineWidth, lineCap, lineJoin, miterLimit,shadowOffsetX,shadowOffsetY,shadowBlur,shadowColor,globalCompositeOperation 속성 값

3. 현재 컨텍스트 객체

위의 일련의 구성은 이동, 회전, 크기 조정, globalCompositeOperation(조합) 및 자르기를 포함한 컨텍스트 객체의 상태를 결정합니다. 곧.

2. 상태 저장 및 복원

위에서 특정 순간의 상태는 여러 속성에 의해 결정된다고 말했습니다. 순간적으로 이 속성들을 사용해야 하는데, 값을 하나씩 저장했다가 복원할 때 하나씩 다시 설정하는 것은 너무 번거로울 것입니다. 이것이 사실이므로 컨텍스트는 상태를 저장하고 복원하는 두 가지 간단한 방법을 제공합니다:

save( ) 및 Restore( )

save 및 Restore 메소드를 호출할 수 있습니다. save 메소드가 호출될 때마다 호출 당시의 상태(즉, 일련의 속성 값)가 스택에 푸시됩니다.

복원 메소드가 호출될 때마다 마지막 저장 상태가 복원됩니다. 즉, 스택에서 팝됩니다.

탄창을 상상해 보세요. 처음 발사된 총알은 항상 탄창에 마지막으로 박힌 총알입니다.

3. 변형

1. 이동: 번역(dx,dy)

이 방법은 매우 간단해 보이지만 사실은 어떤 수학적 의미를 담고 있습니다. 전체 좌표계의 원점이 이동했다고 생각하면 됩니다. 새로운 좌표계의 모든 점(x, y)은 원래 좌표계의 좌표와 동일합니다. system:

x'=x+dx
y'=y+dy

ctx.translate(5,8)를 호출하여 컨텍스트 객체의 좌표계 상태를 변경하는 경우 , 새 상태에서 점 (3,2)에 그리는 것은 원래 상태에서 점 (8,10)에 그리는 이미지와 동일합니다. 즉,

x'=5+3=8입니다.
y'=5+ 2=10

왜 그렇게 귀찮게 하는지 (8,10)에서 직접 비교하는 것이 괜찮냐고 물으실 수도 있습니다. 예를 들어

ctx.translate(5,8)
ctx.drawImage(img,3,2)

ctx.drawImage(img, 8,10)

이것이 더 간단하고 직접적이지 않나요?

움직임이 많을수록 다른 그래픽 변환을 제공하는 것으로 이해됩니다. 좌표 원점을 적절하게 변경하면 그래픽 계산이 더 잘 이해되고 매우 편리해집니다. 간단한 예를 들어 보겠습니다. :

에는 x축의 양의 방향으로 작은 선분이 있습니다.

y = 0(1

좌표의 원점을 원의 중심으로 잡고 시계 반대 방향으로 90도 회전하면 선분은 y축의 양의 방향과 일치하게 됩니다.

x = 0 (1 <= y <= 3)

그러나 매번 하나의 끝점(1, 0) 원의 중심인 선분을 회전한 후 선분의 각 점의 좌표값을 어떻게 얻을 수 있습니까? 실제로 이 프로세스는 세 단계로 나눌 수 있습니다.

1단계: 원점 좌표를 (1,0)으로 이동합니다. 새 선분은 여전히 ​​x축에 있습니다. 그러나 방정식은 다음과 같습니다. y = 0 (0 <= x <= 2)

2단계: 새 좌표계의 원점을 원의 중심으로 하여 회전 새 좌표계 (0 <= y <= 2)

에서 선분 x = 0을 얻습니다.3단계: 새 좌표계

의 원점

을 (- 1,0) 새로운 좌표계에서, 즉 원점을 복원하여 원래 위치로, 이때의 선분은 x = 1 (0 <= y <= 2)

세 번째 단계에서 얻은 선분은 그려야 할 마지막 선분입니다.

이 예를 보면 이렇게 간단한 경우에도 좌표 원점을 이동하지 않고 회전된 도형을 직접 계산하기는 어렵다는 것을 알 수 있습니다. : 좌표 원점을 이동하기 전에 상태를 저장하는 것을 잊지 마세요. 물론 그린 후에는 상태를 복원하지 마세요.

2. 스케일링

scale

(sx, sy)

이것도 매우 간단합니다. sx, sy는 스케일링 요소이며 새로운 좌표입니다. 크기 조정 후 시스템의 모든 점(x,y)은 원래 좌표계의 좌표와 동일합니다.

x' = x * sxy' = y * sy

마찬가지로 좌표계를 변경할 때는 항상 상태를 저장하고 복원하는 것을 잊지 마세요

3.회전회전(A)

각도는 회전 각도입니다. 회전 후 새 좌표계의 모든 점(x, y)은 원래 좌표계의 좌표와 동일합니다.

x' = x cosA - y sinA
y ' = x sinA + y cosA

마찬가지로 좌표계 변경 시 항상 상태를 저장하고 복원하는 것을 잊지 마세요

Transformtransform (m11, m12, m21, m22, dx, dy)

사실 앞서 언급한 이동, 크기 조정, 회전은 변환 방법의 6가지 매개변수가 변환을 이루는 특수한 경우입니다. 행렬은 다음과 같습니다

m11 m21 dx
m12 m22 dy
0 0 1

변환 메소드를 호출하는 것은 이러한 매개변수를 사용하여 컨텍스트 객체에 대한 새로운 변환 행렬 을 설정하는 것과 같습니다. 변환 행렬의 특정 내용은 그래픽 관련 정보, 다음은 몇 가지 간단한 특수 사례입니다.

Movetranslate(dx,dy):Transform(

1,0,0,1과 동일) ,dx,dy)

스케일 스케일(sx,xy): 변환(

sx,0,0,sy,0,0)

과 동일 회전(A) : 변환(

cosA,sinA,-sinA,cosA,0,0)

(dx,dy)을 기준점으로 사용하여 각도 A를 회전하는 것과 동일: 변환 (

cosA, sinA, -sinA, cosA, dx(1-cosA) + dysinA, dy(1-cosA) - dxsinA)

(dx,dy)를 기준점으로 사용 (sx,sy) 스케일링을 수행하려면 스케일링: 변환(

sx, 0, 0, sy, dx(1-sx), dy(1-sy))

그 밖에도 여러 가지가 있습니다 더 복잡한 변환에 대해서는 그래픽 관련 정보를 참조할 수 있습니다.

다음은 기준점 변형의 예입니다. 이미지의 특정 지점에 마우스를 계속 누르고 있으면 해당 지점을 기준점으로 이미지의 크기가 조정되거나 회전됩니다. 버튼을 놓은 후.

팁: 이 크기 조정 및 회전 예제는 변형 행렬을 사용하지 않고 네 가지 단순 변형으로 구성됩니다. 효과는 다음과 같습니다.

이동 - 이미지 위에서 마우스를 누른 채 이동
기준점 크기 조절 - 이미지의 특정 지점에서 마우스를 누른 채
기준점 회전 - 이미지의 특정 지점에서 마우스를 길게 누르세요
기준점이 확대/축소되면서 동시에 회전합니다 - 이미지의 특정 지점에서 마우스를 길게 누르세요

4. 조합

조합이란 하나의 그래픽이 다른 그래픽 위에 그려졌을 때 어떤 효과가 나타나는지를 말합니다. 기본적으로 위쪽 그래픽이 아래쪽 그래픽을 덮는데, 이를 소스 오버라고 합니다.

컨텍스트 개체에는 총 12개의 조합 유형이 있습니다. globalCompositeOperation 속성은 다음과 같이 조합 유형을 설정하는 데 사용됩니다.

globalCompositeOperation = type

유형은 다음과 같습니다. 다음 12개의 문자열 값 중 하나 1:

참고: 위의 모든 예에서는 파란색 사각형이 먼저 그려집니다. 즉, "existing" 빨간색 원은 다음에 그려진 이며, 이는 "새로운 모양"입니다.

5. 클리핑 경로

첫 번째 기사에서는 선 그리기를 위한

스트로크 일련의 메소드와 영역을 채우는

fill 시리즈의 메소드 실제로 컨텍스트 객체에는 클리핑 clip이라는 그리기 메소드 유형도 있습니다. 크롭이란 무엇인가요? 부적절한 비유를 하자면, TV 화면을 천으로 덮으면 TV 화면에서는 아무런 변화도 볼 수 없습니다.

그러나 천의 한 부분을 잘라내면 최소한 그 부분에서 화면이 바뀌는 것을 볼 수 있습니다.

물론

크롭 영역 밖의 화면도 끊임없이 변화하고 있지만(즉, 다시 그려지는 중이기도 하지만) 볼 수는 없습니다

. 이를 자르기라고 하며 이미지를 처리할 때 이러한 요구 사항이 자주 발생합니다.

그럼 클리핑 경로

는 무엇인가요? 천에 있는 부분을 잘라내야 한다고 나와 있는데, 이 부분은 어떻게 생겼나요?

이 영역은 클리핑 작업 클립

전의 그리기 경로에 의해 설정됩니다. 사각형, 원형, 별 다섯개 모양 또는 그릴 수 있는 기타 윤곽선 모양이 될 수 있습니다.

따라서 클리핑 경로는 실제로 그리기 경로이지만 이 경로는 그리는 데 사용되지 않고 표시 영역과 폐색 영역 사이의 구분선을 설정하는 데 사용됩니다.

그리기 경로가 무엇인지 이해하지 못하신다면 이전 글 HTML5 놀면서 배우기(2): 기초 그리기에서 소개되어 있습니다.

다음 예에서는 두 가지 자르기 방법을 사용합니다. 첫 번째 방법은 앞뒤로 이동하는 원형 자르기 영역을 표시합니다.

1. 캔버스를 지웁니다

2.

3. 새로운 원 중앙에 원형 자르기 영역 설정

4. 캔버스에 아름다운 이미지 그리기

계속해서 새 위치에 자르기 영역을 설정하므로 , 크롭 영역을 볼 수 있습니다. 이동 중에는 크롭 영역 외부의 이미지가 표시되지 않습니다

클립 방식을 사용하여 크롭 영역을 설정합니다. 이후에 그려지는 그래픽은 크롭 영역의 일부만 표시할 수 있으며, 캔버스는 항상 자르기 영역 배경색 외부에 표시됩니다.

예를 들어 자르기 영역 외부의 이미지를 완전히 차단하고 싶지 않은 경우 자르기 영역 내의 이미지는 완전히 표시되지만 자르기 영역 외부의 이미지는 반쯤 표시되도록 합니다. -투명매너, 모직물은 어떻게 해야 할까?

위에서 언급한 조합 지식이 필요합니다. 두 번째 방법은 반투명한 폐색을 표시하는 것입니다.

1. 캔버스를 지웁니다.

2. 여기서는 반투명 색상을 사용합니다. , 투명도 0.9

3. 원의 중심 위치 변경

4、在新的圆心位置处以 XOR 方式绘制圆,这样和圆形重叠的部分将被擦除掉
这时候我们得到的图形效果是一个半透明的画布,上面有一块完全透明的圆形区域

5、 在第 4 步的基础上,以 destination-over 方式绘制美女图像,这时候美女图像将会出现在第 4 步图形效果的下方,想象一下,正好是我们想要的效果吧?!

代码



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas1" width="250" height="300" 

    onmousedown="trans.transform(event);"  

    onmouseup="trans.init(event);" 

    onmousemove="trans.translate(event);" 

    style="background-color:black">

    你的浏览器不支持 &lt;canvas&gt;标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="radio" name="r" id="r1" checked="checked">移动——在图像上按住鼠标并移动<br />

<input type="radio" name="r" id="r2">基准点缩放——在图像某点处按住鼠标<br />

<input type="radio" name="r"  id="r3">基准点旋转——在图像某点处按住鼠标<br />

<input type="radio" name="r"  id="r4">基准点缩放同时旋转——在图像某点处按住鼠标<br />



<canvas id="canvas3" width="250" height="300" style="background-color:black">

    你的浏览器不支持 &lt;canvas&gt;标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="button" onclick="move(1);" value="移动裁剪区域">

<input type="button" onclick="move(2);" value="移动蒙版">

<input type="button" onclick="stop();" value="停止移动"><br />



        <div>

            <table>

                <tr>

                    <td><canvas id="tut0" width="125" height="125"></canvas><br/><label id="lab0"></label></td>

                <td><canvas id="tut1" width="125" height="125"></canvas><br/><label id="lab1"></label></td>

                <td><canvas id="tut2" width="125" height="125"></canvas><br/><label id="lab2"></label></td>

                <td><canvas id="tut3" width="125" height="125"></canvas><br/><label id="lab3"></label></td>

                </tr>

                <tr>

                    <td><canvas id="tut4" width="125" height="125"></canvas><br/><label id="lab4"></label></td>

                <td><canvas id="tut5" width="125" height="125"></canvas><br/><label id="lab5"></label></td>

                <td><canvas id="tut6" width="125" height="125"></canvas><br/><label id="lab6"></label></td>

                <td><canvas id="tut7" width="125" height="125"></canvas><br/><label id="lab7"></label></td>

                </tr>

                <tr>

                    <td><canvas id="tut8" width="125" height="125"></canvas><br/><label id="lab8"></label></td>

                <td><canvas id="tut9" width="125" height="125"></canvas><br/><label id="lab9"></label></td>

                <td><canvas id="tut10" width="125" height="125"></canvas><br/><label id="lab10"></label></td>

                <td><canvas id="tut11" width="125" height="125"></canvas><br/><label id="lab11"></label></td>

                </tr>

            </table>

        </div>





<script type="text/javascript">

    //美女图的 Base64 编码

    IMG_SRC=&#39;data:image/gif;base64,/9j/4QDfRXhpZgAASUkqAAgAAAAFABIBAwA......&#39;;//省略四十字节



    //==========================================

    //基准点变形类

    //==========================================

    function Transform(){

        //获取画布对象

        this.ctx = document.getElementById("canvas1").getContext("2d");

        //创建图像对象

        this.img=new Image();

        //指定图像源

        this.img.src=IMG_SRC;

        this.interval = null;

        //鼠标按钮状态

        this.pressed=false;

        this.init();

    }

    

    //初始化图形

    Transform.prototype.init=function(){

        //鼠标按钮状态

        this.pressed=false;

        //停止计时器

        if(this.interval) clearInterval(this.interval);

        //变化值

        this.delta = 0.06;

        //清空

        this.ctx.clearRect(0,0,250,300);

        //重绘

        this.paint();

    }

    

    //绘制图像

    Transform.prototype.paint=function(){

        var that=this;

        var img=this.img

        if(img.complete)

            that.ctx.drawImage(img,0,0);

        else 

            var interval = setInterval(function(){

                if(img.complete){

                    that.ctx.drawImage(img,0,0);

                    clearInterval(interval);

                }

            },300);

    }

    

    //鼠标按钮按下后,开始变形

    Transform.prototype.transform = function(){

        //获取基准点

        this.dx=event.offsetX;

        this.dy=event.offsetY;

        //获取基准点

        this.startx=event.offsetX;

        this.starty=event.offsetY;

        //初始缩放比例

        this.sc=1;

        //初旋转角度

        this.angle=0;

        

        var that=this;

        if(document.getElementById("r1").checked)

            //鼠标按钮状态

            this.pressed=true;

        else if(document.getElementById("r2").checked)

            this.interval = setInterval(function(){that.scale()},50);

        else if((document.getElementById("r3").checked))

            this.interval = setInterval(function(){that.rotate()},50);

        else 

            this.interval = setInterval(function(){that.scaleAndRotate()},50);

    }

    

    //移动

    Transform.prototype.translate = function(){

        this.ddx=event.offsetX-this.startx;

        this.ddy=event.offsetY-this.starty;

        if(this.pressed){

            //清空

            this.ctx.clearRect(0,0,250,300);

            //保存状态

            this.ctx.save();

            //平移

            this.ctx.translate(this.ddx,this.ddy);

            //重绘

            this.paint();

            //绘制基准点

            this.ctx.fillStyle="red";

            this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

            //恢复状态

            this.ctx.restore();

        }

    }



    //缩放变形

    Transform.prototype.scale = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        this.sc=this.sc - this.delta;

        if(this.sc<0.2 || this.sc>2) 

            this.delta = -this.delta;

        //保存状态

        this.ctx.save();

        //以 (dx,dy) 为基准点进行 (sx,sy)比例缩放:transform(sx, 0, 0, sy, dx(1-sx), dy(1-sy))

        this.ctx.transform(this.sc, 0, 0, this.sc, this.dx*(1-this.sc), this.dy*(1-this.sc))

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    //旋转变形

    Transform.prototype.rotate = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        var PI = Math.PI;

        this.angle=this.angle + PI/60;

        //保存状态

        this.ctx.save();

        //以 (dx,dy) 为基准点旋转角度 A:transform(cosA, sinA, -sinA, cosA, dx(1-cosA) + dysinA, dy(1-cosA) - dxsinA)

        this.ctx.transform(Math.cos(this.angle), Math.sin(this.angle), 

                -Math.sin(this.angle), Math.cos(this.angle), 

                this.dx*(1-Math.cos(this.angle)) + this.dy*Math.sin(this.angle), 

                this.dy*(1-Math.cos(this.angle)) - this.dx*Math.sin(this.angle))

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    //即缩放又旋转变形,没有使用变形矩阵

    Transform.prototype.scaleAndRotate = function(){

        //清空

        this.ctx.clearRect(0,0,250,300);

        //改变缩放比例

        this.sc=this.sc - this.delta;

        if(this.sc<0.2 || this.sc>2) 

            this.delta = -this.delta;

        var PI = Math.PI;

        this.angle=this.angle + PI/60;

        //保存状态

        this.ctx.save();

        //先移动原点到基点

        this.ctx.translate(this.dx,this.dy);

        this.ctx.scale(this.sc,this.sc);

        this.ctx.rotate(this.angle);

        this.ctx.translate(-this.dx,-this.dy);

        //用新的变形矩阵重绘

        this.paint();

        //绘制基准点

        this.ctx.fillStyle="red";

        this.ctx.fillRect(this.dx-5,this.dy-5,10,10);

        //恢复状态

        this.ctx.restore();

    }

    

    var trans = new Transform();

    

    //==========================================

    function Clip(){

        var canvas = document.getElementById("canvas3");

        this.ctx = canvas.getContext("2d");

        this.img=new Image();

        this.img.src=IMG_SRC;

        //移动方向

        this.delta=[3,3];

        //起始点

        this.pos_x = 225;

        this.pos_y = 120;

        //半径

        this.radius = 40;

        //画布的长和宽

        this.w = parseInt(canvas.getAttribute("width"));

        this.h = parseInt(canvas.getAttribute("height"));

    }

    

    Clip.prototype.draw1=function(){

        //碰撞检测

        if (this.pos_x < this.radius) {

            this.delta[0] = Math.random() % 4 + 5;

        } else if (this.pos_x > this.w - this.radius) {

            this.delta[0] = -(Math.random() % 4 + 5);

        }

        if (this.pos_y < this.radius) {

            this.delta[1] = Math.random() % 4 + 5;

        } else if (this.pos_y > this.h - this.radius) {

            this.delta[1] = -(Math.random() % 4 + 5);

        }

        this.pos_x += this.delta[0];

        this.pos_y += this.delta[1];



        this.ctx.clearRect(0, 0, this.w, this.h);

        //保存状态

        this.ctx.save()

        //移动变形

        this.ctx.translate(this.pos_x,this.pos_y);

        //设置裁剪区域

        this.ctx.beginPath();

        this.ctx.arc(0 ,0,this.radius,0,Math.PI*2,true);

        this.ctx.clip();         

        // 将图片画到画布上

        this.ctx.drawImage(this.img, -this.pos_x, -this.pos_y,this.w, this.h);

        //恢复状态

        this.ctx.restore();

    }

    

    Clip.prototype.draw2=function(){

        //碰撞检测

        if (this.pos_x < this.radius) {

            this.delta[0] = Math.random() % 4 + 5;

        } else if (this.pos_x > this.w - this.radius) {

            this.delta[0] = -(Math.random() % 4 + 5);

        }

        if (this.pos_y < this.radius) {

            this.delta[1] = Math.random() % 4 + 5;

        } else if (this.pos_y > this.h - this.radius) {

            this.delta[1] = -(Math.random() % 4 + 5);

        }

        this.pos_x += this.delta[0];

        this.pos_y += this.delta[1];



        this.ctx.clearRect(0, 0, this.w, this.h);

        //绘制灰色的半透明蒙版

        this.ctx.fillStyle="rgba(125,125,125,0.9)"

        this.ctx.fillRect(0, 0, this.w, this.h);

        //保存状态

        this.ctx.save()

        //移动坐标

        this.ctx.translate(this.pos_x,this.pos_y);

        //裁剪透明的圆形区域

        this.ctx.globalCompositeOperation = "xor";   

        this.ctx.fillStyle="white"

        this.ctx.beginPath();

        this.ctx.arc(0 ,0,this.radius,0,Math.PI*2,true);

        this.ctx.fill();       

        // 将图片画到蒙版的下面,即只露出透明区域

        this.ctx.globalCompositeOperation = "destination-over";   

        this.ctx.drawImage(this.img, -this.pos_x, -this.pos_y,this.w, this.h);

        //恢复状态

        this.ctx.restore();

    }



    var cl=new Clip();

    cl.interval=null;

    

    function move(id){      

        if(cl.interval)

            clearInterval(cl.interval)

        if(id==1){

            cl.ctx.clearRect(0, 0, 450, 300);    

            cl.interval=setInterval(function(){cl.draw1()},20);

        }

        else{

            cl.ctx.clearRect(0, 0, 450, 300);    

            cl.interval=setInterval(function(){cl.draw2()},20);

        }

    }



    function stop(){

        clearInterval(cl.interval)

    }

    

    var compositeTypes = [

        &#39;source-over&#39;,&#39;source-in&#39;,&#39;source-out&#39;,&#39;source-atop&#39;,

        &#39;destination-over&#39;,&#39;destination-in&#39;,&#39;destination-out&#39;,&#39;destination-atop&#39;,

        &#39;lighter&#39;,&#39;darker&#39;,&#39;copy&#39;,&#39;xor&#39;

    ];

    function drawComp(){

        for (i=0;i<compositeTypes.length;i++){

            var label = document.createTextNode(compositeTypes[i]);

            document.getElementById(&#39;lab&#39;+i).appendChild(label);

            var ctx = document.getElementById(&#39;tut&#39;+i).getContext(&#39;2d&#39;);



            // draw rectangle

            ctx.fillStyle = "#09f";

            ctx.fillRect(15,15,70,70);



            // set composite property

            ctx.globalCompositeOperation = compositeTypes[i];



            // draw circle

            ctx.fillStyle = "#f30";

            ctx.beginPath();

            ctx.arc(75,75,35,0,Math.PI*2,true);

            ctx.fill();

        }

    }

    drawComp();

</script>
로그인 후 복사

위 내용은 HTML5로 놀면서 배우기 (6) - 오토봇과 변환에 대한 자세한 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!