├── .eslintrc
├── .gitignore
├── README.CN.md
├── README.md
├── asset
├── cax-matter.png
├── cax-wegame.png
├── cax0712.png
├── demo.jpg
├── draw.png
├── getting-start.png
├── hot.png
├── qq.png
├── ss1.png
├── ss3.png
├── wegame.jpg
├── wegame.png
├── wx.png
└── xqbl.png
├── change-log.md
├── index.html
├── packages
├── cax-weapp
│ ├── app.js
│ ├── app.json
│ ├── app.wxss
│ ├── cax
│ │ ├── cax.js
│ │ ├── cax.json
│ │ ├── cax.wxml
│ │ ├── cax.wxss
│ │ └── index.js
│ ├── images
│ │ └── wx.png
│ ├── index
│ │ ├── index.js
│ │ ├── index.json
│ │ ├── index.wxml
│ │ └── index.wxss
│ └── project.config.json
├── cax-wegame
│ ├── audio
│ │ ├── bgm.mp3
│ │ ├── boom.mp3
│ │ └── bullet.mp3
│ ├── game.js
│ ├── game.json
│ ├── images
│ │ ├── Common.png
│ │ ├── bg.jpg
│ │ ├── bullet.png
│ │ ├── enemy.png
│ │ ├── explosion1.png
│ │ ├── explosion10.png
│ │ ├── explosion11.png
│ │ ├── explosion12.png
│ │ ├── explosion13.png
│ │ ├── explosion14.png
│ │ ├── explosion15.png
│ │ ├── explosion16.png
│ │ ├── explosion17.png
│ │ ├── explosion18.png
│ │ ├── explosion19.png
│ │ ├── explosion2.png
│ │ ├── explosion3.png
│ │ ├── explosion4.png
│ │ ├── explosion5.png
│ │ ├── explosion6.png
│ │ ├── explosion7.png
│ │ ├── explosion8.png
│ │ ├── explosion9.png
│ │ └── hero.png
│ ├── js
│ │ ├── background.js
│ │ ├── bullet.js
│ │ ├── enemy-group.js
│ │ ├── enemy.js
│ │ ├── libs
│ │ │ └── cax.js
│ │ ├── music.js
│ │ └── player.js
│ └── project.config.json
├── cax
│ ├── .babelrc
│ ├── .eslintignore
│ ├── README.md
│ ├── asset
│ │ ├── cax-wegame.png
│ │ ├── cax0712.png
│ │ ├── demo.jpg
│ │ ├── getting-start.png
│ │ ├── qq.png
│ │ ├── wegame.png
│ │ └── wx.png
│ ├── change-log.md
│ ├── dist
│ │ ├── cax.js
│ │ └── cax.min.js
│ ├── examples
│ │ ├── button
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── mario-sheet.png
│ │ │ └── wepay.png
│ │ ├── cache
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── mario-sheet.png
│ │ │ └── wepay.png
│ │ ├── caching
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── mario-sheet.png
│ │ │ └── wepay.png
│ │ ├── clip-transform
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay.png
│ │ ├── clip-transition
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── pay.png
│ │ │ └── wepay.png
│ │ ├── clip
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ ├── composite-operation
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ ├── filter
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── wegame.test.js
│ │ │ └── wepay-diy.jpg
│ │ ├── getting-start
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ ├── graphics
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ └── main.js
│ │ ├── group-clip
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ ├── matter
│ │ │ ├── img
│ │ │ │ ├── basketball.png
│ │ │ │ └── box.jpg
│ │ │ ├── index.html
│ │ │ └── matter.js
│ │ ├── path
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ └── main.js
│ │ ├── pie
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ └── main.js
│ │ ├── simple
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ ├── mario-sheet.png
│ │ │ └── wepay.png
│ │ ├── sprite
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── mario-sheet.png
│ │ ├── to-animate
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ ├── to-shape
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ └── main.js
│ │ ├── to
│ │ │ ├── bundler.js
│ │ │ ├── index.html
│ │ │ ├── main.js
│ │ │ └── wepay-diy.jpg
│ │ └── vision
│ │ │ ├── bundler.js
│ │ │ ├── hero-m.png
│ │ │ ├── index.html
│ │ │ └── main.js
│ ├── package.json
│ ├── src
│ │ ├── common
│ │ │ ├── animate.js
│ │ │ ├── raf-interval.js
│ │ │ ├── to.js
│ │ │ ├── tween.js
│ │ │ └── util.js
│ │ ├── index.js
│ │ └── render
│ │ │ ├── base
│ │ │ ├── a2c.js
│ │ │ ├── arc-to-bezier.js
│ │ │ ├── event-dispatcher.js
│ │ │ ├── event.js
│ │ │ ├── matrix2d.js
│ │ │ ├── path-parser.js
│ │ │ ├── stage-propagation-tag.js
│ │ │ └── uid.js
│ │ │ ├── display
│ │ │ ├── bitmap.js
│ │ │ ├── display-object.js
│ │ │ ├── element
│ │ │ │ └── button.js
│ │ │ ├── graphics.js
│ │ │ ├── group.js
│ │ │ ├── shape
│ │ │ │ ├── arrow-path.js
│ │ │ │ ├── circle.js
│ │ │ │ ├── ellipse.js
│ │ │ │ ├── equilateral-polygon.js
│ │ │ │ ├── path.js
│ │ │ │ ├── polygon.js
│ │ │ │ ├── rect.js
│ │ │ │ ├── rounded-rect.js
│ │ │ │ ├── sector.js
│ │ │ │ └── shape.js
│ │ │ ├── sprite.js
│ │ │ ├── stage.js
│ │ │ ├── text.js
│ │ │ ├── we-stage.js
│ │ │ └── wegame-canvas.js
│ │ │ ├── filter
│ │ │ ├── README.md
│ │ │ ├── blur.js
│ │ │ ├── brightness.js
│ │ │ ├── colorize.js
│ │ │ ├── contrast.js
│ │ │ ├── create-image-data.js
│ │ │ ├── gamma.js
│ │ │ ├── grayscale.js
│ │ │ ├── index.js
│ │ │ ├── invert.js
│ │ │ ├── sepia.js
│ │ │ └── threshold.js
│ │ │ └── render
│ │ │ ├── canvas-render.js
│ │ │ ├── hit-render.js
│ │ │ ├── render.js
│ │ │ ├── renderer.js
│ │ │ └── wx-hit-render.js
│ └── webpack.config.js
└── to
│ ├── README.EN.md
│ ├── README.md
│ ├── dist
│ ├── to.js
│ └── to.min.js
│ ├── examples
│ ├── animate
│ │ ├── index.html
│ │ └── wepay-diy.jpg
│ ├── simple
│ │ ├── bundler.js
│ │ ├── index.html
│ │ ├── main.js
│ │ └── wepay-diy.jpg
│ ├── swing
│ │ ├── index.html
│ │ └── wepay-diy.jpg
│ └── to
│ │ ├── index.html
│ │ └── wepay-diy.jpg
│ ├── package.json
│ ├── src
│ ├── animate.js
│ ├── index.js
│ ├── raf-interval.js
│ ├── to.js
│ └── tween.js
│ └── webpack.config.js
└── tutorial
└── cax-matter.md
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "standard",
3 | "rules": {
4 | "one-var": 0,
5 | "no-mixed-operators": 0,
6 | "standard/no-callback-literal": 0,
7 | "new-cap": 0
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /*/*/node_modules
3 | /packages/node_modules
4 | .DS_Store
5 | packages/.DS_Store
6 | /packages/*/test
7 |
--------------------------------------------------------------------------------
/asset/cax-matter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/cax-matter.png
--------------------------------------------------------------------------------
/asset/cax-wegame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/cax-wegame.png
--------------------------------------------------------------------------------
/asset/cax0712.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/cax0712.png
--------------------------------------------------------------------------------
/asset/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/demo.jpg
--------------------------------------------------------------------------------
/asset/draw.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/draw.png
--------------------------------------------------------------------------------
/asset/getting-start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/getting-start.png
--------------------------------------------------------------------------------
/asset/hot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/hot.png
--------------------------------------------------------------------------------
/asset/qq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/qq.png
--------------------------------------------------------------------------------
/asset/ss1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/ss1.png
--------------------------------------------------------------------------------
/asset/ss3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/ss3.png
--------------------------------------------------------------------------------
/asset/wegame.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/wegame.jpg
--------------------------------------------------------------------------------
/asset/wegame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/wegame.png
--------------------------------------------------------------------------------
/asset/wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/wx.png
--------------------------------------------------------------------------------
/asset/xqbl.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/asset/xqbl.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
--------------------------------------------------------------------------------
/packages/cax-weapp/app.js:
--------------------------------------------------------------------------------
1 | App({
2 | onLaunch: function () {
3 |
4 | }
5 | })
6 |
--------------------------------------------------------------------------------
/packages/cax-weapp/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "pages": [
3 | "index/index"
4 | ],
5 | "window": {
6 | "backgroundTextStyle": "light",
7 | "navigationBarBackgroundColor": "#fff",
8 | "navigationBarTitleText": "WeChat",
9 | "navigationBarTextStyle": "black"
10 | }
11 | }
--------------------------------------------------------------------------------
/packages/cax-weapp/app.wxss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-weapp/app.wxss
--------------------------------------------------------------------------------
/packages/cax-weapp/cax/cax.js:
--------------------------------------------------------------------------------
1 | import cax from './index'
2 |
3 | Component({
4 | /**
5 | * 组件的属性列表
6 | */
7 | properties: {
8 |
9 | option: {
10 | type: Object
11 | }
12 | },
13 |
14 | /**
15 | * 组件的初始数据
16 | */
17 | data: {
18 | width: 0,
19 | height: 0,
20 | id: 'caxCanvas' + cax.caxCanvasId++,
21 | index: cax.caxCanvasId - 1
22 | },
23 |
24 | /**
25 | * 组件的方法列表
26 | */
27 | methods: {
28 |
29 | getCaxCanvasId: function () {
30 | return this.data.id
31 | },
32 |
33 | touchStart: function (evt) {
34 | this.stage.touchStartHandler(evt)
35 | this.stage.touchStart && this.stage.touchStart(evt)
36 | },
37 |
38 | touchMove: function (evt) {
39 | this.stage.touchMoveHandler(evt)
40 | this.stage.touchMove && this.stage.touchMove(evt)
41 | },
42 |
43 | touchEnd: function (evt) {
44 | this.stage.touchEndHandler(evt)
45 | this.stage.touchEnd && this.stage.touchEnd(evt)
46 | }
47 |
48 | }
49 | })
50 |
--------------------------------------------------------------------------------
/packages/cax-weapp/cax/cax.json:
--------------------------------------------------------------------------------
1 | {
2 | "component": true,
3 | "usingComponents": {}
4 | }
--------------------------------------------------------------------------------
/packages/cax-weapp/cax/cax.wxml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/packages/cax-weapp/cax/cax.wxss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-weapp/cax/cax.wxss
--------------------------------------------------------------------------------
/packages/cax-weapp/images/wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-weapp/images/wx.png
--------------------------------------------------------------------------------
/packages/cax-weapp/index/index.js:
--------------------------------------------------------------------------------
1 | import cax from '../cax/index'
2 |
3 | Page({
4 | onLoad: function (options) {
5 | const info = wx.getSystemInfoSync()
6 | const stage = new cax.Stage(info.windowWidth, info.windowHeight / 2, 'myCanvas', this)
7 |
8 | const rect = new cax.Rect(100, 100, {
9 | fillStyle: 'black'
10 | })
11 |
12 | rect.originX = 50
13 | rect.originY = 50
14 | rect.x = 100
15 | rect.y = 100
16 | rect.rotation = 30
17 |
18 | rect.on('touchstart', () => {
19 | console.log('rect touchstart')
20 | })
21 |
22 | rect.on('touchmove', () => {
23 | console.log('rect touchmove')
24 | })
25 |
26 | rect.on('touchend', () => {
27 | console.log('rect touchend')
28 | })
29 |
30 | rect.on('tap', () => {
31 | console.log('rect tap')
32 | })
33 |
34 |
35 | stage.add(rect)
36 |
37 | const button = new cax.Button({ width: 100, height: 40, text: "I am button!" })
38 | button.y = 170
39 | button.x = 20
40 | stage.add(button)
41 |
42 |
43 |
44 |
45 | const bitmap = new cax.Bitmap('/images/wx.png')
46 |
47 |
48 |
49 | bitmap.on('tap', () => {
50 | console.log('bitmap tap')
51 | })
52 |
53 | stage.add(bitmap)
54 |
55 |
56 | const sprite = new cax.Sprite({
57 | framerate: 7,
58 | imgs: ['https://r.photo.store.qq.com/psb?/V137Nysk1nVBJS/09YJstVgoLEi0niIWFcOJCyGmkyDaYLq.tlpDE62Zdc!/r/dDMBAAAAAAAA'],
59 | frames: [
60 | // x, y, width, height, originX, originY ,imageIndex
61 | [0, 0, 32, 32],
62 | [32 * 1, 0, 32, 32],
63 | [32 * 2, 0, 32, 32],
64 | [32 * 3, 0, 32, 32],
65 | [32 * 4, 0, 32, 32],
66 | [32 * 5, 0, 32, 32],
67 | [32 * 6, 0, 32, 32],
68 | [32 * 7, 0, 32, 32],
69 | [32 * 8, 0, 32, 32],
70 | [32 * 9, 0, 32, 32],
71 | [32 * 10, 0, 32, 32],
72 | [32 * 11, 0, 32, 32],
73 | [32 * 12, 0, 32, 32],
74 | [32 * 13, 0, 32, 32],
75 | [32 * 14, 0, 32, 32]
76 | ],
77 | animations: {
78 | walk: {
79 | frames: [0, 1]
80 | },
81 | happy: {
82 | frames: [11, 12, 13, 14]
83 | },
84 | win: {
85 | frames: [7, 8, 9, 10]
86 | }
87 | },
88 | currentAnimation: 'walk',
89 | animationEnd: function () {
90 | }
91 | })
92 |
93 | sprite.x = 100
94 | sprite.y = 100
95 | stage.add(sprite)
96 |
97 |
98 |
99 | const stage2 = new cax.Stage(info.windowWidth, info.windowHeight / 2, 'myCanvas2', this)
100 |
101 | const button2 = new cax.Button({ width: 100, height: 40, text: "I am in stage2!" })
102 | button2.y = 170
103 | button2.x = 20
104 | stage2.add(button2)
105 | const bitmap2 = new cax.Bitmap('/images/wx.png')
106 | bitmap2.y=100
107 | stage2.add(bitmap2)
108 |
109 | cax.To.get(rect).to().x(200, 2000, cax.easing.elasticInOut).start()
110 |
111 |
112 |
113 |
114 | setInterval(function () {
115 | rect.rotation++
116 | stage.update()
117 | stage2.update()
118 | }, 16)
119 |
120 | }
121 | })
122 |
--------------------------------------------------------------------------------
/packages/cax-weapp/index/index.json:
--------------------------------------------------------------------------------
1 | {
2 | "usingComponents": {
3 | "cax":"../cax/cax"
4 | }
5 | }
--------------------------------------------------------------------------------
/packages/cax-weapp/index/index.wxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/cax-weapp/index/index.wxss:
--------------------------------------------------------------------------------
1 | .container{
2 | height:1000px;
3 | }
--------------------------------------------------------------------------------
/packages/cax-weapp/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "setting": {
4 | "urlCheck": true,
5 | "es6": true,
6 | "postcss": true,
7 | "minified": true,
8 | "newFeature": true
9 | },
10 | "compileType": "miniprogram",
11 | "libVersion": "1.9.94",
12 | "appid": "wxdf970566455966b0",
13 | "projectname": "cax-weapp",
14 | "condition": {
15 | "search": {
16 | "current": -1,
17 | "list": []
18 | },
19 | "conversation": {
20 | "current": -1,
21 | "list": []
22 | },
23 | "plugin": {
24 | "current": -1,
25 | "list": []
26 | },
27 | "game": {
28 | "currentL": -1,
29 | "list": []
30 | },
31 | "miniprogram": {
32 | "current": -1,
33 | "list": []
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/packages/cax-wegame/audio/bgm.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/audio/bgm.mp3
--------------------------------------------------------------------------------
/packages/cax-wegame/audio/boom.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/audio/boom.mp3
--------------------------------------------------------------------------------
/packages/cax-wegame/audio/bullet.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/audio/bullet.mp3
--------------------------------------------------------------------------------
/packages/cax-wegame/game.js:
--------------------------------------------------------------------------------
1 | import cax from './js/libs/cax'
2 |
3 | import Background from './js/background'
4 | import Player from './js/player'
5 | import EnemyGroup from './js/enemy-group'
6 | import Music from './js/music'
7 |
8 | const bg = new Background()
9 | const player = new Player()
10 | const stage = new cax.Stage()
11 | const enemyGroup = new EnemyGroup()
12 | const music = new Music()
13 | const info = wx.getSystemInfoSync()
14 | const screenHeight = info.windowHeight
15 |
16 | stage.add(bg, enemyGroup, player)
17 |
18 | stage.add(player.bulletGroup)
19 |
20 | let touchX = null
21 | let touchY = null
22 |
23 | wx.onTouchStart(function (e) {
24 | touchX = e.touches[0].clientX
25 | touchY = e.touches[0].clientY
26 | })
27 |
28 | wx.onTouchMove(function (e) {
29 | touchX = e.touches[0].clientX
30 | touchY = e.touches[0].clientY
31 | })
32 |
33 | function update () {
34 | stage.update()
35 | bg.update()
36 |
37 | player.update()
38 | if (touchX !== null) {
39 | player.x = touchX
40 | player.y = touchY
41 | }
42 | enemyGroup.update()
43 |
44 | enemyGroup.children.forEach(enemy => {
45 | player.bulletGroup.children.forEach(bullet => {
46 | if (bullet.isCollideWith(enemy)) {
47 | bullet.visible = false
48 | enemy.explode()
49 | music.playExplosion()
50 | }
51 | })
52 | })
53 |
54 | requestAnimationFrame(update)
55 | }
56 |
57 | update()
58 |
59 |
60 | const text = new cax.Text('powered by cax', {
61 | font: '20px Arial',
62 | color: '#42B035',
63 | baseline: 'top'
64 | })
65 | text.y = screenHeight - 30
66 | text.x = 4
67 | text.alpha = 0.6
68 | stage.add(text)
69 |
70 | cax.To.get(text).to().x(100, 2000, cax.easing.elasticInOut).start()
--------------------------------------------------------------------------------
/packages/cax-wegame/game.json:
--------------------------------------------------------------------------------
1 | {
2 | "deviceOrientation": "portrait"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/cax-wegame/images/Common.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/Common.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/bg.jpg
--------------------------------------------------------------------------------
/packages/cax-wegame/images/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/bullet.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/enemy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/enemy.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion1.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion10.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion11.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion12.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion13.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion14.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion15.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion16.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion17.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion18.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion19.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion2.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion3.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion4.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion5.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion6.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion7.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion8.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/explosion9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/explosion9.png
--------------------------------------------------------------------------------
/packages/cax-wegame/images/hero.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax-wegame/images/hero.png
--------------------------------------------------------------------------------
/packages/cax-wegame/js/background.js:
--------------------------------------------------------------------------------
1 | import cax from './libs/cax'
2 |
3 | const info = wx.getSystemInfoSync()
4 | const screenWidth = info.windowWidth
5 | const screenHeight = info.windowHeight
6 |
7 | const BG_IMG_SRC = 'images/bg.jpg'
8 | const BG_WIDTH = 512
9 | const BG_HEIGHT = 512
10 |
11 | export default class BackGround extends cax.Group {
12 | constructor () {
13 | super()
14 |
15 | this.bgUp = new cax.Bitmap(BG_IMG_SRC)
16 | this.bgDown = new cax.Bitmap(BG_IMG_SRC)
17 |
18 | this.bgDown.y = screenHeight * -1
19 | this.bgUp.y = -1
20 |
21 | this.bgDown.scaleX = this.bgUp.scaleX = screenWidth / BG_WIDTH
22 | this.bgDown.scaleY = this.bgUp.scaleY = screenHeight / BG_HEIGHT
23 |
24 | this.add(this.bgUp, this.bgDown)
25 | }
26 |
27 | update () {
28 | this.bgDown.y += 2
29 | this.bgUp.y += 2
30 |
31 | if (this.bgUp.y >= screenHeight) {
32 | this.bgUp.y = this.bgDown.y - screenHeight
33 | }
34 |
35 | if (this.bgDown.y >= screenHeight) {
36 | this.bgDown.y = this.bgUp.y - screenHeight
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/packages/cax-wegame/js/bullet.js:
--------------------------------------------------------------------------------
1 | import cax from './libs/cax'
2 |
3 | const BULLET_IMG_SRC = 'images/bullet.png'
4 | const IMG_WIDTH = 62
5 | const IMG_HEIGHT = 108
6 |
7 | export default class Bullet extends cax.Group {
8 | constructor () {
9 | super()
10 | this.bitmap = new cax.Bitmap(BULLET_IMG_SRC)
11 | this.bitmap.originX = IMG_WIDTH / 2
12 | this.bitmap.originY = IMG_HEIGHT / 2
13 | this.add(this.bitmap)
14 | this.scaleX = this.scaleY = 0.3
15 | this.speed = 5
16 |
17 | this.width = IMG_WIDTH / 2
18 | this.height = IMG_WIDTH / 2
19 | }
20 |
21 | // 每一帧更新子弹位置
22 | update () {
23 | this.y -= this.speed
24 | // 超出屏幕外回收自身
25 | if (this.y < -200) {
26 | this.destroy()
27 | }
28 | }
29 |
30 | isCollideWith (sp) {
31 | if (this.visible && !sp.exploded) {
32 | let spX = sp.x
33 | let spY = sp.y
34 |
35 | return !!(spX >= this.x - this.width / 2 &&
36 | spX <= this.x + this.width / 2 &&
37 | spY >= this.y - this.height / 2 &&
38 | spY <= this.y + this.height / 2)
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/packages/cax-wegame/js/enemy-group.js:
--------------------------------------------------------------------------------
1 | import cax from './libs/cax'
2 | import Enemy from './enemy'
3 |
4 | const info = wx.getSystemInfoSync()
5 | const screenWidth = info.windowWidth
6 |
7 | function rnd (start, end) {
8 | return Math.floor(Math.random() * (end - start) + start)
9 | }
10 |
11 | export default class EnemyGroup extends cax.Group {
12 | constructor () {
13 | super()
14 | this.preGenerateTime = Date.now()
15 | }
16 |
17 | generate () {
18 | const e = new Enemy()
19 | e.x = rnd(0, screenWidth)
20 | e.y = -60
21 | this.add(e)
22 | }
23 |
24 | update () {
25 | this.currentTime = Date.now()
26 | if (this.currentTime - this.preGenerateTime > 1000) {
27 | this.generate()
28 |
29 | this.preGenerateTime = this.currentTime
30 | }
31 |
32 | this.children.forEach(child => {
33 | child.update()
34 | })
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/cax-wegame/js/enemy.js:
--------------------------------------------------------------------------------
1 | import cax from './libs/cax'
2 |
3 | const ENEMY_IMG_SRC = 'images/enemy.png'
4 |
5 | const IMG_WIDTH = 120
6 | const IMG_HEIGHT = 79
7 |
8 | const info = wx.getSystemInfoSync()
9 | const screenHeight = info.windowHeight
10 |
11 | export default class Enemy extends cax.Group {
12 | constructor () {
13 | super()
14 | this.bitmap = new cax.Bitmap(ENEMY_IMG_SRC)
15 | this.bitmap.originX = IMG_WIDTH / 2
16 | this.bitmap.originY = IMG_HEIGHT / 2
17 | this.add(this.bitmap)
18 |
19 | this.scaleX = this.scaleY = 0.5
20 | this.speed = 1
21 |
22 | this.width = IMG_WIDTH / 2
23 | this.height = IMG_WIDTH / 2
24 |
25 | this.spriteOption = {
26 | framerate: 20,
27 | imgs: [
28 | 'images/explosion1.png',
29 | 'images/explosion2.png',
30 | 'images/explosion3.png',
31 | 'images/explosion4.png',
32 | 'images/explosion5.png',
33 | 'images/explosion6.png',
34 | 'images/explosion7.png',
35 | 'images/explosion8.png',
36 | 'images/explosion9.png',
37 | 'images/explosion10.png',
38 | 'images/explosion11.png',
39 | 'images/explosion12.png',
40 | 'images/explosion13.png',
41 | 'images/explosion14.png',
42 | 'images/explosion15.png',
43 | 'images/explosion16.png',
44 | 'images/explosion17.png',
45 | 'images/explosion18.png',
46 | 'images/explosion19.png'
47 | ],
48 | frames: [
49 | // x, y, width, height, originX, originY ,imageIndex
50 | [0, 0, 64, 48, 0, 0, 0],
51 | [0, 0, 64, 48, 0, 0, 1],
52 | [0, 0, 64, 48, 0, 0, 2],
53 | [0, 0, 64, 48, 0, 0, 3],
54 | [0, 0, 64, 48, 0, 0, 4],
55 | [0, 0, 64, 48, 0, 0, 5],
56 | [0, 0, 64, 48, 0, 0, 6],
57 | [0, 0, 64, 48, 0, 0, 7],
58 | [0, 0, 64, 48, 0, 0, 8],
59 | [0, 0, 64, 48, 0, 0, 9],
60 | [0, 0, 64, 48, 0, 0, 10],
61 | [0, 0, 64, 48, 0, 0, 11],
62 | [0, 0, 64, 48, 0, 0, 12],
63 | [0, 0, 64, 48, 0, 0, 13],
64 | [0, 0, 64, 48, 0, 0, 14],
65 | [0, 0, 64, 48, 0, 0, 15],
66 | [0, 0, 64, 48, 0, 0, 16],
67 | [0, 0, 64, 48, 0, 0, 17],
68 | [0, 0, 64, 48, 0, 0, 18]
69 | ],
70 | animations: {
71 | explode: {
72 | frames: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
73 | }
74 | },
75 | currentAnimation: 'explode',
76 | animationEnd: () => {
77 | this.destroy()
78 | }
79 | }
80 | }
81 |
82 | explode () {
83 | this.bitmap.visible = false
84 | this.exploded = true
85 | const es = new cax.Sprite(this.spriteOption)
86 | es.fixed = true
87 | es.x = this.x - 32
88 | es.y = this.y - 24
89 | this.es = es
90 | this.add(es)
91 | }
92 |
93 | update () {
94 | if(this.es){
95 | this.es.y += this.speed * 2
96 | }
97 | this.y += this.speed
98 | if (this.y > screenHeight) {
99 | this.destroy()
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/packages/cax-wegame/js/music.js:
--------------------------------------------------------------------------------
1 | let instance
2 |
3 | /**
4 | * 统一的音效管理器
5 | */
6 | export default class Music {
7 | constructor () {
8 | if (instance) { return instance }
9 |
10 | instance = this
11 |
12 | this.bgmAudio = wx.createInnerAudioContext()
13 | this.bgmAudio.loop = true
14 | this.bgmAudio.src = 'audio/bgm.mp3'
15 |
16 | this.shootAudio = wx.createInnerAudioContext()
17 | this.shootAudio.src = 'audio/bullet.mp3'
18 |
19 | this.boomAudio = wx.createInnerAudioContext()
20 | this.boomAudio.src = 'audio/boom.mp3'
21 |
22 | this.playBgm()
23 | }
24 |
25 | playBgm () {
26 | this.bgmAudio.play()
27 | }
28 |
29 | playShoot () {
30 | // this.shootAudio.currentTime = 0
31 | this.shootAudio.play()
32 | }
33 |
34 | playExplosion () {
35 | // this.boomAudio.currentTime = 0
36 | this.boomAudio.play()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/cax-wegame/js/player.js:
--------------------------------------------------------------------------------
1 | import cax from './libs/cax'
2 | import Bullet from './bullet'
3 | import Music from './music'
4 |
5 | const info = wx.getSystemInfoSync()
6 | const screenWidth = info.windowWidth
7 | const screenHeight = info.windowHeight
8 |
9 | // 玩家相关常量设置
10 | const PLAYER_IMG_SRC = 'images/hero.png'
11 | const IMG_WIDTH = 186
12 | const IMG_HEIGHT = 130
13 |
14 | export default class Player extends cax.Group {
15 | constructor (ctx) {
16 | super()
17 | this.music = new Music()
18 | this.bitmap = new cax.Bitmap(PLAYER_IMG_SRC)
19 | this.bitmap.originX = IMG_WIDTH / 2
20 | this.bitmap.originY = IMG_HEIGHT / 2
21 |
22 | this.add(this.bitmap)
23 | this.x = screenWidth / 2
24 | this.y = screenHeight - 80
25 |
26 | this.scaleX = this.scaleY = 0.5
27 |
28 | this.preShootTime = Date.now()
29 | this.bulletGroup = new cax.Group()
30 | }
31 |
32 | update () {
33 | this.currentTime = Date.now()
34 | if (this.currentTime - this.preShootTime > 200) {
35 | this.shoot()
36 | this.preShootTime = this.currentTime
37 | }
38 |
39 | this.bulletGroup.children.forEach(bullet => {
40 | bullet.update()
41 | })
42 | }
43 |
44 | shoot () {
45 | let bullet = new Bullet()
46 | bullet.x = this.x
47 | bullet.y = this.y - 30
48 | this.music.playShoot()
49 | this.bulletGroup.add(bullet)
50 | }
51 |
52 | isCollideWith (sp) {
53 | let spX = sp.x + sp.width / 2
54 | let spY = sp.y + sp.height / 2
55 |
56 | return !!(spX >= this.x &&
57 | spX <= this.x + this.width &&
58 | spY >= this.y &&
59 | spY <= this.y + this.height)
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/cax-wegame/project.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "项目配置文件。",
3 | "setting": {
4 | "urlCheck": true,
5 | "es6": true,
6 | "postcss": true,
7 | "minified": true,
8 | "newFeature": true
9 | },
10 | "compileType": "game",
11 | "libVersion": "game",
12 | "appid": "wx5d552c03ad3810b9",
13 | "projectname": "cax-wegame",
14 | "condition": {
15 | "search": {
16 | "current": -1,
17 | "list": []
18 | },
19 | "conversation": {
20 | "current": -1,
21 | "list": []
22 | },
23 | "game": {
24 | "currentL": -1,
25 | "list": []
26 | },
27 | "miniprogram": {
28 | "current": -1,
29 | "list": []
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/packages/cax/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": [
3 | "transform-class-properties"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/packages/cax/.eslintignore:
--------------------------------------------------------------------------------
1 |
2 | dist
3 | node_modules
4 |
5 | example/hyperscript/bundler.js
6 | example/life-cycle/bundler.js
7 | example/nest/bundler.js
8 | example/pagination/bundler.js
9 | example/perfs
10 | example/plugin/bundler.js
11 | example/ref/bundler.js
12 | example/simple/bundler.js
13 | example/slot/bundler.js
14 | example/todo/bundler.js
15 | example/tree/bundler.js
16 |
17 | ../cax-weapp/cax/index.js
18 | ../cax-wegame/js/libs/cax.js
--------------------------------------------------------------------------------
/packages/cax/asset/cax-wegame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/cax-wegame.png
--------------------------------------------------------------------------------
/packages/cax/asset/cax0712.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/cax0712.png
--------------------------------------------------------------------------------
/packages/cax/asset/demo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/demo.jpg
--------------------------------------------------------------------------------
/packages/cax/asset/getting-start.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/getting-start.png
--------------------------------------------------------------------------------
/packages/cax/asset/qq.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/qq.png
--------------------------------------------------------------------------------
/packages/cax/asset/wegame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/wegame.png
--------------------------------------------------------------------------------
/packages/cax/asset/wx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/asset/wx.png
--------------------------------------------------------------------------------
/packages/cax/examples/button/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Simple Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/button/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 |
4 | const stage = new cax.Stage(300, 400, 'body')
5 |
6 | const button = new cax.Button({
7 | width: 100,
8 | height: 40,
9 | // textX:8,
10 | text: "sfsdf Me!",
11 | //autoHeight: true
12 | })
13 | button.x =100
14 | button.y =200
15 | stage.add(button)
16 |
17 | cax.setInterval(() => {
18 | stage.update()
19 | }, 16)
--------------------------------------------------------------------------------
/packages/cax/examples/button/mario-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/button/mario-sheet.png
--------------------------------------------------------------------------------
/packages/cax/examples/button/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/button/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/cache/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Cache Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/packages/cax/examples/cache/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 |
4 |
5 | const stage = new cax.Stage(600, 400, '#canvasCtn')
6 |
7 | const radius = 50
8 | const rings = 40
9 |
10 | const colors = ["#828b20", "#b0ac31", "#cbc53d", "#fad779", "#f9e4ad", "#faf2db", "#563512", "#9b4a0b", "#d36600", "#fe8a00", "#f9a71f"]
11 |
12 | for (let i = 0; i < 200; i++) {
13 |
14 | const shape = new cax.Graphics()
15 | for (var j = rings; j > 0; j--) {
16 | shape.beginPath().fillStyle(colors[Math.random() * colors.length | 0]).arc(0,0,radius * j / rings,0,Math.PI*2).fill()
17 | }
18 | shape.x = Math.random() * 600
19 | shape.y = Math.random() * 400
20 | shape.velX = Math.random() * 10 - 5
21 | shape.velY = Math.random() * 10 - 5
22 |
23 |
24 | stage.add(shape);
25 | }
26 |
27 |
28 |
29 |
30 | cax.tick(function () {
31 |
32 | var w = 600 + radius * 2;
33 | var h = 400 + radius * 2;
34 |
35 | for (var i = 0; i < 200; i++) {
36 | var shape = stage.children[i];
37 | shape.x = (shape.x + radius + shape.velX + w) % w - radius;
38 | shape.y = (shape.y + radius + shape.velY + h) % h - radius;
39 | }
40 |
41 | stage.update();
42 | })
43 |
44 |
45 |
46 | let tag = true
47 |
48 | document.querySelector('#toggleBtn').addEventListener('click', () => {
49 |
50 | for (var i = 0; i < 200; i++) {
51 | var shape = stage.children[i];
52 | if (tag) {
53 | shape.cache(-radius, -radius, radius * 2, radius * 2)
54 | } else {
55 | shape.uncache()
56 | }
57 | }
58 |
59 | tag =!tag
60 |
61 | })
--------------------------------------------------------------------------------
/packages/cax/examples/cache/mario-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/cache/mario-sheet.png
--------------------------------------------------------------------------------
/packages/cax/examples/cache/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/cache/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/caching/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Simple Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/packages/cax/examples/caching/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 |
4 | const stage = new cax.Stage(300, 400, '#canvasCtn')
5 |
6 | const circle = new cax.Circle(40, { fillStyle: 'black' })
7 |
8 | circle.x = 200
9 | circle.y = 250
10 | circle.rotation = 15
11 | circle.cache(0, 0, 40, 40, 1)
12 |
13 |
14 |
15 |
16 | const text = new cax.Text("abc", {
17 | font: '60px Arial'
18 | })
19 |
20 | text.x = 100
21 | text.y = 100
22 | //text.scaleX = 0.5
23 | text.cache(0, 0, 80, 60)
24 | stage.add(text,circle)
25 |
26 | stage.update()
27 |
28 | setInterval(()=>{
29 | stage.update()
30 | },16)
31 |
32 | const gt = new cax.Text("Group Cache", {
33 | font: '20px Arial'
34 | })
35 | const group = new cax.Group()
36 |
37 | group.x =130
38 | group.y =30
39 |
40 | const rect = new cax.Rect(140,40, { fillStyle: 'red' })
41 |
42 | group.cache(-20,0,100,20 ,1)
43 |
44 | group.add(rect, gt)
45 | stage.add(group)
46 | stage.update()
47 |
48 |
49 | group.cursor = 'move'
50 |
51 | group.on('drag',(evt)=>{
52 | evt.target.x +=evt.dx
53 | evt.target.y+=evt.dy
54 | })
55 | text.cursor = 'move'
56 | circle.cursor = 'pointer'
57 |
58 |
59 | let tag = false
60 |
61 | document.querySelector('#toggleBtn').addEventListener('click', () => {
62 | group[(tag ? 'cache' : 'uncache')](-20,0,100,20 ,1)
63 | text[(tag ? 'cache' : 'uncache')](0, 0, 80, 60)
64 | circle[(tag ? 'cache' : 'uncache')](0, 0, 40, 40, 1)
65 | tag =!tag
66 | stage.update()
67 | })
68 |
69 | // cax.setInterval(function(){
70 | // stage.update()
71 | // },16)
--------------------------------------------------------------------------------
/packages/cax/examples/caching/mario-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/caching/mario-sheet.png
--------------------------------------------------------------------------------
/packages/cax/examples/caching/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/caching/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transform/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Clip Demo
7 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Click The Canvas
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transform/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const w = 576
4 | const h = 360
5 | const r = 65
6 | const stage = new cax.Stage(w, h, '#canvasCtn')
7 | const bitmap = new cax.Bitmap('./wepay.png', () => {
8 | stage.update()
9 | })
10 |
11 |
12 | const clipPath = new cax.Graphics()
13 | clipPath.x = 40 + Math.random() * 200
14 | clipPath.y = 40 + Math.random() * 200
15 | clipPath.arc(0, 0, r, 0, Math.PI * 2)
16 | bitmap.clip(clipPath)
17 |
18 | stage.add(bitmap)
19 |
20 | let tag = true
21 |
22 | stage.on('click', (evt) => {
23 | const rt = 576 / (window.innerWidth>800?800:window.innerWidth)
24 | clipPath.x = evt.stageX * rt
25 | clipPath.y = evt.stageY * rt
26 | })
27 |
28 | let speedX = 1,
29 | speedY = 1
30 |
31 | cax.setInterval(function () {
32 |
33 | clipPath.x += speedX
34 | clipPath.y += speedY
35 | if (clipPath.y > h - r) {
36 | clipPath.y = h - r
37 | speedY *= -1
38 | } else if (clipPath.y < r) {
39 | clipPath.y = r
40 | speedY *= -1
41 | }
42 |
43 | if (clipPath.x > w - r) {
44 | clipPath.x = w - r
45 | speedX *= -1
46 | } else if (clipPath.x < r) {
47 | clipPath.x = r
48 | speedX *= -1
49 | }
50 |
51 | stage.update()
52 | }, 15)
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transform/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/clip-transform/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transition/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Clip Demo
7 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
Click The Canvas
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transition/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const w = 576
4 | const h = 360
5 | const r = 700
6 | const stage = new cax.Stage(w, h, '#canvasCtn')
7 | const group = new cax.Group()
8 |
9 | cax.loadImgs({
10 | imgs:['./wepay.png','./pay.png'],
11 | progress:function(a,b,c,d){
12 | console.log(a,b,c,d)
13 | },
14 | complete:function(imgs){
15 |
16 |
17 | const bitmap = new cax.Bitmap(imgs[0])
18 | const payBmp = new cax.Bitmap(imgs[1])
19 |
20 | const clipPath = new cax.Graphics()
21 | clipPath.x = 280
22 | clipPath.y = 180
23 | clipPath.arc(0, 0, r, 0, Math.PI * 2)
24 | group.clip(clipPath)
25 | bitmap.visible = false
26 | group.add(bitmap, payBmp)
27 | stage.add(group)
28 |
29 |
30 | stage.on('click', (evt) => {
31 | const rt = 576 / (window.innerWidth > 800 ? 800 : window.innerWidth)
32 | clipPath.x = evt.stageX * rt
33 | clipPath.y = evt.stageY * rt
34 | })
35 |
36 | let flag = false
37 |
38 | cax.To.get(clipPath)
39 | .to().scaleY(0.0001, 1000).scaleX(0.0001, 1000)
40 | .end(()=>{
41 | bitmap.visible = !flag
42 | payBmp.visible = flag
43 | flag = !flag
44 | })
45 | .wait(100)
46 | .to().scaleY(1, 1000).scaleX(1, 1000)
47 | .wait(1900)
48 | .cycle().start()
49 |
50 |
51 | cax.setInterval(function () {
52 | stage.update()
53 | }, 15)
54 | }
55 | })
56 |
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transition/pay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/clip-transition/pay.png
--------------------------------------------------------------------------------
/packages/cax/examples/clip-transition/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/clip-transition/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/clip/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Clip Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/packages/cax/examples/clip/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 | const stage = new cax.Stage(260, 200, '#canvasCtn')
3 |
4 | cax.loadImg({
5 | img:'./wepay-diy.jpg',
6 | complete:function(img){
7 |
8 | const bitmap = new cax.Bitmap(img)
9 |
10 | bitmap.x = 130
11 | bitmap.y = 100
12 | bitmap.originX = 40
13 | bitmap.originY = 40
14 | bitmap.cursor = 'pointer'
15 | bitmap.on('click', () => {
16 | alert('微信支付')
17 | })
18 |
19 | bitmap.on('drag',(evt)=>{
20 | evt.target.x+=evt.dx
21 | evt.target.y+=evt.dy
22 | })
23 |
24 |
25 |
26 | cax.setInterval(()=>{
27 | stage.update()
28 | },16)
29 |
30 | const clipPath = new cax.Graphics()
31 | clipPath.x = 40
32 | clipPath.y = 40
33 | clipPath.arc(0, 0, 25, 0, Math.PI * 2)
34 | bitmap.clip(clipPath)
35 |
36 | stage.add(bitmap)
37 |
38 | let tag = true
39 |
40 | document.querySelector('#toggleBtn').addEventListener('click', () => {
41 | bitmap.clip(tag ? null : clipPath)
42 | tag =!tag
43 | stage.update()
44 | })
45 | }
46 | })
--------------------------------------------------------------------------------
/packages/cax/examples/clip/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/clip/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/composite-operation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Composite Operation Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/packages/cax/examples/composite-operation/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 | const stage = new cax.Stage(260, 200, '#canvasCtn')
3 | const group = new cax.Group()
4 | group.x = 90
5 | group.y = 60
6 | const bitmap = new cax.Bitmap('./wepay-diy.jpg', () => {
7 | group.cache(0, 0, 100, 100, 1)
8 | stage.update()
9 | })
10 |
11 |
12 | group.cursor = 'pointer'
13 | group.on('click', () => {
14 | alert('微信支付')
15 | })
16 |
17 | group.on('drag', (evt) => {
18 | evt.target.x += evt.dx
19 | evt.target.y += evt.dy
20 | })
21 | const bg = new cax.Rect(11200, 1180, { fillStyle: '#DE5347' })
22 | //bg.cursor = 'default'
23 |
24 | const rect = new cax.Rect(80, 20, { fillStyle: 'black' })
25 | rect.compositeOperation = 'source-atop'
26 |
27 |
28 | group.add(bitmap, rect)
29 |
30 | stage.add(bg, group)
31 |
32 | cax.tick(() => {
33 | stage.update()
34 | })
35 |
36 | let tag = true
37 |
38 | document.querySelector('#toggleBtn').addEventListener('click', () => {
39 |
40 | if (tag) {
41 |
42 | group.uncache()
43 | } else {
44 | group.cache(0, 0, 100, 100)
45 | }
46 |
47 |
48 | tag = !tag
49 |
50 | })
--------------------------------------------------------------------------------
/packages/cax/examples/composite-operation/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/composite-operation/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/filter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Filter Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/packages/cax/examples/filter/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 |
4 | const stage = new cax.Stage(300, 400, '#canvasCtn')
5 |
6 | cax.loadImg({
7 | img: './wepay-diy.jpg',
8 | complete: (img) => {
9 | const bitmap = new cax.Bitmap(img)
10 | bitmap.x = 20
11 | bitmap.y = 30
12 | stage.add(bitmap)
13 |
14 |
15 | const bitmapA = bitmap.clone()
16 | bitmapA.x = 20
17 | bitmapA.y = 110
18 | stage.add(bitmapA)
19 |
20 | const bitmapB = bitmapA.clone()
21 | bitmapB.x = 110
22 | stage.add(bitmapB)
23 |
24 | const bitmapC = bitmapA.clone()
25 | bitmapC.x = 200
26 | stage.add(bitmapC)
27 |
28 | const bitmapD = bitmapA.clone()
29 | bitmapD.x = 200
30 | bitmapD.y = 30
31 | stage.add(bitmapD)
32 |
33 | const bitmapE = bitmapA.clone()
34 | bitmapE.x = 110
35 | bitmapE.y = 30
36 | stage.add(bitmapE)
37 |
38 | const bitmapF = bitmapA.clone()
39 | bitmapF.x = 200
40 | bitmapF.y = 190
41 | stage.add(bitmapF)
42 |
43 | const bitmapG = bitmapA.clone()
44 | bitmapG.x = 20
45 | bitmapG.y = 190
46 | stage.add(bitmapG)
47 |
48 | const bitmapH = bitmapA.clone()
49 | bitmapH.x = 110
50 | bitmapH.y = 190
51 | stage.add(bitmapH)
52 |
53 | const bitmapI = bitmapA.clone()
54 | bitmapI.x = 110
55 | bitmapI.y = 270
56 | stage.add(bitmapI)
57 |
58 | const bitmapJ = bitmapA.clone()
59 | bitmapJ.x = 20
60 | bitmapJ.y = 270
61 | stage.add(bitmapJ)
62 |
63 | const bitmapK = bitmapA.clone()
64 | bitmapK.x = 200
65 | bitmapK.y = 270
66 | stage.add(bitmapK)
67 |
68 |
69 | filter()
70 |
71 | let tag = true
72 | document.querySelector('#toggleBtn').addEventListener('click', function () {
73 | if (tag) {
74 | unfilter()
75 | } else {
76 | filter()
77 | }
78 | tag = !tag
79 | })
80 |
81 | function unfilter() {
82 | bitmapA.unfilter()
83 | bitmapB.unfilter()
84 | bitmapC.unfilter()
85 | bitmapD.unfilter()
86 | bitmapE.unfilter()
87 | bitmapF.unfilter()
88 | bitmapG.unfilter()
89 | bitmapH.unfilter()
90 | bitmapI.unfilter()
91 | bitmapJ.unfilter()
92 | bitmapK.unfilter()
93 | }
94 |
95 | function filter() {
96 | bitmapA.filter('invert(1)', { x: 0, y: 0, width: 80, height: 80 })
97 | bitmapB.filter('brightness(1.3)', { x: 0, y: 0, width: 80, height: 80 })
98 | bitmapC.filter('blur(15px)', { x: 0, y: 0, width: 80, height: 80 })
99 | bitmapD.filter('contrast(1.3)', { x: 0, y: 0, width: 80, height: 80 })
100 | bitmapE.filter('brightness(0.5)', { x: 0, y: 0, width: 80, height: 80 })
101 | bitmapF.filter('contrast(0.3)', { x: 0, y: 0, width: 80, height: 80 })
102 | bitmapG.filter('grayscale(1)', { x: 0, y: 0, width: 80, height: 80 })
103 | bitmapH.filter('sepia(1)', { x: 0, y: 0, width: 80, height: 80 })
104 | bitmapI.filter('threshold(168)', { x: 0, y: 0, width: 80, height: 80 })
105 | bitmapJ.filter('gamma(10)', { x: 0, y: 0, width: 80, height: 80 })
106 | bitmapK.filter({
107 | type: 'colorize',
108 | color: '#FF0000',
109 | amount: 0.6
110 | }, { x: 0, y: 0, width: 80, height: 80 })
111 | }
112 |
113 | cax.tick(() => {
114 | stage.update()
115 | })
116 |
117 | }
118 | })
119 |
120 |
121 | // const circle = new cax.Circle(40, { fillStyle: 'red' })
122 |
123 |
124 |
125 | // circle.filter('brightness(150%)', { x: -40, y: -40, width: 80, height: 80 })
126 |
127 | // circle.x = 140
128 | // circle.y = 40
129 | // circle.scaleX = 0.5
130 | // circle.rotation = 30
131 |
132 | // circle.cursor = 'pointer'
--------------------------------------------------------------------------------
/packages/cax/examples/filter/wegame.test.js:
--------------------------------------------------------------------------------
1 | import cax from './js/libs/cax'
2 |
3 |
4 | const stage = new cax.Stage()
5 |
6 | const bitmap = new cax.Bitmap('images/wepay-diy.jpg')
7 | bitmap.x = 20
8 | bitmap.y = 30
9 | stage.add(bitmap)
10 |
11 |
12 | const bitmapA = bitmap.clone()
13 | bitmapA.x = 20
14 | bitmapA.y = 110
15 | stage.add(bitmapA)
16 |
17 | const bitmapB = bitmapA.clone()
18 | bitmapB.x = 110
19 | stage.add(bitmapB)
20 |
21 | const bitmapC = bitmapA.clone()
22 | bitmapC.x = 200
23 | stage.add(bitmapC)
24 |
25 | const bitmapD = bitmapA.clone()
26 | bitmapD.x = 200
27 | bitmapD.y = 30
28 | stage.add(bitmapD)
29 |
30 | const bitmapE = bitmapA.clone()
31 | bitmapE.x = 110
32 | bitmapE.y = 30
33 | stage.add(bitmapE)
34 |
35 | const bitmapF = bitmapA.clone()
36 | bitmapF.x = 200
37 | bitmapF.y = 190
38 | stage.add(bitmapF)
39 |
40 | const bitmapG = bitmapA.clone()
41 | bitmapG.x = 20
42 | bitmapG.y = 190
43 | stage.add(bitmapG)
44 |
45 | const bitmapH = bitmapA.clone()
46 | bitmapH.x = 110
47 | bitmapH.y = 190
48 | stage.add(bitmapH)
49 |
50 | const bitmapI = bitmapA.clone()
51 | bitmapI.x = 110
52 | bitmapI.y = 270
53 | stage.add(bitmapI)
54 |
55 | const bitmapJ = bitmapA.clone()
56 | bitmapJ.x = 20
57 | bitmapJ.y = 270
58 | stage.add(bitmapJ)
59 |
60 | const bitmapK = bitmapA.clone()
61 | bitmapK.x = 200
62 | bitmapK.y = 270
63 | stage.add(bitmapK)
64 |
65 |
66 | filter()
67 |
68 |
69 |
70 | function unfilter(){
71 | bitmapA.unfilter()
72 | bitmapB.unfilter()
73 | bitmapC.unfilter()
74 | bitmapD.unfilter()
75 | bitmapE.unfilter()
76 | bitmapF.unfilter()
77 | bitmapG.unfilter()
78 | bitmapH.unfilter()
79 | bitmapI.unfilter()
80 | bitmapJ.unfilter()
81 | bitmapK.unfilter()
82 | }
83 |
84 | function filter(){
85 | bitmapA.filter('invert(1)', { x: 0, y: 0, width: 80, height: 80 })
86 | bitmapB.filter('brightness(1.1)', { x: 0, y: 0, width: 80, height: 80 })
87 | bitmapC.filter('blur(15px)', { x: 0, y: 0, width: 80, height: 80 })
88 | bitmapD.filter('contrast(1.3)', { x: 0, y: 0, width: 80, height: 80 })
89 | bitmapE.filter('brightness(0.5)', { x: 0, y: 0, width: 80, height: 80 })
90 | bitmapF.filter('contrast(0.3)', { x: 0, y: 0, width: 80, height: 80 })
91 | bitmapG.filter('grayscale(1)', { x: 0, y: 0, width: 80, height: 80 })
92 | bitmapH.filter('sepia(1)', { x: 0, y: 0, width: 80, height: 80 })
93 | bitmapI.filter('threshold(168)', { x: 0, y: 0, width: 80, height: 80 })
94 | bitmapJ.filter('gamma(10)', { x: 0, y: 0, width: 80, height: 80 })
95 | bitmapK.filter({
96 | type:'colorize',
97 | color:'#FF0000',
98 | amount: 0.6
99 | }, { x: 0, y: 0, width: 80, height: 80 })
100 | }
101 |
102 | cax.tick(() => {
103 | stage.update()
104 | })
105 |
106 | setTimeout(function(){
107 | unfilter()
108 | },2000)
109 |
110 | setTimeout(function(){
111 | filter()
112 | },4000)
--------------------------------------------------------------------------------
/packages/cax/examples/filter/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/filter/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/getting-start/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Simple Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/getting-start/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(200, 200, 'body')
4 |
5 | cax.loadImgs({
6 | imgs: ['./wepay-diy.jpg'],
7 | complete: (imgs) => {
8 | const img = imgs[0]
9 | const bitmap = new cax.Bitmap(img)
10 |
11 | bitmap.x = stage.width / 2
12 | bitmap.y = stage.height / 2
13 | bitmap.rotation = -10
14 | bitmap.originX = img.width / 2
15 | bitmap.originY = img.height / 2
16 | bitmap.filter('blur(10px)')
17 |
18 | stage.add(bitmap)
19 | stage.update()
20 | }
21 | })
22 |
--------------------------------------------------------------------------------
/packages/cax/examples/getting-start/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/getting-start/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/graphics/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Graphics Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/packages/cax/examples/graphics/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(300, 400, '#canvasCtn')
4 |
5 | const ball = new cax.Graphics()
6 |
7 | ball.beginPath()
8 | .arc(0, 0, 140, 0, Math.PI * 2)
9 | .closePath()
10 | .fillStyle('#f4862c').fill()
11 | .strokeStyle("#046ab4").lineWidth(8).stroke()
12 | .lineWidth(6)
13 | .beginPath().moveTo(298 - 377, 506 - 391).bezierCurveTo(236 - 377, 396 - 391, 302 - 377, 272 - 391, 407 - 377, 254 - 391).stroke()
14 | .beginPath().moveTo(328 - 377, 258 - 391).bezierCurveTo(360 - 377, 294 - 391, 451 - 377, 272 - 391, 503 - 377, 332 - 391).stroke()
15 | .beginPath().moveTo(282 - 377, 288 - 391).bezierCurveTo(391 - 377, 292 - 391, 481 - 377, 400 - 391, 488 - 377, 474 - 391).stroke()
16 | .beginPath().moveTo(242 - 377, 352 - 391).bezierCurveTo(352 - 377, 244 - 391, 319 - 377, 423 - 391, 409 - 377, 527 - 391).stroke();
17 |
18 | ball.x = 150
19 | ball.y = 200
20 | ball.scaleX = ball.scaleY = 0.4
21 |
22 | stage.add(ball)
23 |
24 | ball.on('drag', (evt) => {
25 | evt.target.x += evt.dx
26 | evt.target.y += evt.dy
27 | evt.preventDefault()
28 | })
29 |
30 | ball.cursor = 'move'
31 |
32 | document.querySelector('#addScaleBtn').addEventListener('click', () => {
33 | ball.scaleX += 0.1
34 | ball.scaleY += 0.1
35 | })
36 |
37 | document.querySelector('#subScaleBtn').addEventListener('click', () => {
38 |
39 | ball.scaleX -= 0.1
40 | ball.scaleY -= 0.1
41 |
42 | if (ball.scaleX < 0.1) {
43 | ball.scaleX = ball.scaleY = 0.1
44 | }
45 | })
46 |
47 | cax.tick(stage.update.bind(stage))
--------------------------------------------------------------------------------
/packages/cax/examples/group-clip/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Clip Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/packages/cax/examples/group-clip/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 | const stage = new cax.Stage(260, 200, '#canvasCtn')
3 | const group = new cax.Group()
4 | const bitmap = new cax.Bitmap('./wepay-diy.jpg', () => {
5 | stage.update()
6 | })
7 |
8 | group.x = 130
9 | group.y = 100
10 | bitmap.originX = 40
11 | bitmap.originY = 40
12 | bitmap.cursor = 'pointer'
13 | bitmap.on('click', () => {
14 | alert('微信支付')
15 | })
16 |
17 | const clipPath = new cax.Graphics()
18 | clipPath.x = 0
19 | clipPath.y = 0
20 | clipPath.arc(0, 0, 25, 0, Math.PI * 2)
21 |
22 | const text = new cax.Text('Hello Cax Clip!')
23 | text.x = -30
24 | group.add(bitmap, text)
25 |
26 | group.clip(clipPath)
27 | stage.add(group)
28 | group.cursor = 'move'
29 | group.on('drag',(evt)=>{
30 | evt.target.x+=evt.dx
31 | evt.target.y+=evt.dy
32 | })
33 | let tag = true
34 | group.on('click',(evt)=>{
35 | console.log(1)
36 | })
37 |
38 | cax.setInterval(()=>{
39 | stage.update()
40 | },16)
41 |
42 | document.querySelector('#toggleBtn').addEventListener('click', () => {
43 | group.clip(tag ? null : clipPath)
44 | tag = !tag
45 | stage.update()
46 | })
--------------------------------------------------------------------------------
/packages/cax/examples/group-clip/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/group-clip/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/matter/img/basketball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/matter/img/basketball.png
--------------------------------------------------------------------------------
/packages/cax/examples/matter/img/box.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/matter/img/box.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/matter/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax + Matter-js
7 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/packages/cax/examples/path/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Simple Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/path/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(300, 400, 'body')
4 | // const path = new cax.Path('M4.645,45.577c-0.017-0.383-0.029-0.767-0.029-1.154c0-13.997,11.387-25.385,25.385-25.385 s25.385,11.387,25.385,25.385c0,0.387-0.012,0.771-0.029,1.154h4.616C59.985,45.193,60,44.81,60,44.423c0-16.569-13.431-30-30-30 s-30,13.431-30,30c0,0.387,0.015,0.77,0.029,1.154H4.645z',{
5 | // strokeStyle:'black',
6 | // // fillStyle:'black'
7 | // })
8 |
9 | const path = new cax.Path('M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80',{
10 | strokeStyle:'black',
11 | // fillStyle:'black'
12 | })
13 |
14 | //path.x = 100
15 | stage.add(path)
16 | stage.update()
17 |
--------------------------------------------------------------------------------
/packages/cax/examples/pie/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Pie Chart Demo
7 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/packages/cax/examples/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Simple Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/simple/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(300, 400, 'body')
4 |
5 | const bitmap = new cax.Bitmap('./wepay.png')
6 | bitmap.rect = [0, 0, 170, 140]
7 | bitmap.x = 60
8 | bitmap.y = 60
9 | bitmap.cursor = 'pointer'
10 | bitmap.on('click', () => {
11 | alert('wepay')
12 | })
13 |
14 |
15 | const group = new cax.Group()
16 | const rr = new cax.RoundedRect(100, 40, 2, { fillStyle: '#42B035', strokeStyle: '#42B035', lineWidth: 4 })
17 | const text = new cax.Text('Drag Me!', {
18 | color: 'white',
19 | font: '20px Arial'
20 | })
21 | text.x = 50 - text.getWidth() / 2
22 | text.y = 40 / 2 - 10
23 | group.add(rr, text)
24 | group.cursor = 'move'
25 | group.on('drag', (evt) => {
26 | group.x += evt.dx
27 | group.y += evt.dy
28 | evt.preventDefault()
29 | })
30 | group.x=100
31 | group.y=250
32 |
33 | const caxText = new cax.Text('Hello Cax!', {
34 | color: '#42B035',
35 | font: '30px Arial'
36 | })
37 | caxText.shadow = {
38 | color: '#42B035',
39 | offsetX: -5,
40 | offsetY: 5,
41 | blur: 10
42 | }
43 | caxText.x = 150 - caxText.getWidth() / 2
44 | caxText.y = 200
45 | caxText.on('drag', (evt) => {
46 | evt.target.x += evt.dx
47 | evt.target.y += evt.dy
48 | evt.preventDefault()
49 | })
50 | caxText.cursor = 'move'
51 |
52 | stage.add(group, bitmap, caxText)
53 |
54 | cax.tick(() => {
55 | stage.update()
56 | })
57 |
58 |
59 | // bitmap.on('touchstart', () => {
60 | // console.log('touchstart')
61 | // })
62 |
63 | // bitmap.on('tap', () => {
64 | // console.log('tap')
65 | // })
66 |
67 |
68 | // bitmap.on('touchmove', () => {
69 | // console.log('touchmove')
70 | // })
71 |
72 | // bitmap.on('drag', () => {
73 | // console.log('dragging')
74 | // })
75 |
76 | // bitmap.on('touchend', () => {
77 | // console.log('touchend')
78 | // })
79 |
80 |
81 | // const ap = new cax.ArrowPath([{ x: 100, y: 200 }, { x: 100, y: 300 }])
82 | // stage.add(ap)
83 |
84 | // const ap2 = new cax.ArrowPath([{ x: 100, y: 200 }, { x: 200, y: 200 }])
85 | // stage.add(ap2)
86 |
87 |
88 |
89 | // const ap3 = new cax.ArrowPath([{ x: 100, y: 200 }, { x: 0, y: 200 }])
90 | // stage.add(ap3)
91 |
92 |
93 | // const ap4 = new cax.ArrowPath([{ x: 100, y: 200 }, { x: 100, y: 100 }])
94 | // stage.add(ap4)
--------------------------------------------------------------------------------
/packages/cax/examples/simple/mario-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/simple/mario-sheet.png
--------------------------------------------------------------------------------
/packages/cax/examples/simple/wepay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/simple/wepay.png
--------------------------------------------------------------------------------
/packages/cax/examples/sprite/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Simple Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/sprite/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 |
4 | const stage = new cax.Stage(300, 400, 'body')
5 |
6 | const sprite = new cax.Sprite({
7 | framerate: 7,
8 | imgs: ['./mario-sheet.png'],
9 | frames: [
10 | // x, y, width, height, originX, originY ,imageIndex
11 | [0, 0, 32, 32],
12 | [32 * 1, 0, 32, 32],
13 | [32 * 2, 0, 32, 32],
14 | [32 * 3, 0, 32, 32],
15 | [32 * 4, 0, 32, 32],
16 | [32 * 5, 0, 32, 32],
17 | [32 * 6, 0, 32, 32],
18 | [32 * 7, 0, 32, 32],
19 | [32 * 8, 0, 32, 32],
20 | [32 * 9, 0, 32, 32],
21 | [32 * 10, 0, 32, 32],
22 | [32 * 11, 0, 32, 32],
23 | [32 * 12, 0, 32, 32],
24 | [32 * 13, 0, 32, 32],
25 | [32 * 14, 0, 32, 32]
26 | ],
27 | animations: {
28 | walk: {
29 | frames: [0, 1]
30 | },
31 | happy: {
32 | frames: [5, 6, 7, 8, 9]
33 | },
34 | win: {
35 | frames: [12]
36 | }
37 | },
38 | playOnce: false,
39 | currentAnimation: "walk",
40 | animationEnd: function () {
41 |
42 | }
43 | });
44 | stage.add(sprite)
45 |
46 | cax.setInterval(() => {
47 |
48 | sprite.x += 0.8
49 | stage.update()
50 | }, 16)
--------------------------------------------------------------------------------
/packages/cax/examples/sprite/mario-sheet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/sprite/mario-sheet.png
--------------------------------------------------------------------------------
/packages/cax/examples/to-animate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Motion Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/to-animate/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(300, 400, 'body')
4 | const bitmap = new cax.Bitmap('./wepay-diy.jpg',()=>{
5 | cax.To.get(bitmap).animate('rubber').start()
6 | })
7 |
8 | bitmap.x = 150
9 | bitmap.y = 200
10 | bitmap.scaleX = 0.6
11 | bitmap.scaleY = 0.6
12 | bitmap.originX = 40
13 | bitmap.originY = 40
14 | bitmap.cursor = 'pointer'
15 | bitmap.on('click', () => {
16 | alert('微信支付')
17 | })
18 |
19 | stage.add(bitmap)
20 |
21 |
22 | cax.setInterval(() => {
23 | stage.update()
24 | }, 16)
--------------------------------------------------------------------------------
/packages/cax/examples/to-animate/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/to-animate/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/to-shape/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Motion Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
Click AnyWhere to Tween
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/packages/cax/examples/to-shape/main.js:
--------------------------------------------------------------------------------
1 |
2 | import cax from '../../src/index.js'
3 |
4 |
5 | const stage = new cax.Stage(300, 400, '#canvasCtn');
6 |
7 | for (var i = 0; i < 25; i++) {
8 | var circle = new cax.Circle((i + 1) * 4, {
9 | lineWidth: 15,
10 | strokeStyle: '#113355'
11 | });
12 |
13 | circle.alpha = 1 - i * 0.02;
14 | circle.x = Math.random() * 300;
15 | circle.y = Math.random() * 400;
16 | circle.compositeOperation = "lighter";
17 |
18 | cax.To.get(circle).to({ x: 150, y: 200 }, (0.5 + i * 0.04) * 1500, cax.easing.bounceOut).start()
19 | stage.add(circle);
20 | }
21 |
22 |
23 | stage.on('click', function (evt) {
24 | stage.children.forEach((child, index) => {
25 | cax.To.get(child).to({ x: evt.stageX, y: evt.stageY }, (0.5 + index * 0.04) * 1500, cax.easing.bounceOut).start()
26 | })
27 | })
28 |
29 | cax.tick(function () {
30 | stage.update()
31 | })
--------------------------------------------------------------------------------
/packages/cax/examples/to/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Cax Motion Demo
7 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/packages/cax/examples/to/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 |
3 | const stage = new cax.Stage(300, 400, 'body')
4 | const bitmap = new cax.Bitmap('./wepay-diy.jpg')
5 |
6 | bitmap.x = 200
7 | bitmap.y = -200
8 | bitmap.scaleX = 0.6
9 | bitmap.scaleY = 0.6
10 | bitmap.originX = 40
11 | bitmap.originY = 40
12 | bitmap.cursor = 'pointer'
13 | bitmap.on('click', () => {
14 | alert('微信支付')
15 | })
16 |
17 |
18 | stage.add(bitmap)
19 |
20 |
21 | const easing = cax.To.easing.elasticInOut
22 |
23 | cax.To.get(bitmap)
24 | .to({ y: 340, rotation: 240 }, 2000, easing)
25 | .begin(() => {
26 | console.log("Task one has began!")
27 | })
28 | .progress(() => {
29 | console.log("Task one is progressing!")
30 | })
31 | .end(() => {
32 | console.log("Task one has completed!")
33 | })
34 | .wait(500)
35 | .to()
36 | .rotation(0, 1400, easing)
37 | .begin(() => {
38 | console.log("Task two has began!")
39 | })
40 | .progress(() => {
41 | console.log("Task two is progressing!")
42 | })
43 | .end(() => {
44 | console.log("Task two has completed!")
45 | })
46 | .wait(500)
47 | .to()
48 | .scaleX(1, 1400, easing)
49 | .scaleY(1, 1400, easing)
50 | .begin(() => {
51 | console.log("Task three has began!")
52 | })
53 | .progress(() => {
54 | console.log("Task three is progressing!")
55 | })
56 | .end(() => {
57 | console.log("Task three has completed!")
58 | })
59 | .wait(500)
60 | .to({ x: 160, y: 200 }, 1000, easing)
61 | .rotation(360, 1000, easing)
62 | .begin(() => {
63 | console.log("Task four has began!")
64 | })
65 | .progress(() => {
66 | console.log("Task four is progressing!")
67 | })
68 | .end(() => {
69 | console.log("Task four has completed!")
70 | })
71 | .start();
72 |
73 |
74 |
75 | cax.setInterval(() => {
76 | stage.update()
77 | }, 16)
--------------------------------------------------------------------------------
/packages/cax/examples/to/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/to/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/cax/examples/vision/hero-m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/cax/examples/vision/hero-m.png
--------------------------------------------------------------------------------
/packages/cax/examples/vision/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Vision Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/packages/cax/examples/vision/main.js:
--------------------------------------------------------------------------------
1 | import cax from '../../src/index.js'
2 | import Bitmap from '../../src/render/display/bitmap.js';
3 |
4 |
5 | const stage = new cax.Stage(300, 400, '#canvasCtn')
6 | let filter = false
7 |
8 | class Player extends cax.Group {
9 | constructor() {
10 | super()
11 |
12 | this.sprite = new cax.Sprite({
13 |
14 | framerate: 5,
15 | imgs: ['./hero-m.png'],
16 | frames: [
17 | // x, y, width, height, originX, originY ,imageIndex
18 | [64, 64, 64, 64],
19 | [128, 64, 64, 64],
20 | [192, 64, 64, 64],
21 | [256, 64, 64, 64],
22 | [320, 64, 64, 64],
23 | [384, 64, 64, 64],
24 | [448, 64, 64, 64],
25 |
26 | [0, 192, 64, 64],
27 | [64, 192, 64, 64],
28 | [128, 192, 64, 64],
29 | [192, 192, 64, 64],
30 | [256, 192, 64, 64],
31 | [320, 192, 64, 64],
32 | [384, 192, 64, 64],
33 | [448, 192, 64, 64],
34 | [448, 192, 64, 64]
35 | ],
36 | animations: {
37 | walk: {
38 | frames: [0, 1, 2, 3, 4, 5, 6],
39 | next: "run",
40 | speed: 2,
41 | loop: false
42 | },
43 | happy: {
44 | frames: [11, 12, 13, 14]
45 | },
46 | win: {
47 | frames: [7, 8, 9, 10]
48 | }
49 | },
50 | currentAnimation: "walk"
51 | })
52 |
53 | this.sprite.originX = 32
54 | this.sprite.originY = 32
55 | this.visionGroup = new cax.Group()
56 | this.visionGroup.fixed = true
57 | this.add(this.visionGroup, this.sprite)
58 | this.directionRight = false
59 | this.preTime = Date.now()
60 | }
61 |
62 | update() {
63 | if(!this.sprite.visible){
64 | this.sprite.updateFrame()
65 | }
66 | this.x += (this.directionRight ? 1 : -1)
67 | if (Date.now() - this.preTime > 50) {
68 | this.addVision()
69 | this.preTime = Date.now()
70 | }
71 | if (this.x < -20) {
72 | this.x = 310
73 | }
74 |
75 | if (this.x > 310) {
76 | this.x = -19
77 | }
78 |
79 |
80 | }
81 |
82 | addVision() {
83 | if(this.sprite.rect){
84 | const vision = new Bitmap('./hero-m.png')
85 | vision.rect = this.sprite.rect.slice(0)
86 | if(filter){
87 | vision.compositeOperation = 'lighter'
88 | vision.filter({
89 | type:'colorize',
90 | color:'#ff4725',
91 | amount: 1
92 | },)
93 | }
94 | vision.scaleX = this.scaleX
95 | vision.originX = 32
96 | vision.originY = 32
97 | vision.alpha = 0.5
98 | vision.x = this.x
99 | vision.y = this.y
100 | this.visionGroup.add(vision)
101 |
102 | cax.To.get(vision).to({ alpha: 0 }, 1500).end((obj) => {
103 | obj.destroy()
104 | }).start()
105 | }
106 | }
107 |
108 | }
109 |
110 | const player = new Player()
111 | stage.add(player)
112 |
113 | player.x = 200
114 | player.y = 200
115 |
116 | cax.setInterval(() => {
117 | player.update()
118 | stage.update()
119 | }, 16)
120 |
121 |
122 | let tag = false
123 |
124 | document.querySelector('#toggleBtn').addEventListener('click', () => {
125 | player.sprite.visible = tag
126 | tag =!tag
127 | stage.update()
128 | })
129 |
130 |
131 | document.querySelector('#toggleFilterBtn').addEventListener('click', () => {
132 | filter = !filter
133 | })
134 |
135 | document.querySelector('#toggleDirectionBtn').addEventListener('click', () => {
136 | player.directionRight = !player.directionRight
137 | player.scaleX *= -1
138 | })
139 |
--------------------------------------------------------------------------------
/packages/cax/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cax",
3 | "version": "1.3.6",
4 | "description": "小程序、小游戏和 Web 通用 Canvas 渲染引擎",
5 | "main": "dist/cax.js",
6 | "scripts": {
7 | "lint": "eslint src",
8 | "fix": "eslint src --fix",
9 | "fixwegame": "eslint ../cax-wegame --fix",
10 | "fixweapp": "eslint ../cax-weapp --fix",
11 | "lint:example": "eslint example --fix",
12 | "to-animate": "webpack -w",
13 | "pie": "webpack -w",
14 | "clip": "webpack -w",
15 | "graphics": "webpack -w",
16 | "sprite": "webpack -w",
17 | "group-clip": "webpack -w",
18 | "clip-transform": "webpack -w",
19 | "filter": "webpack -w",
20 | "getting-start": "webpack -w",
21 | "vision": "webpack -w",
22 | "to-shape": "webpack -w",
23 | "clip-transition": "webpack -w",
24 | "composite-operation": "webpack -w",
25 | "cache": "webpack -w",
26 | "caching": "webpack -w",
27 | "to": "webpack -w",
28 | "simple": "webpack -w",
29 | "build": "webpack",
30 | "build-min": "webpack",
31 | "test": "karma start test/karma.conf.js"
32 | },
33 | "devDependencies": {
34 | "eslint": "^4.3.0",
35 | "eslint-config-standard": "^10.2.1",
36 | "eslint-plugin-import": "^2.7.0",
37 | "eslint-plugin-node": "^5.1.1",
38 | "eslint-plugin-promise": "^3.5.0",
39 | "eslint-plugin-standard": "^3.0.1",
40 | "babel-core": "^6.26.0",
41 | "babel-loader": "^7.1.4",
42 | "babel-plugin-transform-class-properties": "^6.24.1",
43 | "babel-plugin-transform-react-jsx": "^6.24.1",
44 | "babel-preset-env": "^1.6.1",
45 | "chai": "^4.1.2",
46 | "jasmine-core": "^2.5.2",
47 | "karma": "^1.3.0",
48 | "karma-babel-preprocessor": "^7.0.0",
49 | "karma-chai-sinon": "^0.1.5",
50 | "karma-chrome-launcher": "^2.0.0",
51 | "karma-coverage": "^1.0.0",
52 | "karma-jasmine": "^1.1.0",
53 | "karma-mocha": "^1.1.1",
54 | "karma-mocha-reporter": "^2.0.4",
55 | "karma-sauce-launcher": "^1.1.0",
56 | "karma-sinon": "^1.0.5",
57 | "karma-source-map-support": "^1.2.0",
58 | "karma-sourcemap-loader": "^0.3.6",
59 | "karma-webpack": "^2.0.4",
60 | "mocha": "^5.0.4",
61 | "node-libs-browser": "^0.5.3",
62 | "sinon": "^4.5.0",
63 | "sinon-chai": "^3.0.0",
64 | "webpack": "^3.4.1"
65 | },
66 | "repository": {
67 | "type": "git",
68 | "url": "git+https://github.com/dntzhang/cax.git"
69 | },
70 | "keywords": [
71 | "canvas",
72 | "web",
73 | "weapp"
74 | ],
75 | "devEngines": {
76 | "node": "6.x || 7.x || 8.x",
77 | "npm": "3.x || 4.x || 5.x"
78 | },
79 | "author": "dntzhang",
80 | "license": "MIT",
81 | "bugs": {
82 | "url": "https://github.com/dntzhang/cax/issues/new"
83 | },
84 | "homepage": "http://dntzhang.github.io/cax"
85 | }
--------------------------------------------------------------------------------
/packages/cax/src/common/animate.js:
--------------------------------------------------------------------------------
1 | import To from './to'
2 |
3 | To.extend('rubber', [['to', ['scaleX', {
4 | '0': 1.25,
5 | '1': 300
6 | }], ['scaleY', {
7 | '0': 0.75,
8 | '1': 300
9 | }]], ['to', ['scaleX', {
10 | '0': 0.75,
11 | '1': 100
12 | }], ['scaleY', {
13 | '0': 1.25,
14 | '1': 100
15 | }]], ['to', ['scaleX', {
16 | '0': 1.15,
17 | '1': 100
18 | }], ['scaleY', {
19 | '0': 0.85,
20 | '1': 100
21 | }]], ['to', ['scaleX', {
22 | '0': 0.95,
23 | '1': 150
24 | }], ['scaleY', {
25 | '0': 1.05,
26 | '1': 150
27 | }]], ['to', ['scaleX', {
28 | '0': 1.05,
29 | '1': 100
30 | }], ['scaleY', {
31 | '0': 0.95,
32 | '1': 100
33 | }]], ['to', ['scaleX', {
34 | '0': 1,
35 | '1': 250
36 | }], ['scaleY', {
37 | '0': 1,
38 | '1': 250
39 | }]]])
40 |
41 | To.extend('bounceIn', [['to', ['scaleX', {
42 | '0': 0,
43 | '1': 0
44 | }], ['scaleY', {
45 | '0': 0,
46 | '1': 0
47 | }]], ['to', ['scaleX', {
48 | '0': 1.35,
49 | '1': 200
50 | }], ['scaleY', {
51 | '0': 1.35,
52 | '1': 200
53 | }]], ['to', ['scaleX', {
54 | '0': 0.9,
55 | '1': 100
56 | }], ['scaleY', {
57 | '0': 0.9,
58 | '1': 100
59 | }]], ['to', ['scaleX', {
60 | '0': 1.1,
61 | '1': 100
62 | }], ['scaleY', {
63 | '0': 1.1,
64 | '1': 100
65 | }]], ['to', ['scaleX', {
66 | '0': 0.95,
67 | '1': 100
68 | }], ['scaleY', {
69 | '0': 0.95,
70 | '1': 100
71 | }]], ['to', ['scaleX', {
72 | '0': 1,
73 | '1': 100
74 | }], ['scaleY', {
75 | '0': 1,
76 | '1': 100
77 | }]]])
78 |
79 | To.extend('flipInX', [['to', ['rotateX', {
80 | '0': -90,
81 | '1': 0
82 | }]], ['to', ['rotateX', {
83 | '0': 20,
84 | '1': 300
85 | }]], ['to', ['rotateX', {
86 | '0': -20,
87 | '1': 300
88 | }]], ['to', ['rotateX', {
89 | '0': 10,
90 | '1': 300
91 | }]], ['to', ['rotateX', {
92 | '0': -5,
93 | '1': 300
94 | }]], ['to', ['rotateX', {
95 | '0': 0,
96 | '1': 300
97 | }]]])
98 |
99 | To.extend('zoomOut', [['to', ['scaleX', {
100 | '0': 0,
101 | '1': 400
102 | }], ['scaleY', {
103 | '0': 0,
104 | '1': 400
105 | }]]])
106 |
--------------------------------------------------------------------------------
/packages/cax/src/common/raf-interval.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * raf-interval v0.3.0 By dntzhang
3 | * Github: https://github.com/dntzhang/raf-interval
4 | * MIT Licensed.
5 | */
6 |
7 | if (!Date.now) {
8 | Date.now = function now () {
9 | return new Date().getTime()
10 | }
11 | }
12 |
13 | let queue = [],
14 | id = -1,
15 | ticking = false,
16 | tickId = null,
17 | now = Date.now,
18 | lastTime = 0,
19 | vendors = ['ms', 'moz', 'webkit', 'o'],
20 | x = 0,
21 | isWeapp = typeof wx !== 'undefined' && typeof Page !== 'undefined',
22 | isWegame = typeof wx !== 'undefined' && typeof Page === 'undefined',
23 | isBrowser = typeof window !== 'undefined'
24 |
25 | let raf = isBrowser ? window.requestAnimationFrame : null
26 | let caf = isBrowser ? window.cancelAnimationFrame : null
27 |
28 | function mockRaf (callback, element) {
29 | let currTime = now()
30 | let timeToCall = Math.max(0, 16 - (currTime - lastTime))
31 | let id = setTimeout(function () {
32 | callback(currTime + timeToCall)
33 | }, timeToCall)
34 | lastTime = currTime + timeToCall
35 | return id
36 | }
37 |
38 | function mockCaf (id) {
39 | clearTimeout(id)
40 | }
41 |
42 | if (isBrowser) {
43 | window.setRafInterval = setRafInterval
44 | window.clearRafInterval = clearRafInterval
45 |
46 | for (; x < vendors.length && !window.requestAnimationFrame; ++x) {
47 | window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
48 | window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
49 | window[vendors[x] + 'CancelRequestAnimationFrame']
50 | }
51 |
52 | if (!raf) {
53 | raf = mockRaf
54 | caf = mockCaf
55 | window.requestAnimationFrame = raf
56 | window.cancelAnimationFrame = caf
57 | }
58 | } else if (isWeapp) {
59 | raf = mockRaf
60 | caf = mockCaf
61 | } else if (isWegame) {
62 | raf = requestAnimationFrame
63 | caf = cancelAnimationFrame
64 | }
65 |
66 | export function setRafInterval (fn, interval) {
67 | id++
68 | queue.push({ id: id, fn: fn, interval: interval, lastTime: now() })
69 | if (!ticking) {
70 | let tick = function () {
71 | tickId = raf(tick)
72 | each(queue, function (item) {
73 | if (item.interval < 17 || now() - item.lastTime >= item.interval) {
74 | item.fn()
75 | item.lastTime = now()
76 | }
77 | })
78 | }
79 | ticking = true
80 | tick()
81 | }
82 | return id
83 | }
84 |
85 | export function clearRafInterval (id) {
86 | let i = 0,
87 | len = queue.length
88 |
89 | for (; i < len; i++) {
90 | if (id === queue[i].id) {
91 | queue.splice(i, 1)
92 | break
93 | }
94 | }
95 |
96 | if (queue.length === 0) {
97 | caf(tickId)
98 | ticking = false
99 | }
100 | }
101 |
102 | function each (arr, fn) {
103 | if (Array.prototype.forEach) {
104 | arr.forEach(fn)
105 | } else {
106 | let i = 0,
107 | len = arr.length
108 | for (; i < len; i++) {
109 | fn(arr[i], i)
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/packages/cax/src/common/util.js:
--------------------------------------------------------------------------------
1 | export function getImageInWx (img, callback) {
2 | if ((img.indexOf('https://') === -1 && img.indexOf('http://') === -1) || img.indexOf('http://tmp/') === 0) {
3 | wx.getImageInfo({
4 | src: img,
5 | success: (info) => {
6 | callback({
7 | img: img,
8 | width: info.width,
9 | height: info.height
10 | })
11 | }
12 | })
13 | } else {
14 | wx.downloadFile({
15 | url: img,
16 | success: (res) => {
17 | if (res.statusCode === 200) {
18 | wx.getImageInfo({
19 | src: res.tempFilePath,
20 | success: (info) => {
21 | callback({
22 | img: res.tempFilePath,
23 | width: info.width,
24 | height: info.height
25 | })
26 | }
27 | })
28 | }
29 | }
30 | })
31 | }
32 | }
33 |
34 | function getGlobal () {
35 | if (typeof global !== 'object' || !global || global.Math !== Math || global.Array !== Array) {
36 | if (typeof self !== 'undefined') {
37 | return self
38 | } else if (typeof window !== 'undefined') {
39 | return window
40 | } else if (typeof global !== 'undefined') {
41 | return global
42 | }
43 | return (function () {
44 | return this
45 | })()
46 | }
47 | return global
48 | }
49 |
50 | const root = getGlobal()
51 |
52 | export default{
53 | getImageInWx,
54 | root,
55 | isWeapp: typeof wx !== 'undefined' && typeof Page !== 'undefined',
56 | isWegame: typeof wx !== 'undefined' && typeof Page === 'undefined'
57 | }
58 |
--------------------------------------------------------------------------------
/packages/cax/src/index.js:
--------------------------------------------------------------------------------
1 | import TWEEN from './common/tween'
2 | import To from './common/to'
3 | import './common/animate'
4 |
5 | import Stage from './render/display/stage'
6 | import WeStage from './render/display/we-stage'
7 | import Graphics from './render/display/graphics'
8 | import Bitmap from './render/display/bitmap'
9 | import Text from './render/display/text'
10 | import Group from './render/display/group'
11 | import Sprite from './render/display/sprite'
12 | import Shape from './render/display/shape/shape'
13 |
14 | import RoundedRect from './render/display/shape/rounded-rect'
15 | import ArrowPath from './render/display/shape/arrow-path'
16 | import Ellipse from './render/display/shape/ellipse'
17 | import Path from './render/display/shape/path'
18 |
19 | import Button from './render/display/element/button'
20 |
21 | import Rect from './render/display/shape/rect'
22 | import Circle from './render/display/shape/circle'
23 | import Polygon from './render/display/shape/polygon'
24 | import EquilateralPolygon from './render/display/shape/equilateral-polygon'
25 |
26 | import {setRafInterval, clearRafInterval} from './common/raf-interval'
27 |
28 | To.easing = {
29 | linear: TWEEN.Easing.Linear.None
30 | }
31 |
32 | const cax = {
33 | easing: {
34 | linear: TWEEN.Easing.Linear.None
35 | },
36 | util: {
37 | randomInt: (min, max) => {
38 | return min + Math.floor(Math.random() * (max - min + 1))
39 | }
40 | },
41 |
42 | Stage,
43 | WeStage,
44 | Graphics,
45 | Bitmap,
46 | Text,
47 | Group,
48 | Sprite,
49 | Shape,
50 |
51 | ArrowPath,
52 | Ellipse,
53 | Path,
54 |
55 | Button,
56 |
57 | RoundedRect,
58 | Rect,
59 | Circle,
60 | Polygon,
61 | EquilateralPolygon,
62 |
63 | setInterval: setRafInterval,
64 | clearInterval: clearRafInterval,
65 | tick: function (fn) {
66 | return setRafInterval(fn, 16)
67 | },
68 | untick: function (tickId) {
69 | clearRafInterval(tickId)
70 | },
71 |
72 | caxCanvasId: 0,
73 | TWEEN,
74 | To
75 | };
76 |
77 | ['Quadratic',
78 | 'Cubic',
79 | 'Quartic',
80 | 'Quintic',
81 | 'Sinusoidal',
82 | 'Exponential',
83 | 'Circular',
84 | 'Elastic',
85 | 'Back',
86 | 'Bounce'].forEach(item => {
87 | const itemLower = item.toLowerCase()
88 | cax.easing[itemLower + 'In'] = TWEEN.Easing[item].In
89 | cax.easing[itemLower + 'Out'] = TWEEN.Easing[item].Out
90 | cax.easing[itemLower + 'InOut'] = TWEEN.Easing[item].InOut
91 |
92 | To.easing[itemLower + 'In'] = TWEEN.Easing[item].In
93 | To.easing[itemLower + 'Out'] = TWEEN.Easing[item].Out
94 | To.easing[itemLower + 'InOut'] = TWEEN.Easing[item].InOut
95 | })
96 |
97 | const isWegame = typeof wx !== 'undefined' && typeof Page === 'undefined'
98 |
99 | cax.loadImg = function (option) {
100 | const img = isWegame ? wx.createImage() : new Image()
101 | img.onload = function () {
102 | option.complete(this)
103 | }
104 | img.src = option.img
105 | }
106 |
107 | cax.loadImgs = function (option) {
108 | const result = []
109 | let loaded = 0
110 | const len = option.imgs.length
111 | option.imgs.forEach((src, index) => {
112 | const img = isWegame ? wx.createImage() : new Image()
113 | img.onload = (function (i, img) {
114 | return function () {
115 | result[i] = img
116 | loaded++
117 | option.progress && option.progress(loaded / len, loaded, i, img, result)
118 | if (loaded === len) {
119 | option.complete && option.complete(result)
120 | }
121 | }
122 | })(index, img)
123 | img.src = src
124 | })
125 | }
126 |
127 | module.exports = cax
128 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/a2c.js:
--------------------------------------------------------------------------------
1 | // https://src.chromium.org/viewvc/blink/trunk/Source/core/svg/SVGPathParser.cpp?revision=195686#l225
2 | // https://github.com/adobe-webplatform/Snap.svg/blob/master/src/path.js#L752
3 |
4 | const math = Math
5 | const PI = math.PI
6 | const abs = math.abs
7 |
8 | function cacher (fn) {
9 | const cache = {}
10 | return function () {
11 | const key = [...arguments].join('-')
12 | if (cache.hasOwnProperty(key)) return cache[key]
13 | const result = fn.apply(null, arguments)
14 | cache[key] = result
15 | return result
16 | }
17 | }
18 |
19 | function a2c (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) {
20 | // for more information of where this math came from visit:
21 | // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
22 | var _120 = PI * 120 / 180,
23 | rad = PI / 180 * (+angle || 0),
24 | res = [],
25 | xy,
26 | rotate = cacher(function (x, y, rad) {
27 | var X = x * math.cos(rad) - y * math.sin(rad),
28 | Y = x * math.sin(rad) + y * math.cos(rad)
29 | return { x: X, y: Y }
30 | })
31 | if (!rx || !ry) {
32 | return [x1, y1, x2, y2, x2, y2]
33 | }
34 | if (!recursive) {
35 | xy = rotate(x1, y1, -rad)
36 | x1 = xy.x
37 | y1 = xy.y
38 | xy = rotate(x2, y2, -rad)
39 | x2 = xy.x
40 | y2 = xy.y
41 | var cos = math.cos(PI / 180 * angle),
42 | sin = math.sin(PI / 180 * angle),
43 | x = (x1 - x2) / 2,
44 | y = (y1 - y2) / 2
45 | var h = x * x / (rx * rx) + y * y / (ry * ry)
46 | if (h > 1) {
47 | h = math.sqrt(h)
48 | rx = h * rx
49 | ry = h * ry
50 | }
51 | var rx2 = rx * rx,
52 | ry2 = ry * ry,
53 | k = (large_arc_flag == sweep_flag ? -1 : 1) *
54 | math.sqrt(abs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))),
55 | cx = k * rx * y / ry + (x1 + x2) / 2,
56 | cy = k * -ry * x / rx + (y1 + y2) / 2,
57 | f1 = math.asin(((y1 - cy) / ry).toFixed(9)),
58 | f2 = math.asin(((y2 - cy) / ry).toFixed(9))
59 |
60 | f1 = x1 < cx ? PI - f1 : f1
61 | f2 = x2 < cx ? PI - f2 : f2
62 | f1 < 0 && (f1 = PI * 2 + f1)
63 | f2 < 0 && (f2 = PI * 2 + f2)
64 | if (sweep_flag && f1 > f2) {
65 | f1 = f1 - PI * 2
66 | }
67 | if (!sweep_flag && f2 > f1) {
68 | f2 = f2 - PI * 2
69 | }
70 | } else {
71 | f1 = recursive[0]
72 | f2 = recursive[1]
73 | cx = recursive[2]
74 | cy = recursive[3]
75 | }
76 | var df = f2 - f1
77 | if (abs(df) > _120) {
78 | var f2old = f2,
79 | x2old = x2,
80 | y2old = y2
81 | f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1)
82 | x2 = cx + rx * math.cos(f2)
83 | y2 = cy + ry * math.sin(f2)
84 | res = a2c(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy])
85 | }
86 | df = f2 - f1
87 | var c1 = math.cos(f1),
88 | s1 = math.sin(f1),
89 | c2 = math.cos(f2),
90 | s2 = math.sin(f2),
91 | t = math.tan(df / 4),
92 | hx = 4 / 3 * rx * t,
93 | hy = 4 / 3 * ry * t,
94 | m1 = [x1, y1],
95 | m2 = [x1 + hx * s1, y1 - hy * c1],
96 | m3 = [x2 + hx * s2, y2 - hy * c2],
97 | m4 = [x2, y2]
98 | m2[0] = 2 * m1[0] - m2[0]
99 | m2[1] = 2 * m1[1] - m2[1]
100 | if (recursive) {
101 | return [m2, m3, m4].concat(res)
102 | } else {
103 | res = [m2, m3, m4].concat(res).join().split(',')
104 | var newres = []
105 | for (var i = 0, ii = res.length; i < ii; i++) {
106 | newres[i] = i % 2 ? rotate(res[i - 1], res[i], rad).y : rotate(res[i], res[i + 1], rad).x
107 | }
108 | return newres
109 | }
110 | }
111 |
112 | export default a2c
113 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/arc-to-bezier.js:
--------------------------------------------------------------------------------
1 | // https://github.com/colinmeinke/svg-arc-to-cubic-bezier
2 |
3 | const TAU = Math.PI * 2
4 |
5 | const mapToEllipse = ({ x, y }, rx, ry, cosphi, sinphi, centerx, centery) => {
6 | x *= rx
7 | y *= ry
8 |
9 | const xp = cosphi * x - sinphi * y
10 | const yp = sinphi * x + cosphi * y
11 |
12 | return {
13 | x: xp + centerx,
14 | y: yp + centery
15 | }
16 | }
17 |
18 | const approxUnitArc = (ang1, ang2) => {
19 | const a = 4 / 3 * Math.tan(ang2 / 4)
20 |
21 | const x1 = Math.cos(ang1)
22 | const y1 = Math.sin(ang1)
23 | const x2 = Math.cos(ang1 + ang2)
24 | const y2 = Math.sin(ang1 + ang2)
25 |
26 | return [
27 | {
28 | x: x1 - y1 * a,
29 | y: y1 + x1 * a
30 | },
31 | {
32 | x: x2 + y2 * a,
33 | y: y2 - x2 * a
34 | },
35 | {
36 | x: x2,
37 | y: y2
38 | }
39 | ]
40 | }
41 |
42 | const vectorAngle = (ux, uy, vx, vy) => {
43 | const sign = (ux * vy - uy * vx < 0) ? -1 : 1
44 | const umag = Math.sqrt(ux * ux + uy * uy)
45 | const vmag = Math.sqrt(ux * ux + uy * uy)
46 | const dot = ux * vx + uy * vy
47 |
48 | let div = dot / (umag * vmag)
49 |
50 | if (div > 1) {
51 | div = 1
52 | }
53 |
54 | if (div < -1) {
55 | div = -1
56 | }
57 |
58 | return sign * Math.acos(div)
59 | }
60 |
61 | const getArcCenter = (
62 | px,
63 | py,
64 | cx,
65 | cy,
66 | rx,
67 | ry,
68 | largeArcFlag,
69 | sweepFlag,
70 | sinphi,
71 | cosphi,
72 | pxp,
73 | pyp
74 | ) => {
75 | const rxsq = Math.pow(rx, 2)
76 | const rysq = Math.pow(ry, 2)
77 | const pxpsq = Math.pow(pxp, 2)
78 | const pypsq = Math.pow(pyp, 2)
79 |
80 | let radicant = (rxsq * rysq) - (rxsq * pypsq) - (rysq * pxpsq)
81 |
82 | if (radicant < 0) {
83 | radicant = 0
84 | }
85 |
86 | radicant /= (rxsq * pypsq) + (rysq * pxpsq)
87 | radicant = Math.sqrt(radicant) * (largeArcFlag === sweepFlag ? -1 : 1)
88 |
89 | const centerxp = radicant * rx / ry * pyp
90 | const centeryp = radicant * -ry / rx * pxp
91 |
92 | const centerx = cosphi * centerxp - sinphi * centeryp + (px + cx) / 2
93 | const centery = sinphi * centerxp + cosphi * centeryp + (py + cy) / 2
94 |
95 | const vx1 = (pxp - centerxp) / rx
96 | const vy1 = (pyp - centeryp) / ry
97 | const vx2 = (-pxp - centerxp) / rx
98 | const vy2 = (-pyp - centeryp) / ry
99 |
100 | let ang1 = vectorAngle(1, 0, vx1, vy1)
101 | let ang2 = vectorAngle(vx1, vy1, vx2, vy2)
102 |
103 | if (sweepFlag === 0 && ang2 > 0) {
104 | ang2 -= TAU
105 | }
106 |
107 | if (sweepFlag === 1 && ang2 < 0) {
108 | ang2 += TAU
109 | }
110 |
111 | return [ centerx, centery, ang1, ang2 ]
112 | }
113 |
114 | const arcToBezier = ({
115 | px,
116 | py,
117 | cx,
118 | cy,
119 | rx,
120 | ry,
121 | xAxisRotation = 0,
122 | largeArcFlag = 0,
123 | sweepFlag = 0
124 | }) => {
125 | const curves = []
126 |
127 | if (rx === 0 || ry === 0) {
128 | return []
129 | }
130 |
131 | const sinphi = Math.sin(xAxisRotation * TAU / 360)
132 | const cosphi = Math.cos(xAxisRotation * TAU / 360)
133 |
134 | const pxp = cosphi * (px - cx) / 2 + sinphi * (py - cy) / 2
135 | const pyp = -sinphi * (px - cx) / 2 + cosphi * (py - cy) / 2
136 |
137 | if (pxp === 0 && pyp === 0) {
138 | return []
139 | }
140 |
141 | rx = Math.abs(rx)
142 | ry = Math.abs(ry)
143 |
144 | const lambda =
145 | Math.pow(pxp, 2) / Math.pow(rx, 2) +
146 | Math.pow(pyp, 2) / Math.pow(ry, 2)
147 |
148 | if (lambda > 1) {
149 | rx *= Math.sqrt(lambda)
150 | ry *= Math.sqrt(lambda)
151 | }
152 |
153 | let [ centerx, centery, ang1, ang2 ] = getArcCenter(
154 | px,
155 | py,
156 | cx,
157 | cy,
158 | rx,
159 | ry,
160 | largeArcFlag,
161 | sweepFlag,
162 | sinphi,
163 | cosphi,
164 | pxp,
165 | pyp
166 | )
167 |
168 | const segments = Math.max(Math.ceil(Math.abs(ang2) / (TAU / 4)), 1)
169 |
170 | ang2 /= segments
171 |
172 | for (let i = 0; i < segments; i++) {
173 | curves.push(approxUnitArc(ang1, ang2))
174 | ang1 += ang2
175 | }
176 |
177 | return curves.map(curve => {
178 | const { x: x1, y: y1 } = mapToEllipse(curve[ 0 ], rx, ry, cosphi, sinphi, centerx, centery)
179 | const { x: x2, y: y2 } = mapToEllipse(curve[ 1 ], rx, ry, cosphi, sinphi, centerx, centery)
180 | const { x, y } = mapToEllipse(curve[ 2 ], rx, ry, cosphi, sinphi, centerx, centery)
181 |
182 | return { x1, y1, x2, y2, x, y }
183 | })
184 | }
185 |
186 | export default arcToBezier
187 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/event-dispatcher.js:
--------------------------------------------------------------------------------
1 | import option from './stage-propagation-tag'
2 |
3 | class EventDispatcher {
4 | constructor () {
5 | this._listeners = null
6 | this._captureListeners = null
7 | }
8 |
9 | addEventListener (type, listener, useCapture) {
10 | var listeners
11 | if (useCapture) {
12 | listeners = this._captureListeners = this._captureListeners || {}
13 | } else {
14 | listeners = this._listeners = this._listeners || {}
15 | }
16 | var arr = listeners[type]
17 | if (arr) { this.removeEventListener(type, listener, useCapture) }
18 | arr = listeners[type] // remove may have deleted the array
19 | if (!arr) { listeners[type] = [listener] } else { arr.push(listener) }
20 | return listener
21 | }
22 |
23 | removeEventListener (type, listener, useCapture) {
24 | var listeners = useCapture ? this._captureListeners : this._listeners
25 | if (!listeners) { return }
26 | var arr = listeners[type]
27 | if (!arr) { return }
28 |
29 | arr.every((item, index) => {
30 | if (item === listener) {
31 | arr.splice(index, 1)
32 | return false
33 | }
34 | return true
35 | })
36 | }
37 |
38 | on (type, listener, useCapture) {
39 | this.addEventListener(type, listener, useCapture)
40 | }
41 |
42 | off (type, listener, useCapture) {
43 | this.removeEventListener(type, listener, useCapture)
44 | }
45 |
46 | dispatchEvent (evt) {
47 | option.stagePropagationStopped[evt.type] = false
48 |
49 | var top = this, list = [top]
50 | while (top.parent) { list.push(top = top.parent) }
51 | var i, l = list.length
52 |
53 | // capture & atTarget
54 | for (i = l - 1; i >= 0 && !evt.propagationStopped; i--) {
55 | list[i]._dispatchEvent(evt, 0)
56 | }
57 | // bubbling
58 | for (i = 0; i < l && !evt.propagationStopped; i++) {
59 | list[i]._dispatchEvent(evt, 1)
60 | }
61 | }
62 |
63 | _dispatchEvent (evt, type) {
64 | evt.target = this
65 | if (this._captureListeners && type === 0) {
66 | let cls = this._captureListeners[evt.type]
67 | cls && cls.forEach(fn => {
68 | fn.call(this, evt)
69 | })
70 | }
71 |
72 | if (this._listeners && type === 1) {
73 | let ls = this._listeners[evt.type]
74 | ls && ls.forEach(fn => {
75 | fn.call(this, evt)
76 | })
77 | }
78 | }
79 | }
80 |
81 | export default EventDispatcher
82 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/event.js:
--------------------------------------------------------------------------------
1 | import option from './stage-propagation-tag'
2 |
3 | class Event {
4 | constructor () {
5 | this.propagationStopped = false
6 | this.stageX = null
7 | this.stageY = null
8 | this.pureEvent = null
9 | }
10 |
11 | stopPropagation () {
12 | option.stagePropagationStopped[this.type] = true
13 | this.propagationStopped = true
14 | }
15 |
16 | preventDefault () {
17 | this.pureEvent.preventDefault()
18 | }
19 | }
20 |
21 | export default Event
22 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/matrix2d.js:
--------------------------------------------------------------------------------
1 |
2 | const DEG_TO_RAD = 0.017453292519943295
3 | const PI_2 = Math.PI * 2
4 |
5 | class Matrix2D {
6 | constructor (a, b, c, d, tx, ty) {
7 | this.a = a == null ? 1 : a
8 | this.b = b || 0
9 | this.c = c || 0
10 | this.d = d == null ? 1 : d
11 | this.tx = tx || 0
12 | this.ty = ty || 0
13 | return this
14 | }
15 |
16 | identity () {
17 | this.a = this.d = 1
18 | this.b = this.c = this.tx = this.ty = 0
19 | return this
20 | }
21 |
22 | appendTransform (x, y, scaleX, scaleY, rotation, skewX, skewY, originX, originY) {
23 | if (rotation % 360) {
24 | var r = rotation * DEG_TO_RAD
25 | var cos = Math.cos(r)
26 | var sin = Math.sin(r)
27 | } else {
28 | cos = 1
29 | sin = 0
30 | }
31 | if (skewX || skewY) {
32 | skewX *= DEG_TO_RAD
33 | skewY *= DEG_TO_RAD
34 | this.append(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y)
35 | this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0)
36 | } else {
37 | this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y)
38 | }
39 | if (originX || originY) {
40 | this.tx -= originX * this.a + originY * this.c
41 | this.ty -= originX * this.b + originY * this.d
42 | }
43 | return this
44 | }
45 |
46 | append (a, b, c, d, tx, ty) {
47 | var a1 = this.a
48 | var b1 = this.b
49 | var c1 = this.c
50 | var d1 = this.d
51 | this.a = a * a1 + b * c1
52 | this.b = a * b1 + b * d1
53 | this.c = c * a1 + d * c1
54 | this.d = c * b1 + d * d1
55 | this.tx = tx * a1 + ty * c1 + this.tx
56 | this.ty = tx * b1 + ty * d1 + this.ty
57 | return this
58 | }
59 |
60 | initialize (a, b, c, d, tx, ty) {
61 | this.a = a
62 | this.b = b
63 | this.c = c
64 | this.d = d
65 | this.tx = tx
66 | this.ty = ty
67 | return this
68 | }
69 |
70 | setValues (a, b, c, d, tx, ty) {
71 | this.a = a == null ? 1 : a
72 | this.b = b || 0
73 | this.c = c || 0
74 | this.d = d == null ? 1 : d
75 | this.tx = tx || 0
76 | this.ty = ty || 0
77 | return this
78 | }
79 |
80 | invert () {
81 | let a1 = this.a
82 | let b1 = this.b
83 | let c1 = this.c
84 | let d1 = this.d
85 | let tx1 = this.tx
86 | let n = a1 * d1 - b1 * c1
87 |
88 | this.a = d1 / n
89 | this.b = -b1 / n
90 | this.c = -c1 / n
91 | this.d = a1 / n
92 | this.tx = (c1 * this.ty - d1 * tx1) / n
93 | this.ty = -(a1 * this.ty - b1 * tx1) / n
94 | return this
95 | };
96 |
97 | copy (matrix) {
98 | return this.setValues(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty)
99 | }
100 | }
101 |
102 | Matrix2D.decompose = function (a, b, c, d, tx, ty, transform) {
103 | const skewX = -Math.atan2(-c, d)
104 | const skewY = Math.atan2(b, a)
105 |
106 | const delta = Math.abs(skewX + skewY)
107 |
108 | if (delta < 0.00001 || Math.abs(PI_2 - delta) < 0.00001) {
109 | transform.rotation = skewY
110 |
111 | if (a < 0 && d >= 0) {
112 | transform.rotation += (transform.rotation <= 0) ? Math.PI : -Math.PI
113 | }
114 |
115 | transform.skewX = transform.skewY = 0
116 | } else {
117 | transform.rotation = 0
118 | transform.skewX = skewX
119 | transform.skewY = skewY
120 | }
121 |
122 | // next set scale
123 | transform.scaleX = Math.sqrt((a * a) + (b * b))
124 | transform.scaleY = Math.sqrt((c * c) + (d * d))
125 |
126 | // next set position
127 | transform.x = tx
128 | transform.y = ty
129 | }
130 |
131 | export default Matrix2D
132 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/path-parser.js:
--------------------------------------------------------------------------------
1 | // https://github.com/jkroso/parse-svg-path/blob/master/index.js
2 | /**
3 | * expected argument lengths
4 | * @type {Object}
5 | */
6 |
7 | var length = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}
8 |
9 | /**
10 | * segment pattern
11 | * @type {RegExp}
12 | */
13 |
14 | var segment = /([astvzqmhlc])([^astvzqmhlc]*)/ig
15 |
16 | /**
17 | * parse an svg path data string. Generates an Array
18 | * of commands where each command is an Array of the
19 | * form `[command, arg1, arg2, ...]`
20 | *
21 | * @param {String} path
22 | * @return {Array}
23 | */
24 |
25 | function parse (path) {
26 | var data = []
27 | path.replace(segment, function (_, command, args) {
28 | var type = command.toLowerCase()
29 | args = parseValues(args)
30 |
31 | // overloaded moveTo
32 | if (type === 'm' && args.length > 2) {
33 | data.push([command].concat(args.splice(0, 2)))
34 | type = 'l'
35 | command = command === 'm' ? 'l' : 'L'
36 | }
37 |
38 | while (true) {
39 | if (args.length === length[type]) {
40 | args.unshift(command)
41 | return data.push(args)
42 | }
43 | if (args.length < length[type]) throw new Error('malformed path data')
44 | data.push([command].concat(args.splice(0, length[type])))
45 | }
46 | })
47 | return data
48 | }
49 |
50 | var number = /-?[0-9]*\.?[0-9]+(?:e[-+]?\d+)?/ig
51 |
52 | function parseValues (args) {
53 | var numbers = args.match(number)
54 | return numbers ? numbers.map(Number) : []
55 | }
56 |
57 | export default parse
58 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/stage-propagation-tag.js:
--------------------------------------------------------------------------------
1 | export default {
2 | stagePropagationStopped: {}
3 | }
4 |
--------------------------------------------------------------------------------
/packages/cax/src/render/base/uid.js:
--------------------------------------------------------------------------------
1 | var UID = {}
2 |
3 | UID._nextID = 0
4 |
5 | UID.get = function () {
6 | return UID._nextID++
7 | }
8 |
9 | export default UID
10 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/bitmap.js:
--------------------------------------------------------------------------------
1 | import DisplayObject from './display-object.js'
2 | import util from '../../common/util'
3 |
4 | class Bitmap extends DisplayObject {
5 | constructor (img, onLoad) {
6 | super()
7 | if (typeof img === 'string') {
8 | if (Bitmap.cache[img]) {
9 | if (util.isWeapp) {
10 | this.img = Bitmap.cache[img].img
11 | this.rect = [0, 0, Bitmap.cache[img].width, Bitmap.cache[img].height]
12 | this.width = this.rect[2]
13 | this.height = this.rect[3]
14 | } else {
15 | this.img = Bitmap.cache[img]
16 | this.rect = [0, 0, this.img.width, this.img.height]
17 | this.width = this.img.width
18 | this.height = this.img.height
19 | }
20 | onLoad && onLoad.call(this)
21 | } else if (util.isWeapp) {
22 | util.getImageInWx(img, (result) => {
23 | this.img = result.img
24 | if (!this.rect) {
25 | this.rect = [0, 0, result.width, result.height]
26 | }
27 | this.width = result.width
28 | this.height = result.height
29 | onLoad && onLoad.call(this)
30 | Bitmap.cache[img] = result
31 | })
32 | } else {
33 | this.img = util.isWegame ? wx.createImage() : new window.Image()
34 |
35 | this.img.onload = () => {
36 | if (!this.rect) {
37 | this.rect = [0, 0, this.img.width, this.img.height]
38 | }
39 | this.width = this.img.width
40 | this.height = this.img.height
41 | onLoad && onLoad.call(this)
42 | Bitmap.cache[img] = this.img
43 | }
44 | this.img.src = img
45 | }
46 | } else {
47 | this.img = img
48 | this.rect = [0, 0, img.width, img.height]
49 | this.width = img.width
50 | this.height = img.height
51 | Bitmap.cache[img.src] = img
52 | }
53 | }
54 |
55 | clone () {
56 | // 复制完img宽度0??所以直接传字符串
57 | const bitmap = new Bitmap(typeof this.img === 'string' ? this.img : this.img.src)
58 | bitmap.x = this.x
59 | bitmap.y = this.y
60 | bitmap.scaleX = this.scaleX
61 | bitmap.scaleY = this.scaleY
62 | bitmap.rotation = this.rotation
63 | bitmap.skewX = this.skewX
64 | bitmap.skewY = this.skewY
65 | bitmap.originX = this.originX
66 | bitmap.originY = this.originY
67 | bitmap.width = this.width
68 | bitmap.height = this.height
69 | bitmap.cursor = this.cursor
70 |
71 | return bitmap
72 | }
73 | }
74 |
75 | Bitmap.cache = {
76 |
77 | }
78 |
79 | export default Bitmap
80 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/element/button.js:
--------------------------------------------------------------------------------
1 | import Group from '../group'
2 | import Text from '../text'
3 | import RoundedRect from '../shape/rounded-rect'
4 | import Bitmap from '../bitmap'
5 |
6 | /*
7 | Options
8 | font:
9 | text:
10 | textColor:
11 | image: [path, width, height]
12 | bgColor:
13 | bgImage: [path, width, height]
14 | borderRadius:
15 | borderColor:
16 | */
17 |
18 | class Button extends Group {
19 | constructor (option) {
20 | super()
21 | this.width = option.width
22 | this.height = option.height
23 | this.x = option.x
24 | this.y = option.y
25 |
26 | let textHeight = 0
27 | var textGroup
28 |
29 | if (option.text) {
30 | textGroup = new Group()
31 | this.text = new Text(option.text, {
32 | font: option.font,
33 | color: option.color
34 | })
35 | const textWidth = this.text.getWidth()
36 |
37 | if (textWidth > option.width) {
38 | const step = Math.round(option.text.length * (option.width) / textWidth / 2)
39 |
40 | const textList = this.stringSplit(option.text, step)
41 | const lineHeight = option.lineHeight || 12
42 | textHeight = textList.length * lineHeight + 6
43 |
44 | textList.forEach((text, index) => {
45 | this.text = new Text(text, {
46 | font: option.font,
47 | color: option.color
48 | })
49 |
50 | this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX + (option.textX || 0)
51 | this.text.y = Math.max(textHeight, option.height) / 2 - 10 + 5 * this.text.scaleY + (option.textY || 0) + index * 12 - textHeight / 2 + lineHeight / 2
52 | textGroup.add(this.text)
53 | })
54 | } else {
55 | this.text.x = option.width / 2 - this.text.getWidth() / 2 * this.text.scaleX + (option.textX || 0)
56 | this.text.y = option.height / 2 - 10 + 5 * this.text.scaleY + (option.textY || 0)
57 | textGroup.add(this.text)
58 | }
59 | }
60 |
61 | if (option.bgImage) {
62 | var ratio = option.ratio || 1
63 | let bitmap = new Bitmap(option.bgImage[0])
64 | bitmap.scaleX = ratio
65 | bitmap.scaleY = ratio
66 | bitmap.width = option.bgImage[1]
67 | bitmap.height = option.bgImage[2]
68 | bitmap.x = (this.width - bitmap.width) / 2
69 | bitmap.y = (this.height - bitmap.height) / 2
70 | this.add(bitmap)
71 | } else if (option.bgColor || option.borderColor) {
72 | this.roundedRect = new RoundedRect(option.width, option.autoHeight ? Math.max(textHeight, option.height) : option.height, option.borderRadius, {
73 | strokeStyle: option.borderColor || 'black',
74 | fillStyle: option.bgColor || '#F5F5F5'
75 | })
76 | this.add(this.roundedRect)
77 | }
78 |
79 | if (option.image) {
80 | var ratio = option.ratio || 1
81 | let bitmap = new Bitmap(option.image[0])
82 | bitmap.scaleX = ratio
83 | bitmap.scaleY = ratio
84 | bitmap.width = option.image[1]
85 | bitmap.height = option.image[2]
86 | bitmap.x = (this.width - bitmap.width) / 2
87 | bitmap.y = (this.height - bitmap.height) / 2
88 | this.add(bitmap)
89 | }
90 |
91 | if (textGroup) {
92 | this.add(textGroup)
93 | }
94 | }
95 |
96 | stringSplit (str, len) {
97 | let arr = [],
98 | offset = 0,
99 | char_length = 0
100 | for (let i = 0; i < str.length; i++) {
101 | let son_str = str.charAt(i)
102 | encodeURI(son_str).length > 2 ? char_length += 1 : char_length += 0.5
103 | if (char_length >= len || (char_length < len && i === str.length - 1)) {
104 | let sub_len = char_length == len ? i + 1 : i
105 | arr.push(str.substr(offset, sub_len - offset + ((char_length < len && i === str.length - 1) ? 1 : 0)))
106 | offset = i + 1
107 | char_length = 0
108 | }
109 | }
110 | return arr
111 | }
112 | }
113 |
114 | export default Button
115 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/graphics.js:
--------------------------------------------------------------------------------
1 | import DisplayObject from './display-object.js'
2 |
3 | const assMap = {
4 | fillStyle: true,
5 | strokeStyle: true,
6 | lineWidth: true,
7 | lineCap: true,
8 | lineDashOffset: true,
9 | lineJoin: true,
10 | miterLimit: true
11 | }
12 |
13 | class Graphics extends DisplayObject {
14 | constructor () {
15 | super()
16 | this.cmds = []
17 | this.currentGradient = null
18 | }
19 |
20 | clearRect () {
21 | this.cmds.push(['clearRect', arguments])
22 | return this
23 | }
24 |
25 | rect () {
26 | this.cmds.push(['rect', arguments])
27 | return this
28 | }
29 |
30 | clear () {
31 | this.cmds.length = 0
32 | return this
33 | }
34 |
35 | setLineDash () {
36 | this.cmds.push(['setLineDash', arguments])
37 | return this
38 | }
39 |
40 | strokeRect () {
41 | this.cmds.push(['strokeRect', arguments])
42 | return this
43 | }
44 |
45 | fillRect () {
46 | this.cmds.push(['fillRect', arguments])
47 | return this
48 | }
49 |
50 | beginPath () {
51 | this.cmds.push(['beginPath', arguments])
52 | return this
53 | }
54 |
55 | arc () {
56 | this.cmds.push(['arc', arguments])
57 | return this
58 | }
59 |
60 | closePath () {
61 | this.cmds.push(['closePath', arguments])
62 | return this
63 | }
64 |
65 | fillStyle () {
66 | this.cmds.push(['fillStyle', arguments])
67 | return this
68 | }
69 |
70 | fill () {
71 | this.cmds.push(['fill', arguments])
72 | return this
73 | }
74 |
75 | strokeStyle () {
76 | this.cmds.push(['strokeStyle', arguments])
77 | return this
78 | }
79 |
80 | lineWidth () {
81 | this.cmds.push(['lineWidth', arguments])
82 | return this
83 | }
84 |
85 | lineCap () {
86 | this.cmds.push(['lineCap', arguments])
87 | return this
88 | }
89 |
90 | lineDashOffset () {
91 | this.cmds.push(['lineDashOffset', arguments])
92 | return this
93 | }
94 |
95 | lineJoin () {
96 | this.cmds.push(['lineJoin', arguments])
97 | return this
98 | }
99 |
100 | miterLimit () {
101 | this.cmds.push(['miterLimit', arguments])
102 | return this
103 | }
104 |
105 | stroke () {
106 | this.cmds.push(['stroke', arguments])
107 | return this
108 | }
109 |
110 | moveTo () {
111 | this.cmds.push(['moveTo', arguments])
112 | return this
113 | }
114 |
115 | lineTo () {
116 | this.cmds.push(['lineTo', arguments])
117 | return this
118 | }
119 |
120 | bezierCurveTo () {
121 | this.cmds.push(['bezierCurveTo', arguments])
122 | return this
123 | }
124 |
125 | quadraticCurveTo () {
126 | this.cmds.push(['quadraticCurveTo', arguments])
127 | return this
128 | }
129 |
130 | createRadialGradient () {
131 | this.cmds.push(['createRadialGradient', arguments])
132 | return this
133 | }
134 |
135 | createLinearGradient () {
136 | this.cmds.push(['createLinearGradient', arguments])
137 | return this
138 | }
139 |
140 | addColorStop () {
141 | this.cmds.push(['addColorStop', arguments])
142 | return this
143 | }
144 |
145 | fillGradient () {
146 | this.cmds.push(['fillGradient'])
147 | return this
148 | }
149 |
150 | arcTo () {
151 | this.cmds.push(['arcTo', arguments])
152 | return this
153 | }
154 |
155 | render (ctx) {
156 | this.cmds.forEach(cmd => {
157 | const methodName = cmd[0]
158 | if (assMap[methodName]) {
159 | ctx[methodName] = cmd[1][0]
160 | } else if (methodName === 'addColorStop') {
161 | this.currentGradient && this.currentGradient.addColorStop(cmd[1][0], cmd[1][1])
162 | } else if (methodName === 'fillGradient') {
163 | ctx.fillStyle = this.currentGradient
164 | } else {
165 | let result = ctx[methodName].apply(ctx, Array.prototype.slice.call(cmd[1]))
166 | if (methodName === 'createRadialGradient' || methodName === 'createLinearGradient') {
167 | this.currentGradient = result
168 | }
169 | }
170 | })
171 | }
172 | }
173 |
174 | export default Graphics
175 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/group.js:
--------------------------------------------------------------------------------
1 | import DisplayObject from './display-object.js'
2 |
3 | class Group extends DisplayObject {
4 | constructor (data) {
5 | super(data)
6 | this.children = []
7 | }
8 |
9 | add (child) {
10 | const len = arguments.length
11 |
12 | for (let i = 0; i < len; i++) {
13 | const c = arguments[i]
14 | const parent = c.parent
15 | if (parent) {
16 | parent.removeChildAt(parent.children.indexOf(c))
17 | }
18 | this.children.push(c)
19 | c.parent = this
20 | }
21 | }
22 |
23 | addChildAt (child, index) {
24 | var par = child.parent
25 | par && par.removeChildAt(par.children.indexOf(child))
26 | child.parent = this
27 | this.children.splice(index, 0, child)
28 | }
29 |
30 | removeChildAt (index) {
31 | var child = this.children[index]
32 | if (child) { child.parent = null }
33 | this.children.splice(index, 1)
34 | }
35 |
36 | replace (current, pre) {
37 | const index = pre.parent.children.indexOf(pre)
38 | this.removeChildAt(index)
39 | this.addChildAt(current, index)
40 | }
41 |
42 | remove (child) {
43 | const len = arguments.length
44 | let cLen = this.children.length
45 |
46 | for (let i = 0; i < len; i++) {
47 | for (let j = 0; j < cLen; j++) {
48 | if (child.id === this.children[j].id) {
49 | child.parent = null
50 | this.children.splice(j, 1)
51 | j--
52 | cLen--
53 | }
54 | }
55 | }
56 | }
57 |
58 | empty () {
59 | this.children.forEach(child => {
60 | child.parent = null
61 | })
62 | this.children.length = 0
63 | }
64 |
65 | destroy () {
66 | this.empty()
67 | // Stage does not have a parent
68 | this.parent && super.destroy()
69 | }
70 | }
71 |
72 | export default Group
73 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/arrow-path.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class ArrowPath extends Shape {
4 | constructor (path, option) {
5 | super()
6 |
7 | this.path = path
8 | this.option = Object.assign({
9 | strokeStyle: 'black',
10 | lineWidth: 1,
11 | headSize: 10
12 | }, option)
13 | }
14 |
15 | draw () {
16 | const path = this.path
17 | this.beginPath()
18 | const len = path.length
19 | if (len === 2) {
20 | this.drawArrow(path[0].x, path[0].y, path[1].x, path[1].y, 30)
21 | } else {
22 | this.moveTo(path[0].x, path[0].y)
23 | for (let i = 1; i < len - 1; i++) {
24 | this.lineTo(path[i].x, path[i].y)
25 | }
26 | this.drawArrow(path[len - 2].x, path[len - 2].y, path[len - 1].x, path[len - 1].y, 30)
27 | }
28 |
29 | this.stroke()
30 | }
31 |
32 | drawArrow (fromX, fromY, toX, toY, theta) {
33 | let angle = Math.atan2(fromY - toY, fromX - toX) * 180 / Math.PI,
34 | angle1 = (angle + theta) * Math.PI / 180,
35 | angle2 = (angle - theta) * Math.PI / 180,
36 | hs = this.option.headSize,
37 | topX = hs * Math.cos(angle1),
38 | topY = hs * Math.sin(angle1),
39 | botX = hs * Math.cos(angle2),
40 | botY = hs * Math.sin(angle2)
41 |
42 | let arrowX = fromX - topX,
43 | arrowY = fromY - topY
44 |
45 | this.moveTo(arrowX, arrowY)
46 | this.moveTo(fromX, fromY)
47 | this.lineTo(toX, toY)
48 | arrowX = toX + topX
49 | arrowY = toY + topY
50 | this.moveTo(arrowX, arrowY)
51 | this.lineTo(toX, toY)
52 | arrowX = toX + botX
53 | arrowY = toY + botY
54 | this.lineTo(arrowX, arrowY)
55 | this.strokeStyle(this.option.strokeStyle)
56 | this.lineWidth(this.option.lineWidth)
57 | }
58 | }
59 |
60 | export default ArrowPath
61 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/circle.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class Circle extends Shape {
4 | constructor (r, option) {
5 | super()
6 | this.option = option || {}
7 | this.r = r
8 |
9 | this._dp = Math.PI * 2
10 | }
11 |
12 | draw () {
13 | this.beginPath()
14 | this.arc(0, 0, this.r, 0, this._dp, false)
15 |
16 | if (this.option.strokeStyle) {
17 | if (this.option.lineWidth !== undefined) {
18 | this.lineWidth(this.option.lineWidth)
19 | }
20 | this.strokeStyle(this.option.strokeStyle)
21 | this.stroke()
22 | }
23 |
24 | if (this.option.fillStyle) {
25 | this.fillStyle(this.option.fillStyle)
26 | this.fill()
27 | }
28 | }
29 | }
30 |
31 | export default Circle
32 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/ellipse.js:
--------------------------------------------------------------------------------
1 |
2 | import Shape from './shape'
3 |
4 | class Ellipse extends Shape {
5 | constructor (width, height, option) {
6 | super()
7 | this.option = option || {}
8 | this.width = width
9 | this.height = height
10 | }
11 |
12 | draw () {
13 | const w = this.width
14 | const h = this.height
15 | const k = 0.5522848
16 | const ox = (w / 2) * k
17 | const oy = (h / 2) * k
18 | const xe = w
19 | const ye = h
20 | const xm = w / 2
21 | const ym = h / 2
22 |
23 | this.beginPath()
24 | this.moveTo(0, ym)
25 | this.bezierCurveTo(0, ym - oy, xm - ox, 0, xm, 0)
26 | this.bezierCurveTo(xm + ox, 0, xe, ym - oy, xe, ym)
27 | this.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye)
28 | this.bezierCurveTo(xm - ox, ye, 0, ym + oy, 0, ym)
29 |
30 | if (this.option.strokeStyle) {
31 | if (this.option.lineWidth !== undefined) {
32 | this.lineWidth(this.option.lineWidth)
33 | }
34 | this.strokeStyle(this.option.strokeStyle)
35 | this.stroke()
36 | }
37 |
38 | if (this.option.fillStyle) {
39 | this.fillStyle(this.option.fillStyle)
40 | this.fill()
41 | }
42 | }
43 | }
44 |
45 | export default Ellipse
46 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/equilateral-polygon.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class EquilateralPolygon extends Shape {
4 | constructor (num, r, options) {
5 | super()
6 |
7 | this.num = num
8 | this.r = r
9 | this.options = options || {}
10 |
11 | this.vertex = []
12 | this.initVertex()
13 | }
14 |
15 | initVertex () {
16 | this.vertex.length = []
17 | const num = this.num
18 | const r = this.r
19 | let i, startX, startY, newX, newY
20 |
21 | if (num % 2 === 0) {
22 | startX = r * Math.cos(2 * Math.PI * 0 / num)
23 | startY = r * Math.sin(2 * Math.PI * 0 / num)
24 |
25 | this.vertex.push([startX, startY])
26 | for (i = 1; i < num; i++) {
27 | newX = r * Math.cos(2 * Math.PI * i / num)
28 | newY = r * Math.sin(2 * Math.PI * i / num)
29 |
30 | this.vertex.push([newX, newY])
31 | }
32 | } else {
33 | startX = r * Math.cos(2 * Math.PI * 0 / num - Math.PI / 2)
34 | startY = r * Math.sin(2 * Math.PI * 0 / num - Math.PI / 2)
35 |
36 | this.vertex.push([startX, startY])
37 | for (i = 1; i < num; i++) {
38 | newX = r * Math.cos(2 * Math.PI * i / num - Math.PI / 2)
39 | newY = r * Math.sin(2 * Math.PI * i / num - Math.PI / 2)
40 |
41 | this.vertex.push([newX, newY])
42 | }
43 | }
44 | }
45 |
46 | draw () {
47 | this.beginPath()
48 |
49 | this.moveTo(this.vertex[0][0], this.vertex[0][1])
50 |
51 | for (let i = 1, len = this.vertex.length; i < len; i++) {
52 | this.lineTo(this.vertex[i][0], this.vertex[i][1])
53 | }
54 | this.closePath()
55 |
56 | if (this.options.fillStyle) {
57 | this.fillStyle(this.options.fillStyle)
58 | this.fill()
59 | }
60 |
61 | if (this.options.strokeStyle) {
62 | this.strokeStyle(this.options.strokeStyle)
63 | if (typeof this.options.lineWidth === 'number') {
64 | this.lineWidth(this.options.lineWidth)
65 | }
66 | this.stroke()
67 | }
68 | }
69 | }
70 |
71 | export default EquilateralPolygon
72 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/polygon.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class Polygon extends Shape {
4 | constructor (vertex, options) {
5 | super()
6 |
7 | this.vertex = vertex || []
8 | this.options = options || {}
9 | this.strokeColor = this.options.strokeColor
10 | this.fillColor = this.options.fillColor
11 | }
12 |
13 | draw () {
14 | this.clear().beginPath()
15 | this.strokeStyle(this.strokeColor)
16 | this.moveTo(this.vertex[0][0], this.vertex[0][1])
17 |
18 | for (let i = 1, len = this.vertex.length; i < len; i++) {
19 | this.lineTo(this.vertex[i][0], this.vertex[i][1])
20 | }
21 | this.closePath()
22 | // 路径闭合
23 | // if (this.options.strokeStyle) {
24 | // this.strokeStyle = strokeStyle;
25 | // this.lineWidth(this.options.width);
26 | // this.lineJoin('round');
27 | // this.stroke();
28 | // }
29 | if (this.strokeColor) {
30 | this.strokeStyle(this.strokeColor)
31 | this.stroke()
32 | }
33 | if (this.fillColor) {
34 | this.fillStyle(this.fillColor)
35 | this.fill()
36 | }
37 | }
38 | }
39 |
40 | export default Polygon
41 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/rect.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class Rect extends Shape {
4 | constructor(width, height, option) {
5 | super()
6 |
7 | this.width = width
8 | this.height = height
9 | this.option = option || {}
10 | }
11 |
12 | draw() {
13 | if (this.option.fillStyle) {
14 | this.fillStyle(this.option.fillStyle)
15 | this.fillRect(0, 0, this.width, this.height)
16 | }
17 |
18 | if (this.option.strokeStyle) {
19 | this.strokeStyle(this.option.strokeStyle)
20 | if (typeof this.option.lineWidth === 'number') {
21 | this.lineWidth(this.option.lineWidth)
22 | }
23 | this.strokeRect(0, 0, this.width, this.height)
24 | }
25 | }
26 |
27 | clone() {
28 | return new Rect(this.width, this.height, {
29 | fillStyle: this.option.fillStyle,
30 | strokeStyle: this.option.strokeStyle,
31 | lineWidth: this.option.lineWidth
32 | })
33 | }
34 | }
35 |
36 | export default Rect
37 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/rounded-rect.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class RoundedRect extends Shape {
4 | constructor (width, height, r, option) {
5 | super()
6 | this.option = Object.assign({
7 | lineWidth: 1,
8 | lt: true,
9 | rt: true,
10 | lb: true,
11 | rb: true
12 | }, option)
13 | this.r = r || 0
14 | this.width = width
15 | this.height = height
16 | }
17 |
18 | draw () {
19 | const width = this.width,
20 | height = this.height,
21 | r = this.r
22 |
23 | const ax = r,
24 | ay = 0,
25 | bx = width,
26 | by = 0,
27 | cx = width,
28 | cy = height,
29 | dx = 0,
30 | dy = height,
31 | ex = 0,
32 | ey = 0
33 |
34 | this.beginPath()
35 |
36 | this.moveTo(ax, ay)
37 | if (this.option.rt) {
38 | this.arcTo(bx, by, cx, cy, r)
39 | } else {
40 | this.lineTo(bx, by)
41 | }
42 |
43 | if (this.option.rb) {
44 | this.arcTo(cx, cy, dx, dy, r)
45 | } else {
46 | this.lineTo(cx, cy)
47 | }
48 |
49 | if (this.option.lb) {
50 | this.arcTo(dx, dy, ex, ey, r)
51 | } else {
52 | this.lineTo(dx, dy)
53 | }
54 |
55 | if (this.option.lt) {
56 | this.arcTo(ex, ey, ax, ay, r)
57 | } else {
58 | this.lineTo(ex, ey)
59 | }
60 |
61 | if (this.option.fillStyle) {
62 | this.closePath()
63 | this.fillStyle(this.option.fillStyle)
64 | this.fill()
65 | }
66 |
67 | if (this.option.strokeStyle) {
68 | this.lineWidth(this.option.lineWidth)
69 | this.strokeStyle(this.option.strokeStyle)
70 | this.stroke()
71 | }
72 | }
73 | }
74 |
75 | export default RoundedRect
76 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/sector.js:
--------------------------------------------------------------------------------
1 | import Shape from './shape'
2 |
3 | class Sector extends Shape {
4 | constructor (r, from, to, option) {
5 | super()
6 |
7 | this.option = option || {}
8 | this.r = r
9 | this.from = from
10 | this.to = to
11 | }
12 |
13 | draw () {
14 | this.beginPath()
15 | .moveTo(0, 0)
16 | .arc(0, 0, this.r, this.from, this.to)
17 | .closePath()
18 | .fillStyle(this.option.fillStyle)
19 | .fill()
20 | .strokeStyle(this.option.strokeStyle)
21 | .lineWidth(this.option.lineWidth)
22 | .stroke()
23 | }
24 | }
25 |
26 | export default Sector
27 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/shape/shape.js:
--------------------------------------------------------------------------------
1 | import Graphics from '../graphics'
2 |
3 | class Shape extends Graphics {
4 | // constructor() {
5 | // super()
6 | // }
7 |
8 | draw () {
9 |
10 | }
11 |
12 | render (ctx) {
13 | this.clear()
14 | this.draw()
15 | super.render(ctx)
16 | }
17 | }
18 |
19 | export default Shape
20 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/sprite.js:
--------------------------------------------------------------------------------
1 | import DisplayObject from './display-object'
2 | import util from '../../common/util'
3 | import Bitmap from './bitmap'
4 |
5 | class Sprite extends DisplayObject {
6 | constructor (option) {
7 | super()
8 | this.option = option
9 | const len = this.option.imgs.length
10 | let count = 0
11 | const firstImg = this.option.imgs[0]
12 | this.imgMap = {}
13 |
14 | if (util.isWeapp) {
15 | this.option.imgs.forEach(img => {
16 | util.getImageInWx(img, (result) => {
17 | this.imgMap[img] = result.img
18 | count++
19 | if (count === len) {
20 | this.img = this.imgMap[firstImg]
21 | this.rect = [0, 0, 0, 0]
22 | }
23 | })
24 | }
25 | )
26 | } else {
27 | if (typeof firstImg === 'string') {
28 | const len = this.option.imgs.length
29 | let loadedCount = 0
30 | this.option.imgs.forEach(src => {
31 | if (Bitmap.cache[src]) {
32 | this.imgMap[src] = Bitmap.cache[src]
33 | loadedCount++
34 | if (loadedCount === len) {
35 | this.img = this.imgMap[firstImg]
36 | this.rect = [0, 0, 0, 0]
37 | }
38 | } else {
39 | const img = util.isWegame ? wx.createImage() : new window.Image()
40 | img.onload = () => {
41 | this.imgMap[src] = img
42 | loadedCount++
43 | if (loadedCount === len) {
44 | this.img = this.imgMap[firstImg]
45 | this.rect = [0, 0, 0, 0]
46 | }
47 | Bitmap.cache[src] = img
48 | }
49 | img.src = src
50 | }
51 | })
52 | } else if (firstImg instanceof Bitmap) {
53 | this.rect = [0, 0, 0, 0]
54 | this.img = firstImg.img
55 | } else {
56 | this.rect = [0, 0, 0, 0]
57 | this.img = firstImg
58 | }
59 | }
60 |
61 | this.x = option.x || 0
62 | this.y = option.y || 0
63 | this.currentFrameIndex = 0
64 | this.animationFrameIndex = 0
65 | this.currentAnimation = option.currentAnimation || null
66 |
67 | this.interval = 1e3 / option.framerate
68 |
69 | this.paused = false
70 | this.animationEnd = option.animationEnd || function () {}
71 | if (this.currentAnimation) {
72 | if (option.playOnce) {
73 | this.gotoAndPlayOnce(this.currentAnimation)
74 | } else {
75 | this.gotoAndPlay(this.currentAnimation)
76 | }
77 | }
78 | }
79 |
80 | play () {
81 | this.paused = false
82 | }
83 |
84 | pause () {
85 | this.paused = true
86 | }
87 |
88 | reset () {
89 | this.currentFrameIndex = 0
90 | this.animationFrameIndex = 0
91 | }
92 |
93 | updateFrame () {
94 | if (!this.paused) {
95 | let opt = this.option
96 | this.dt = Date.now() - this.startTime
97 | let frames = opt.animations[this.currentAnimation].frames
98 | const len = frames.length
99 | const index = Math.floor(this.dt / this.interval % len)
100 | this.rect = opt.frames[ frames[ index ] ]
101 | const rectLen = this.rect.length
102 |
103 | rectLen > 4 && (this.originX = this.rect[2] * this.rect[4])
104 | rectLen > 5 && (this.originY = this.rect[3] * this.rect[5])
105 | if (rectLen > 6) {
106 | const img = this.option.imgs[this.rect[6]]
107 | this.img = typeof img === 'string' ? this.imgMap[img] : img
108 | }
109 |
110 | if (index === len - 1 && (!this.endTime || Date.now() - this.endTime > this.interval)) {
111 | this.endTime = Date.now()
112 | this.animationEnd()
113 | if (this._willDestroy) {
114 | this.destroy()
115 | }
116 | }
117 | }
118 | }
119 |
120 | gotoAndPlay (animation) {
121 | this.paused = false
122 | this.reset()
123 | this.currentAnimation = animation
124 | this.startTime = Date.now()
125 | }
126 |
127 | gotoAndStop (animation) {
128 | this.reset()
129 | this.paused = true
130 | this.currentAnimation = animation
131 | var opt = this.option
132 | var frames = opt.animations[this.currentAnimation].frames
133 | this.rect = opt.frames[frames[this.animationFrameIndex]]
134 | const rect = this.rect
135 | this.width = rect[2]
136 | this.height = rect[3]
137 | const rectLen = rect.length
138 | rectLen > 4 && (this.originX = rect[2] * rect[4])
139 | rectLen > 5 && (this.originY = rect[3] * rect[5])
140 | if (rectLen > 6) {
141 | const img = this.option.imgs[rect[6]]
142 | this.img = typeof img === 'string' ? this.imgMap[img] : img
143 | }
144 | }
145 |
146 | gotoAndPlayOnce (animation) {
147 | this.gotoAndPlay(animation)
148 | this._willDestroy = true
149 | }
150 | }
151 |
152 | export default Sprite
153 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/text.js:
--------------------------------------------------------------------------------
1 | import DisplayObject from './display-object'
2 | import util from '../../common/util'
3 |
4 | let measureCtx
5 |
6 | if (util.isWeapp) {
7 | measureCtx = wx.createCanvasContext('measure0')
8 | } else if (typeof document !== 'undefined') {
9 | measureCtx = document.createElement('canvas').getContext('2d')
10 | }
11 |
12 | class Text extends DisplayObject {
13 | constructor (text, option) {
14 | super()
15 |
16 | this.text = text
17 | option = option || {}
18 | this.font = option.font || '10px sans-serif'
19 | this.fontSize = option.fontSize || 10
20 | this.textAlign = option.textAlign || 'left'
21 | this.baseline = option.baseline || 'top'
22 | // color 待废弃
23 | this.fillStyle = option.fillStyle || option.color
24 | this.lineWidth = option.lineWidth || 1
25 | this.strokeStyle = option.strokeStyle
26 | }
27 |
28 | getWidth () {
29 | if (!measureCtx) {
30 | if (util.isWegame) {
31 | measureCtx = wx.createCanvas().getContext('2d')
32 | }
33 | }
34 |
35 | if (this.font) {
36 | measureCtx.font = this.font
37 | }
38 | return measureCtx.measureText(this.text).width
39 | }
40 | }
41 |
42 | export default Text
43 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/we-stage.js:
--------------------------------------------------------------------------------
1 | import Group from './group.js'
2 | import Renderer from '../render/renderer.js'
3 | import WxHitRender from '../render/wx-hit-render.js'
4 | import Event from '../base/event.js'
5 |
6 | class WeStage extends Group {
7 | constructor (width, height, id, page) {
8 | super()
9 |
10 | const component = page.selectComponent('#' + id)
11 | component.setData({
12 | width,
13 | height
14 | })
15 | component.stage = this
16 | const canvasId = component.getCaxCanvasId()
17 |
18 | const ctx = wx.createCanvasContext(canvasId, component)
19 | const hitCtx = wx.createCanvasContext(canvasId + 'Hit', component)
20 | this.renderer = new Renderer(ctx, width, height)
21 | this._hitRender = new WxHitRender(hitCtx, component, canvasId)
22 | this._overObject = null
23 | this.ctx = ctx
24 | this.hitAABB = true
25 | this.width = width
26 | this.height = height
27 | }
28 |
29 | touchStartHandler (evt) {
30 | const p1 = evt.changedTouches[0]
31 |
32 | evt.stageX = Math.round(p1.x * this.scaleX)
33 | evt.stageY = Math.round(p1.y * this.scaleY)
34 |
35 | this._getObjectUnderPoint(evt, (obj) => {
36 | this.willDragObject = obj
37 | this._mouseDownX = evt.stageX
38 | this._mouseDownY = evt.stageY
39 | this.preStageX = evt.stageX
40 | this.preStageY = evt.stageY
41 | })
42 | }
43 |
44 | touchMoveHandler (evt) {
45 | const p1 = evt.changedTouches[0]
46 |
47 | evt.stageX = Math.round(p1.x * this.scaleX)
48 | evt.stageY = Math.round(p1.y * this.scaleY)
49 |
50 | this._getObjectUnderPoint(evt, (obj) => {
51 | let mockEvt = new Event()
52 | mockEvt.stageX = evt.stageX
53 | mockEvt.stageY = evt.stageY
54 | mockEvt.pureEvent = evt
55 |
56 | if (this.willDragObject) {
57 | mockEvt.type = 'drag'
58 | mockEvt.dx = mockEvt.stageX - this.preStageX
59 | mockEvt.dy = mockEvt.stageY - this.preStageY
60 | this.preStageX = mockEvt.stageX
61 | this.preStageY = mockEvt.stageY
62 | this.willDragObject.dispatchEvent(mockEvt)
63 | }
64 |
65 | if (obj) {
66 | if (this._overObject === null) {
67 | this._overObject = obj
68 | } else {
69 | if (obj.id !== this._overObject.id) {
70 | this._overObject = obj
71 | } else {
72 | mockEvt.type = 'touchmove'
73 | obj.dispatchEvent(mockEvt)
74 | }
75 | }
76 | } else if (this._overObject) {
77 | this._overObject = null
78 | }
79 | })
80 | }
81 |
82 | touchEndHandler (evt) {
83 | const p1 = evt.changedTouches[0]
84 |
85 | evt.stageX = Math.round(p1.x * this.scaleX)
86 | evt.stageY = Math.round(p1.y * this.scaleY)
87 |
88 | let mockEvt = new Event()
89 | mockEvt.stageX = evt.stageX
90 | mockEvt.stageY = evt.stageY
91 |
92 | mockEvt.pureEvent = evt
93 |
94 | this._getObjectUnderPoint(evt, (obj) => {
95 | this._mouseUpX = evt.stageX
96 | this._mouseUpY = evt.stageY
97 |
98 | this.willDragObject = null
99 | this.preStageX = null
100 | this.preStageY = null
101 |
102 | if (obj && Math.abs(this._mouseDownX - this._mouseUpX) < 30 && Math.abs(this._mouseDownY - this._mouseUpY) < 30) {
103 | mockEvt.type = 'tap'
104 | obj.dispatchEvent(mockEvt)
105 | }
106 | })
107 | }
108 |
109 | _handleMouseOut (evt) {
110 | this.dispatchEvent({
111 | pureEvent: evt,
112 | type: 'mouseout',
113 | stageX: evt.stageX,
114 | stageY: evt.stageY
115 | })
116 | }
117 |
118 | _getObjectUnderPoint (evt, cb) {
119 | const list = this.renderer.getHitRenderList(this)
120 | if (this.hitAABB) {
121 | return this._hitRender.hitAABB(list, evt, cb)
122 | } else {
123 | this._hitRender.clear()
124 | this._hitRender.hit(list, evt, cb, list.length - 1)
125 | }
126 | }
127 |
128 | on (type, cb) {
129 | switch (type) {
130 | case 'touchstart':
131 | this.touchStart = cb
132 | break
133 | case 'touchmove':
134 | this.touchMove = cb
135 | break
136 | case 'touchend':
137 | this.touchEnd = cb
138 | break
139 | }
140 | }
141 |
142 | update () {
143 | this.renderer.update(this)
144 | }
145 | }
146 |
147 | export default WeStage
148 |
--------------------------------------------------------------------------------
/packages/cax/src/render/display/wegame-canvas.js:
--------------------------------------------------------------------------------
1 | let wegameCanvas = null
2 | if (typeof wx !== 'undefined') {
3 | // 在开放数据域的环境下,用`wx.getSharedCanvas`创建canvas
4 | if (wx.getSharedCanvas) {
5 | wegameCanvas = wx.getSharedCanvas()
6 | } else if (wx.createCanvas) {
7 | wegameCanvas = wx.createCanvas()
8 | }
9 | }
10 |
11 | export default wegameCanvas
12 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/README.md:
--------------------------------------------------------------------------------
1 | ## Interface design reference
2 |
3 | * https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter
4 | * http://www.runoob.com/cssref/css3-pr-filter.html
5 | * https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function
6 |
7 | ## Usage
8 |
9 | ``` js
10 | const bitmap = new cax.Bitmap(img)
11 | bitmap.filter('brightness(0.5)')
12 |
13 | //or filter rect of bitmap
14 | //bitmap.filter('brightness(0.5)'), { x: 0, y: 0, width: 80, height: 80 }
15 | ```
16 |
17 | ## Todo
18 |
19 | horizontalFlip 和 verticalFlip 来制作镜像 spritesheet
20 |
21 | ``` js
22 | new cax.Sprite({
23 | imgs:[bitmap.flipX()]
24 | })
25 |
26 | //bitmap.flipX()
27 | //flipX return的就是 this.cacheCanvas
28 | //bitmap.filpY()
29 | ```
30 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/blur.js:
--------------------------------------------------------------------------------
1 | import { createImageData } from './create-image-data'
2 |
3 | export function blur (pixels, diameter) {
4 | diameter = Math.abs(diameter)
5 | if (diameter <= 1) return pixels
6 | var radius = diameter / 2
7 | var len = Math.ceil(diameter) + (1 - (Math.ceil(diameter) % 2))
8 | var weights = new Float32Array(len)
9 | var rho = (radius + 0.5) / 3
10 | var rhoSq = rho * rho
11 | var gaussianFactor = 1 / Math.sqrt(2 * Math.PI * rhoSq)
12 | var rhoFactor = -1 / (2 * rho * rho)
13 | var wsum = 0
14 | var middle = Math.floor(len / 2)
15 | for (var i = 0; i < len; i++) {
16 | var x = i - middle
17 | var gx = gaussianFactor * Math.exp(x * x * rhoFactor)
18 | weights[i] = gx
19 | wsum += gx
20 | }
21 | for (var i = 0; i < weights.length; i++) {
22 | weights[i] /= wsum
23 | }
24 | return separableConvolve(pixels, weights, weights, false)
25 | }
26 |
27 | function separableConvolve (pixels, horizWeights, vertWeights, opaque) {
28 | return horizontalConvolve(
29 | verticalConvolve(pixels, vertWeights, opaque),
30 | horizWeights, opaque
31 | )
32 | }
33 |
34 | function horizontalConvolve (pixels, weightsVector, opaque) {
35 | var side = weightsVector.length
36 | var halfSide = Math.floor(side / 2)
37 |
38 | var src = pixels.data
39 | var sw = pixels.width
40 | var sh = pixels.height
41 |
42 | var w = sw
43 | var h = sh
44 | var output = createImageData(w, h)
45 | var dst = output.data
46 |
47 | var alphaFac = opaque ? 1 : 0
48 |
49 | for (var y = 0; y < h; y++) {
50 | for (var x = 0; x < w; x++) {
51 | var sy = y
52 | var sx = x
53 | var dstOff = (y * w + x) * 4
54 | var r = 0, g = 0, b = 0, a = 0
55 | for (var cx = 0; cx < side; cx++) {
56 | var scy = sy
57 | var scx = Math.min(sw - 1, Math.max(0, sx + cx - halfSide))
58 | var srcOff = (scy * sw + scx) * 4
59 | var wt = weightsVector[cx]
60 | r += src[srcOff] * wt
61 | g += src[srcOff + 1] * wt
62 | b += src[srcOff + 2] * wt
63 | a += src[srcOff + 3] * wt
64 | }
65 | dst[dstOff] = r
66 | dst[dstOff + 1] = g
67 | dst[dstOff + 2] = b
68 | dst[dstOff + 3] = a + alphaFac * (255 - a)
69 | }
70 | }
71 | return output
72 | }
73 |
74 | function verticalConvolve (pixels, weightsVector, opaque) {
75 | var side = weightsVector.length
76 | var halfSide = Math.floor(side / 2)
77 |
78 | var src = pixels.data
79 | var sw = pixels.width
80 | var sh = pixels.height
81 |
82 | var w = sw
83 | var h = sh
84 | var output = createImageData(w, h)
85 | var dst = output.data
86 |
87 | var alphaFac = opaque ? 1 : 0
88 |
89 | for (var y = 0; y < h; y++) {
90 | for (var x = 0; x < w; x++) {
91 | var sy = y
92 | var sx = x
93 | var dstOff = (y * w + x) * 4
94 | var r = 0, g = 0, b = 0, a = 0
95 | for (var cy = 0; cy < side; cy++) {
96 | var scy = Math.min(sh - 1, Math.max(0, sy + cy - halfSide))
97 | var scx = sx
98 | var srcOff = (scy * sw + scx) * 4
99 | var wt = weightsVector[cy]
100 | r += src[srcOff] * wt
101 | g += src[srcOff + 1] * wt
102 | b += src[srcOff + 2] * wt
103 | a += src[srcOff + 3] * wt
104 | }
105 | dst[dstOff] = r
106 | dst[dstOff + 1] = g
107 | dst[dstOff + 2] = b
108 | dst[dstOff + 3] = a + alphaFac * (255 - a)
109 | }
110 | }
111 | return output
112 | };
113 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/brightness.js:
--------------------------------------------------------------------------------
1 | export function brightness (pixels, adjustment) {
2 | const data = pixels.data
3 | const length = data.length
4 | for (let i = 0; i < length; i += 4) {
5 | data[i] += adjustment
6 | data[i + 1] += adjustment
7 | data[i + 2] += adjustment
8 | }
9 | return pixels
10 | }
11 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/colorize.js:
--------------------------------------------------------------------------------
1 | export function colorize (pixels, option) {
2 | const data = pixels.data
3 | const length = data.length
4 | const hex = (option.color.charAt(0) === '#') ? option.color.substr(1) : option.color
5 | const colorRGB = {
6 | r: parseInt(hex.substr(0, 2), 16),
7 | g: parseInt(hex.substr(2, 2), 16),
8 | b: parseInt(hex.substr(4, 2), 16)
9 | }
10 |
11 | for (let i = 0; i < length; i += 4) {
12 | data[i] -= (data[i] - colorRGB.r) * (option.amount)
13 | data[i + 1] -= (data[i + 1] - colorRGB.g) * (option.amount)
14 | data[i + 2] -= (data[i + 2] - colorRGB.b) * (option.amount)
15 | }
16 |
17 | return pixels
18 | };
19 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/contrast.js:
--------------------------------------------------------------------------------
1 | export function contrast (pixels, contrast) {
2 | const data = pixels.data
3 | const length = data.length
4 | const factor = (259 * (contrast + 255)) / (255 * (259 - contrast))
5 |
6 | for (let i = 0; i < length; i += 4) {
7 | data[i] = factor * (data[i] - 128) + 128
8 | data[i + 1] = factor * (data[i + 1] - 128) + 128
9 | data[i + 2] = factor * (data[i + 2] - 128) + 128
10 | }
11 |
12 | return pixels
13 | };
14 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/create-image-data.js:
--------------------------------------------------------------------------------
1 | let tmpCtx = null
2 |
3 | if (typeof document !== 'undefined') {
4 | tmpCtx = document.createElement('canvas').getContext('2d')
5 | } else if (typeof wx !== 'undefined' && wx.createCanvas) {
6 | tmpCtx = wx.createCanvas().getContext('2d')
7 | }
8 |
9 | export function createImageData (w, h) {
10 | return tmpCtx.createImageData(w, h)
11 | }
12 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/gamma.js:
--------------------------------------------------------------------------------
1 | export function gamma (pixels, adjustment) {
2 | const data = pixels.data
3 | const length = data.length
4 | for (let i = 0; i < length; i += 4) {
5 | data[i] = Math.pow(data[i] / 255, adjustment) * 255
6 | data[i + 1] = Math.pow(data[i + 1] / 255, adjustment) * 255
7 | data[i + 2] = Math.pow(data[i + 2] / 255, adjustment) * 255
8 | }
9 | return pixels
10 | };
11 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/grayscale.js:
--------------------------------------------------------------------------------
1 | export function grayscale (pixels, adjustment) {
2 | const data = pixels.data
3 | const length = data.length
4 | for (let i = 0; i < length; i += 4) {
5 | let r = data[i]
6 | let g = data[i + 1]
7 | let b = data[i + 2]
8 |
9 | // CIE luminance for the RGB
10 | // The human eye is bad at seeing red and blue, so we de-emphasize them.
11 | let v = 0.2126 * r + 0.7152 * g + 0.0722 * b
12 | data[i] = r + (v - r) * adjustment
13 | data[i + 1] = g + (v - g) * adjustment
14 | data[i + 2] = b + (v - b) * adjustment
15 | }
16 | return pixels
17 | };
18 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/index.js:
--------------------------------------------------------------------------------
1 |
2 | import { invert } from './invert'
3 | import { blur } from './blur'
4 | import { brightness } from './brightness'
5 | import { contrast } from './contrast'
6 | import { grayscale } from './grayscale'
7 | import { sepia } from './sepia'
8 | import { threshold } from './threshold'
9 | import { gamma } from './gamma'
10 | import { colorize } from './colorize'
11 |
12 | export function filter (pixels, name) {
13 | if (typeof name === 'string') {
14 | let type = name.split('(')[0]
15 | let num = getNumber(name)
16 | switch (type) {
17 | case 'invert':
18 | return invert(pixels, num)
19 | case 'brightness':
20 | return brightness(pixels, -255 + num * 255)
21 | case 'blur':
22 | return blur(pixels, num)
23 | case 'contrast':
24 | return contrast(pixels, -255 + num * 255)
25 | case 'grayscale':
26 | return grayscale(pixels, num)
27 | case 'sepia':
28 | return sepia(pixels, num)
29 | case 'threshold':
30 | return threshold(pixels, num)
31 | case 'gamma':
32 | return gamma(pixels, num)
33 | }
34 | } else {
35 | switch (name.type) {
36 | case 'colorize':
37 | return colorize(pixels, name)
38 | }
39 | }
40 | }
41 |
42 | function getNumber (str) {
43 | str = str.replace(/(invert)|(brightness)|(blur)|(contrast)|(grayscale)|(sepia)|(threshold)|(gamma)?\(/g, '').replace(')', '')
44 | if (str.indexOf('%') !== -1) {
45 | return Number(str.replace('%', '')) / 100
46 | } else if (str.indexOf('px') !== -1) {
47 | return Number(str.replace('px', ''))
48 | } else {
49 | return Number(str)
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/invert.js:
--------------------------------------------------------------------------------
1 |
2 | export function invert (pixels, ratio) {
3 | const d = pixels.data
4 | ratio = ratio === undefined ? 1 : ratio
5 | for (var i = 0; i < d.length; i += 4) {
6 | d[i] = d[i] + ratio * (255 - 2 * d[i])
7 | d[i + 1] = d[i + 1] + ratio * (255 - 2 * d[i + 1])
8 | d[i + 2] = d[i + 2] + ratio * (255 - 2 * d[i + 2])
9 | }
10 | return pixels
11 | }
12 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/sepia.js:
--------------------------------------------------------------------------------
1 | export function sepia (pixels, adjustment) {
2 | const data = pixels.data
3 | const length = data.length
4 | for (let i = 0; i < length; i += 4) {
5 | const r = data[i]
6 | const g = data[i + 1]
7 | const b = data[i + 2]
8 |
9 | const sr = (r * 0.393) + (g * 0.769) + (b * 0.189)
10 | const sg = (r * 0.349) + (g * 0.686) + (b * 0.168)
11 | const sb = (r * 0.272) + (g * 0.534) + (b * 0.131)
12 |
13 | data[i] = r + (sr - r) * adjustment
14 | data[i + 1] = g + (sg - g) * adjustment
15 | data[i + 2] = b + (sb - b) * adjustment
16 | }
17 |
18 | return pixels
19 | };
20 |
--------------------------------------------------------------------------------
/packages/cax/src/render/filter/threshold.js:
--------------------------------------------------------------------------------
1 | export function threshold (pixels, threshold) {
2 | const data = pixels.data
3 | const length = data.length
4 | for (let i = 0; i < length; i += 4) {
5 | const r = data[i]
6 | const g = data[i + 1]
7 | const b = data[i + 2]
8 | const v = (0.2126 * r + 0.7152 * g + 0.0722 * b >= threshold) ? 255 : 0
9 | data[i] = data[i + 1] = data[i + 2] = v
10 | }
11 | return pixels
12 | };
13 |
--------------------------------------------------------------------------------
/packages/cax/src/render/render/render.js:
--------------------------------------------------------------------------------
1 | class Render {
2 | render () {
3 |
4 | }
5 |
6 | renderGraphics () {
7 |
8 | }
9 |
10 | clear () {
11 |
12 | }
13 | }
14 |
15 | export default Render
16 |
--------------------------------------------------------------------------------
/packages/cax/src/render/render/renderer.js:
--------------------------------------------------------------------------------
1 | import CanvasRender from '../render/canvas-render'
2 | import Group from '../display/group.js'
3 |
4 | class Renderer {
5 | constructor (canvasOrContext, width, height) {
6 | this.renderList = []
7 | if (arguments.length === 3) {
8 | this.renderer = new CanvasRender(canvasOrContext, width, height)
9 | this.width = width
10 | this.height = height
11 | } else {
12 | this.renderer = new CanvasRender(canvasOrContext)
13 | this.width = canvasOrContext.width
14 | this.height = canvasOrContext.height
15 | }
16 | this.ctx = this.renderer.ctx
17 | }
18 |
19 | update (stage) {
20 | this.renderer.clear(this.ctx, this.width, this.height)
21 | this.renderer.render(this.ctx, stage)
22 | this.ctx.draw && this.ctx.draw()
23 | }
24 |
25 | getHitRenderList (stage) {
26 | const objs = this.renderList
27 | objs.length = 0
28 | this.computeMatrix(stage)
29 | return objs
30 | }
31 |
32 | computeMatrix (stage) {
33 | for (var i = 0, len = stage.children.length; i < len; i++) {
34 | this._computeMatrix(stage.children[i])
35 | }
36 | }
37 |
38 | initComplex (o) {
39 | o.complexCompositeOperation = this._getCompositeOperation(o)
40 | o.complexAlpha = this._getAlpha(o, 1)
41 | }
42 |
43 | _computeMatrix (o, mtx) {
44 | if (!o.isVisible()) {
45 | return
46 | }
47 | if (mtx && !o.fixed) {
48 | o._matrix.initialize(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
49 | } else {
50 | o._matrix.initialize(1, 0, 0, 1, 0, 0)
51 | }
52 |
53 | o._matrix.appendTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.originX, o.originY)
54 |
55 | if (o instanceof Group) {
56 | var list = o.children,
57 | len = list.length,
58 | i = 0
59 | for (; i < len; i++) {
60 | this._computeMatrix(list[i], o._matrix)
61 | }
62 | } else {
63 | // if (o instanceof Graphics) {
64 | // this.renderList.push(o)
65 | // this.initComplex(o)
66 | // } else {
67 | o.initAABB()
68 | // if (this.isInStage(o)) {
69 | this.renderList.push(o)
70 | this.initComplex(o)
71 | // }
72 | // }
73 | }
74 | }
75 |
76 | _getCompositeOperation (o) {
77 | if (o.compositeOperation) return o.compositeOperation
78 | if (o.parent) return this._getCompositeOperation(o.parent)
79 | }
80 |
81 | _getAlpha (o, alpha) {
82 | var result = o.alpha * alpha
83 | if (o.parent) {
84 | return this._getAlpha(o.parent, result)
85 | }
86 | return result
87 | }
88 |
89 | isInStage (o) {
90 | return this.collisionBetweenAABB(o.AABB, this.stage.AABB)
91 | }
92 |
93 | collisionBetweenAABB (AABB1, AABB2) {
94 | var maxX = AABB1[0] + AABB1[2]
95 | if (maxX < AABB2[0]) return false
96 | var minX = AABB1[0]
97 | if (minX > AABB2[0] + AABB2[2]) return false
98 | var maxY = AABB1[1] + AABB1[3]
99 | if (maxY < AABB2[1]) return false
100 | var minY = AABB1[1]
101 | if (minY > AABB2[1] + AABB2[3]) return false
102 | return true
103 | }
104 | }
105 |
106 | export default Renderer
107 |
--------------------------------------------------------------------------------
/packages/cax/src/render/render/wx-hit-render.js:
--------------------------------------------------------------------------------
1 |
2 | import Graphics from '../display/graphics.js'
3 | import Render from './render.js'
4 | import Event from '../base/event.js'
5 | import Sprite from '../display/sprite.js'
6 | import Bitmap from '../display/bitmap.js'
7 | import Text from '../display/text.js'
8 |
9 | class WxHitRender extends Render {
10 | constructor (ctx, component, canvasId) {
11 | super()
12 |
13 | this.ctx = ctx
14 | this._isWeapp = true
15 | this._component = component
16 | this._hitCanvasId = canvasId + 'Hit'
17 |
18 | this.disableEvents = ['mouseover', 'mouseout', 'mousemove', 'touchmove']
19 | }
20 |
21 | clear () {
22 | this.ctx.clearRect(0, 0, 2, 2)
23 | }
24 |
25 | hitAABB (list, evt, cb) {
26 | const len = list.length
27 | for (let i = len - 1; i >= 0; i--) {
28 | let o = list[i]
29 |
30 | if (o.AABB && this.checkPointInAABB(evt.stageX, evt.stageY, o.AABB)) {
31 | this._dispatchEvent(o, evt)
32 | cb(o)
33 | return o
34 | }
35 | }
36 | }
37 |
38 | checkPointInAABB (x, y, AABB) {
39 | let minX = AABB[0]
40 | if (x < minX) return false
41 | let minY = AABB[1]
42 | if (y < minY) return false
43 | let maxX = minX + AABB[2]
44 | if (x > maxX) return false
45 | let maxY = minY + AABB[3]
46 | if (y > maxY) return false
47 | return true
48 | }
49 |
50 | hit (list, evt, cb, current) {
51 | const ctx = this.ctx
52 | const obj = list[current]
53 | const mtx = obj._hitMatrix.initialize(1, 0, 0, 1, 0, 0)
54 | ctx.save()
55 | mtx.appendTransform(obj.x - evt.stageX, obj.y - evt.stageY, obj.scaleX, obj.scaleY, obj.rotation, obj.skewX, obj.skewY, obj.originX, obj.originY)
56 | ctx.globalCompositeOperation = obj.complexCompositeOperation
57 | ctx.globalAlpha = obj.complexAlpha
58 | ctx.setTransform(mtx.a, mtx.b, mtx.c, mtx.d, mtx.tx, mtx.ty)
59 | if (obj instanceof Graphics) {
60 | obj.render(ctx)
61 | } else if (obj instanceof Sprite && obj.rect) {
62 | obj.updateFrame()
63 | const rect = obj.rect
64 | ctx.drawImage(obj.img, rect[0], rect[1], rect[2], rect[3], 0, 0, rect[2], rect[3])
65 | } else if (obj instanceof Bitmap && obj.rect) {
66 | const bRect = obj.rect
67 | ctx.drawImage(obj.img, bRect[0], bRect[1], bRect[2], bRect[3], 0, 0, bRect[2], bRect[3])
68 | } else if (obj instanceof Text) {
69 | ctx.font = obj.font
70 | ctx.fillStyle = obj.color
71 | ctx.textAlign = obj.textAlign
72 | ctx.fillText(obj.text, 0, 0)
73 | }
74 | ctx.restore()
75 | current--
76 | ctx.draw(false, () => {
77 | wx.canvasGetImageData({
78 | canvasId: this._hitCanvasId,
79 | x: 0,
80 | y: 0,
81 | width: 1,
82 | height: 1,
83 | success: (res) => {
84 | if (res.data[3] > 1) {
85 | this._dispatchEvent(obj, evt)
86 | cb(obj)
87 | } else {
88 | if (current > -1) { this.hit(list, evt, cb, current) }
89 | }
90 | }
91 | }, this._component)
92 | })
93 | }
94 |
95 | _dispatchEvent (obj, evt) {
96 | if (this.disableEvents.indexOf(evt.type) !== -1) return
97 | let mockEvt = new Event()
98 | mockEvt.stageX = evt.stageX
99 | mockEvt.stageY = evt.stageY
100 | mockEvt.pureEvent = evt
101 | mockEvt.type = evt.type
102 | obj.dispatchEvent(mockEvt)
103 | }
104 | }
105 |
106 | export default WxHitRender
107 |
--------------------------------------------------------------------------------
/packages/cax/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 | var packageJSON = require('./package.json');
4 | /**
5 | * Env
6 | * Get npm lifecycle event to identify the environment
7 | */
8 | var ENV = process.env.npm_lifecycle_event;
9 |
10 | var config = {
11 | entry: './examples/todo/main.js',
12 | output: {
13 | // path: __dirname,
14 | path: './examples/todo/',
15 | filename: 'bundler.js'
16 | },
17 | module: {
18 | loaders: [
19 | {
20 | loader: 'babel-loader',
21 | test: /\.js$/,
22 | query: {
23 | presets: 'env',
24 | "plugins": [
25 | "transform-class-properties",
26 | ["transform-react-jsx", {
27 | "pragma": "Cax.h"
28 | }]
29 | ]
30 | },
31 |
32 | }
33 | ]
34 | },
35 | plugins: [
36 | // Avoid publishing files when compilation fails
37 | new webpack.NoEmitOnErrorsPlugin()
38 | ],
39 | stats: {
40 | // Nice colored output
41 | colors: true
42 | },
43 | // Create Sourcemaps for the bundle
44 | // devtool: 'source-map',
45 | };
46 |
47 | if (ENV === 'build' || ENV === 'build-min') {
48 | config = {
49 | entry: {
50 | 'cax': './src/index.js'
51 | },
52 | output: {
53 | // path: __dirname,
54 | path: path.resolve(__dirname, './dist/'),
55 | library: 'cax',
56 | libraryTarget: 'umd',
57 | filename: '[name].js'
58 | //umdNamedDefine: true
59 | },
60 | module: {
61 | loaders: [
62 | {
63 | loader: 'babel-loader',
64 | test: path.join(__dirname, 'src'),
65 | query: {
66 | presets: 'env'
67 | },
68 | }
69 | ]
70 | },
71 | plugins: [
72 | // Avoid publishing files when compilation fails
73 | new webpack.BannerPlugin(" cax v" + packageJSON.version + "\r\n By https://github.com/dntzhang \r\n Github: https://github.com/dntzhang/cax\r\n MIT Licensed."),
74 | new webpack.NoEmitOnErrorsPlugin()
75 | ],
76 | stats: {
77 | // Nice colored output
78 | colors: true
79 | },
80 | // Create Sourcemaps for the bundle
81 | // devtool: 'source-map',
82 | };
83 |
84 | if (ENV === 'build-min') {
85 | config.plugins.push(new webpack.optimize.UglifyJsPlugin({
86 | compress: {
87 | warnings: false,
88 | screw_ie8: false
89 | },
90 | mangle: {
91 | screw_ie8: false
92 | },
93 | output: { screw_ie8: false }
94 | }));
95 | config.entry = {
96 | 'cax.min': './src/index.js'
97 | };
98 | }
99 | } else if (ENV === 'todomvc') {
100 | config.entry = './' + ENV + '/js/main.js';
101 | config.output.path = './' + ENV + '/';
102 | } else {
103 | config.entry = path.resolve(__dirname, './examples/' + ENV + '/main.js');
104 | config.output.path = path.resolve(__dirname, './examples/' + ENV + '/');
105 | }
106 |
107 |
108 | //console.log(ENV);
109 |
110 | module.exports = config;
111 |
--------------------------------------------------------------------------------
/packages/to/README.EN.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](./README.md)
2 |
3 | # to2to [](https://www.npmjs.com/package/to2to)
4 |
5 | > Simple and lightweight javascript animation engine
6 |
7 | * [Simple DEMO](http://dntzhang.github.io/cax/packages/to/examples/simple/)
8 | * [Animation DEMO](https://dntzhang.github.io/cax/packages/to/examples/to/)
9 | * [To + Shape](https://dntzhang.github.io/cax/packages/cax/examples/to-shape/)
10 | * [Animate DEMO](https://dntzhang.github.io/cax/packages/cax/examples/to-animate/)
11 | * [Swing DEMO](https://dntzhang.github.io/cax/packages/to/examples/swing/)
12 |
13 | ## Features
14 |
15 | * Simple API and lightweight
16 | * Support cycle movement
17 | * Support parallel and serial motion
18 | * Can be used in all environments (Canvas, DOM, WebGL, SVG, Object..)
19 | * Support weapp, wegame and browsers with the same simple API
20 |
21 | ## Getting Started
22 |
23 | Get to2to through npm or cdn:
24 |
25 | ``` bash
26 | npm i to2to
27 | ```
28 |
29 | * [https://unpkg.com/to2to@latest/dist/to.min.js](https://unpkg.com/to2to@latest/dist/to.min.js)
30 | * [https://unpkg.com/to2to@latest/dist/to.js](https://unpkg.com/to2to@latest/dist/to.js)
31 |
32 | Usage:
33 |
34 | ``` js
35 | import To from 'to2to'
36 |
37 | const ele = document.querySelector('#animateEle')
38 |
39 | To.get({ rotate: 0, x: 0, y: 0 })
40 | .to({ rotate: 720, x: 200, y: 200 }, 1600, To.easing.elasticInOut)
41 | .progress(function () {
42 | ele.style.transform = `translate(${this.x}px, ${this.y}px) rotate(${this.rotate}deg)`
43 | })
44 | .start()
45 | ```
46 |
47 | ## Using to2to in cax
48 |
49 | Cax has built-in to capability to write motion effects in a continuous way.
50 |
51 | ``` js
52 | const easing = cax.To.easing.elasticInOut
53 |
54 | cax.To.get(bitmap)
55 | .to({ y: 340, rotation: 240 }, 2000, easing)
56 | .begin(() => {
57 | console.log("Task one has began!")
58 | })
59 | .progress(() => {
60 | console.log("Task one is progressing!")
61 | })
62 | .end(() => {
63 | console.log("Task one has completed!")
64 | })
65 | .wait(500)
66 | .to()
67 | .rotation(0, 1400, easing)
68 | .begin(() => {
69 | console.log("Task two has began!")
70 | })
71 | .progress(() => {
72 | console.log("Task two is progressing!")
73 | })
74 | .end(() => {
75 | console.log("Task two has completed!")
76 | })
77 | .start();
78 | ```
79 |
80 | * `to` and `to` are parallel
81 | * `to` and `wait` are serial
82 | * The serial between `to` and `to` is serial with the next `to` and `to`
83 |
84 | Of course, `set` can also be used to support the movement of arbitrary attributes, such as:
85 |
86 | ``` js
87 | .set('y', 240, 2000, cax.easing.elasticInOut)
88 | ```
89 |
90 | Equate to:
91 |
92 | ``` js
93 | .y(240, 2000, cax.easing.elasticInOut)
94 | ```
95 |
96 | If you want circular motion, you can use the `cycle` method:
97 |
98 | ``` js
99 | cax.To.get(bitmap)
100 | .to()
101 | .y(340, 2000, cax.easing.elasticInOut)
102 | .to
103 | .y(0, 2000, cax.easing.elasticInOut)
104 | .cycle()
105 | .start()
106 | ```
107 |
108 | [Motion Demo](http://dntzhang.github.io/cax/packages/cax/examples/to/)
109 |
110 |
111 | ## Custom animation
112 |
113 | You can use custom animation through the `animate` method:
114 |
115 | ``` js
116 | const stage = new cax.Stage(300, 400, 'body')
117 | const bitmap = new cax.Bitmap('./wepay-diy.jpg', function () {
118 | var eio = To.easing.elasticInOut
119 | To.get(bitmap).animate('rubber').start()
120 | })
121 |
122 | bitmap.x = 150
123 | bitmap.y = 200
124 | bitmap.originX = 40
125 | bitmap.originY = 40
126 | stage.add(bitmap)
127 |
128 | cax.setInterval(() => {
129 | stage.update()
130 | }, 16)
131 | ```
132 |
133 | to2to has a few custom animations built in:
134 |
135 | * rubber
136 | * bounceIn
137 | * flipInX
138 | * zoomOut
139 |
140 | ## Extend custom animation
141 |
142 | Built in is not enough to use? do-it-yourselfery!
143 |
144 | For example, `customAnimation` is implemented through the following:
145 |
146 | ``` js
147 | To.extend('customAnimation', [['to', ['scaleX', {
148 | '0': 0,
149 | '1': 400,
150 | '2': To.easing.elasticInOut
151 | }], ['scaleY', {
152 | '0': 0,
153 | '1': 400
154 | }]]])
155 | ```
156 |
157 | An index of 2 easing can be transmitted or transmitted without representing a linear uniform change.
158 |
159 | Using the defined custom animation:
160 |
161 | ```js
162 | To.get(obj).animate('customAnimation').start()
163 | ```
164 |
165 | # Who is using cax?
166 |
167 |  
168 |
169 | ## License
170 |
171 | MIT
172 |
--------------------------------------------------------------------------------
/packages/to/README.md:
--------------------------------------------------------------------------------
1 | 简体中文 | [English](./README.EN.md)
2 |
3 | # to2to [](https://www.npmjs.com/package/to2to)
4 |
5 | > 简单轻量的 Javascript 运动引擎
6 |
7 | * [Simple DEMO](http://dntzhang.github.io/cax/packages/to/examples/simple/)
8 | * [Animation DEMO](https://dntzhang.github.io/cax/packages/to/examples/to/)
9 | * [To + Shape](https://dntzhang.github.io/cax/packages/cax/examples/to-shape/)
10 | * [Animate DEMO](https://dntzhang.github.io/cax/packages/cax/examples/to-animate/)
11 | * [Swing DEMO](https://dntzhang.github.io/cax/packages/to/examples/swing/)
12 |
13 | to2to 中文念 '兔兔兔',作为 cax 内置的运动套件独立出一个package ,因为它本身可以和平台环境运动对象无关。既可运动 dom,也可运动 cax 内置对象,也可运动对象字面量。众所周知,运动需要循环的 tick 去不断执行偏移函数,小程序,小游戏和web各浏览器的 相应的 API 还是有差异,to2to 抹平了这些差异,让你使用同样的api可以在不同环境畅快运动。
14 |
15 | ## 特性
16 |
17 | * 超轻量级的代码体积
18 | * 支持周期运动
19 | * 支持并行与串行运动
20 | * 运动一切(Canvas、DOM、WebGL、SVG、Object..)
21 | * 支持小程序、小游戏以及 Web 浏览器用相同简介的 API 运动
22 |
23 | ## 一分钟入门 to2to 使用
24 |
25 | 通过 npm 安装或者 cdn 下载下来在 HTML 引用该脚本:
26 |
27 | ``` bash
28 | npm i to2to
29 | ```
30 |
31 | * [https://unpkg.com/to2to@latest/dist/to.min.js](https://unpkg.com/to2to@latest/dist/to.min.js)
32 | * [https://unpkg.com/to2to@latest/dist/to.js](https://unpkg.com/to2to@latest/dist/to.js)
33 |
34 | 使用:
35 |
36 | ``` js
37 | import To from 'to2to'
38 |
39 | const ele = document.querySelector('#animateEle')
40 |
41 | To.get({ rotate: 0, x: 0, y: 0 })
42 | .to({ rotate: 720, x: 200, y: 200 }, 1600, To.easing.elasticInOut)
43 | .progress(function () {
44 | ele.style.transform = `translate(${this.x}px, ${this.y}px) rotate(${this.rotate}deg)`
45 | })
46 | .start()
47 | ```
48 |
49 | ## 在 cax 中使用 to2to
50 |
51 | cax 内置了 to 的能力以连缀的方式写运动效果:
52 |
53 | ``` js
54 | const easing = cax.To.easing.elasticInOut
55 |
56 | cax.To.get(bitmap)
57 | .to({ y: 340, rotation: 240 }, 2000, easing)
58 | .begin(() => {
59 | console.log("Task one has began!")
60 | })
61 | .progress(() => {
62 | console.log("Task one is progressing!")
63 | })
64 | .end(() => {
65 | console.log("Task one has completed!")
66 | })
67 | .wait(500)
68 | .to()
69 | .rotation(0, 1400, easing)
70 | .begin(() => {
71 | console.log("Task two has began!")
72 | })
73 | .progress(() => {
74 | console.log("Task two is progressing!")
75 | })
76 | .end(() => {
77 | console.log("Task two has completed!")
78 | })
79 | .start();
80 | ```
81 |
82 | * `to` 和 `to` 之间的是并行
83 | * `to` 和 `wait` 之前的是串行
84 | * `to` 和 `to` 之间的 与 下一个 `to` 和 `to` 之间的是串行
85 |
86 | 有点绕,但是很直观,慢慢体会。
87 |
88 | 如果想要循环播放的话可以使用 `cycle` 方法:
89 |
90 | ``` js
91 | cax.To.get(bitmap)
92 | .to()
93 | .y(340, 2000, cax.easing.elasticInOut)
94 | .to
95 | .y(0, 2000, cax.easing.elasticInOut)
96 | .cycle()
97 | .start()
98 | ```
99 |
100 | [运动演示地址](http://dntzhang.github.io/cax/packages/cax/examples/to/)
101 |
102 | ## 自定义动画
103 |
104 | 通过 `animate` 方法可以使用自定义的动画:
105 |
106 | ``` js
107 | const stage = new cax.Stage(300, 400, 'body')
108 | const bitmap = new cax.Bitmap('./wepay-diy.jpg', function () {
109 | var eio = To.easing.elasticInOut
110 | To.get(bitmap).animate('rubber').start()
111 | })
112 |
113 | bitmap.x = 150
114 | bitmap.y = 200
115 | bitmap.originX = 40
116 | bitmap.originY = 40
117 | stage.add(bitmap)
118 |
119 | cax.setInterval(() => {
120 | stage.update()
121 | }, 16)
122 | ```
123 |
124 | to2to 内置了少数几个自定义动画
125 |
126 | * rubber
127 | * bounceIn
128 | * flipInX
129 | * zoomOut
130 |
131 | ## 扩展自定义动画
132 |
133 | 内置的不够用?自己动手丰衣足食:
134 |
135 | 比如 `customAnimation` 就是通过下面实现的:
136 |
137 | ``` js
138 | To.extend('customAnimation', [['to', ['scaleX', {
139 | '0': 0,
140 | '1': 400,
141 | '2': To.easing.elasticInOut
142 | }], ['scaleY', {
143 | '0': 0,
144 | '1': 400
145 | }]]])
146 | ```
147 |
148 | 索引为 2 的 easing 可以传可不传,不传代表线性匀速变化。
149 |
150 | 使用刚刚定义的自定义动画:
151 |
152 | ```js
153 | To.get(obj).animate('customAnimation').start()
154 | ```
155 |
156 | ## 谁在使用?
157 |
158 |  
159 |
160 | ## License
161 |
162 | MIT
163 |
--------------------------------------------------------------------------------
/packages/to/examples/animate/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Motion Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/packages/to/examples/animate/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/to/examples/animate/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/to/examples/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | To Simple Demo
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/packages/to/examples/simple/main.js:
--------------------------------------------------------------------------------
1 | import To from '../../src/index.js'
2 |
3 | const ele = document.querySelector('#animateEle')
4 |
5 | ele.onload = function(){
6 |
7 | To.get({ rotate: 0, x: 0, y: 0 })
8 | .to({ rotate: 720, x: 200, y: 200 }, 1600, To.easing.elasticInOut)
9 | .progress(function () {
10 | ele.style.transform = `translate(${this.x}px, ${this.y}px) rotate(${this.rotate}deg)`
11 | })
12 | .start()
13 | }
14 |
15 | ele.src = ele.src
--------------------------------------------------------------------------------
/packages/to/examples/simple/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/to/examples/simple/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/to/examples/swing/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Motion Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
80 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/packages/to/examples/swing/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/to/examples/swing/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/to/examples/to/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Cax Motion Demo
8 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/packages/to/examples/to/wepay-diy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dntzhang/cax/f52df2b6822447b6c35d2efb6a50c1b6a86b1e54/packages/to/examples/to/wepay-diy.jpg
--------------------------------------------------------------------------------
/packages/to/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "to2to",
3 | "version": "1.0.4",
4 | "description": "Simple and lightweight javascript animation engine - 小程序、小游戏和 Web 通用运动引擎",
5 | "main": "dist/to.js",
6 | "scripts": {
7 | "lint": "eslint src",
8 | "fix": "eslint src --fix",
9 | "fixwegame": "eslint ../cax-wegame --fix",
10 | "fixweapp": "eslint ../cax-weapp --fix",
11 | "lint:example": "eslint example --fix",
12 | "nest": "webpack -w",
13 | "clip": "webpack -w",
14 | "clip-transform": "webpack -w",
15 | "map": "webpack -w",
16 | "dag": "webpack -w",
17 | "clip-transform-to": "webpack -w",
18 | "cache": "webpack -w",
19 | "bar-x": "webpack -w",
20 | "bar": "webpack -w",
21 | "to": "webpack -w",
22 | "rect": "webpack -w",
23 | "radar": "webpack -w",
24 | "line": "webpack -w",
25 | "lines": "webpack -w",
26 | "circle": "webpack -w",
27 | "doughnut": "webpack -w",
28 | "cylinder": "webpack -w",
29 | "simple": "webpack -w",
30 | "scoped-style": "webpack -w",
31 | "on": "webpack -w",
32 | "render-to-string": "webpack -w",
33 | "newly-added": "webpack -w",
34 | "undo": "webpack -w",
35 | "slot": "webpack -w",
36 | "plugin": "webpack -w",
37 | "todo": "webpack -w",
38 | "ref": "webpack -w",
39 | "tree": "webpack -w",
40 | "perfs": "webpack -w",
41 | "life-cycle": "webpack -w",
42 | "pagination": "webpack -w",
43 | "build": "webpack",
44 | "hyperscript": "webpack -w",
45 | "select": "webpack -w",
46 | "build-min": "webpack",
47 | "test": "karma start test/karma.conf.js"
48 | },
49 | "devDependencies": {
50 | "eslint": "^4.3.0",
51 | "eslint-config-standard": "^10.2.1",
52 | "eslint-plugin-import": "^2.7.0",
53 | "eslint-plugin-node": "^5.1.1",
54 | "eslint-plugin-promise": "^3.5.0",
55 | "eslint-plugin-standard": "^3.0.1",
56 | "babel-core": "^6.26.0",
57 | "babel-loader": "^7.1.4",
58 | "babel-plugin-transform-class-properties": "^6.24.1",
59 | "babel-plugin-transform-react-jsx": "^6.24.1",
60 | "babel-preset-env": "^1.6.1",
61 | "chai": "^4.1.2",
62 | "jasmine-core": "^2.5.2",
63 | "karma": "^1.3.0",
64 | "karma-babel-preprocessor": "^7.0.0",
65 | "karma-chai-sinon": "^0.1.5",
66 | "karma-chrome-launcher": "^2.0.0",
67 | "karma-coverage": "^1.0.0",
68 | "karma-jasmine": "^1.1.0",
69 | "karma-mocha": "^1.1.1",
70 | "karma-mocha-reporter": "^2.0.4",
71 | "karma-sauce-launcher": "^1.1.0",
72 | "karma-sinon": "^1.0.5",
73 | "karma-source-map-support": "^1.2.0",
74 | "karma-sourcemap-loader": "^0.3.6",
75 | "karma-webpack": "^2.0.4",
76 | "mocha": "^5.0.4",
77 | "node-libs-browser": "^0.5.3",
78 | "sinon": "^4.5.0",
79 | "sinon-chai": "^3.0.0",
80 | "webpack": "^3.4.1"
81 | },
82 | "repository": {
83 | "type": "git",
84 | "url": "git+https://github.com/dntzhang/cax.git"
85 | },
86 | "keywords": [
87 | "canvas",
88 | "web",
89 | "weapp"
90 | ],
91 | "devEngines": {
92 | "node": "6.x || 7.x || 8.x",
93 | "npm": "3.x || 4.x || 5.x"
94 | },
95 | "author": "dntzhang",
96 | "license": "MIT",
97 | "bugs": {
98 | "url": "https://github.com/dntzhang/cax/issues/new"
99 | },
100 | "homepage": "http://dntzhang.github.io/cax"
101 | }
102 |
--------------------------------------------------------------------------------
/packages/to/src/animate.js:
--------------------------------------------------------------------------------
1 | import To from './to'
2 |
3 | To.extend('rubber', [['to', ['scaleX', {
4 | '0': 1.25,
5 | '1': 300
6 | }], ['scaleY', {
7 | '0': 0.75,
8 | '1': 300
9 | }]], ['to', ['scaleX', {
10 | '0': 0.75,
11 | '1': 100
12 | }], ['scaleY', {
13 | '0': 1.25,
14 | '1': 100
15 | }]], ['to', ['scaleX', {
16 | '0': 1.15,
17 | '1': 100
18 | }], ['scaleY', {
19 | '0': 0.85,
20 | '1': 100
21 | }]], ['to', ['scaleX', {
22 | '0': 0.95,
23 | '1': 150
24 | }], ['scaleY', {
25 | '0': 1.05,
26 | '1': 150
27 | }]], ['to', ['scaleX', {
28 | '0': 1.05,
29 | '1': 100
30 | }], ['scaleY', {
31 | '0': 0.95,
32 | '1': 100
33 | }]], ['to', ['scaleX', {
34 | '0': 1,
35 | '1': 250
36 | }], ['scaleY', {
37 | '0': 1,
38 | '1': 250
39 | }]]])
40 |
41 |
42 | To.extend('bounceIn', [['to', ['scaleX', {
43 | '0': 0,
44 | '1': 0
45 | }], ['scaleY', {
46 | '0': 0,
47 | '1': 0
48 | }]], ['to', ['scaleX', {
49 | '0': 1.35,
50 | '1': 200
51 | }], ['scaleY', {
52 | '0': 1.35,
53 | '1': 200
54 | }]], ['to', ['scaleX', {
55 | '0': 0.9,
56 | '1': 100
57 | }], ['scaleY', {
58 | '0': 0.9,
59 | '1': 100
60 | }]], ['to', ['scaleX', {
61 | '0': 1.1,
62 | '1': 100
63 | }], ['scaleY', {
64 | '0': 1.1,
65 | '1': 100
66 | }]], ['to', ['scaleX', {
67 | '0': 0.95,
68 | '1': 100
69 | }], ['scaleY', {
70 | '0': 0.95,
71 | '1': 100
72 | }]], ['to', ['scaleX', {
73 | '0': 1,
74 | '1': 100
75 | }], ['scaleY', {
76 | '0': 1,
77 | '1': 100
78 | }]]])
79 |
80 | To.extend('flipInX', [['to', ['rotateX', {
81 | '0': -90,
82 | '1': 0
83 | }]], ['to', ['rotateX', {
84 | '0': 20,
85 | '1': 300
86 | }]], ['to', ['rotateX', {
87 | '0': -20,
88 | '1': 300
89 | }]], ['to', ['rotateX', {
90 | '0': 10,
91 | '1': 300
92 | }]], ['to', ['rotateX', {
93 | '0': -5,
94 | '1': 300
95 | }]], ['to', ['rotateX', {
96 | '0': 0,
97 | '1': 300
98 | }]]])
99 |
100 |
101 | To.extend('zoomOut', [['to', ['scaleX', {
102 | '0': 0,
103 | '1': 400
104 | }], ['scaleY', {
105 | '0': 0,
106 | '1': 400
107 | }]]])
--------------------------------------------------------------------------------
/packages/to/src/index.js:
--------------------------------------------------------------------------------
1 | import To from './to'
2 | import './animate'
3 | import TWEEN from './tween'
4 |
5 | To.easing = {
6 | linear: TWEEN.Easing.Linear.None
7 | };
8 |
9 | ['Quadratic',
10 | 'Cubic',
11 | 'Quartic',
12 | 'Quintic',
13 | 'Sinusoidal',
14 | 'Exponential',
15 | 'Circular',
16 | 'Elastic',
17 | 'Back',
18 | 'Bounce'].forEach(item => {
19 | const itemLower = item.toLowerCase()
20 | To.easing[itemLower + 'In'] = TWEEN.Easing[item].In
21 | To.easing[itemLower + 'Out'] = TWEEN.Easing[item].Out
22 | To.easing[itemLower + 'InOut'] = TWEEN.Easing[item].InOut
23 | })
24 |
25 |
26 | module.exports = To
--------------------------------------------------------------------------------
/packages/to/src/raf-interval.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * raf-interval v0.3.0 By dntzhang
3 | * Github: https://github.com/dntzhang/raf-interval
4 | * MIT Licensed.
5 | */
6 |
7 | if (!Date.now) {
8 | Date.now = function now () {
9 | return new Date().getTime()
10 | }
11 | }
12 |
13 | let queue = [],
14 | id = -1,
15 | ticking = false,
16 | tickId = null,
17 | now = Date.now,
18 | lastTime = 0,
19 | vendors = ['ms', 'moz', 'webkit', 'o'],
20 | x = 0,
21 | isWeapp = typeof wx !== 'undefined' && typeof Page !== 'undefined',
22 | isWegame = typeof wx !== 'undefined' && typeof Page === 'undefined',
23 | isBrowser = typeof window !== 'undefined'
24 |
25 | let raf = isBrowser ? window.requestAnimationFrame : null
26 | let caf = isBrowser ? window.cancelAnimationFrame : null
27 |
28 | function mockRaf (callback, element) {
29 | let currTime = now()
30 | let timeToCall = Math.max(0, 16 - (currTime - lastTime))
31 | let id = setTimeout(function () {
32 | callback(currTime + timeToCall)
33 | }, timeToCall)
34 | lastTime = currTime + timeToCall
35 | return id
36 | }
37 |
38 | function mockCaf (id) {
39 | clearTimeout(id)
40 | }
41 |
42 | if (isBrowser) {
43 | window.setRafInterval = setRafInterval
44 | window.clearRafInterval = clearRafInterval
45 |
46 | for (; x < vendors.length && !window.requestAnimationFrame; ++x) {
47 | window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
48 | window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] ||
49 | window[vendors[x] + 'CancelRequestAnimationFrame']
50 | }
51 |
52 | if (!raf) {
53 | raf = mockRaf
54 | caf = mockCaf
55 | window.requestAnimationFrame = raf
56 | window.cancelAnimationFrame = caf
57 | }
58 | } else if (isWeapp) {
59 | raf = mockRaf
60 | caf = mockCaf
61 | } else if (isWegame) {
62 | raf = requestAnimationFrame
63 | caf = cancelAnimationFrame
64 | }
65 |
66 | export function setRafInterval (fn, interval) {
67 | id++
68 | queue.push({ id: id, fn: fn, interval: interval, lastTime: now() })
69 | if (!ticking) {
70 | let tick = function () {
71 | tickId = raf(tick)
72 | each(queue, function (item) {
73 | if (item.interval < 17 || now() - item.lastTime >= item.interval) {
74 | item.fn()
75 | item.lastTime = now()
76 | }
77 | })
78 | }
79 | ticking = true
80 | tick()
81 | }
82 | return id
83 | }
84 |
85 | export function clearRafInterval (id) {
86 | let i = 0,
87 | len = queue.length
88 |
89 | for (; i < len; i++) {
90 | if (id === queue[i].id) {
91 | queue.splice(i, 1)
92 | break
93 | }
94 | }
95 |
96 | if (queue.length === 0) {
97 | caf(tickId)
98 | ticking = false
99 | }
100 | }
101 |
102 | function each (arr, fn) {
103 | if (Array.prototype.forEach) {
104 | arr.forEach(fn)
105 | } else {
106 | let i = 0,
107 | len = arr.length
108 | for (; i < len; i++) {
109 | fn(arr[i], i)
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/packages/to/webpack.config.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var webpack = require('webpack');
3 | var packageJSON = require('./package.json');
4 | /**
5 | * Env
6 | * Get npm lifecycle event to identify the environment
7 | */
8 | var ENV = process.env.npm_lifecycle_event;
9 |
10 | var config = {
11 | entry: '',
12 | output: {
13 | // path: __dirname,
14 | path: '',
15 | filename: 'bundler.js'
16 | },
17 | module: {
18 | loaders: [
19 | {
20 | loader: 'babel-loader',
21 | test: /\.js$/,
22 | query: {
23 | presets: 'env',
24 | "plugins": [
25 | "transform-class-properties"
26 | ]
27 | },
28 |
29 | }
30 | ]
31 | },
32 | plugins: [
33 | // Avoid publishing files when compilation fails
34 | new webpack.NoEmitOnErrorsPlugin()
35 | ],
36 | stats: {
37 | // Nice colored output
38 | colors: true
39 | },
40 | // Create Sourcemaps for the bundle
41 | // devtool: 'source-map',
42 | };
43 |
44 | if(ENV === 'build'||ENV === 'build-min'){
45 | config = {
46 | entry: {
47 | 'to': './src/index.js'
48 | },
49 | output: {
50 | // path: __dirname,
51 | path: path.resolve(__dirname,'./dist/'),
52 | library:'To',
53 | libraryTarget: 'umd',
54 | filename: '[name].js'
55 | //umdNamedDefine: true
56 | },
57 | module: {
58 | loaders: [
59 | {
60 | loader: 'babel-loader',
61 | test: path.join(__dirname, 'src'),
62 | query: {
63 | presets: 'env'
64 | },
65 | }
66 | ]
67 | },
68 | plugins: [
69 | // Avoid publishing files when compilation fails
70 | new webpack.BannerPlugin(" to2to v"+packageJSON.version+" \r\n By https://github.com/dntzhang \r\n Github: https://github.com/dntzhang/cax\r\n MIT Licensed."),
71 | new webpack.NoEmitOnErrorsPlugin()
72 | ],
73 | stats: {
74 | // Nice colored output
75 | colors: true
76 | },
77 | // Create Sourcemaps for the bundle
78 | // devtool: 'source-map',
79 | };
80 |
81 | if(ENV === 'build-min'){
82 | config.plugins.push(new webpack.optimize.UglifyJsPlugin({
83 | compress: {
84 | warnings: false,
85 | screw_ie8 : false
86 | },
87 | mangle: {
88 | screw_ie8: false
89 | },
90 | output: { screw_ie8: false }
91 | }));
92 | config.entry = {
93 | 'to.min': './src/index.js'
94 | };
95 | }
96 | }else{
97 | config.entry = path.resolve(__dirname,'./examples/' + ENV + '/main.js');
98 | config.output.path = path.resolve(__dirname,'./examples/' + ENV + '/');
99 | }
100 |
101 |
102 | //console.log(ENV);
103 |
104 | module.exports = config;
105 |
--------------------------------------------------------------------------------
/tutorial/cax-matter.md:
--------------------------------------------------------------------------------
1 | # Cax + Matter-js 物理引擎结合使用
2 |
3 | 最初试过 box2dweb 与 [cax框架](https://github.com/dntzhang/cax) 结合使用,发现 box2dweb 的代码会导致 webpack 编译出的 cax 包模块执行顺序乱套。
4 | box2dweb 貌似也没有官方文档和维护地址,所以弃坑转战 Matter-js。
5 |
6 | Matter-js 是 Github 上最流行的 Web 2D 物理引擎,主要有如下特性:
7 |
8 | * 支持刚体、混合体、复合体
9 | * 支持凹凸多边形刚体
10 | * 支持刚体间约束条件
11 | * 内置睡眠与静止身体
12 | * 物理模拟时间加快变慢
13 | * 移动兼容(触摸事件和PC鼠标事件响应)
14 | * 物理性质(质量、面积、密度、动量守恒、摩擦阻力、重力、弹性或非碰撞检测以及恢复等)
15 |
16 | ## 开始结合 Cax 和 Matter-js
17 |
18 | ### 引入 js
19 |
20 | 先在 HTML 引入 matter-js 和 cax, 你可以通过 npm 或 cdn 获取 js:
21 |
22 | * [https://unpkg.com/matter-js](https://unpkg.com/matter-js)
23 | * [https://unpkg.com/cax](https://unpkg.com/cax)
24 |
25 | ### 准备工作
26 |
27 | 页面添加 Canvas
28 |
29 | ``` html
30 |
31 | ```
32 |
33 | 提前声明好变量:
34 |
35 | ``` js
36 | var Engine = Matter.Engine,
37 | Render = Matter.Render,
38 | World = Matter.World,
39 | Bodies = Matter.Bodies,
40 | Composites = Matter.Composites,
41 | Body = Matter.Body,
42 | Constraint = Matter.Constraint,
43 | MouseConstraint = Matter.MouseConstraint,
44 | Common = Matter.Common,
45 | Events = Matter.Events,
46 | Composite = Matter.Composite
47 | ```
48 |
49 | ### 创建刚体
50 |
51 | ```js
52 | Bodies.rectangle(100, 49, 800, 44, { isStatic: true })
53 | ```
54 |
55 | * 前四个参数分别代表 x y width height。需要注意的是 x 和 y 是矩形中心的坐标
56 | * `isStatic` 为 true 的话代表是静止刚体,不传或者传 false 为可运动刚体。
57 |
58 | ### 创建四面墙并添加到世界
59 |
60 | ```js
61 | // 创建引擎
62 | var engine = Engine.create();
63 |
64 | // 创建四面墙壁墙壁并添加到世界
65 | var offset = 10;
66 | World.add(engine.world, [
67 | Bodies.rectangle(400, 600 - offset, 800, offset * 2, { isStatic: true }),
68 | Bodies.rectangle(400, offset, 800, offset * 2, { isStatic: true }),
69 | Bodies.rectangle(offset, 300, offset * 2, 600, { isStatic: true }),
70 | Bodies.rectangle(800 - offset, 300, offset * 2, 600, { isStatic: true }),
71 | ]);
72 | ```
73 |
74 | ### 创建物体并添加到世界
75 |
76 | ``` js
77 | var stack = Composites.stack(20, 20, 6, 4, 0, 0, function (x, y) {
78 | if (Common.random() > 0.5) {
79 | return Bodies.rectangle(x, y, 64, 64, {
80 | bitmap: new cax.Bitmap("img/box.jpg")
81 | });
82 | } else {
83 | return Bodies.circle(x, y, 46, {
84 | desity: 0.0005,
85 | frictionAir: 0.06,
86 | friction: 0.01,
87 | bitmap: new cax.Bitmap("img/basketball.png"),
88 |
89 | });
90 | }
91 | });
92 |
93 | World.add(engine.world, stack);
94 | ```
95 |
96 | 通过`Composites.stack(xx, yy, columns, rows, columnGap, rowGap, callback)`可以用来创建物体堆。
97 | 参数xx,yy分别为物体堆中第一个物体的x和y坐标,columns和 rows分别为所要创建的物体堆的列数和行数,columnGap和rowGap分别为物体与物体之间的列间隙和行间隙,最后,由var body = callback(x, y, column, row, lastBody, i); 可以看出callback为生成的具体物体的方法。
98 |
99 | 看以看到,创建的时候挂在 bitmap 上去用户后续的渲染。
100 |
101 | ### 发动引擎
102 |
103 | ```js
104 | Engine.run(engine)
105 | ```
106 | ### 初始化渲染墙壁和物体
107 |
108 | ```js
109 | var bodies = Composite.allBodies(engine.world);
110 |
111 | for (var i = 0; i < bodies.length; i += 1) {
112 | var obj = bodies[i]
113 | if (obj.bitmap) {
114 | obj.bitmap.x = obj.position.x
115 | obj.bitmap.y = obj.position.y
116 | if (obj.label === 'Circle Body') {
117 | obj.bitmap.scaleX = obj.bitmap.scaleY = 92 / 128
118 | obj.bitmap.originX = 64
119 | obj.bitmap.originY = 64
120 | obj.bitmap.rotation = obj.angle * 180 / Math.PI
121 | } else {
122 | obj.bitmap.scaleX = obj.bitmap.scaleY = 64 / 200
123 | obj.bitmap.originX = 100
124 | obj.bitmap.originY = 100
125 | obj.bitmap.rotation = obj.angle * 180 / Math.PI
126 | }
127 | stage.add(obj.bitmap)
128 | }
129 | }
130 |
131 | //墙壁
132 | var topRect = new cax.Rect(800, 20, { fillStyle: '#2CB044' })
133 | stage.add(topRect)
134 | var bottomRect = new cax.Rect(800, 20, { fillStyle: '#2CB044' })
135 | bottomRect.y = 600 - 20
136 | stage.add(bottomRect)
137 | var leftTop = new cax.Rect(20, 600, { fillStyle: '#2CB044' })
138 | stage.add(leftTop)
139 | var rightRect = new cax.Rect(20, 600, { fillStyle: '#2CB044' })
140 | rightRect.x = 800 - 20
141 | stage.add(rightRect)
142 | ```
143 |
144 | * 通过 `Composite.allBodies` 可以拿到所以刚体
145 | * 通过设置 bitmap 的 scaleX 和 scaleY 可以使 刚体大小和纹理大小对应起来
146 |
147 | ### 更新渲染舞台
148 |
149 | ```js
150 | cax.setInterval(function () {
151 | var bodies = Composite.allBodies(engine.world);
152 | for (var i = 0; i < bodies.length; i += 1) {
153 | var obj = bodies[i]
154 | if (obj.bitmap) {
155 | obj.bitmap.x = obj.position.x
156 | obj.bitmap.y = obj.position.y
157 | obj.bitmap.rotation = obj.angle * 180 / Math.PI
158 | }
159 | }
160 |
161 | stage.update()
162 | }, 16)
163 | ```
164 |
165 | ### 添加 Matter-js 内置 Debug Canvas
166 |
167 | ```js
168 | var render = Render.create({
169 | element: document.body,
170 | engine: engine,
171 | options: {
172 | wireframes: false
173 | }
174 | });
175 | var renderOptions = render.options;
176 |
177 | renderOptions.wireframes = true;
178 | Render.run(render);
179 | ```
180 |
181 | 最终效果:
182 |
183 | 
184 |
185 | [【→ 在线演示】](https://dntzhang.github.io/cax/packages/cax/examples/matter/)
186 |
--------------------------------------------------------------------------------