如题所述
HTML5 çæ åå·²ç»åºæ¥å¥½ä¹
äºï¼ä½æ¯ä¼¼ä¹å
¶ä¸ç Canvas ç°å¨å¹¶æ²¡æå¨å¤ªå¤çå°æ¹ç¨å°ãä¸ä¸ªå¾éè¦çåå æ¯ï¼Canvas çæ åè¿æ²¡æå®å
¨ç¡®å®ï¼ä¸éå大è§æ¨¡ç¨å¨ç产ç¯å¢ãä½æ¯ï¼Canvas çä¼ç¹ä¹æ¯å¾ææ¾çï¼ä¾å¦å¨ç»å¶å«æ大éå
ç´ çå¾è¡¨çæ¶åï¼SVG å¾å¾å 为æ§è½é®é¢èæ æ³èä»»ï¼ä¾å¦æè§è¿çä¸æ¬¡ææ¯å享ä¼çæ½å¥ç¯èï¼è½ç¶æææ¯è¾ç«ï¼ä½å 为æ¯ä¸ªå¤´åé½æ¯ DOMï¼å©ç¨ CSS3 æ§å¶çå¨ç»ï¼å¯¼è´äºæ§è½é常ä½ä¸ãæ¤å¤ï¼éç硬件æ§è½çæé«ï¼è§é¢æªå¾ãå¾åå¤ççåè½ä¹éæ¸å¯ä»¥å¨ç½é¡µä¸å®ç°äºï¼å¤§å¤æ°ç½ç«ç¨çæ¯ Flashï¼ä½æ¯ Flash å¨ Mac çµèä¸æ§è½ä¸é«ï¼è¿éè¦å¦ä¸äºé¢å¤çç¥è¯ãCanvas åæ¯ç´æ¥ä½¿ç¨ JavaScript æ¥è¿è¡ç»å¾ï¼å¯¹ Mac å好ï¼æ以ä¸å¤±ä¸º Flash çä¸ä¸ªç»§æ¿è
ã
ä½¿ç¨ Canvas
说äºè¿ä¹å¤ï¼Canvas 究ç«æ¯ä¸ªå¥ï¼
è±æä¸ Canvas çæææ¯âç»å¸âï¼ä¸è¿è¿é说ç Canvas æ¯ HTML5 ä¸æ°åºçä¸ä¸ªå ç´ ï¼å¼åè å¯ä»¥å¨ä¸é¢ç»å¶ä¸ç³»åå¾å½¢ãCanvas å¨ HTML æ件ä¸çåæ³å¾ç®åï¼
<canvas id="canvas" width="宽度" height="é«åº¦"></canvas>
å ¶ä¸ id å±æ§æ¯ææ HTML å ç´ é½å¯ä»¥ç¨çï¼Canvas èªå¸¦çå±æ§åªæåé¢ä¸¤ä¸ªï¼åå«æ§å¶å®½åº¦ãé«åº¦ï¼ï¼æ²¡æå ¶å®çäºãè³äºå ¼å®¹æ§ï¼CanIUse ä¸é¢åäºï¼åºç¡çåè½ç®åç¨æ·ä½¿ç¨ç 90% çæµè§å¨é½æ¯æï¼æ以大é¨åæ åµä¸è¿æ¯å¯ä»¥æ¾å¿ä½¿ç¨çã
注æï¼ä¸å®è¦ä½¿ç¨ Canvas èªå¸¦ç width å height å±æ§ï¼ä¸è¦ä½¿ç¨ CSS æ¥æ§å¶ï¼å 为 CSS æ§å¶ä¼å¯¼è´ Canvas åå½¢ãå¯ä»¥è¯çä¸ PhptpShop 对æ¯ä¸ä¸ï¼åè æ¯æ¹åâå¾å大å°âï¼åè ææ¯æ£ç¡®çæ¹åâç»å¸å¤§å°âãä¾å¦ä¸å¾æ¯ä¸å¼ å¾çç横åæ¼æ¥ï¼æ左边çé»æ¡ä¸æ¯å¤§å°ä¸º 50px * 50px çåå¾ï¼ä¸é´æ¯æ¹åäºå¾å大å°ä¸º 100px * 100px çææï¼å¾ååå¾æ¨¡ç³ï¼ä½æ¯å¯¹äºå¾åæ¬èº«æ¥è¯´åæ èå´å¹¶æ²¡æå大ï¼æå³è¾¹ææ¯æ£ç¡®ç 100px * 100px ç Canvasã
Canvas ç»å¤§é¨åçç»å¾æ¹æ³é½ä¸ <canvas> æ ç¾æ å ³ï¼éè¦ä½¿ç¨ JavaScript å¯¹å ¶è¿è¡æä½ï¼è¿å°±æ¯æè°ç Canvas APIã
æ们é¦å è·åå°è¿ä¸ªå ç´ ï¼
var canvas = document.getElementById('canvas');
ç¶åéè¿ä¸ä¸ªæ¹æ³æ¥è·åå¯ä»¥è°ç¨ä¸å Canvas API çå ¥å£ï¼
var ctx = canvas.getContext('2d');
çå° 2d æ¯ä¸æ¯å¾æ¿å¨å°èæ³å°æ没æ 3d å¢ï¼æ²¡æ 3d çåæ³ï¼ä¸è¿å¦ææ³è¦å¼å¯ 3D ä¸çç大é¨ï¼åå¯ä»¥å canvas.getContext('webgl')ãç¶è WebGL æ¯åºäº OpenGL ES 2.0 çä¸å¥æ åï¼ä¸æ¬ææ¯å½»å½»åºåºç两æ¡è·¯ï¼å æ¤è¿éå°±ä¸è®¨è®ºäºã
Canvas ä¸çåºæ¬æ¦å¿µ
åæ
ä¸æ°å¦ä¸å¸¸è§çç¬å¡å°åæ ç³»ä¸å¤ªç¸åï¼Canvas çåæ ç³»æ¯è®¡ç®æºä¸å¸¸è§çåæ ç³»ï¼å®é¿è¿æ ·ï¼
ç»å¸çæå·¦ä¸è§æ¯ (0,0)ï¼å¾å³ x å¢å¤§ï¼å¾ä¸ y å¢å¤§ï¼èä¸ x å y é½æ¯æ´æ°ï¼å°±ç®å¨è®¡ç®è¿ç¨ä¸ä¸æ¯æ´æ°ï¼å¨ç»å¶çæ¶åä¹ä¼å½ä½æ´æ°å¤çï¼ï¼åä½æ¯åç´ ã
ç»å¾
带大家ææ§ä¸ä¸ãä¸ç¥éæå¤å°åå¦å°æ¶åç©è¿ logo è¯è¨ï¼å¨éé¢ä½ å¯ä»¥æ§å¶ä¸åªå°æµ·é¾å¨ä¸åæ¿åä¸è¡èµ°ãç»ç»ãæç¬ãè½ç¬ãCanvas ä¸ä¹ä¸æ ·ï¼ä½ éè¦æ§å¶ä¸åªç»ç¬ç移å¨åç»å¶ãç¶è Canvas æ´é«çº§ä¸äºï¼ä½ å¯ä»¥ç´æ¥å©ç¨ä¸äºå½æ°æ¥ç»å¾ï¼ä¸ç¨å»æ§å¶é£åªç»ç¬çä½ç½®ã
Canvas ä¸çåºæ¬å¾å½¢
éè¿ä¸æå®ä¹ç ctx åéå¯ä»¥å¹²è®¸å¤æææçäºæ ï¼æ们å ççå¦ä½ç»å¶ä¸äºåºæ¬å¾å½¢ã
线æ¡
æ们æå®ç»ç¬ç§»å¨å°æä¸ç¹ï¼ç¶ååè¯ç»ç¬éè¦ä»å½åè¿ä¸ç¹ç»å°å¦ä¸ç¹ãæ们å¯ä»¥è®©ç»ç¬å¤æ¬¡ç§»å¨ãç»å¶ï¼æåç»ä¸è¾åºå°å±å¹ä¸ãä¾åå¦ä¸ï¼
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.moveTo(10, 20);
ctx.lineTo(40, 70);
ctx.stroke();
ä¸é¢ç代ç ä¸ï¼lineTo æ¯äº§ç线æ¡ç¨çå½æ°ï¼æ§è¡å®ä¹åç»ç¬å°±ç§»å°äºçº¿æ¡çç»ç¹ãéè¦æ³¨æçæ¯ï¼çº¿æ¡æ¤æ¶å¹¶æ²¡ææ¾ç¤ºå¨å±å¹ä¸ï¼å¿ é¡»è°ç¨ stroke æä¼æ¾ç¤ºãè¿æ ·è®¾è®¡æ¯æéççï¼å 为åå±å¹ä¸è¾åºå 容éè¦è费大éçèµæºï¼æ们å®å ¨å¯ä»¥å æå¤ä¸æ³¢ lineToï¼æåç¨ stroke æ¾ä¸ä¸ªå¤§çã
è·¯å¾
ç»å¶è·¯å¾é常ç®åï¼åªéè¦å åè¯ ctx ä¸å£°âæè¦å¼å§ç»è·¯å¾äºâï¼ç¶åéè¿åç§æ¹æ³ï¼ä¾å¦ lineToï¼ç»å¶è·¯å¾ãå¦æéè¦ç»ä¸ä¸ªå°éè·¯å¾ï¼é£å°±æååè¯ ctxä¸å£°ï¼âæç»å®äºï¼ä½ æå®å°éèµ·æ¥å§ãâå½ç¶ï¼ä¸è¦å¿è®°å©ç¨ stroke è¾åºå°å±å¹ä¸ã
ä¸ä¸ªç®åçä¾åï¼
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.closePath();
ctx.stroke();
å¦ææä¸æ³åªæç»è·¯å¾çº¿æ¡ï¼èæ¯æ³å¡«å æ´ä¸ªè·¯å¾å¢ï¼å¯ä»¥å°æåä¸è¡ç stroke æ¹æ fillï¼è¿æ ·å°±è·ä½¿ç¨äºç»å¾ä¸çæ²¹æ¼æ¡¶ä¸æ ·ï¼å°éè·¯å¾éé¢çå 容就é½è¢«å¡«å ä¸é¢è²äºï¼
ctx.fill();
弧 / åå½¢
ç»å¶å¼§çå½æ°åæ°æ¯è¾å¤ï¼
ctx.arc(åå¿ x åæ , åå¿ y åæ , åå¾, èµ·å§è§åº¦, ç»æ¢è§åº¦, æ¯å¦ä¸ºéæ¶é);
注æï¼å¨ Canvas çåæ ç³»ä¸ï¼è§çä¸è¾¹æ¯ä»¥åå¿ä¸ºä¸å¿çæ°´å¹³åå³çç´çº¿ãè§åº¦åä½å为弧度ãä¾å¦ä¸å¾ï¼ç¡®å®äºåå¿ãèµ·å§è§åº¦ï¼å¾ä¸æ æçéè§ï¼åç»æ¢è§åº¦ï¼å¾ä¸æ æçéè§ï¼ï¼æ¹å为éæ¶éï¼äºæ¯å°±æäºè¿ä¹ä¸ä¸ªå¼§ãå¦ææ¹å为顺æ¶éï¼é£ä¹å°±ä¼æ¯ä¸ä¸ªè·å®äºè¡¥çãé常é常大ç弧â¦â¦
æ以å¦æè½¬äº 2Ï åä¹åï¼å¼§å°±æäºåå½¢ï¼å æ¤ä¹å¯ä»¥ä½¿ç¨ç»å¶å¼§çæ¹å¼æ¥ç»å¶åå½¢ï¼
ctx.beginPath();
ctx.arc(åå¿ x åæ , åå¿ y åæ , åå¾, 0, Math.PI * 2, true);
ctx.closePath();
æåä¸ä¸ªåæ°é便填ï¼å½ç¶ä¹å¯ä»¥ä¸å¡«ï¼ï¼å 为ä¸ç®¡æ¯é¡ºæ¶éè¿æ¯éæ¶éï¼è½¬äº 2Ï åä¹åé½æ¯ä¸ä¸ªåã
ç©å½¢
å¦æåªæ¯æ³ç»å¶ä¸ä¸ªæ¨ªå¹³ç«ç´çç©å½¢ï¼å¯ä»¥ä½¿ç¨ä¸é¢ç两个æ¹æ³ï¼
// åªæè¾¹
ctx.strokeRect(å·¦ä¸è§ x åæ , å·¦ä¸è§ y åæ , 宽度, é«åº¦);
// åªå¡«å
ctx.fillRect(å·¦ä¸è§ x åæ , å·¦ä¸è§ y åæ , 宽度, é«åº¦);
线æ¡æ ·å¼ / å¡«å æ ·å¼
ä¹åç»å¶çææå¾å½¢é½æ¯é»è²çï¼ä½æ¯ Canvas è¯å®ä¸æ¢è¿ä¹ä¸ç§é¢è²ï¼ä¸ç¶æ åçå¶å®è ä¼è¢«å·çå¾æ¨ï¼ãäºå®ä¸ï¼Canvas å¯ä»¥åç¬è®¾ç½®çº¿æ¡æ ·å¼åå¡«å æ ·å¼ï¼åå«ä½¿ç¨çæ¯ strokeStyle å fillStyleãå¯è½çå¼æä¸ç§ï¼çº¯è²ãæ¸åãå¾åãæ¢ç¶çº¿æ¡æ ·å¼ä¸å¡«å æ ·å¼ç使ç¨æ¹æ³ç¸åï¼é£ä¹ä¸é¢ç»ä¸ä»¥å¡«å æ ·å¼ä¸ºä¾ãå¦ææ³è®¾ç½®çº¿æ¡æ ·å¼ï¼ç´æ¥å°ææç fillStyleæ¹æ strokeStyle å³å¯ï¼éé¢çåæ°é½ä¸åã
/* 纯è²å¡«å */
// æ®éçé¢è²
ctx.fillStyle = '#0000ff';
// 带æéæ度çé¢è²
ctx.fillStyle = 'rgba(64, 0, 127, 0.5)';
/* æ¸åå¡«å */
// 设置æ¸åç尺寸ï¼åæ°åå«ä¸ºèµ·å§ç¹ç x å yãç»æ¢ç¹ç x å yï¼
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
// 设置è¿æ¸¡è²ï¼ç¬¬ä¸ä¸ªåæ°æ¯æ¸åçä½ç½®ï¼ç¬¬äºä¸ªåæ°æ¯é¢è²
gradient.addColorStop(0, 'magenta');
gradient.addColorStop(0.5, 'blue');
gradient.addColorStop(1.0, 'red');
// 设置填å æ ·å¼
ctx.fillStyle = gradient;
/* å¾çå¡«å */
// å建å¾ç
var image = new Image;
image.src = '/path/to/image.png';
// å建å¾çç¬è§¦ï¼å¯ä»¥æå®å¾ççå¹³éºæ¹å¼ï¼è¿éæ¯æ¨ªåå¹³éº
var pattern = ctx.createPattern(image, 'repeat-x');
// 设置ç¬è§¦å¡«å
ctx.fillStyle = pattern;
å ³äºæ¸åï¼é¤äºä»£ç ä¸æå°ç线æ§æ¸å以å¤ï¼è¿æ createRadialGradientï¼ä¹å°±æ¯å¾åæ¸åã
设置å®å¡«å æ ·å¼ä¹åï¼å°±å¯ä»¥ä½¿ç¨ fill æ¥å¡«å å¦ï¼å¦æ设置çæ¯çº¿æ¡æ ·å¼ï¼é£ä¹å°±å¯ä»¥ä½¿ç¨ stroke æ¥æè¾¹ã
å½ç¶ï¼å¯¹äºçº¿æ¡æ ·å¼ï¼è¿æ个é¢å¤çæ¹æ³å« lineWidth å¯ä»¥ç¨æ¥æ§å¶çº¿æ¡ç宽度ã
æå
è¦æ³å¨ç»å¸ä¸ç»æåï¼é¦å éè¦ç¥éæ使ç¨çåä½ååå·ï¼
ctx.font = '30px Verdana';
ç¶åå°±å¯ä»¥éè¿ strokeText æè fillText æ¥å¯¹åä½æè¾¹æè å¡«å åä½ã
ctx.strokeText("Hello Coding!", 23, 33);
ctx.fillText("Hello Coding!", 23, 66);
å¾ç
å¨ Canvas ä¸ç»å¶å¾çæä¸ç§æ¹æ³ï¼
// æå®ç»å¶ä½ç½®
ctx.drawImage(image, x, y);
// æå®ç»å¶ä½ç½®åå¾å宽é«
ctx.drawImage(image, x, y, width, height);
// æå®åªè£åºåãç»å¶ä½ç½®åå¾å宽é«
ctx.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
åæ°çå«ä¹ä¾æ¬¡å¦ä¸ï¼
image: è¦ä½¿ç¨ç ImageãCanvas æ Video
sx: å¯éï¼å¼å§åªåç x åæ
sy: å¯éï¼å¼å§åªåç y åæ
swidth: å¯éï¼è¢«åªåå¾åç宽度
sheight: å¯éï¼è¢«åªåå¾åçé«åº¦
x: å¨ç»å¸ä¸æ¾ç½®å¾åç x åæ
y: å¨ç»å¸ä¸æ¾ç½®å¾åç y åæ
width: å¯éï¼è¦ä½¿ç¨çå¾åç宽度
height: å¯éï¼è¦ä½¿ç¨çå¾åçé«åº¦
ç»å¸è®¾ç½®
ç»å¿çåå¦å¯è½ä¼åç°ï¼åææäºå±æ§æ¯ç´æ¥å¯¹ ctx åéå设置ï¼ä¾å¦ ctx.lineWidthï¼åªè¦è®¾ç½®äºå®ï¼é£ä¹åç»ç»åºæ¥ç线æ¡å ¨é½æ¯è¿ä¹ä¸ªå®½åº¦ã
å ¶å®ï¼Canvas ç设置项è¿æ许å¤ï¼ä¾å¦æ们å¯ä»¥ç´æ¥ç§»å¨ç»å¸ãæ转ç»å¸ãè®¾ç½®å ¨å±çç»å¶éæ度ççãè¿äºè®¾ç½®è¿å¯ä»¥éæ¶ä¿ååæ¢å¤ã
è¦æ³¨æçä¸ç¹æ¯ï¼ææå·²ç»ç»å¨ç»å¸ä¸çä¸è¥¿ï¼æ¯å·²ç»å®æ»äºçï¼ä¸ç®¡ä¹åå次è¿è¡ä»»ä½è®¾ç½®é½ä¸ä¼åæ¹åãè¿ä¸ªå¾å Windows ä¸çç»å¾ç¨åºã
åºè¯ä¸å¤è¯´ï¼ç´æ¥ä¸ä»£ç ï¼
// 移å¨ç»å¸ï¼å ¶å®å°±æ¯ç§»å¨åæ ç³»
ctx.translate(å¾å³ç§»å¨çé, å¾ä¸ç§»å¨çé);
// æ转ç»å¸ï¼æ转ä¸å¿ä¸ºåæ ç³»åç¹
ctx.rotate(顺æ¶éæ转çè§åº¦);
// 以åæ ç³»åç¹ä¸ºä¸å¿ç¼©æ¾ç»å¸
ctx.scale(横åæ¾å¤§åæ°, 纵åæ¾å¤§åæ°);
// 设置ç»å¶éæ度ï¼å¦æ fillStyle çå±æ§è®¾ç½®äºéæ度åä¼å å
ctx.globalAlpha(é¶å°ä¸çå°æ°);
// è®¾ç½®å ¨å±ç»åæä½
ctx.globalCompositeOperation = 'lighter';
// ä¿åå½å设置
ctx.save();
// æ¢å¤ä¸æ¬¡ä¿åç设置
ctx.restore();
移å¨ãæ转ã缩æ¾å ¶å®å°±æ¯å¨æ§å¶ç»å¾çåæ ç³»ï¼å¦æä½ å¨è°ç¨è¿ä¸ä¸ªæ¹æ³çæ¶åï¼èåéæ¶å»æä¸ä¸ªå¸¦å»åº¦çåæ ç³»ï¼ææä¼é常好ã
äºå®ä¸ï¼Canvas çåæ åæ¢éµå¾ªè®¡ç®æºå¾å½¢å¦çç¥è¯ï¼åæ¢ç©éµãç®åæ¥è¯´ï¼ä¸ä¸ªåæ å¯ä»¥çææ¯ä¸ä¸ªç©éµï¼åæ æ对åºçç©éµä¹ä¸åæ¢ç©éµå°±å¯ä»¥å®ç°å¯¹åæ çåæ¢ã为äºæå计ç®çæçï¼å¯ä»¥å 计ç®åºå ç§åæ¢å¤åä¹åçåæ¢ç©éµï¼ç¶åç´æ¥éè¿ transform å½æ°å¯¹å½ååæ ç³»è¿è¡åæ¢ï¼æè éè¿ setTransform å½æ°å°åæ ç³»é置为åå§ç¶æååè¿è¡åæ¢ãè³äºåæ¢ç©éµçå 容ï¼å¯¹äºæ¬ææ¥è¯´å°±æäºè¶ 纲äºã
å ¨å±ç»åæä½æç¹å PhotoShop éé¢çâæ··åé项âï¼å ·ä½çå®ç°æ¹å¼è¿æ²¡æå®å ¨ç¡®å®ï¼ç®å常è§æµè§å¨é½ç»ä¸äºçå®ç°æ¹å¼æï¼source-overãsource-atopãdestination-overãdestination-outãlighterãxorãå ·ä½çè¡ä¸ºå¯ä»¥ç Mozilla å®æ¹ææ¡£ï¼ä½æ¯ç±äºæ åè¿æªå®å ¨ç¡®å®ï¼å æ¤å ¶å®æµè§å¨ä¸ä¿è¯ææçè¡ä¸ºé½è· Mozilla çæ åä¸è´ãä¸è¬æ¥è¯´ï¼æ¯è¾å¸¸è§çæ¯ source-over å lighter 两ç§ï¼è¿ä¸¤ç§çæ åå¨æµè§å¨çä¹ç®æ¯æ å¯äºè®®çã
è³äºä¿ååæ¢å¤è®¾ç½®å°±æç¹å¥½ç©äºï¼é¦å éè¦äºè§£ä¸ä¸ªå«âæ âçä¸è¥¿ã
æ æ¯ä¸ä¸ªä¸ç»´æ°ç»ï¼è§å®åªè½ä»ä¸ä¸ªæ¹åæä½ãæ ä¸å¼å§æ¯ç©ºçï¼æ们å¯ä»¥ä»è¿ä¸ªæ¹åå¾æ°ç» push å ç´ ï¼ä¹åªè½ä»è¿ä¸ªæ¹åææåä¸ä¸ªå ç´ ï¼æ 顶å ç´ ï¼pop åºæ¥ï¼é¤æ¤ä»¥å¤æ²¡æä»»ä½å¤ä½çæä½ãå½ç¶ï¼pop ç次æ°ä¸è½å¤äº push ç次æ°ï¼å 为 pop å°æ åºçæ¶åæ é就已ç»æ²¡æå ç´ äºï¼æ¤æ¶å pop æ¯æ²¡ææä¹çãæ çç¨å¤æå¾å¤ï¼ä¾å¦æ¬å·å¹é ã表达å¼æ±å¼ã深度ä¼å æç´¢ï¼çè³ç»å¤§é¨åè¯è¨çå½æ°è°ç¨é½è¦ç¨å°æ ã
æ¯æ¬¡æ们è°ç¨ save å½æ°ï¼å®é ä¸æ¯å°å½åçå ¨å±è®¾ç½® push å°äºä¸ä¸ªä¸é¨æ ä¸ï¼æ¯æ¬¡è°ç¨ restore å½æ°çæ¶åå°æåä¸æ¬¡ä¿åçå 容 pop åºæ¥å¹¶ç¨å®è¦çå½åçå ¨å±è®¾ç½®ï¼è¿æ ·æ 顶就æ¯æè¿ä¸æ¬¡ä¿åçå 容äºãä¿ååæ¢å¤å¨æäºæ åµä¸å¾å¥½ç¨ï¼ä¾å¦æéè¦ç»ä¸ä¸ªæªççå¾å½¢ï¼ç¶å继ç»ç»æ£ççå¾å½¢ï¼è¿æ ·å°±å¯ä»¥å è°ç¨ saveï¼ç¶åè°ç¨ rotateï¼ç»å®å¾å½¢ä¹åå restore åæ¥ï¼ç»§ç»ç»å ¶å®çå¾å½¢ã
å ¶å® Canvas è¿æ许å¤æ¹æ³ï¼ä¾å¦ toDataURL ç´æ¥å°å½åç»å¸ä¸çå 容转æ¢ä¸ºåå è¿å¶ç data-urlï¼getImageDataç´æ¥å°å¾å转æ¢ä¸º RGBA æ°ç»ä»¥ä¾å¾åå¤çç®æ³ä½¿ç¨ï¼putImageData å° RGBA æ°ç»è½¬æ¢ä¸ºå¾çæ¾ç¤ºå¨ç»å¸ä¸ççãå¦æé ä¸ JavaScript çå®æ¶æ´æ°ï¼æå¥½ç¨ requestAnimationFrame èä¸æ¯ setIntervalï¼ï¼åå¯ä»¥äº§çå¨ç»ææãç½ä¸è¿æè®¸å¤ Canvas çåºï¼å¯ä»¥è®©ç¨åºåæ´ç®ä¾¿å°åºäº Canvas ç¼åå±äºèªå·±çç¹ææåè½ãå¨è¿å¿ææ³è¯´ä¸å¥è¯ï¼å¤§å®¶çèæ´æå¤å¤§ï¼Canvas çè½åå°±æå¤å¼º~
ä½¿ç¨ Canvas
说äºè¿ä¹å¤ï¼Canvas 究ç«æ¯ä¸ªå¥ï¼
è±æä¸ Canvas çæææ¯âç»å¸âï¼ä¸è¿è¿é说ç Canvas æ¯ HTML5 ä¸æ°åºçä¸ä¸ªå ç´ ï¼å¼åè å¯ä»¥å¨ä¸é¢ç»å¶ä¸ç³»åå¾å½¢ãCanvas å¨ HTML æ件ä¸çåæ³å¾ç®åï¼
<canvas id="canvas" width="宽度" height="é«åº¦"></canvas>
å ¶ä¸ id å±æ§æ¯ææ HTML å ç´ é½å¯ä»¥ç¨çï¼Canvas èªå¸¦çå±æ§åªæåé¢ä¸¤ä¸ªï¼åå«æ§å¶å®½åº¦ãé«åº¦ï¼ï¼æ²¡æå ¶å®çäºãè³äºå ¼å®¹æ§ï¼CanIUse ä¸é¢åäºï¼åºç¡çåè½ç®åç¨æ·ä½¿ç¨ç 90% çæµè§å¨é½æ¯æï¼æ以大é¨åæ åµä¸è¿æ¯å¯ä»¥æ¾å¿ä½¿ç¨çã
注æï¼ä¸å®è¦ä½¿ç¨ Canvas èªå¸¦ç width å height å±æ§ï¼ä¸è¦ä½¿ç¨ CSS æ¥æ§å¶ï¼å 为 CSS æ§å¶ä¼å¯¼è´ Canvas åå½¢ãå¯ä»¥è¯çä¸ PhptpShop 对æ¯ä¸ä¸ï¼åè æ¯æ¹åâå¾å大å°âï¼åè ææ¯æ£ç¡®çæ¹åâç»å¸å¤§å°âãä¾å¦ä¸å¾æ¯ä¸å¼ å¾çç横åæ¼æ¥ï¼æ左边çé»æ¡ä¸æ¯å¤§å°ä¸º 50px * 50px çåå¾ï¼ä¸é´æ¯æ¹åäºå¾å大å°ä¸º 100px * 100px çææï¼å¾ååå¾æ¨¡ç³ï¼ä½æ¯å¯¹äºå¾åæ¬èº«æ¥è¯´åæ èå´å¹¶æ²¡æå大ï¼æå³è¾¹ææ¯æ£ç¡®ç 100px * 100px ç Canvasã
Canvas ç»å¤§é¨åçç»å¾æ¹æ³é½ä¸ <canvas> æ ç¾æ å ³ï¼éè¦ä½¿ç¨ JavaScript å¯¹å ¶è¿è¡æä½ï¼è¿å°±æ¯æè°ç Canvas APIã
æ们é¦å è·åå°è¿ä¸ªå ç´ ï¼
var canvas = document.getElementById('canvas');
ç¶åéè¿ä¸ä¸ªæ¹æ³æ¥è·åå¯ä»¥è°ç¨ä¸å Canvas API çå ¥å£ï¼
var ctx = canvas.getContext('2d');
çå° 2d æ¯ä¸æ¯å¾æ¿å¨å°èæ³å°æ没æ 3d å¢ï¼æ²¡æ 3d çåæ³ï¼ä¸è¿å¦ææ³è¦å¼å¯ 3D ä¸çç大é¨ï¼åå¯ä»¥å canvas.getContext('webgl')ãç¶è WebGL æ¯åºäº OpenGL ES 2.0 çä¸å¥æ åï¼ä¸æ¬ææ¯å½»å½»åºåºç两æ¡è·¯ï¼å æ¤è¿éå°±ä¸è®¨è®ºäºã
Canvas ä¸çåºæ¬æ¦å¿µ
åæ
ä¸æ°å¦ä¸å¸¸è§çç¬å¡å°åæ ç³»ä¸å¤ªç¸åï¼Canvas çåæ ç³»æ¯è®¡ç®æºä¸å¸¸è§çåæ ç³»ï¼å®é¿è¿æ ·ï¼
ç»å¸çæå·¦ä¸è§æ¯ (0,0)ï¼å¾å³ x å¢å¤§ï¼å¾ä¸ y å¢å¤§ï¼èä¸ x å y é½æ¯æ´æ°ï¼å°±ç®å¨è®¡ç®è¿ç¨ä¸ä¸æ¯æ´æ°ï¼å¨ç»å¶çæ¶åä¹ä¼å½ä½æ´æ°å¤çï¼ï¼åä½æ¯åç´ ã
ç»å¾
带大家ææ§ä¸ä¸ãä¸ç¥éæå¤å°åå¦å°æ¶åç©è¿ logo è¯è¨ï¼å¨éé¢ä½ å¯ä»¥æ§å¶ä¸åªå°æµ·é¾å¨ä¸åæ¿åä¸è¡èµ°ãç»ç»ãæç¬ãè½ç¬ãCanvas ä¸ä¹ä¸æ ·ï¼ä½ éè¦æ§å¶ä¸åªç»ç¬ç移å¨åç»å¶ãç¶è Canvas æ´é«çº§ä¸äºï¼ä½ å¯ä»¥ç´æ¥å©ç¨ä¸äºå½æ°æ¥ç»å¾ï¼ä¸ç¨å»æ§å¶é£åªç»ç¬çä½ç½®ã
Canvas ä¸çåºæ¬å¾å½¢
éè¿ä¸æå®ä¹ç ctx åéå¯ä»¥å¹²è®¸å¤æææçäºæ ï¼æ们å ççå¦ä½ç»å¶ä¸äºåºæ¬å¾å½¢ã
线æ¡
æ们æå®ç»ç¬ç§»å¨å°æä¸ç¹ï¼ç¶ååè¯ç»ç¬éè¦ä»å½åè¿ä¸ç¹ç»å°å¦ä¸ç¹ãæ们å¯ä»¥è®©ç»ç¬å¤æ¬¡ç§»å¨ãç»å¶ï¼æåç»ä¸è¾åºå°å±å¹ä¸ãä¾åå¦ä¸ï¼
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.moveTo(10, 20);
ctx.lineTo(40, 70);
ctx.stroke();
ä¸é¢ç代ç ä¸ï¼lineTo æ¯äº§ç线æ¡ç¨çå½æ°ï¼æ§è¡å®ä¹åç»ç¬å°±ç§»å°äºçº¿æ¡çç»ç¹ãéè¦æ³¨æçæ¯ï¼çº¿æ¡æ¤æ¶å¹¶æ²¡ææ¾ç¤ºå¨å±å¹ä¸ï¼å¿ é¡»è°ç¨ stroke æä¼æ¾ç¤ºãè¿æ ·è®¾è®¡æ¯æéççï¼å 为åå±å¹ä¸è¾åºå 容éè¦è费大éçèµæºï¼æ们å®å ¨å¯ä»¥å æå¤ä¸æ³¢ lineToï¼æåç¨ stroke æ¾ä¸ä¸ªå¤§çã
è·¯å¾
ç»å¶è·¯å¾é常ç®åï¼åªéè¦å åè¯ ctx ä¸å£°âæè¦å¼å§ç»è·¯å¾äºâï¼ç¶åéè¿åç§æ¹æ³ï¼ä¾å¦ lineToï¼ç»å¶è·¯å¾ãå¦æéè¦ç»ä¸ä¸ªå°éè·¯å¾ï¼é£å°±æååè¯ ctxä¸å£°ï¼âæç»å®äºï¼ä½ æå®å°éèµ·æ¥å§ãâå½ç¶ï¼ä¸è¦å¿è®°å©ç¨ stroke è¾åºå°å±å¹ä¸ã
ä¸ä¸ªç®åçä¾åï¼
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.closePath();
ctx.stroke();
å¦ææä¸æ³åªæç»è·¯å¾çº¿æ¡ï¼èæ¯æ³å¡«å æ´ä¸ªè·¯å¾å¢ï¼å¯ä»¥å°æåä¸è¡ç stroke æ¹æ fillï¼è¿æ ·å°±è·ä½¿ç¨äºç»å¾ä¸çæ²¹æ¼æ¡¶ä¸æ ·ï¼å°éè·¯å¾éé¢çå 容就é½è¢«å¡«å ä¸é¢è²äºï¼
ctx.fill();
弧 / åå½¢
ç»å¶å¼§çå½æ°åæ°æ¯è¾å¤ï¼
ctx.arc(åå¿ x åæ , åå¿ y åæ , åå¾, èµ·å§è§åº¦, ç»æ¢è§åº¦, æ¯å¦ä¸ºéæ¶é);
注æï¼å¨ Canvas çåæ ç³»ä¸ï¼è§çä¸è¾¹æ¯ä»¥åå¿ä¸ºä¸å¿çæ°´å¹³åå³çç´çº¿ãè§åº¦åä½å为弧度ãä¾å¦ä¸å¾ï¼ç¡®å®äºåå¿ãèµ·å§è§åº¦ï¼å¾ä¸æ æçéè§ï¼åç»æ¢è§åº¦ï¼å¾ä¸æ æçéè§ï¼ï¼æ¹å为éæ¶éï¼äºæ¯å°±æäºè¿ä¹ä¸ä¸ªå¼§ãå¦ææ¹å为顺æ¶éï¼é£ä¹å°±ä¼æ¯ä¸ä¸ªè·å®äºè¡¥çãé常é常大ç弧â¦â¦
æ以å¦æè½¬äº 2Ï åä¹åï¼å¼§å°±æäºåå½¢ï¼å æ¤ä¹å¯ä»¥ä½¿ç¨ç»å¶å¼§çæ¹å¼æ¥ç»å¶åå½¢ï¼
ctx.beginPath();
ctx.arc(åå¿ x åæ , åå¿ y åæ , åå¾, 0, Math.PI * 2, true);
ctx.closePath();
æåä¸ä¸ªåæ°é便填ï¼å½ç¶ä¹å¯ä»¥ä¸å¡«ï¼ï¼å 为ä¸ç®¡æ¯é¡ºæ¶éè¿æ¯éæ¶éï¼è½¬äº 2Ï åä¹åé½æ¯ä¸ä¸ªåã
ç©å½¢
å¦æåªæ¯æ³ç»å¶ä¸ä¸ªæ¨ªå¹³ç«ç´çç©å½¢ï¼å¯ä»¥ä½¿ç¨ä¸é¢ç两个æ¹æ³ï¼
// åªæè¾¹
ctx.strokeRect(å·¦ä¸è§ x åæ , å·¦ä¸è§ y åæ , 宽度, é«åº¦);
// åªå¡«å
ctx.fillRect(å·¦ä¸è§ x åæ , å·¦ä¸è§ y åæ , 宽度, é«åº¦);
线æ¡æ ·å¼ / å¡«å æ ·å¼
ä¹åç»å¶çææå¾å½¢é½æ¯é»è²çï¼ä½æ¯ Canvas è¯å®ä¸æ¢è¿ä¹ä¸ç§é¢è²ï¼ä¸ç¶æ åçå¶å®è ä¼è¢«å·çå¾æ¨ï¼ãäºå®ä¸ï¼Canvas å¯ä»¥åç¬è®¾ç½®çº¿æ¡æ ·å¼åå¡«å æ ·å¼ï¼åå«ä½¿ç¨çæ¯ strokeStyle å fillStyleãå¯è½çå¼æä¸ç§ï¼çº¯è²ãæ¸åãå¾åãæ¢ç¶çº¿æ¡æ ·å¼ä¸å¡«å æ ·å¼ç使ç¨æ¹æ³ç¸åï¼é£ä¹ä¸é¢ç»ä¸ä»¥å¡«å æ ·å¼ä¸ºä¾ãå¦ææ³è®¾ç½®çº¿æ¡æ ·å¼ï¼ç´æ¥å°ææç fillStyleæ¹æ strokeStyle å³å¯ï¼éé¢çåæ°é½ä¸åã
/* 纯è²å¡«å */
// æ®éçé¢è²
ctx.fillStyle = '#0000ff';
// 带æéæ度çé¢è²
ctx.fillStyle = 'rgba(64, 0, 127, 0.5)';
/* æ¸åå¡«å */
// 设置æ¸åç尺寸ï¼åæ°åå«ä¸ºèµ·å§ç¹ç x å yãç»æ¢ç¹ç x å yï¼
var gradient = ctx.createLinearGradient(0, 0, 170, 0);
// 设置è¿æ¸¡è²ï¼ç¬¬ä¸ä¸ªåæ°æ¯æ¸åçä½ç½®ï¼ç¬¬äºä¸ªåæ°æ¯é¢è²
gradient.addColorStop(0, 'magenta');
gradient.addColorStop(0.5, 'blue');
gradient.addColorStop(1.0, 'red');
// 设置填å æ ·å¼
ctx.fillStyle = gradient;
/* å¾çå¡«å */
// å建å¾ç
var image = new Image;
image.src = '/path/to/image.png';
// å建å¾çç¬è§¦ï¼å¯ä»¥æå®å¾ççå¹³éºæ¹å¼ï¼è¿éæ¯æ¨ªåå¹³éº
var pattern = ctx.createPattern(image, 'repeat-x');
// 设置ç¬è§¦å¡«å
ctx.fillStyle = pattern;
å ³äºæ¸åï¼é¤äºä»£ç ä¸æå°ç线æ§æ¸å以å¤ï¼è¿æ createRadialGradientï¼ä¹å°±æ¯å¾åæ¸åã
设置å®å¡«å æ ·å¼ä¹åï¼å°±å¯ä»¥ä½¿ç¨ fill æ¥å¡«å å¦ï¼å¦æ设置çæ¯çº¿æ¡æ ·å¼ï¼é£ä¹å°±å¯ä»¥ä½¿ç¨ stroke æ¥æè¾¹ã
å½ç¶ï¼å¯¹äºçº¿æ¡æ ·å¼ï¼è¿æ个é¢å¤çæ¹æ³å« lineWidth å¯ä»¥ç¨æ¥æ§å¶çº¿æ¡ç宽度ã
æå
è¦æ³å¨ç»å¸ä¸ç»æåï¼é¦å éè¦ç¥éæ使ç¨çåä½ååå·ï¼
ctx.font = '30px Verdana';
ç¶åå°±å¯ä»¥éè¿ strokeText æè fillText æ¥å¯¹åä½æè¾¹æè å¡«å åä½ã
ctx.strokeText("Hello Coding!", 23, 33);
ctx.fillText("Hello Coding!", 23, 66);
å¾ç
å¨ Canvas ä¸ç»å¶å¾çæä¸ç§æ¹æ³ï¼
// æå®ç»å¶ä½ç½®
ctx.drawImage(image, x, y);
// æå®ç»å¶ä½ç½®åå¾å宽é«
ctx.drawImage(image, x, y, width, height);
// æå®åªè£åºåãç»å¶ä½ç½®åå¾å宽é«
ctx.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
åæ°çå«ä¹ä¾æ¬¡å¦ä¸ï¼
image: è¦ä½¿ç¨ç ImageãCanvas æ Video
sx: å¯éï¼å¼å§åªåç x åæ
sy: å¯éï¼å¼å§åªåç y åæ
swidth: å¯éï¼è¢«åªåå¾åç宽度
sheight: å¯éï¼è¢«åªåå¾åçé«åº¦
x: å¨ç»å¸ä¸æ¾ç½®å¾åç x åæ
y: å¨ç»å¸ä¸æ¾ç½®å¾åç y åæ
width: å¯éï¼è¦ä½¿ç¨çå¾åç宽度
height: å¯éï¼è¦ä½¿ç¨çå¾åçé«åº¦
ç»å¸è®¾ç½®
ç»å¿çåå¦å¯è½ä¼åç°ï¼åææäºå±æ§æ¯ç´æ¥å¯¹ ctx åéå设置ï¼ä¾å¦ ctx.lineWidthï¼åªè¦è®¾ç½®äºå®ï¼é£ä¹åç»ç»åºæ¥ç线æ¡å ¨é½æ¯è¿ä¹ä¸ªå®½åº¦ã
å ¶å®ï¼Canvas ç设置项è¿æ许å¤ï¼ä¾å¦æ们å¯ä»¥ç´æ¥ç§»å¨ç»å¸ãæ转ç»å¸ãè®¾ç½®å ¨å±çç»å¶éæ度ççãè¿äºè®¾ç½®è¿å¯ä»¥éæ¶ä¿ååæ¢å¤ã
è¦æ³¨æçä¸ç¹æ¯ï¼ææå·²ç»ç»å¨ç»å¸ä¸çä¸è¥¿ï¼æ¯å·²ç»å®æ»äºçï¼ä¸ç®¡ä¹åå次è¿è¡ä»»ä½è®¾ç½®é½ä¸ä¼åæ¹åãè¿ä¸ªå¾å Windows ä¸çç»å¾ç¨åºã
åºè¯ä¸å¤è¯´ï¼ç´æ¥ä¸ä»£ç ï¼
// 移å¨ç»å¸ï¼å ¶å®å°±æ¯ç§»å¨åæ ç³»
ctx.translate(å¾å³ç§»å¨çé, å¾ä¸ç§»å¨çé);
// æ转ç»å¸ï¼æ转ä¸å¿ä¸ºåæ ç³»åç¹
ctx.rotate(顺æ¶éæ转çè§åº¦);
// 以åæ ç³»åç¹ä¸ºä¸å¿ç¼©æ¾ç»å¸
ctx.scale(横åæ¾å¤§åæ°, 纵åæ¾å¤§åæ°);
// 设置ç»å¶éæ度ï¼å¦æ fillStyle çå±æ§è®¾ç½®äºéæ度åä¼å å
ctx.globalAlpha(é¶å°ä¸çå°æ°);
// è®¾ç½®å ¨å±ç»åæä½
ctx.globalCompositeOperation = 'lighter';
// ä¿åå½å设置
ctx.save();
// æ¢å¤ä¸æ¬¡ä¿åç设置
ctx.restore();
移å¨ãæ转ã缩æ¾å ¶å®å°±æ¯å¨æ§å¶ç»å¾çåæ ç³»ï¼å¦æä½ å¨è°ç¨è¿ä¸ä¸ªæ¹æ³çæ¶åï¼èåéæ¶å»æä¸ä¸ªå¸¦å»åº¦çåæ ç³»ï¼ææä¼é常好ã
äºå®ä¸ï¼Canvas çåæ åæ¢éµå¾ªè®¡ç®æºå¾å½¢å¦çç¥è¯ï¼åæ¢ç©éµãç®åæ¥è¯´ï¼ä¸ä¸ªåæ å¯ä»¥çææ¯ä¸ä¸ªç©éµï¼åæ æ对åºçç©éµä¹ä¸åæ¢ç©éµå°±å¯ä»¥å®ç°å¯¹åæ çåæ¢ã为äºæå计ç®çæçï¼å¯ä»¥å 计ç®åºå ç§åæ¢å¤åä¹åçåæ¢ç©éµï¼ç¶åç´æ¥éè¿ transform å½æ°å¯¹å½ååæ ç³»è¿è¡åæ¢ï¼æè éè¿ setTransform å½æ°å°åæ ç³»é置为åå§ç¶æååè¿è¡åæ¢ãè³äºåæ¢ç©éµçå 容ï¼å¯¹äºæ¬ææ¥è¯´å°±æäºè¶ 纲äºã
å ¨å±ç»åæä½æç¹å PhotoShop éé¢çâæ··åé项âï¼å ·ä½çå®ç°æ¹å¼è¿æ²¡æå®å ¨ç¡®å®ï¼ç®å常è§æµè§å¨é½ç»ä¸äºçå®ç°æ¹å¼æï¼source-overãsource-atopãdestination-overãdestination-outãlighterãxorãå ·ä½çè¡ä¸ºå¯ä»¥ç Mozilla å®æ¹ææ¡£ï¼ä½æ¯ç±äºæ åè¿æªå®å ¨ç¡®å®ï¼å æ¤å ¶å®æµè§å¨ä¸ä¿è¯ææçè¡ä¸ºé½è· Mozilla çæ åä¸è´ãä¸è¬æ¥è¯´ï¼æ¯è¾å¸¸è§çæ¯ source-over å lighter 两ç§ï¼è¿ä¸¤ç§çæ åå¨æµè§å¨çä¹ç®æ¯æ å¯äºè®®çã
è³äºä¿ååæ¢å¤è®¾ç½®å°±æç¹å¥½ç©äºï¼é¦å éè¦äºè§£ä¸ä¸ªå«âæ âçä¸è¥¿ã
æ æ¯ä¸ä¸ªä¸ç»´æ°ç»ï¼è§å®åªè½ä»ä¸ä¸ªæ¹åæä½ãæ ä¸å¼å§æ¯ç©ºçï¼æ们å¯ä»¥ä»è¿ä¸ªæ¹åå¾æ°ç» push å ç´ ï¼ä¹åªè½ä»è¿ä¸ªæ¹åææåä¸ä¸ªå ç´ ï¼æ 顶å ç´ ï¼pop åºæ¥ï¼é¤æ¤ä»¥å¤æ²¡æä»»ä½å¤ä½çæä½ãå½ç¶ï¼pop ç次æ°ä¸è½å¤äº push ç次æ°ï¼å 为 pop å°æ åºçæ¶åæ é就已ç»æ²¡æå ç´ äºï¼æ¤æ¶å pop æ¯æ²¡ææä¹çãæ çç¨å¤æå¾å¤ï¼ä¾å¦æ¬å·å¹é ã表达å¼æ±å¼ã深度ä¼å æç´¢ï¼çè³ç»å¤§é¨åè¯è¨çå½æ°è°ç¨é½è¦ç¨å°æ ã
æ¯æ¬¡æ们è°ç¨ save å½æ°ï¼å®é ä¸æ¯å°å½åçå ¨å±è®¾ç½® push å°äºä¸ä¸ªä¸é¨æ ä¸ï¼æ¯æ¬¡è°ç¨ restore å½æ°çæ¶åå°æåä¸æ¬¡ä¿åçå 容 pop åºæ¥å¹¶ç¨å®è¦çå½åçå ¨å±è®¾ç½®ï¼è¿æ ·æ 顶就æ¯æè¿ä¸æ¬¡ä¿åçå 容äºãä¿ååæ¢å¤å¨æäºæ åµä¸å¾å¥½ç¨ï¼ä¾å¦æéè¦ç»ä¸ä¸ªæªççå¾å½¢ï¼ç¶å继ç»ç»æ£ççå¾å½¢ï¼è¿æ ·å°±å¯ä»¥å è°ç¨ saveï¼ç¶åè°ç¨ rotateï¼ç»å®å¾å½¢ä¹åå restore åæ¥ï¼ç»§ç»ç»å ¶å®çå¾å½¢ã
å ¶å® Canvas è¿æ许å¤æ¹æ³ï¼ä¾å¦ toDataURL ç´æ¥å°å½åç»å¸ä¸çå 容转æ¢ä¸ºåå è¿å¶ç data-urlï¼getImageDataç´æ¥å°å¾å转æ¢ä¸º RGBA æ°ç»ä»¥ä¾å¾åå¤çç®æ³ä½¿ç¨ï¼putImageData å° RGBA æ°ç»è½¬æ¢ä¸ºå¾çæ¾ç¤ºå¨ç»å¸ä¸ççãå¦æé ä¸ JavaScript çå®æ¶æ´æ°ï¼æå¥½ç¨ requestAnimationFrame èä¸æ¯ setIntervalï¼ï¼åå¯ä»¥äº§çå¨ç»ææãç½ä¸è¿æè®¸å¤ Canvas çåºï¼å¯ä»¥è®©ç¨åºåæ´ç®ä¾¿å°åºäº Canvas ç¼åå±äºèªå·±çç¹ææåè½ãå¨è¿å¿ææ³è¯´ä¸å¥è¯ï¼å¤§å®¶çèæ´æå¤å¤§ï¼Canvas çè½åå°±æå¤å¼º~
温馨提示:答案为网友推荐,仅供参考