{"id":13602615,"url":"https://github.com/dntzhang/cax","last_synced_at":"2025-05-14T20:08:56.801Z","repository":{"id":4851112,"uuid":"6005548","full_name":"dntzhang/cax","owner":"dntzhang","description":"Canvas 渲染引擎，支持 SVG，兼容了小程序、小游戏和 Web ","archived":false,"fork":false,"pushed_at":"2023-07-26T01:14:13.000Z","size":6611,"stargazers_count":2100,"open_issues_count":49,"forks_count":323,"subscribers_count":138,"default_branch":"master","last_synced_at":"2025-05-11T08:36:29.522Z","etag":null,"topics":["2d","canvas","minigame","miniprogram","render","svg","weapp","web","wegame"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"NYTimes/backbone.stickit","license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dntzhang.png","metadata":{"files":{"readme":"README.CN.md","changelog":"change-log.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2012-09-29T02:49:41.000Z","updated_at":"2025-05-01T11:02:08.000Z","dependencies_parsed_at":"2024-01-14T17:04:05.588Z","dependency_job_id":"ec01cd70-38ce-4a12-9daa-73455dfa7599","html_url":"https://github.com/dntzhang/cax","commit_stats":{"total_commits":607,"total_committers":13,"mean_commits":46.69230769230769,"dds":0.1812191103789127,"last_synced_commit":"787138e959c7f8fb13f2b10cdff0d89e79ebb3d5"},"previous_names":["alloyteam/alloygameengine","alloyteam/alloyrender"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dntzhang%2Fcax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dntzhang%2Fcax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dntzhang%2Fcax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dntzhang%2Fcax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dntzhang","download_url":"https://codeload.github.com/dntzhang/cax/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254129529,"owners_count":22019628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d","canvas","minigame","miniprogram","render","svg","weapp","web","wegame"],"created_at":"2024-08-01T18:01:31.744Z","updated_at":"2025-05-14T20:08:56.752Z","avatar_url":"https://github.com/dntzhang.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"简体中文 | [English](./README.md) \n\n# Cax [![](https://img.shields.io/npm/v/cax.svg)](https://www.npmjs.com/package/cax) \n\n\u003e Canvas 渲染引擎，支持SVG，兼容了小程序、小游戏和 Web\n\n\n* [Wechart by Cax![](./asset/hot.png)](https://github.com/dntzhang/wechart)\n* Web DEMO \u0026 [→ Source Code](https://github.com/dntzhang/cax/tree/master/packages/cax/examples)\n  * [Simple](https://dntzhang.github.io/cax) \n  * [Animation](https://dntzhang.github.io/cax/packages/cax/examples/to/) \n  * [Clip](https://dntzhang.github.io/cax/packages/cax/examples/clip/) \n  * [Clip Transform](https://dntzhang.github.io/cax/packages/cax/examples/clip-transform/) \n  * [Clip Transition](https://dntzhang.github.io/cax/packages/cax/examples/clip-transition/) \n  * [To2To Animate](https://dntzhang.github.io/cax/packages/cax/examples/to-animate/) \n  * [Swing](https://dntzhang.github.io/cax/packages/to/examples/swing/) \n  * [Cax + Matter](https://dntzhang.github.io/cax/packages/cax/examples/matter/) \n  * [Pie Chart](https://dntzhang.github.io/wechart/packages/pie/examples/simple/)\n  * [To + Shape](https://dntzhang.github.io/cax/packages/cax/examples/to-shape/)\n  * [Vision](https://dntzhang.github.io/cax/packages/cax/examples/vision/)\n  * [Cache](https://dntzhang.github.io/cax/packages/cax/examples/cache/)\n  * [Filter](https://dntzhang.github.io/cax/packages/cax/examples/filter/)\n  * [SVG](https://dntzhang.github.io/wechart/packages/path/examples/man/)\n  * [Graphics](https://dntzhang.github.io/cax/packages/cax/examples/graphics/)\n  * [Composite Operation](http://dntzhang.github.io/cax/packages/cax/examples/composite-operation/)\n  * [Cax + Dragonbones](https://dntzhang.github.io/wechart/packages/cax-dragonbones/examples/simple/index.html)\n\n\n\n## 特性\n\n* Learn Once, Write Anywhere(小程序、小游戏、PC Web、Mobile Web)\n* Write Once, Run Anywhere(小程序、小游戏、Web只需要修改`new Stage`传入参数即可)\n* 支持小程序、小游戏以及 Web 浏览器渲染\n* 小程序、小游戏和 Web 拥有相同简洁轻巧的 API\n* 高性能且松耦合的渲染架构\n* 超轻量级的代码体积\n* 支持 Canvas 元素管理\n* 支持 Canvas 元素事件体系\n* 图灵完备的 group 嵌套体系\n* 内置 [to2to](https://github.com/dntzhang/cax/tree/master/packages/to) 的跨平台运动引擎\n* 支持可以变形的 clip 裁剪体系\n* 内置文本、位图、序列帧、绘图对象和多种矢量绘制对象\n* 支持 SVG Path 渲染\n* 支持几乎全部的 CSS 滤镜和其他常用滤镜\n* 内置图片加载器\n---\n\n- [一分钟入门小程序 cax 使用](#一分钟入门小程序-cax-使用)\n- [一分钟入门小游戏 cax 使用](#一分钟入门小游戏-cax-使用)\n- [一分钟入门 Web cax 使用](#一分钟入门-web-cax-使用)\n- [内置对象](#内置对象)\n  - [Group](#group)\n    - [Group 方法](#group-方法)\n      - [add](#add)\n      - [remove](#remove)\n      - [empty](#empty)\n      - [replace](#replace)\n  - [Stage](#stage)\n    - [Stage 方法](#stage-方法)\n      - [update](#update)\n      - [scaleEventPoint](#scaleeventpoint)\n    - [Stage 属性](#stage-属性)  \n      - [disableMoveDetection](#disablemovedetection)\n      - [moveDetectionInterval](#movedetectioninterval)\n  - [Bitmap](#bitmap)\n  - [Sprite](#sprite)\n      - [Sprite 方法](#sprite-方法)\n        - [gotoAndPlay](#gotoandplay)\n        - [gotoAndStop](#gotoandstop)\n        - [gotoAndPlayOnce](#gotoandplayonce)\n  - [Text](#text)\n      - [Text 方法](#text-方法)\n        - [getWidth](#getwidth)\n  - [Graphics](#graphics)\n  - [Shape](#shape)\n\t- [Rect](#rect)\n\t- [Circle](#circle)\n\t- [Ellipse](#ellipse)\n  - [Element](#element)\n\t- [Button](#button)\n- [属性](#属性)\n  - [Transform](#transform)\n  - [Alpha](#alpha)\n  - [CompositeOperation](#compositeoperation)\n  - [Cursor](#cursor)\n  - [Fixed](#fixed)\n  - [Shadow](#shadow)\n  - [Stage](#stage-1)    \n- [方法](#方法)  \n  - [destroy](#destroy)\n- [事件](#事件)\n\t- [小程序事件](#小程序事件) \n  - [Web 事件](#web-事件) \n- [运动](#运动)\n- [裁剪](#裁剪)\n- [自定义对象](#自定义对象)\n\t- [自定义 Shape](#自定义-shape) \n  - [自定义 Element](#自定义-element) \n- [图片加载器](#图片加载器)\n- [谁在使用？](#谁在使用)\n- [微信交流群](#微信交流群2)\n- [License](#license)\n\n\n\n## 一分钟入门小程序 cax 使用\n\n到 GitHub [下载 cax 自定义组件](https://github.com/dntzhang/cax/tree/master/packages/cax-weapp)，然后小程序引入 cax 自定义组件:\n\n```\n└── cax\n    ├── cax.js\n    ├── cax.json  \n    ├── cax.wxml  \n    ├── cax.wxss\n    └── index.js\n```\n\n在 page 或者 component 里声明依赖:\n\n```json\n{\n  \"usingComponents\": {\n    \"cax\":\"../cax/cax\"\n  }\n}\n```\n\n在的 wxml 里引入 cax 标签:\n\n```html \n\u003ccax id=\"myCanvas\"\u003e\u003c/cax\u003e\n```\n\n在 js 里渲染逻辑:\n\n```js\nimport cax from '../cax/index'\n\nPage({\n  onLoad: function () {\n    //比 web 里使用 cax 多传递 this，this 代表 Page 或 Component 的实例\n    const stage = new cax.Stage(200, 200, 'myCanvas', this)\n    const rect = new cax.Rect(100, 100, {\n      fillStyle: 'black'\n    })\n    \n    rect.originX = 50\n    rect.originY = 50\n    rect.x = 100\n    rect.y = 100\n    rect.rotation = 30\n\n    rect.on('tap', () =\u003e {\n      console.log('tap')\n    })\n\n    stage.add(rect)\n    stage.update()\n  }\n})\n```\n\n效果如下所示:\n\n![](./asset/demo.jpg)\n\n除了 tap 事件，也可以帮 rect 绑定其他触摸事件：\n\n```js\nrect.on('touchstart', () =\u003e {\n  console.log('touchstart')\n})\n\nrect.on('touchmove', () =\u003e {\n  console.log('touchmove')\n})\n\nrect.on('touchend', () =\u003e {\n  console.log('touchend')\n})\n```\n\n主要，小程序事件触发是根据元素的矩形区域，所以需要设置 width 和 height 才能绑定触发事件。\n\n## 一分钟入门小游戏 cax 使用\n\n到 GitHub [下载 cax 小游戏示例](https://github.com/dntzhang/cax/tree/master/packages/cax-wegame)，目录结构和运行效果如下:\n\n![](./asset/cax-wegame.png)\n\n``` js\nconst stage = new cax.Stage()\n```\n\n和小程序以及 Web 不同的是，小游戏创建 Stage 不需要传任何参数。\n\n## 一分钟入门 Web cax 使用\n\n通过 npm 或者 CDN 获取:\n\n``` bash\nnpm i cax\n```\n\n* [https://unpkg.com/cax@latest/dist/cax.min.js](https://unpkg.com/cax@latest/dist/cax.min.js)\n* [https://unpkg.com/cax@latest/dist/cax.js](https://unpkg.com/cax@latest/dist/cax.js)\n\n使用方法:\n\n``` js\nimport cax from 'cax'\n\nconst stage = new cax.Stage(200, 200, 'body')\n\ncax.loadImgs({\n  imgs: ['./test.jpg'],\n  complete: (imgs) =\u003e {\n    const img = imgs[0]\n    const bitmap = new cax.Bitmap(img)\n\n    bitmap.x = stage.width / 2\n    bitmap.y = stage.height / 2\n    bitmap.rotation = -10\n    bitmap.originX = img.width / 2\n    bitmap.originY = img.height / 2\n    bitmap.filter('blur(10px)')\n\n    stage.add(bitmap)\n    stage.update()\n  }\n})\n```\n\n除了 Stage 构造函数比小程序第四个参数 `this`，其他使用方式都一样。\n\n## 内置对象\n\n### Group\n\n用于分组， group 也可以嵌套 group，父容器的属性会叠加在子属性上, 比如：\n\n* group 的 x 是 100, group 里的 bitmap 的 x 是 200， 最后 bitmap 渲染到 stage 上的 x 是 300\n* group 的 alpha 是 0.7, group 里的 bitmap 的 alpha 是 0.6, 最后 bitmap 渲染到 stage 上的 alpha 是 0.42\n\n```js\nconst group = new cax.Group()\nconst rect = new cax.Rect(100, 100, {\n  fillStyle: 'black'\n})\ngroup.add(rect)\nstage.add(group)\nstage.update()\n```\n\ngroup 拥有常用的 add 和 remove 方法进行元素的增加和删除。先 add 的会先绘制，所有后 add 的会盖在先 add 的上面。\n\n#### Group 方法\n\n##### add\n\n添加对象\n\n``` js\ngroupObj.add (child) \n```\n\n##### remove\n\n移除对象\n\n``` js\ngroupObj.remove (child)\n``` \n\n##### empty\n\n清空子对象\n\n``` js\ngroupObj.empty ()\n``` \n\n##### replace\n\n使用一个对象替代子对象\n\n```js\ngroupObj.replace(current, prev)\n```\n\n### Stage\n\n最大的顶层容器，继承自 Group，所以 Group 拥有的方法它全都有。\n\n#### Stage 方法\n\n##### update\n\n任何元素添加到舞台上是看不到的，你必须执行 update 方法。\n\n```js\nstage.update()\n```\n\n任何元素属性的修改请执行 stage.update() 来更新舞台，或者放在定时器里:\n\n```js\ncax.tick(stage.update.bind(stage))\n```\n\n##### scaleEventPoint\n\n当 canvas 的宽高 和 canvas 的像素不对应的时候，事件触发位置是不准确的，你可以使用 scaleEventPoint 方法使事件校正准确。\n\n```js\n//canvas 宽高是像素的一半\nstage.scaleEventPoint(0.5, 0.5)\n```\n\n例子: https://github.com/dntzhang/cax/blob/master/packages/cax/examples/pie/main.js#L218-L220\n\n#### Stage 属性\n\n##### disableMoveDetection\n\n是否禁用鼠标或触摸移动的事件检测。\n\n```js\nstage.disableMoveDetection = true\n```\n\n这里需要注意，Web 的 disableMoveDetection 默认是 false，微信小游戏默认是 true。所以微信小游戏想要监听 touchmove 和 drag 事件的话需要在创建完 Stage 之后执行下面代码开启监听:\n\n```js\nstage.disableMoveDetection = false\n```\n\n##### moveDetectionInterval\n\n设置 touchmove 和 mousemove 检测的间隔 \n\n```js\n//每秒检测两次\nstage.moveDetectionInterval = 500\n```\n\n### Bitmap\n\n```js\nconst bitmap = new cax.Bitmap(img)\nstage.add(bitmap)\nstage.update()\n```\n\n如果只传 url 而不是 Image 对象的实例，需要这样:\n\n```js\nconst bitmap = new cax.Bitmap('./wepay.png', ()=\u003e{\n  stage.update()\n})\nstage.add(bitmap)\n```\n\n这里需要注意小程序需要配置 downloadFile 需要配置合法域名才能正常加载到图片。\n\n可以设置图片裁剪显示区域，和其他 transform 属性:\n\n```js\nbitmap.rect = [0, 0, 170, 140]\nbitmap.x = 200\n```\n\n### Sprite\n\n序列帧动画组件，可以把任意图片的任意区域组合成一串动画。\n\n```js\nconst sprite = new cax.Sprite({\n    framerate: 7,\n    imgs: ['./mario-sheet.png'],\n    frames: [\n        // x, y, width, height, originX, originY ,imageIndex\n        [0, 0, 32, 32],\n        [32 * 1, 0, 32, 32],\n        [32 * 2, 0, 32, 32],\n        [32 * 3, 0, 32, 32],\n        [32 * 4, 0, 32, 32],\n        [32 * 5, 0, 32, 32],\n        [32 * 6, 0, 32, 32],\n        [32 * 7, 0, 32, 32],\n        [32 * 8, 0, 32, 32],\n        [32 * 9, 0, 32, 32],\n        [32 * 10, 0, 32, 32],\n        [32 * 11, 0, 32, 32],\n        [32 * 12, 0, 32, 32],\n        [32 * 13, 0, 32, 32],\n        [32 * 14, 0, 32, 32]\n    ],\n    animations: {\n        walk: {\n            frames: [0, 1]\n        },\n        happy: {\n            frames: [5, 6, 7, 8, 9]\n        },\n        win: {\n            frames: [12]\n        }\n    },\n    playOnce: false,\n    currentAnimation: \"walk\",\n    animationEnd: function () {\n\n    }\n});\n```\n\n#### Sprite 方法\n\n##### gotoAndPlay\n\n跳到当前 animationName 并开始播放\n\n```js\nspriteObj.gotoAndPlay(animationName)\n```\n\n##### gotoAndStop\n\n跳到当前 animationName 并开始停止\n\n```js\nspriteObj.gotoAndStop(animationName)\n```\n\n##### gotoAndPlayOnce\n\n跳到当前 animationName 并开始播放，播完一轮销毁自己。常用于爆炸\n\n```js\nspriteObj.gotoAndPlayOnce(animationName)\n```\n\n### Text\n\n文本对象\n\n``` js\nconst text = new cax.Text('Hello World', {\n  font: '20px Arial',\n  color: '#ff7700',\n  baseline: 'top'\n})\n```\n\n#### Text 方法\n\n##### getWidth\n\n获取文本宽度\n\n```js\ntextObj.getWidth()\n```\n\n### Graphics\n\n绘图对象，用于使用基本的连缀方式的 Canvas 指令绘制图形。\n\n``` js\nconst graphics = new cax.Graphics()\ngraphics\n    .beginPath()\n    .arc(0, 0, 10, 0, Math.PI * 2)\n    .closePath()\n    .fillStyle('#f4862c')\n    .fill()\n    .strokeStyle('black')\n    .stroke()\n\ngraphics.x = 100\ngraphics.y = 200\n\nstage.add(graphics)\n```\n\n特别注意，如果你在某个循环中执行 graphics 连缀绘制操作，请务必加上 clear() 方法，不然路径叠加到你的浏览器不堪重负:\n\n```js\ncax.setInterval(function(){\n  graphics\n    .clear()\n    .beginPath()\n    .arc(0, 0, 10, 0, Math.PI * 2)\n    .stroke()\n}, 16)\n```\n\n### Shape\n\n与 Graphics 不同的是， Shape 一般拥有有限的宽高，所以可以使用离屏 Canvas 进行缓存。下面这些属于 Shape。\n\n#### Rect\n\n``` js\nconst rect = new cax.Rect(200, 100, {\n  fillStyle: 'black'\n})\n```\n\n#### Circle\n\n``` js\nconst circle = new cax.Circle(10)\n```\n\n#### Ellipse\n\n``` js\nconst ellipse = new cax.Ellipse(120, 20)\n```\n\n注意：从技术上小游戏和 Web 可以离屏 Canvas，小程序不行，因为小程序不支持动态创建离屏 Canvas。\n\n### Element\n\nElement 是多种元素的组合，如 Bitmap、Group、 Text、 Shape 等混合起来的图像。\n\n#### Button\n\n``` js\nconst button = new cax.Button({\n  width: 100,\n  height: 40,\n  text: \"Click Me!\"\n})\n```\n\n## 属性\n\n### Transform\n\n|属性名      |描述   |\n|---|---|\n| x | 水平偏移 |\n| y | 竖直偏移 |\n| scaleX | 水平缩放 |\n| scaleY | 竖直缩放 |\n| scale | 同时设置或读取 scaleX 和 scaleY |\n| rotation | 旋转 |\n| skewX | 歪斜 X |\n| skewY | 歪斜 Y |\n| originX | 旋转基点 X |\n| originY | 旋转基点 Y |\n\n### Alpha\n\n|属性名      |描述   |\n|---|---|\n| alpha | 元素的透明度 |\n\n注意这里父子都设置了 alpha 会进行乘法叠加。\n\n### compositeOperation \n\n|属性名      |描述   |\n|---|---|\n| compositeOperation | 源图像绘制到目标图像上的叠加模式 |\n\n注意这里如果自身没有定义 compositeOperation 会进行向上查找，找到最近的定义了 compositeOperation 的父容器作为自己的 compositeOperation。\n\n### Cursor\n\n|属性名      |描述   |\n|---|---|\n| cursor | 鼠标移上去的形状 |\n\n### Fixed\n\n|属性名      |描述   |\n|---|---|\n| fixed | 是否固定定位，默认是 false 设置成 true 不会叠加祖辈们的 transform 属性|\n\n### Shadow\n\n|属性名      |描述   |\n|---|---|\n| shadow | 阴影|\n\n使用方式:\n\n```js\nobj.shadow = {\n    color: '#42B035',\n    offsetX: -5,\n    offsetY: 5,\n    blur: 10\n}\n```\n\n### Stage\n\n|Name      |Describe   |\n|---|---|\n| stage |或者自己所在的 stage|\n\n使用方式:\n\n```js\nobj.stage\n```\n\n## 方法\n\n### destroy\n\n销毁自己\n\n``` js\nobj.destroy()\n```\n\n## 事件\n\n### 小程序事件\n\n|事件名      |描述   |\n|---|---|\n| tap | 手指触摸后马上离开 |\n| touchstart | 手指触摸动作开始 |\n| touchmove | 手指触摸后移动 |\n| touchend | 手指触摸动作结束 |\n| drag | 拖拽 |\n\n### Web 事件\n\n|事件名      |描述   |\n|---|---|\n| click | 元素上发生点击时触发 |\n| mousedown | 当元素上按下鼠标按钮时触发 |\n| mousemove | 当鼠标指针移动到元素上时触发 |\n| mouseup | 当在元素上释放鼠标按钮时触发 |\n| mouseover | 当鼠标指针移动到元素上时触发 |\n| mouseout | 当鼠标指针移出元素时触发 |\n| tap | 手指触摸后马上离开 |\n| touchstart | 手指触摸动作开始 |\n| touchmove | 手指触摸后移动 |\n| touchend | 手指触摸动作结束 |\n| drag | 拖拽 |\n\n## 运动\n\ncax 内置了 to 的能力以连缀的方式写运动效果：\n\n``` js\nconst easing = cax.To.easing.elasticInOut\n\ncax.To.get(bitmap)\n    .to({ y: 340, rotation: 240 }, 2000, easing)\n    .begin(() =\u003e {\n        console.log(\"Task one has began!\")\n    })\n    .progress(() =\u003e {\n        console.log(\"Task one is progressing!\")\n    })\n    .end(() =\u003e {\n        console.log(\"Task one has completed!\")\n    })\n    .wait(500)\n    .to()\n    .rotation(0, 1400, easing)\n    .begin(() =\u003e {\n        console.log(\"Task two has began!\")\n    })\n    .progress(() =\u003e {\n        console.log(\"Task two is progressing!\")\n    })\n    .end(() =\u003e {\n        console.log(\"Task two has completed!\")\n    })\n    .start();\n```\n\n* `to` 和 `to` 之间的是并行\n* `to` 和 `wait` 之前的是串行\n* `to` 和 `to` 之间的 与 下一个 `to` 和 `to` 之间的是串行\n\n有点绕，但是很直观，慢慢体会。\n\n当然，也可以通过 set 方法支持任意属性的运动，如:\n\n``` js\n.set('y', 240, 2000, cax.easing.elasticInOut)\n``` \n\n等同于\n\n``` js\n.y(240, 2000, cax.easing.elasticInOut)\n```\n\n如果想要循环播放的话可以使用 `cycle` 方法:\n\n``` js\ncax.To.get(bitmap)\n    .to()\n    .y(340, 2000, cax.easing.elasticInOut)\n    .to\n    .y(0, 2000, cax.easing.elasticInOut)\n    .cycle()\n    .start()\n```\n\n* [→ 运动演示地址](http://dntzhang.github.io/cax/packages/cax/examples/to/)\n* [→ 去 to2to 一看究竟](https://github.com/dntzhang/cax/tree/master/packages/to)\n* [→ 看看 cax.To.easing 种类](http://tweenjs.github.io/tween.js/examples/03_graphs.html)\n\n这里需要注意，和 tween.js 不同，cax 把 easing 命名全改成了一个单词的驼峰命名。如 Cubic.In 变成了 cubicIn。\n\n## 裁剪\n\n```js\nconst stage = new cax.Stage(600, 400, 'body')\nconst bitmap = new cax.Bitmap('./wepay-diy.jpg', () =\u003e {\n    stage.update()\n})\nconst clipPath = new cax.Graphics()\nclipPath.arc(40, 40, 25, 0, Math.PI * 2)\nbitmap.clip(clipPath)\nstage.add(bitmap)\n```\n\n使用下面的代码可以得到同样的效果:\n\n```js\nconst clipPath = new cax.Graphics()\nclipPath.x = 40\nclipPath.y = 40\nclipPath.arc(0, 0, 25, 0, Math.PI * 2)\n```\n\n所以，裁剪区域也是支持所有 transform 属性(x,y,scaleX,scaleY,rotation,skewX,skewY,originX,originY)。\n\n[→ 裁剪演示地址](http://dntzhang.github.io/cax/packages/cax/examples/clip/)\n\n## 自定义对象\n\n### 自定义 Shape\n\n自定义 Shape 继承自 cax.Shape:\n\n``` js\nclass Sector extends cax.Shape {\n  constructor (r, from, to, option) {\n    super()\n\n    this.option = option || {}\n    this.r = r\n    this.from = from\n    this.to = to\n  }\n\n  draw () {\n    this.beginPath()\n      .moveTo(0, 0)\n      .arc(0, 0, this.r, this.from, this.to)\n      .closePath()\n      .fillStyle(this.option.fillStyle)\n      .fill()\n      .strokeStyle(this.option.strokeStyle)\n      .lineWidth(this.option.lineWidth)\n      .stroke()\n  }\n}\n```\n\n使用 Shape:\n\n``` js\nconst sector = new Sector(10, 0, Math.PI/6, {\n  fillStyle: 'red'\n  lineWidth: 2\n})\nstage.add(sector)\nstage.update()\n```\n\n### 自定义 Element\n\n自定义 Element 继承自 cax.Group:\n\n``` js\nclass Button extends cax.Group {\n  constructor (option) {\n    super()\n    this.width = option.width\n    this.roundedRect = new  cax.RoundedRect(option.width, option.height, option.r)\n    this.text = new cax.Text(option.text, {\n      font: option.font,\n      color: option.color\n    })\n\n    this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX\n    this.text.y = option.height / 2 - 10 + 5 * this.text.scaleY\n    this.add(this.roundedRect, this.text)\n  }\n}\n\nexport default Button\n```\n\n使用:\n\n``` js\nconst button = new cax.Button({\n  width: 100,\n  height: 40,\n  text: \"Click Me!\"\n})\n```\n\n一般情况下，稍微复杂组合体都建议使用继承自 Group，这样利于扩展也方便管理自身内部的元件。\n小游戏的 DEMO 里的 [Player、Bullet、Enemy、Background](https://github.com/dntzhang/cax/tree/master/packages/cax-wegame/js) 全都是继承自 Group。\n[Wechart 的所有图表](https://github.com/dntzhang/wechart/tree/master/packages)全都是继承自 Group。\n\n## 图片加载器\n\n``` js\ncax.loadImg({\n  img: './a.png',\n  complete: function(img){\n\n  }\n})\n```\n\n加载多张图片：\n\n```js\ncax.loadImgs({\n  img: ['./a.png','./b.png'],\n  progress: function(progress){\n    console.log(progress) //0.5 and then 1\n  },\n  complete: function(imgs){\n    console.log(imgs[0]) //Image(a.png)\n    console.log(imgs[1]) //Image(b.png)\n  }\n})\n```\n\n## 小程序案例\n\n![星球部落](./asset/ss1.png)![星球部落](./asset/ss3.png)\n\n## 微信小游戏案例\n\n![你在画什么](https://github.com/dntzhang/cax/raw/master/asset/draw.png)\n\n![点十消除](./asset/wegame.jpg)\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdntzhang%2Fcax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdntzhang%2Fcax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdntzhang%2Fcax/lists"}