├── .travis.yml ├── Gruntfile.js ├── LICENSE ├── README.md ├── dist ├── juggle-all.js └── juggle-all.min.js ├── gulpfile.js ├── juggle-delayedcall-test └── test.html ├── juggle-delayedcall ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-delayedcall.js │ └── juggle-delayedcall.min.js ├── package.json └── src │ ├── DelayedCall.js │ └── DelayedCallPool.js ├── juggle-event-test └── test.html ├── juggle-event ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-event.js │ └── juggle-event.min.js ├── package.json └── src │ ├── Event.js │ ├── EventDispatcher.js │ └── EventPool.js ├── juggle-help-test └── test.html ├── juggle-help ├── Gruntfile.js ├── dist │ ├── juggle-help.js │ └── juggle-help.min.js ├── package.json └── src │ └── Tools.js ├── juggle-http-test └── test.html ├── juggle-http ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-http.js │ └── juggle-http.min.js ├── package.json └── src │ ├── HttpClient.js │ └── HttpEventType.js ├── juggle-httpfilter-test └── test.html ├── juggle-httpfilter ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-httpfilter.js │ └── juggle-httpfilter.min.js ├── package.json └── src │ └── HttpFilter.js ├── juggle-juggler-test └── test.html ├── juggle-juggler ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-juggler.js │ └── juggle-juggler.min.js ├── package.json └── src │ ├── Juggler.js │ ├── JugglerEventType.js │ └── JugglerManager.js ├── juggle-module-test ├── body.html ├── body1.html ├── bottom.html ├── test.html └── top.html ├── juggle-module ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-module.js │ └── juggle-module.min.js ├── package.json └── src │ └── ModuleManager.js ├── juggle-mv-test └── test.html ├── juggle-mv ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-mv.js │ └── juggle-mv.min.js ├── package.json └── src │ └── ViewManager.js ├── juggle-resource-test ├── resource1.html ├── resource2.html └── test.html ├── juggle-resource ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-resource.js │ └── juggle-resource.min.js ├── package.json └── src │ ├── Loader.js │ ├── ResourceEventType.js │ └── ResourceManager.js ├── juggle-tween-test ├── DisplayObject.js └── test.html ├── juggle-tween ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-tween.js │ └── juggle-tween.min.js ├── package.json └── src │ ├── Transitions.js │ ├── Tween.js │ └── TweenPool.js ├── juggle-websocket-test └── test.html ├── juggle-websocket ├── Gruntfile.js ├── README.md ├── dist │ ├── juggle-websocket.js │ └── juggle-websocket.min.js ├── package.json └── src │ ├── WebSocketClient.js │ ├── WebSocketConfig.js │ └── WebSocketEventType.js ├── juggle.png ├── juggle.vsd ├── npm.txt ├── package.json └── test ├── html └── index.html └── tweentest.js /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "4.2" 4 | sudo: false 5 | addons: 6 | apt: 7 | packages: 8 | - xvfb 9 | install: 10 | - export DISPLAY=':99.0' 11 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 12 | before_script: 13 | - npm install -g gulp 14 | - npm install 15 | script: npm test 16 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'juggle-help/src/Tools.js',//无依赖 12 | 'juggle-event/src/Event.js',//依赖juggle-help 13 | 'juggle-event/src/EventPool.js',//依赖Event 14 | 'juggle-event/src/EventDispatcher.js',//依赖juggle-help,EventPool 15 | 'juggle-juggler/src/JugglerEventType.js',//无依赖 16 | 'juggle-juggler/src/Juggler.js',//依赖JugglerEventType,juggle-help 17 | 'juggle-juggler/src/JugglerManager.js',//依赖Juggler 18 | 'juggle-tween/src/Transitions.js',//无依赖 19 | 'juggle-tween/src/Tween.js',//依赖juggle-help,juggle-event,juggle-juggler,transitions 20 | 'juggle-tween/src/TweenPool.js',//依赖Tween,juggle-help 21 | 'juggle-delayedcall/src/DelayedCall.js',//依赖juggle-help,juggle-event,juggle-juggler 22 | 'juggle-delayedcall/src/DelayedCallPool.js',//DelayedCall,juggle-help 23 | 'juggle-websocket/src/WebSocketEventType.js',//无依赖 24 | 'juggle-websocket/src/WebSocketConfig.js',//无依赖 25 | 'juggle-websocket/src/WebSocketClient.js',//依赖WebSocketEventType,WebSocketConfig,juggle-event 26 | 'juggle-http/src/HttpEventType.js',//无依赖 27 | 'juggle-http/src/HttpClient.js',//依赖httpEventType,juggle-event 28 | 'juggle-resource/src/ResourceEventType.js',//无依赖 29 | 'juggle-resource/src/Loader.js',//resourceEventType,juggle-http,juggle-event 30 | 'juggle-resource/src/ResourceManager.js',//依赖resourceEventType,Loader 31 | 'juggle-mv/src/ViewManager.js',//无依赖 32 | 'juggle-module/src/ModuleManager.js',//依赖juggle-resource 33 | 'juggle-httpfilter/src/HttpFilter.js'//依赖juggle-http 34 | ], 35 | dest: 'dist/<%= pkg.name %>.js' 36 | } 37 | }, 38 | uglify: { 39 | build: { 40 | src: 'dist/<%= pkg.name %>.js', 41 | dest: 'dist/<%= pkg.name %>.min.js' 42 | } 43 | } 44 | }); 45 | grunt.loadNpmTasks('grunt-contrib-uglify'); 46 | grunt.loadNpmTasks('grunt-contrib-concat'); 47 | // 默认任务 48 | grunt.registerTask('default', ['concat', 'uglify']); 49 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 电霸儿 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # juggle 2 | 3 | [![Build Status](https://travis-ci.org/dianbaer/juggle.svg?branch=master)](https://travis-ci.org/dianbaer/juggle) 4 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/c787bc1d8f5045d1acad4164a5388084)](https://www.codacy.com/app/232365732/juggle?utm_source=github.com&utm_medium=referral&utm_content=dianbaer/juggle&utm_campaign=Badge_Grade) 5 | [![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) 6 | 7 | ## juggle是一个极简的、组件式的js框架。无依赖,完美闭包,灵活且适合渐进学习,可与任何框架整合。包含(支持冒泡的事件、Tween、MV框架、http、websocket、资源、模块)等组件,按需选择组件,不绑架开发者。 8 | 9 | 10 | ## juggle架构图及其依赖关系(深颜色的是核心组件强烈推荐) 11 | 12 | ![架构图](./juggle.png "juggle.png") 13 | 14 | ## allinone下载 15 | ``` 16 | npm install juggle-all 17 | ``` 18 | 19 | ## 核心组件介绍 20 | 21 | ------------- 22 | 23 | ### 1、juggle-event(支持冒泡的事件) 24 | 25 | **介绍**:支持冒泡的事件,可用于解除包含结构,树形结构的耦合性。支持监听事件、移除事件、派发事件、阻止冒泡、立即阻止。使用对象池减少垃圾回收。 26 | 27 | **优秀且需要注意的特性**: 28 | 29 | 1、支持冒泡,前提是冒泡对象有parent属性并且不为空,有isDisplayObject属性并且为true。 30 | 2、在派发事件的回调函数内将parent设置为null,不能阻止这一次parent接到这次事件 31 | 3、在派发事件某层级的回调函数内,移除这层级的监听或添加这层级的监听,是不会影响这次派发事件目标的改变。 32 | 4、但是如果在某层级的回调函数内,移除上层的监听或添加上层的监听,上层本轮会受到影响。 33 | 34 | **下载**: 35 | 36 | ``` 37 | npm install juggle-event 38 | ``` 39 | 40 | **使用场景**:开发UI组件库,封装任意组件时都可以使用。例如:juggle-http,juggle-websocket都是基于此事件,可以派发专有的自定义事件。 41 | 42 | **示例代码**: 43 | 44 | 1、继承事件类 45 | ```js 46 | function DisplayObj() { 47 | juggle.EventDispatcher.apply(this); 48 | } 49 | ``` 50 | 2、监听事件 51 | ```js 52 | obj.addEventListener("aaa", function(event){}, this); 53 | ``` 54 | 3、派发事件,派发类型为aaa,冒泡,携带数据bbb 55 | ```js 56 | obj.dispatchEventWith("aaa", true, "bbb"); 57 | ``` 58 | 4、事件Demo(双击test.html即可) 59 | 60 | [>>>>>>事件Demo](./juggle-event-test) 61 | 62 | ------------------ 63 | 64 | ### 2、juggle-juggler(时间轴总控) 65 | 66 | **介绍**:时间轴总控,支持添加动画,移除动画,每帧进行动画回调并携带与上一次调用的间隔毫秒数 67 | 68 | **优秀且需要注意的特性**: 69 | 70 | 1、回调中新加入的动画不能在这一次被调度,因为没有经历时间过程这是合理的 71 | 2、回调中移除的分两种可能,已经在本次调度的无影响,没有在本次调度的取消本次调度 72 | 73 | **下载**: 74 | 75 | ``` 76 | npm install juggle-juggler 77 | ``` 78 | 79 | **使用场景**:动画,每帧进行调用的业务逻辑,都可以使用。 80 | 81 | **示例代码**: 82 | 83 | 1、必须实现规定的advanceTime方法 84 | ```js 85 | function View() { 86 | this.advanceTime = function (time) { 87 | } 88 | } 89 | ``` 90 | 2、加入时间轴总控,每帧会调用advanceTime,并携带与上一次调用的间隔毫秒数 91 | ```js 92 | juggle.jugglerManager.juggler.add(new View()); 93 | ``` 94 | 3、时间轴总控Demo 95 | 96 | [>>>>>>时间轴总控Demo](./juggle-juggler-test) 97 | 98 | ----------------- 99 | 100 | ### 3、juggle-tween(缓动类) 101 | 102 | **介绍**:缓动类,支持17种过渡模式,每帧无误差精准定位,完美的平滑过渡。支持对象池减少垃圾回收。 103 | 104 | **优秀且需要注意的特性**: 105 | 106 | 1、每次调用都是开始值+(终点-起点)*(经过时间/总时间),这是最稳定的,没有任何误差 107 | 2、连续调度,每次完成时过剩的时间再次利用不浪费。 108 | 109 | **下载**: 110 | ``` 111 | npm install juggle-tween 112 | ``` 113 | **使用场景**:需要动画过渡的都可以使用。 114 | 115 | **示例代码**: 116 | 117 | 1、创建一个显示对象 118 | ```js 119 | function DisplayObject(obj) { 120 | this.obj = obj; 121 | this.xValue = 0; 122 | this.yValue = 0; 123 | this.getX = function () { 124 | return this.xValue; 125 | }; 126 | this.setX = function (value) { 127 | this.xValue = value; 128 | this.draw(); 129 | }; 130 | this.getY = function () { 131 | return this.yValue; 132 | }; 133 | this.setY = function (value) { 134 | this.yValue = value; 135 | this.draw(); 136 | }; 137 | this.draw = function () { 138 | this.obj.style.position = "absolute"; 139 | this.obj.style.top = this.yValue + "px"; 140 | this.obj.style.left = this.xValue + "px"; 141 | } 142 | } 143 | ``` 144 | 2、使用juggle-tween进行动画过渡 145 | ```js 146 | var display = new DisplayObject(document.getElementById("tween_div")); 147 | display.setX(100); 148 | display.setY(100); 149 | tween = juggle.tweenPool.fromPool(display, 2); 150 | tween.animate(display.getX, display.setX, 800); 151 | tween.animate(display.getY, display.setY, 400); 152 | juggle.jugglerManager.juggler.add(tween); 153 | ``` 154 | 3、Tween的Demo(双击test.html即可) 155 | 156 | [>>>>>>Tween的Demo](./juggle-tween-test) 157 | 158 | 4、Tween的Demo线上演示地址: 159 | 160 | [>>>>>>Tween的Demo线上演示地址](https://www.dianbaer.com/juggle-tween-test/test.html) 161 | 162 | ----------------- 163 | 164 | ### 4、juggle-delayedcall(延迟回调) 165 | 166 | **介绍**:一个绝对精准的延迟回调工具,支持设置回调间隔,回调次数(支持无限次数)。解决setInterval多次调用不精准的问题。使用对象池减少垃圾回收。 167 | 168 | **优秀且需要注意的特性**: 169 | 170 | 1、连续调度,每次完成时过剩的时间再次利用不浪费。调度时间间隔例如:1001毫秒,999毫秒这种模式。 171 | 172 | **下载**: 173 | ``` 174 | npm install juggle-delayedcall 175 | ``` 176 | **使用场景**:所有需要延迟回调的业务,替代setInterval。 177 | 178 | **示例代码**: 179 | 180 | 1、延迟回调例子,参数1延迟回调函数,每1秒回调一次,携带1111参数,重复5次后停止回调。 181 | ```js 182 | var delayedCall = juggle.delayedCallPool.fromPool(function(arg){}, 1, "1111"); 183 | delayedCall.mRepeatCount = 5; 184 | juggle.jugglerManager.juggler.add(delayedCall); 185 | ``` 186 | 187 | 2、延迟回调Demo(双击test.html即可) 188 | 189 | [>>>>>>延迟回调Demo](./juggle-delayedcall-test) 190 | 191 | ------------------ 192 | 193 | ### 5、juggle-mv(MV框架) 194 | 195 | **介绍**:一个MV框架解除数据源与视图控制器的耦合性,视图控制器之间的耦合性,严密的闭包封装,用户只需继承Proxy与Mediator即可开发MV模式的项目。 196 | 197 | **下载**: 198 | ``` 199 | npm install juggle-mv 200 | ``` 201 | **使用场景**:需要与服务器进行交互的web项目。 202 | 203 | **示例代码**: 204 | 205 | 1、继承Proxy作为数据代理,可以请求数据结果后广播消息。 206 | ```js 207 | function UserProxy() { 208 | //继承 209 | juggle.Proxy.apply(this); 210 | //获取数据然后广播 211 | this.getData = function () { 212 | this.notifyObservers(this.getNotification("test", "getData success")); 213 | }; 214 | } 215 | ``` 216 | 2、继承Mediator作为视图控制器,控制视图、调用数据源Proxy、关注数据源Proxy与视图控制器Mediator广播过来的消息并处理。 217 | ```js 218 | function IndexMediator() { 219 | //关注消息 220 | this.listNotificationInterests = ["test"]; 221 | //关注消息的处理 222 | this.handleNotification = function (data) { 223 | switch (data.name) { 224 | case "test": 225 | alert("IndexMediator接到数据" + data.body); 226 | break; 227 | } 228 | }; 229 | //继承 230 | juggle.Mediator.apply(this); 231 | } 232 | ``` 233 | 3、MV框架Demo(双击test.html即可) 234 | 235 | [>>>>>>MV框架Demo](./juggle-mv-test) 236 | 237 | --------------------------------------- 238 | 239 | ## 其他组件介绍 240 | 241 | ------ 242 | ### 1、juggle-websocket(简易封装,支持自定义事件派发的websocket客户端库) 243 | 244 | **下载**: 245 | ``` 246 | npm install juggle-websocket 247 | ``` 248 | **使用场景**:需要与服务器建立长连接,依赖服务器推送消息的web项目。 249 | 250 | **示例代码**: 251 | 252 | 1、websocket客户端与服务器示例 253 | 254 | [>>>>>>websocket客户端](./juggle-websocket-test) 255 | 256 | [>>>>>>websocket服务器](https://github.com/dianbaer/grain/tree/master/grain-threadwebsocket-test) 257 | 258 | 259 | ------ 260 | 261 | ### 2、juggle-http(简易封装,通用性很好的http客户端库) 262 | 263 | **下载**: 264 | ``` 265 | npm install juggle-http 266 | ``` 267 | **使用场景**:需要向服务器发送http请求的web项目。 268 | 269 | **示例代码**: 270 | 271 | 1、http客户端与服务器示例 272 | 273 | [>>>>>>http客户端](./juggle-http-test) 274 | 275 | [>>>>>>http服务器](https://github.com/dianbaer/grain/tree/master/grain-httpserver-test) 276 | 277 | 278 | ------------- 279 | 280 | ### 3、juggle-resource(支持加载多资源回调的资源库) 281 | 282 | **下载**: 283 | ``` 284 | npm install juggle-resource 285 | ``` 286 | 287 | **使用场景**:配合juggle-module使用。 288 | 289 | **示例代码**: 290 | 291 | 1、加载资源Demo 292 | 293 | [>>>>>>加载资源Demo](./juggle-resource-test) 294 | 295 | -------------- 296 | 297 | ### 4、juggle-module(模块库,前端模块化架构) 298 | 299 | **下载**: 300 | ``` 301 | npm install juggle-module 302 | ``` 303 | 304 | **示例代码**: 305 | 306 | 1、模块Demo 307 | 308 | [>>>>>>模块Demo](./juggle-module-test) 309 | 310 | ------------------- 311 | 312 | ## 更多详细介绍 313 | 314 | [>>>>>>juggle-event详细介绍](./juggle-event) 315 | 316 | [>>>>>>juggle-juggler详细介绍](./juggle-juggler) 317 | 318 | [>>>>>>juggle-tween详细介绍](./juggle-tween) 319 | 320 | [>>>>>>juggle-delayedcall详细介绍](./juggle-delayedcall) 321 | 322 | [>>>>>>juggle-mv详细介绍](./juggle-mv) 323 | 324 | [>>>>>>juggle-websocket详细介绍](./juggle-websocket) 325 | 326 | [>>>>>>juggle-http详细介绍](./juggle-http) 327 | 328 | [>>>>>>juggle-resource详细介绍](./juggle-resource) 329 | 330 | [>>>>>>juggle-module详细介绍](./juggle-module) 331 | 332 | ## juggle地址: 333 | 334 | [>>>>>>github](https://github.com/dianbaer/juggle) 335 | 336 | [>>>>>>码云](https://gitee.com/dianbaer/basic) 337 | 338 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var del = require('del'); 3 | var merge = require('merge-stream'); 4 | var concat = require('gulp-concat'); 5 | var rename = require('gulp-rename'); 6 | var uglify = require('gulp-uglify'); 7 | var gulpif = require('gulp-if'); 8 | var replace = require('gulp-replace'); 9 | var header = require('gulp-header'); 10 | var footer = require('gulp-footer'); 11 | var zip = require('gulp-zip'); 12 | var shell = require('gulp-shell'); 13 | var uitest = require('gulp-uitest'); 14 | var transformModule = require('gulp-transform-module'); 15 | var jshint = require('gulp-jshint'); 16 | var pkg = require('./package.json'); 17 | 18 | 19 | 20 | //test 21 | gulp.task('test', [], function () { 22 | return gulp 23 | .src('test/html/index.html') 24 | .pipe(uitest({ 25 | width: 600, 26 | height: 480, 27 | hidpi: false, 28 | useContentSize: true, 29 | show: false 30 | })); 31 | }); 32 | 33 | gulp.task('default', []); 34 | -------------------------------------------------------------------------------- /juggle-delayedcall-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /juggle-delayedcall/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/DelayedCall.js',//依赖juggle-help,juggle-event,juggle-juggler 12 | 'src/DelayedCallPool.js'//DelayedCall,juggle-help 13 | ], 14 | dest: 'dist/<%= pkg.name %>.js' 15 | } 16 | }, 17 | uglify: { 18 | build: { 19 | src: 'dist/<%= pkg.name %>.js', 20 | dest: 'dist/<%= pkg.name %>.min.js' 21 | } 22 | } 23 | }); 24 | grunt.loadNpmTasks('grunt-contrib-uglify'); 25 | grunt.loadNpmTasks('grunt-contrib-concat'); 26 | // 默认任务 27 | grunt.registerTask('default', ['concat', 'uglify']); 28 | }; -------------------------------------------------------------------------------- /juggle-delayedcall/README.md: -------------------------------------------------------------------------------- 1 | # juggle-delayedcall 2 | 3 | 4 | 5 | 6 | # juggle-delayedcall是一个精准的延迟回调类 7 | 8 | 9 | ### 特点: 10 | 11 | 12 | 1、连续调度,如果一次完成,剩余时间再次利用不浪费 13 | 14 | 15 | 16 | ### 依赖juggle-help,juggle-event,juggle-juggler 17 | 18 | 19 | ### 快速开始: 20 | 21 | 22 | npm install juggle-delayedcall 23 | 24 | 25 | ### 如何使用: 26 | 27 | ```html 28 | 29 | 30 | 31 | 32 | 33 | Title 34 | 35 | 36 | 37 | 38 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | ``` 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /juggle-delayedcall/dist/juggle-delayedcall.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | var jugglerEventType = window.juggle.jugglerEventType; 5 | var EventDispatcher = window.juggle.EventDispatcher; 6 | /** 7 | * 创建回调 8 | * @param call 回调函数 9 | * @param delay 间隔 10 | * @param args 携带参数 11 | * @constructor 12 | */ 13 | var DelayedCall = function (call, delay, args) { 14 | this.mCurrentTime = null; 15 | this.mTotalTime = null; 16 | this.mCall = null; 17 | this.mArgs = null; 18 | //重复次数,0为无限次数 19 | this.mRepeatCount = null; 20 | this.reset = function (call, delay, args) { 21 | if (tools.isNull(args)) { 22 | args = null; 23 | } 24 | this.mCurrentTime = 0; 25 | this.mTotalTime = Math.max(delay, 0.0001); 26 | this.mCall = call; 27 | this.mArgs = args; 28 | this.mRepeatCount = 1; 29 | return this; 30 | }; 31 | this.advanceTime = function (time) { 32 | var previousTime = this.mCurrentTime; 33 | this.mCurrentTime = Math.min(this.mTotalTime, this.mCurrentTime + time); 34 | if (this.mCurrentTime === this.mTotalTime) { 35 | if (this.mRepeatCount === 0 || this.mRepeatCount > 1) { 36 | if (this.mRepeatCount > 0) 37 | this.mRepeatCount -= 1; 38 | this.mCurrentTime = 0; 39 | if (this.mArgs === null) { 40 | this.mCall.call(this); 41 | } else { 42 | this.mCall.call(this, this.mArgs); 43 | } 44 | // 精确一点时间都不浪费 45 | this.advanceTime((previousTime + time) - this.mTotalTime); 46 | } else { 47 | //保存回调的函数和参数 48 | var call = this.mCall; 49 | var args = this.mArgs; 50 | this.dispatchEventWith(jugglerEventType.REMOVE_FROM_JUGGLER); 51 | call.call(this, args); 52 | } 53 | } 54 | }; 55 | /** 56 | * 如果mRepeatCount不会再减1,并且mCurrentTime也不会再改变了 57 | * @returns {boolean} 58 | */ 59 | this.isComplete = function () { 60 | return this.mRepeatCount === 1 && this.mCurrentTime === this.mTotalTime; 61 | }; 62 | this.reset(call, delay, args); 63 | EventDispatcher.apply(this); 64 | }; 65 | window.juggle.DelayedCall = DelayedCall; 66 | })(window); 67 | (function (window) { 68 | if (!window.juggle) window.juggle = {}; 69 | var tools = window.juggle.tools; 70 | var DelayedCall = window.juggle.DelayedCall; 71 | var DelayedCallPool = function () { 72 | this.sDelayedCallPool = []; 73 | 74 | this.fromPool = function (call, delay, args) { 75 | if (tools.isNull(args)) { 76 | args = null; 77 | } 78 | if (this.sDelayedCallPool.length) 79 | return this.sDelayedCallPool.pop().reset(call, delay, args); 80 | else { 81 | return new DelayedCall(call, delay, args); 82 | } 83 | }; 84 | this.toPool = function (delayedCall) { 85 | delayedCall.mCall = null; 86 | delayedCall.mArgs = null; 87 | this.sDelayedCallPool[this.sDelayedCallPool.length] = delayedCall; 88 | } 89 | }; 90 | window.juggle.delayedCallPool = new DelayedCallPool(); 91 | })(window); -------------------------------------------------------------------------------- /juggle-delayedcall/dist/juggle-delayedcall.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.juggle||(t.juggle={});var l=t.juggle.tools,e=t.juggle.jugglerEventType,i=t.juggle.EventDispatcher;t.juggle.DelayedCall=function(t,s,n){this.mCurrentTime=null,this.mTotalTime=null,this.mCall=null,this.mArgs=null,this.mRepeatCount=null,this.reset=function(t,e,i){return l.isNull(i)&&(i=null),this.mCurrentTime=0,this.mTotalTime=Math.max(e,1e-4),this.mCall=t,this.mArgs=i,this.mRepeatCount=1,this},this.advanceTime=function(t){var l=this.mCurrentTime;if(this.mCurrentTime=Math.min(this.mTotalTime,this.mCurrentTime+t),this.mCurrentTime===this.mTotalTime)if(0===this.mRepeatCount||this.mRepeatCount>1)this.mRepeatCount>0&&(this.mRepeatCount-=1),this.mCurrentTime=0,null===this.mArgs?this.mCall.call(this):this.mCall.call(this,this.mArgs),this.advanceTime(l+t-this.mTotalTime);else{var i=this.mCall,s=this.mArgs;this.dispatchEventWith(e.REMOVE_FROM_JUGGLER),i.call(this,s)}},this.isComplete=function(){return 1===this.mRepeatCount&&this.mCurrentTime===this.mTotalTime},this.reset(t,s,n),i.apply(this)}}(window),function(t){t.juggle||(t.juggle={});var l=t.juggle.tools,e=t.juggle.DelayedCall;t.juggle.delayedCallPool=new function(){this.sDelayedCallPool=[],this.fromPool=function(t,i,s){return l.isNull(s)&&(s=null),this.sDelayedCallPool.length?this.sDelayedCallPool.pop().reset(t,i,s):new e(t,i,s)},this.toPool=function(t){t.mCall=null,t.mArgs=null,this.sDelayedCallPool[this.sDelayedCallPool.length]=t}}}(window); -------------------------------------------------------------------------------- /juggle-delayedcall/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juggle-delayedcall", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "juggle-delayedcall.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/dianbaer/juggle" 12 | }, 13 | "keywords": [ 14 | "juggle","delayedcall" 15 | ], 16 | "author": "dianbaer", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "grunt": "^1.0.1", 20 | "grunt-contrib-concat": "^1.0.1", 21 | "grunt-contrib-uglify": "^3.0.1" 22 | }, 23 | "dependencies": { 24 | "juggle-help": "^1.0.0", 25 | "juggle-event": "^1.0.0", 26 | "juggle-juggler": "^1.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /juggle-delayedcall/src/DelayedCall.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | var jugglerEventType = window.juggle.jugglerEventType; 5 | var EventDispatcher = window.juggle.EventDispatcher; 6 | /** 7 | * 创建回调 8 | * @param call 回调函数 9 | * @param delay 间隔 10 | * @param args 携带参数 11 | * @constructor 12 | */ 13 | var DelayedCall = function (call, delay, args) { 14 | this.mCurrentTime = null; 15 | this.mTotalTime = null; 16 | this.mCall = null; 17 | this.mArgs = null; 18 | //重复次数,0为无限次数 19 | this.mRepeatCount = null; 20 | this.reset = function (call, delay, args) { 21 | if (tools.isNull(args)) { 22 | args = null; 23 | } 24 | this.mCurrentTime = 0; 25 | this.mTotalTime = Math.max(delay, 0.0001); 26 | this.mCall = call; 27 | this.mArgs = args; 28 | this.mRepeatCount = 1; 29 | return this; 30 | }; 31 | this.advanceTime = function (time) { 32 | var previousTime = this.mCurrentTime; 33 | this.mCurrentTime = Math.min(this.mTotalTime, this.mCurrentTime + time); 34 | if (this.mCurrentTime === this.mTotalTime) { 35 | if (this.mRepeatCount === 0 || this.mRepeatCount > 1) { 36 | if (this.mRepeatCount > 0) 37 | this.mRepeatCount -= 1; 38 | this.mCurrentTime = 0; 39 | if (this.mArgs === null) { 40 | this.mCall.call(this); 41 | } else { 42 | this.mCall.call(this, this.mArgs); 43 | } 44 | // 精确一点时间都不浪费 45 | this.advanceTime((previousTime + time) - this.mTotalTime); 46 | } else { 47 | //保存回调的函数和参数 48 | var call = this.mCall; 49 | var args = this.mArgs; 50 | this.dispatchEventWith(jugglerEventType.REMOVE_FROM_JUGGLER); 51 | call.call(this, args); 52 | } 53 | } 54 | }; 55 | /** 56 | * 如果mRepeatCount不会再减1,并且mCurrentTime也不会再改变了 57 | * @returns {boolean} 58 | */ 59 | this.isComplete = function () { 60 | return this.mRepeatCount === 1 && this.mCurrentTime === this.mTotalTime; 61 | }; 62 | this.reset(call, delay, args); 63 | EventDispatcher.apply(this); 64 | }; 65 | window.juggle.DelayedCall = DelayedCall; 66 | })(window); -------------------------------------------------------------------------------- /juggle-delayedcall/src/DelayedCallPool.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | var DelayedCall = window.juggle.DelayedCall; 5 | var DelayedCallPool = function () { 6 | this.sDelayedCallPool = []; 7 | 8 | this.fromPool = function (call, delay, args) { 9 | if (tools.isNull(args)) { 10 | args = null; 11 | } 12 | if (this.sDelayedCallPool.length) 13 | return this.sDelayedCallPool.pop().reset(call, delay, args); 14 | else { 15 | return new DelayedCall(call, delay, args); 16 | } 17 | }; 18 | this.toPool = function (delayedCall) { 19 | delayedCall.mCall = null; 20 | delayedCall.mArgs = null; 21 | this.sDelayedCallPool[this.sDelayedCallPool.length] = delayedCall; 22 | } 23 | }; 24 | window.juggle.delayedCallPool = new DelayedCallPool(); 25 | })(window); -------------------------------------------------------------------------------- /juggle-event-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /juggle-event/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/Event.js',//依赖juggle-help 12 | 'src/EventPool.js',//依赖Event 13 | 'src/EventDispatcher.js'//依赖juggle-help,EventPool 14 | ], 15 | dest: 'dist/<%= pkg.name %>.js' 16 | } 17 | }, 18 | uglify: { 19 | build: { 20 | src: 'dist/<%= pkg.name %>.js', 21 | dest: 'dist/<%= pkg.name %>.min.js' 22 | } 23 | } 24 | }); 25 | grunt.loadNpmTasks('grunt-contrib-uglify'); 26 | grunt.loadNpmTasks('grunt-contrib-concat'); 27 | // 默认任务 28 | grunt.registerTask('default', ['concat', 'uglify']); 29 | }; -------------------------------------------------------------------------------- /juggle-event/README.md: -------------------------------------------------------------------------------- 1 | # juggle-event 2 | 3 | 4 | 5 | # juggle-event是一个事件库,可用于解除包含结构,树形结构的耦合性。 6 | 7 | 8 | ### 特点: 9 | 10 | 1、支持冒泡,前提冒泡对象的parent不为空并且isDisplayObject是true 11 | 12 | 2、在派发事件的回调函数内将parent设置为null,不能阻止这一次parent接到这次事件 13 | 14 | 3、在派发事件某层级的回调函数内,移除这层级的监听或添加这层级的监听,是不会影响这次派发事件目标的改变的。 15 | 16 | 4、但是如果在某层级的回调函数内,移除上层的监听或添加上层的监听,上层本轮会受到影响。 17 | 18 | 19 | ### 依赖juggle-help 20 | 21 | ### 快速开始: 22 | 23 | npm install juggle-event 24 | 25 | ### 如何使用: 26 | 27 | ```html 28 | 29 | 30 | 31 | 32 | 33 | Title 34 | 35 | 36 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | ``` 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /juggle-event/dist/juggle-event.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | /** 5 | * 创建事件 6 | * @param type 类型 7 | * @param bubbles 是否冒泡 8 | * @param data 携带数据 9 | * @constructor 10 | */ 11 | var Event = function (type, bubbles, data) { 12 | //发起事件的对象 13 | this.mTarget = null; 14 | //监听到事件的对象 15 | this.mCurrentTarget = null; 16 | //事件类型 17 | this.mType = null; 18 | //是否冒泡 19 | this.mBubbles = null; 20 | //是否阻止向上冒泡 21 | this.mStopsPropagation = null; 22 | //是否阻止派发事件 23 | this.mStopsImmediatePropagation = null; 24 | //携带数据 25 | this.mData = null; 26 | /** 阻止向上冒泡,本次循环派发事件不阻止(无回调)* */ 27 | this.stopPropagation = function () { 28 | this.mStopsPropagation = true; 29 | }; 30 | /** 停止派发事件(无回调)* */ 31 | this.stopImmediatePropagation = function () { 32 | this.mStopsPropagation = this.mStopsImmediatePropagation = true; 33 | }; 34 | /** 35 | * 重置事件 36 | * @param type 37 | * @param bubbles 38 | * @param data 39 | * @returns {Event} 40 | */ 41 | this.reset = function (type, bubbles, data) { 42 | if (tools.isNull(bubbles)) { 43 | bubbles = false; 44 | } 45 | if (tools.isNull(data)) { 46 | data = null; 47 | } 48 | this.mType = type; 49 | this.mBubbles = bubbles; 50 | this.mData = data; 51 | this.mTarget = this.mCurrentTarget = null; 52 | this.mStopsPropagation = this.mStopsImmediatePropagation = false; 53 | return this; 54 | }; 55 | this.reset(type, bubbles, data); 56 | }; 57 | window.juggle.Event = Event; 58 | })(window); 59 | (function (window) { 60 | if (!window.juggle) window.juggle = {}; 61 | var Event = window.juggle.Event; 62 | var EventPool = function () { 63 | this.sEventPool = []; 64 | /** 取事件池里面的事件,并且对事件进行重置(无回调)* */ 65 | this.fromPool = function (type, bubbles, data) { 66 | if (this.sEventPool.length) 67 | return this.sEventPool.pop().reset(type, bubbles, data); 68 | else { 69 | return new Event(type, bubbles, data); 70 | } 71 | }; 72 | /** 只清理两个目标和带来的数据,是为了可以释放资源,其他的不清理,等用的时候再重置(无回调)* */ 73 | this.toPool = function (event) { 74 | event.mData = event.mTarget = event.mCurrentTarget = null; 75 | this.sEventPool[this.sEventPool.length] = event; 76 | }; 77 | }; 78 | window.juggle.eventPool = new EventPool(); 79 | })(window); 80 | 81 | 82 | (function (window) { 83 | if (!window.juggle) window.juggle = {}; 84 | var eventPool = window.juggle.eventPool; 85 | var tools = window.juggle.tools; 86 | var sBubbleChains = []; 87 | /** 88 | * EventDispatcher.apply(this);继承此类 89 | * 支持冒泡,前提冒泡对象的parent不为空并且isDisplayObject是true 90 | * 在派发事件的回调函数内将parent设置为null,不能阻止这一次parent接到这次事件 91 | * 在派发事件某层级的回调函数内,移除这层级的监听或添加这层级的监听,是不会影响这次派发事件目标的改变的。 92 | * 靠长度阻止addEventListener,靠重新创建数组阻止removeEventListener 93 | * 但是如果在某层级的回调函数内,移除上层的监听或添加上层的监听,上层本轮会受到影响。 94 | * @constructor 95 | */ 96 | var EventDispatcher = function () { 97 | this.mEventListeners = null; 98 | this.isEventDispatcher = true; 99 | this.functionMapping = []; 100 | /** 101 | * 动态创建,同一函数不能重复添加某类型监听(无回调) 102 | * @param type 103 | * @param listener 104 | * @param parent 105 | */ 106 | this.addEventListener = function (type, listener, parent) { 107 | if (tools.isNull(this.mEventListeners)) 108 | this.mEventListeners = []; 109 | var listeners = this.mEventListeners[type]; 110 | if (tools.isNull(listeners)) { 111 | this.mEventListeners[type] = [listener]; 112 | this.functionMapping[listener] = parent; 113 | } else if (tools.indexOf(listeners, listener) === -1) { 114 | listeners.push(listener); 115 | this.functionMapping[listener] = parent; 116 | } 117 | }; 118 | /** 119 | * 移除监听,临时数组能够阻止派发事件回调函数移除事件带来的本轮影响(无回调) 120 | * @param type 121 | * @param listener 122 | */ 123 | this.removeEventListener = function (type, listener) { 124 | if (this.mEventListeners) { 125 | var listeners = this.mEventListeners[type]; 126 | var numListeners = listeners ? listeners.length : 0; 127 | if (numListeners > 0) { 128 | var index = 0; 129 | var restListeners = []; 130 | for (var i = 0; i < numListeners; ++i) { 131 | var otherListener = listeners[i]; 132 | if (otherListener !== listener) 133 | restListeners[index++] = otherListener; 134 | } 135 | this.mEventListeners[type] = restListeners; 136 | } 137 | } 138 | }; 139 | /** 140 | * 移除某类型监听,传空则移除所有监听(无回调) 141 | * @param type 142 | */ 143 | this.removeEventListeners = function (type) { 144 | if (type && this.mEventListeners) 145 | delete this.mEventListeners[type]; 146 | else 147 | this.mEventListeners = null; 148 | }; 149 | /** 150 | * 派发事件 151 | * @param event 152 | */ 153 | this.dispatchEvent = function (event) { 154 | var bubbles = event.mBubbles; 155 | //不冒泡并且无监听或者没有此类型监听,返回 156 | if (!bubbles && (tools.isNull(this.mEventListeners) || !(event.mType in this.mEventListeners))) 157 | return; 158 | //mTarget参数保留,没意义 159 | var previousTarget = event.mTarget; 160 | // 设置目标 161 | event.mTarget = this; 162 | // 冒泡并且是显示对象 163 | if (bubbles && this.isDisplayObject) 164 | this.bubbleEvent(event); 165 | else 166 | this.invokeEvent(event); 167 | if (previousTarget) 168 | event.mTarget = previousTarget; 169 | }; 170 | /** 171 | * 回调,回调前确认长度和移除事件函数中重新创建数组意义非凡 172 | * @param event 173 | * @returns {*} 174 | */ 175 | this.invokeEvent = function (event) { 176 | var listeners = this.mEventListeners ? this.mEventListeners[event.mType] : null; 177 | var numListeners = tools.isNull(listeners) ? 0 : listeners.length; 178 | if (numListeners) { 179 | // mCurrentTarget当前接到事件的对象 180 | event.mCurrentTarget = this; 181 | for (var i = 0; i < numListeners; ++i) { 182 | var listener = listeners[i]; 183 | var numArgs = listener.length; 184 | if (numArgs === 0) 185 | listener.call(this.functionMapping[listener]); 186 | else if (numArgs === 1) 187 | listener.call(this.functionMapping[listener], event); 188 | else 189 | listener.call(this.functionMapping[listener], event, event.mData); 190 | //立即阻止事件派发 191 | if (event.mStopsImmediatePropagation) { 192 | return true; 193 | } 194 | } 195 | //是否阻止冒泡 196 | return event.mStopsPropagation; 197 | } else { 198 | return false; 199 | } 200 | }; 201 | /** 202 | * 使用了sBubbleChains数组池,减少垃圾回收 203 | * 提前将冒泡数组确认存入数组,意义非凡 204 | * @param event 205 | */ 206 | this.bubbleEvent = function (event) { 207 | var chain; 208 | var element = this; 209 | var length = 1; 210 | if (sBubbleChains.length > 0) { 211 | chain = sBubbleChains.pop(); 212 | chain[0] = element; 213 | } else 214 | chain = [element]; 215 | while (!tools.isNull(element = element.parent)) 216 | chain[length++] = element; 217 | for (var i = 0; i < length; ++i) { 218 | var stopPropagation = chain[i].invokeEvent(event); 219 | if (stopPropagation) 220 | break; 221 | } 222 | chain.length = 0; 223 | sBubbleChains.push(chain); 224 | }; 225 | /** 226 | * 派发事件使用对象池 227 | * @param type 228 | * @param bubbles 229 | * @param data 230 | */ 231 | this.dispatchEventWith = function (type, bubbles, data) { 232 | if (tools.isNull(bubbles)) { 233 | bubbles = false; 234 | } 235 | if (tools.isNull(data)) { 236 | data = null; 237 | } 238 | //如果冒泡或者自己关注这个事件了 239 | if (bubbles || this.hasEventListener(type)) { 240 | var event = eventPool.fromPool(type, bubbles, data); 241 | this.dispatchEvent(event); 242 | eventPool.toPool(event); 243 | } 244 | }; 245 | /** 246 | * 是否关注这个事件 247 | * @param type 248 | * @returns {boolean} 249 | */ 250 | this.hasEventListener = function (type) { 251 | var listeners = this.mEventListeners ? this.mEventListeners[type] : null; 252 | return listeners ? listeners.length !== 0 : false; 253 | } 254 | }; 255 | window.juggle.EventDispatcher = EventDispatcher; 256 | })(window); 257 | -------------------------------------------------------------------------------- /juggle-event/dist/juggle-event.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.juggle||(t.juggle={});var n=t.juggle.tools;t.juggle.Event=function(t,e,i){this.mTarget=null,this.mCurrentTarget=null,this.mType=null,this.mBubbles=null,this.mStopsPropagation=null,this.mStopsImmediatePropagation=null,this.mData=null,this.stopPropagation=function(){this.mStopsPropagation=!0},this.stopImmediatePropagation=function(){this.mStopsPropagation=this.mStopsImmediatePropagation=!0},this.reset=function(t,e,i){return n.isNull(e)&&(e=!1),n.isNull(i)&&(i=null),this.mType=t,this.mBubbles=e,this.mData=i,this.mTarget=this.mCurrentTarget=null,this.mStopsPropagation=this.mStopsImmediatePropagation=!1,this},this.reset(t,e,i)}}(window),function(t){t.juggle||(t.juggle={});var n=t.juggle.Event;t.juggle.eventPool=new function(){this.sEventPool=[],this.fromPool=function(t,e,i){return this.sEventPool.length?this.sEventPool.pop().reset(t,e,i):new n(t,e,i)},this.toPool=function(t){t.mData=t.mTarget=t.mCurrentTarget=null,this.sEventPool[this.sEventPool.length]=t}}}(window),function(t){t.juggle||(t.juggle={});var n=t.juggle.eventPool,e=t.juggle.tools,i=[];t.juggle.EventDispatcher=function(){this.mEventListeners=null,this.isEventDispatcher=!0,this.functionMapping=[],this.addEventListener=function(t,n,i){e.isNull(this.mEventListeners)&&(this.mEventListeners=[]);var s=this.mEventListeners[t];e.isNull(s)?(this.mEventListeners[t]=[n],this.functionMapping[n]=i):-1===e.indexOf(s,n)&&(s.push(n),this.functionMapping[n]=i)},this.removeEventListener=function(t,n){if(this.mEventListeners){var e=this.mEventListeners[t],i=e?e.length:0;if(i>0){for(var s=0,o=[],l=0;l0?(n=i.pop())[0]=s:n=[s];!e.isNull(s=s.parent);)n[o++]=s;for(var l=0;l 0) { 47 | var index = 0; 48 | var restListeners = []; 49 | for (var i = 0; i < numListeners; ++i) { 50 | var otherListener = listeners[i]; 51 | if (otherListener !== listener) 52 | restListeners[index++] = otherListener; 53 | } 54 | this.mEventListeners[type] = restListeners; 55 | } 56 | } 57 | }; 58 | /** 59 | * 移除某类型监听,传空则移除所有监听(无回调) 60 | * @param type 61 | */ 62 | this.removeEventListeners = function (type) { 63 | if (type && this.mEventListeners) 64 | delete this.mEventListeners[type]; 65 | else 66 | this.mEventListeners = null; 67 | }; 68 | /** 69 | * 派发事件 70 | * @param event 71 | */ 72 | this.dispatchEvent = function (event) { 73 | var bubbles = event.mBubbles; 74 | //不冒泡并且无监听或者没有此类型监听,返回 75 | if (!bubbles && (tools.isNull(this.mEventListeners) || !(event.mType in this.mEventListeners))) 76 | return; 77 | //mTarget参数保留,没意义 78 | var previousTarget = event.mTarget; 79 | // 设置目标 80 | event.mTarget = this; 81 | // 冒泡并且是显示对象 82 | if (bubbles && this.isDisplayObject) 83 | this.bubbleEvent(event); 84 | else 85 | this.invokeEvent(event); 86 | if (previousTarget) 87 | event.mTarget = previousTarget; 88 | }; 89 | /** 90 | * 回调,回调前确认长度和移除事件函数中重新创建数组意义非凡 91 | * @param event 92 | * @returns {*} 93 | */ 94 | this.invokeEvent = function (event) { 95 | var listeners = this.mEventListeners ? this.mEventListeners[event.mType] : null; 96 | var numListeners = tools.isNull(listeners) ? 0 : listeners.length; 97 | if (numListeners) { 98 | // mCurrentTarget当前接到事件的对象 99 | event.mCurrentTarget = this; 100 | for (var i = 0; i < numListeners; ++i) { 101 | var listener = listeners[i]; 102 | var numArgs = listener.length; 103 | if (numArgs === 0) 104 | listener.call(this.functionMapping[listener]); 105 | else if (numArgs === 1) 106 | listener.call(this.functionMapping[listener], event); 107 | else 108 | listener.call(this.functionMapping[listener], event, event.mData); 109 | //立即阻止事件派发 110 | if (event.mStopsImmediatePropagation) { 111 | return true; 112 | } 113 | } 114 | //是否阻止冒泡 115 | return event.mStopsPropagation; 116 | } else { 117 | return false; 118 | } 119 | }; 120 | /** 121 | * 使用了sBubbleChains数组池,减少垃圾回收 122 | * 提前将冒泡数组确认存入数组,意义非凡 123 | * @param event 124 | */ 125 | this.bubbleEvent = function (event) { 126 | var chain; 127 | var element = this; 128 | var length = 1; 129 | if (sBubbleChains.length > 0) { 130 | chain = sBubbleChains.pop(); 131 | chain[0] = element; 132 | } else 133 | chain = [element]; 134 | while (!tools.isNull(element = element.parent)) 135 | chain[length++] = element; 136 | for (var i = 0; i < length; ++i) { 137 | var stopPropagation = chain[i].invokeEvent(event); 138 | if (stopPropagation) 139 | break; 140 | } 141 | chain.length = 0; 142 | sBubbleChains.push(chain); 143 | }; 144 | /** 145 | * 派发事件使用对象池 146 | * @param type 147 | * @param bubbles 148 | * @param data 149 | */ 150 | this.dispatchEventWith = function (type, bubbles, data) { 151 | if (tools.isNull(bubbles)) { 152 | bubbles = false; 153 | } 154 | if (tools.isNull(data)) { 155 | data = null; 156 | } 157 | //如果冒泡或者自己关注这个事件了 158 | if (bubbles || this.hasEventListener(type)) { 159 | var event = eventPool.fromPool(type, bubbles, data); 160 | this.dispatchEvent(event); 161 | eventPool.toPool(event); 162 | } 163 | }; 164 | /** 165 | * 是否关注这个事件 166 | * @param type 167 | * @returns {boolean} 168 | */ 169 | this.hasEventListener = function (type) { 170 | var listeners = this.mEventListeners ? this.mEventListeners[type] : null; 171 | return listeners ? listeners.length !== 0 : false; 172 | } 173 | }; 174 | window.juggle.EventDispatcher = EventDispatcher; 175 | })(window); 176 | -------------------------------------------------------------------------------- /juggle-event/src/EventPool.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var Event = window.juggle.Event; 4 | var EventPool = function () { 5 | this.sEventPool = []; 6 | /** 取事件池里面的事件,并且对事件进行重置(无回调)* */ 7 | this.fromPool = function (type, bubbles, data) { 8 | if (this.sEventPool.length) 9 | return this.sEventPool.pop().reset(type, bubbles, data); 10 | else { 11 | return new Event(type, bubbles, data); 12 | } 13 | }; 14 | /** 只清理两个目标和带来的数据,是为了可以释放资源,其他的不清理,等用的时候再重置(无回调)* */ 15 | this.toPool = function (event) { 16 | event.mData = event.mTarget = event.mCurrentTarget = null; 17 | this.sEventPool[this.sEventPool.length] = event; 18 | }; 19 | }; 20 | window.juggle.eventPool = new EventPool(); 21 | })(window); 22 | 23 | -------------------------------------------------------------------------------- /juggle-help-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /juggle-help/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/Tools.js'//无依赖 12 | ], 13 | dest: 'dist/<%= pkg.name %>.js' 14 | } 15 | }, 16 | uglify: { 17 | build: { 18 | src: 'dist/<%= pkg.name %>.js', 19 | dest: 'dist/<%= pkg.name %>.min.js' 20 | } 21 | } 22 | }); 23 | grunt.loadNpmTasks('grunt-contrib-uglify'); 24 | grunt.loadNpmTasks('grunt-contrib-concat'); 25 | // 默认任务 26 | grunt.registerTask('default', ['concat', 'uglify']); 27 | }; -------------------------------------------------------------------------------- /juggle-help/dist/juggle-help.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var Tools = function () { 4 | /** 5 | * 判断数组里是否包含该对象 6 | * @param array 7 | * @param obj 8 | * @returns {number} 9 | */ 10 | this.indexOf = function (array, obj) { 11 | var index = -1; 12 | if (array === null || obj === null) { 13 | return index; 14 | } 15 | for (var i = 0; i < array.length; i++) { 16 | if (array[i] === obj) { 17 | index = i; 18 | break; 19 | } 20 | } 21 | return index; 22 | }; 23 | /** 24 | * 判断对象是否为空 25 | * @param obj 26 | * @returns {boolean} 27 | */ 28 | this.isNull = function (obj) { 29 | return obj === null || obj === undefined; 30 | } 31 | }; 32 | window.juggle.tools = new Tools(); 33 | })(window); -------------------------------------------------------------------------------- /juggle-help/dist/juggle-help.min.js: -------------------------------------------------------------------------------- 1 | !function(n){n.juggle||(n.juggle={});n.juggle.tools=new function(){this.indexOf=function(n,u){var l=-1;if(null===n||null===u)return l;for(var i=0;i 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 53 | 54 | 55 |
56 | 57 | 58 |
59 | 60 | -------------------------------------------------------------------------------- /juggle-http/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/HttpEventType.js',//无依赖 12 | 'src/HttpClient.js'//依赖httpEventType,juggle-event 13 | ], 14 | dest: 'dist/<%= pkg.name %>.js' 15 | } 16 | }, 17 | uglify: { 18 | build: { 19 | src: 'dist/<%= pkg.name %>.js', 20 | dest: 'dist/<%= pkg.name %>.min.js' 21 | } 22 | } 23 | }); 24 | grunt.loadNpmTasks('grunt-contrib-uglify'); 25 | grunt.loadNpmTasks('grunt-contrib-concat'); 26 | // 默认任务 27 | grunt.registerTask('default', ['concat', 'uglify']); 28 | }; -------------------------------------------------------------------------------- /juggle-http/README.md: -------------------------------------------------------------------------------- 1 | # juggle-http 2 | 3 | 4 | 5 | 6 | # juggle-http是可以进行事件派发的httpclient库,可以发文件 7 | 8 | 9 | 10 | ### 依赖juggle-help,juggle-event 11 | 12 | 13 | ### 快速开始: 14 | 15 | 16 | npm install juggle-http 17 | 18 | 19 | ### 如何使用: 20 | 21 | ```html 22 | 23 | 24 | 25 | 26 | 27 | Title 28 | 29 | 30 | 31 | 75 | 76 | 77 |
78 | 79 | 80 |
81 | 82 | 83 | 84 | ``` 85 | 86 | 87 | http服务器(直接可用): 88 | 89 | https://github.com/dianbaer/grain/tree/master/grain-httpserver-test 90 | 91 | -------------------------------------------------------------------------------- /juggle-http/dist/juggle-http.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var HttpEventType = function () { 4 | this.ERROR = "error"; 5 | this.SUCCESS = "success"; 6 | }; 7 | window.juggle.httpEventType = new HttpEventType(); 8 | })(window); 9 | (function (window) { 10 | if (!window.juggle) window.juggle = {}; 11 | var EventDispatcher = window.juggle.EventDispatcher; 12 | var httpEventType = window.juggle.httpEventType; 13 | var HttpClient = function () { 14 | EventDispatcher.apply(this); 15 | this.send = function (data, url, header, type, isAsync) { 16 | this.data = data; 17 | this.url = url; 18 | this.header = header; 19 | var xMLHttpRequest = new XMLHttpRequest(); 20 | if (xMLHttpRequest === null || xMLHttpRequest === undefined) { 21 | return false; 22 | } 23 | if (isAsync === null || isAsync === undefined) { 24 | isAsync = true; 25 | } 26 | if (type === null || type === undefined) { 27 | if (data === null || data === undefined) { 28 | type = "get"; 29 | } else { 30 | type = "post"; 31 | } 32 | } 33 | this.type = type; 34 | this.isAsync = isAsync; 35 | xMLHttpRequest.open(type, url, isAsync); 36 | for (var headName in header) { 37 | xMLHttpRequest.setRequestHeader(headName, header[headName]); 38 | } 39 | this.addHttpListener(this, xMLHttpRequest, this.sendReturn, data); 40 | if (type === "post") { 41 | xMLHttpRequest.setRequestHeader('Content-Type', 'application/json'); 42 | xMLHttpRequest.send(JSON.stringify(data)); 43 | } else { 44 | xMLHttpRequest.send(); 45 | } 46 | }; 47 | this.addHttpListener = function (httpClient, xMLHttpRequest, sendReturn, data) { 48 | var onReadyStateHandle = function (event) { 49 | sendReturn.call(httpClient, xMLHttpRequest, event, data); 50 | }; 51 | xMLHttpRequest.onreadystatechange = onReadyStateHandle; 52 | }; 53 | this.sendReturn = function (xMLHttpRequest, event, data) { 54 | if (xMLHttpRequest.readyState === 4) { 55 | if (xMLHttpRequest.status === 200) { 56 | //派发请求成功返回数据 57 | this.dispatchEventWith(httpEventType.SUCCESS, false, xMLHttpRequest.responseText); 58 | } else { 59 | //派发请求错误 60 | this.dispatchEventWith(httpEventType.ERROR); 61 | } 62 | } 63 | }; 64 | this.sendFile = function (fileList, data, url, header, type, isAsync) { 65 | this.data = data; 66 | this.url = url; 67 | this.header = header; 68 | var xMLHttpRequest = new XMLHttpRequest(); 69 | if (xMLHttpRequest === null || xMLHttpRequest === undefined) { 70 | return false; 71 | } 72 | if (isAsync === null || isAsync === undefined) { 73 | isAsync = true; 74 | } 75 | if (type === null || type === undefined) { 76 | type = "post"; 77 | } 78 | this.type = type; 79 | this.isAsync = isAsync; 80 | xMLHttpRequest.open(type, url, isAsync); 81 | for (var headName in header) { 82 | xMLHttpRequest.setRequestHeader(headName, header[headName]); 83 | } 84 | this.addHttpListener(this, xMLHttpRequest, this.sendReturn, data); 85 | var form = new FormData(); 86 | for (var i = 0; i < fileList.length; i++) { 87 | var file = fileList[i]; 88 | form.append("file" + i, file); 89 | } 90 | if (data !== null && data !== undefined) { 91 | for (var key in data) { 92 | form.append(key, data[key]); 93 | } 94 | } 95 | xMLHttpRequest.send(form); 96 | } 97 | }; 98 | window.juggle.HttpClient = HttpClient; 99 | })(window); 100 | -------------------------------------------------------------------------------- /juggle-http/dist/juggle-http.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.juggle||(t.juggle={});t.juggle.httpEventType=new function(){this.ERROR="error",this.SUCCESS="success"}}(window),function(t){t.juggle||(t.juggle={});var e=t.juggle.EventDispatcher,n=t.juggle.httpEventType;t.juggle.HttpClient=function(){e.apply(this),this.send=function(t,e,n,i,s){this.data=t,this.url=e,this.header=n;var u=new XMLHttpRequest;if(null===u||void 0===u)return!1;null!==s&&void 0!==s||(s=!0),null!==i&&void 0!==i||(i=null===t||void 0===t?"get":"post"),this.type=i,this.isAsync=s,u.open(i,e,s);for(var r in n)u.setRequestHeader(r,n[r]);this.addHttpListener(this,u,this.sendReturn,t),"post"===i?(u.setRequestHeader("Content-Type","application/json"),u.send(JSON.stringify(t))):u.send()},this.addHttpListener=function(t,e,n,i){e.onreadystatechange=function(s){n.call(t,e,s,i)}},this.sendReturn=function(t,e,i){4===t.readyState&&(200===t.status?this.dispatchEventWith(n.SUCCESS,!1,t.responseText):this.dispatchEventWith(n.ERROR))},this.sendFile=function(t,e,n,i,s,u){this.data=e,this.url=n,this.header=i;var r=new XMLHttpRequest;if(null===r||void 0===r)return!1;null!==u&&void 0!==u||(u=!0),null!==s&&void 0!==s||(s="post"),this.type=s,this.isAsync=u,r.open(s,n,u);for(var a in i)r.setRequestHeader(a,i[a]);this.addHttpListener(this,r,this.sendReturn,e);for(var d=new FormData,h=0;h 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 65 | 66 | 67 |
68 | 69 | 70 |
71 | 72 | -------------------------------------------------------------------------------- /juggle-httpfilter/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/HttpFilter.js'//无依赖juugle-http 12 | ], 13 | dest: 'dist/<%= pkg.name %>.js' 14 | } 15 | }, 16 | uglify: { 17 | build: { 18 | src: 'dist/<%= pkg.name %>.js', 19 | dest: 'dist/<%= pkg.name %>.min.js' 20 | } 21 | } 22 | }); 23 | grunt.loadNpmTasks('grunt-contrib-uglify'); 24 | grunt.loadNpmTasks('grunt-contrib-concat'); 25 | // 默认任务 26 | grunt.registerTask('default', ['concat', 'uglify']); 27 | }; -------------------------------------------------------------------------------- /juggle-httpfilter/README.md: -------------------------------------------------------------------------------- 1 | # juggle-httpfilter 2 | 3 | 4 | # juggle-httpfilter是一个过滤器,可以将某些返回认为是错误的回复 5 | 6 | 7 | 8 | ### 依赖juggle-help,juggle-event,juggle-http 9 | 10 | 11 | ### 快速开始: 12 | 13 | 14 | npm install juggle-httpfilter 15 | 16 | 17 | ### 如何使用: 18 | 19 | ```html 20 | 21 | 22 | 23 | 24 | 25 | Title 26 | 27 | 28 | 29 | 30 | 85 | 86 | 87 |
88 | 89 | 90 |
91 | 92 | 93 | 94 | ``` 95 | 96 | 97 | http服务器(直接可用): 98 | 99 | https://github.com/dianbaer/grain/tree/master/grain-httpserver-test 100 | 101 | -------------------------------------------------------------------------------- /juggle-httpfilter/dist/juggle-httpfilter.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var HttpClient = window.juggle.HttpClient; 4 | var httpEventType = window.juggle.httpEventType; 5 | var HttpFilter = function () { 6 | this.filterArray = []; 7 | this.addFilter = function (filter) { 8 | this.filterArray.push(filter); 9 | }; 10 | this.filter = function (result) { 11 | for (var i = 0; i < this.filterArray.length; i++) { 12 | var filter = this.filterArray[i]; 13 | var bool = filter.check(result); 14 | if (!bool) { 15 | return false; 16 | } 17 | } 18 | return true; 19 | }; 20 | this.send = function (data, url, header, type, isAsync, callObj, callSuccess, callError, callData) { 21 | var httpClient = new HttpClient(); 22 | httpClient.callObj = callObj; 23 | httpClient.callSuccess = callSuccess; 24 | httpClient.callError = callError; 25 | httpClient.callData = callData; 26 | httpClient.send(data, url, header, type, isAsync); 27 | httpClient.addEventListener(httpEventType.SUCCESS, this.successHandle, this); 28 | httpClient.addEventListener(httpEventType.ERROR, this.errorHandle, this); 29 | }; 30 | this.sendFile = function (fileList, data, url, header, type, isAsync, callObj, callSuccess, callError, callData) { 31 | var httpClient = new HttpClient(); 32 | httpClient.callObj = callObj; 33 | httpClient.callSuccess = callSuccess; 34 | httpClient.callError = callError; 35 | httpClient.callData = callData; 36 | httpClient.sendFile(fileList, data, url, header, type, isAsync); 37 | httpClient.addEventListener(httpEventType.SUCCESS, this.successHandle, this); 38 | httpClient.addEventListener(httpEventType.ERROR, this.errorHandle, this); 39 | }; 40 | this.successHandle = function (event) { 41 | var result = JSON.parse(event.mData); 42 | var httpClient = event.mTarget; 43 | var check = this.filter(result); 44 | if (check) { 45 | httpClient.callSuccess.call(httpClient.callObj, result, httpClient.callData); 46 | } else { 47 | httpClient.callError.call(httpClient.callObj, result, httpClient.callData); 48 | } 49 | 50 | }; 51 | this.errorHandle = function (event) { 52 | var httpClient = event.mTarget; 53 | httpClient.callError.call(httpClient.callObj, null, httpClient.callData); 54 | } 55 | }; 56 | window.juggle.httpFilter = new HttpFilter(); 57 | })(window); 58 | -------------------------------------------------------------------------------- /juggle-httpfilter/dist/juggle-httpfilter.min.js: -------------------------------------------------------------------------------- 1 | !function(l){l.juggle||(l.juggle={});var t=l.juggle.HttpClient,e=l.juggle.httpEventType;l.juggle.httpFilter=new function(){this.filterArray=[],this.addFilter=function(l){this.filterArray.push(l)},this.filter=function(l){for(var t=0;t 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /juggle-juggler/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/JugglerEventType.js',//无依赖 12 | 'src/Juggler.js',//依赖JugglerEventType,juggle-help 13 | 'src/JugglerManager.js'//依赖Juggler 14 | ], 15 | dest: 'dist/<%= pkg.name %>.js' 16 | } 17 | }, 18 | uglify: { 19 | build: { 20 | src: 'dist/<%= pkg.name %>.js', 21 | dest: 'dist/<%= pkg.name %>.min.js' 22 | } 23 | } 24 | }); 25 | grunt.loadNpmTasks('grunt-contrib-uglify'); 26 | grunt.loadNpmTasks('grunt-contrib-concat'); 27 | // 默认任务 28 | grunt.registerTask('default', ['concat', 'uglify']); 29 | }; -------------------------------------------------------------------------------- /juggle-juggler/README.md: -------------------------------------------------------------------------------- 1 | # juggle-juggler 2 | 3 | 4 | 5 | # juggle-juggler是一个动画管理类,可以添加与移除动画 6 | 7 | ### 特点: 8 | 9 | 1、回调中新加入的动画不能在这一次被调度,因为没有经历时间过程这是合理的 10 | 2、回调中移除的分两种可能,已经在本次调度的无影响,没有在本次调度的取消本次调度 11 | 12 | 13 | ### 依赖juggle-help,juggle-event 14 | 15 | ### 快速开始: 16 | 17 | npm install juggle-juggler 18 | 19 | ### 如何使用: 20 | 21 | ```html 22 | 23 | 24 | 25 | 26 | 27 | Title 28 | 29 | 30 | 31 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | ``` 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /juggle-juggler/dist/juggle-juggler.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var JugglerEventType = function () { 4 | /** 5 | * 离开时间轴 6 | * @type {string} 7 | */ 8 | this.REMOVE_FROM_JUGGLER = "removeFromJuggler"; 9 | }; 10 | window.juggle.jugglerEventType = new JugglerEventType(); 11 | })(window); 12 | (function (window) { 13 | if (!window.juggle) window.juggle = {}; 14 | var tools = window.juggle.tools; 15 | var jugglerEventType = window.juggle.jugglerEventType; 16 | var Juggler = function () { 17 | this.mObjects = []; 18 | this.mElapsedTime = 0; 19 | /** 20 | * 添加对象至时间轴,同一对象不能重复添加,如果继承事件类,会监听离开时间轴的事件(无回调) 21 | * @param object 22 | */ 23 | this.add = function (object) { 24 | if (object && tools.indexOf(this.mObjects, object) === -1) { 25 | this.mObjects[this.mObjects.length] = object; 26 | if (object.isEventDispatcher) 27 | object.addEventListener(jugglerEventType.REMOVE_FROM_JUGGLER, this.onRemove, this); 28 | } 29 | }; 30 | /** 31 | * 判断这个对象是否在时间轴(无回调) 32 | * @param object 33 | * @returns {boolean} 34 | */ 35 | this.contains = function (object) { 36 | return tools.indexOf(this.mObjects, object) !== -1; 37 | }; 38 | /** 39 | * 将时间轴这个对象位置置空意义非凡,能够有效的控制新加入的动画进入这次调度 40 | * 如果是事件类移除事件监听 41 | * @param object 42 | */ 43 | this.remove = function (object) { 44 | if (tools.isNull(object)) 45 | return; 46 | if (object.isEventDispatcher) 47 | object.removeEventListener(jugglerEventType.REMOVE_FROM_JUGGLER, this.onRemove); 48 | var index = tools.indexOf(this.mObjects, object); 49 | if (index !== -1) 50 | this.mObjects[index] = null; 51 | }; 52 | /** 53 | * 动画调度, 54 | * 回调中新加入的动画不能在这一次被调度,因为没有经历时间过程这是合理的 55 | * 回调中移除的分两种可能,已经在本次调度的无影响,没有在本次调度的取消本次调度 56 | * @param time 57 | */ 58 | this.advanceTime = function (time) { 59 | //确定这次调度的长度 60 | var numObjects = this.mObjects.length; 61 | var currentIndex = 0; 62 | var i; 63 | this.mElapsedTime += time; 64 | if (numObjects === 0) 65 | return; 66 | //回调里可能含有后面给前面移除与前面给后面移除两种 67 | //后面给前面移除this.mObjects这轮含有null 68 | //前面给后面移除会进行调换 69 | for (i = 0; i < numObjects; ++i) { 70 | var object = this.mObjects[i]; 71 | if (object) { 72 | //将后面不为空的动画对象换到前面为空的位置上 73 | if (currentIndex !== i) { 74 | this.mObjects[currentIndex] = object; 75 | this.mObjects[i] = null; 76 | } 77 | object.advanceTime(time); 78 | ++currentIndex; 79 | } 80 | } 81 | //这次应该调度的长度和实际长度不一样 82 | if (currentIndex !== i) { 83 | //这个长度在回调过程中,很有可能已经改变了,重新取一下 84 | numObjects = this.mObjects.length; 85 | //将新加入的动画与前面为空的调换 86 | while (i < numObjects) 87 | this.mObjects[currentIndex++] = this.mObjects[i++]; 88 | //清空后面为空的动画对象 89 | this.mObjects.length = currentIndex; 90 | } 91 | }; 92 | /** 93 | * 接受REMOVE_FROM_JUGGLER事件 94 | * @param event 95 | */ 96 | this.onRemove = function (event) { 97 | //离开动画列表,并且移除监听事件 98 | this.remove(event.mTarget); 99 | } 100 | }; 101 | window.juggle.Juggler = Juggler; 102 | })(window); 103 | (function (window) { 104 | if (!window.juggle) window.juggle = {}; 105 | var Juggler = window.juggle.Juggler; 106 | var JugglerManager = function () { 107 | this.onEnterFrame = function () { 108 | var now = new Date().getTime(); 109 | var passedTime = (now - juggle.jugglerManager.processTime) / 1000.0; 110 | juggle.jugglerManager.processTime = now; 111 | if (passedTime === 0.0 || this.isStop) { 112 | return; 113 | } 114 | juggle.jugglerManager.juggler.advanceTime(passedTime); 115 | }; 116 | this.processTime = new Date().getTime(); 117 | this.juggler = new Juggler(); 118 | this.intervalId = setInterval(this.onEnterFrame, 25); 119 | this.isStop = false; 120 | }; 121 | window.juggle.jugglerManager = new JugglerManager(); 122 | })(window); -------------------------------------------------------------------------------- /juggle-juggler/dist/juggle-juggler.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e.juggle||(e.juggle={});e.juggle.jugglerEventType=new function(){this.REMOVE_FROM_JUGGLER="removeFromJuggler"}}(window),function(e){e.juggle||(e.juggle={});var t=e.juggle.tools,i=e.juggle.jugglerEventType;e.juggle.Juggler=function(){this.mObjects=[],this.mElapsedTime=0,this.add=function(e){e&&-1===t.indexOf(this.mObjects,e)&&(this.mObjects[this.mObjects.length]=e,e.isEventDispatcher&&e.addEventListener(i.REMOVE_FROM_JUGGLER,this.onRemove,this))},this.contains=function(e){return-1!==t.indexOf(this.mObjects,e)},this.remove=function(e){if(!t.isNull(e)){e.isEventDispatcher&&e.removeEventListener(i.REMOVE_FROM_JUGGLER,this.onRemove);var s=t.indexOf(this.mObjects,e);-1!==s&&(this.mObjects[s]=null)}},this.advanceTime=function(e){var t,i=this.mObjects.length,s=0;if(this.mElapsedTime+=e,0!==i){for(t=0;tbody -------------------------------------------------------------------------------- /juggle-module-test/body1.html: -------------------------------------------------------------------------------- 1 |
body1
-------------------------------------------------------------------------------- /juggle-module-test/bottom.html: -------------------------------------------------------------------------------- 1 |
bottom
-------------------------------------------------------------------------------- /juggle-module-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 12 | 69 | 70 | 71 |
72 |
73 |
74 |
75 | 76 | -------------------------------------------------------------------------------- /juggle-module-test/top.html: -------------------------------------------------------------------------------- 1 |
top
-------------------------------------------------------------------------------- /juggle-module/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/ModuleManager.js'//依赖juggle-resource 12 | ], 13 | dest: 'dist/<%= pkg.name %>.js' 14 | } 15 | }, 16 | uglify: { 17 | build: { 18 | src: 'dist/<%= pkg.name %>.js', 19 | dest: 'dist/<%= pkg.name %>.min.js' 20 | } 21 | } 22 | }); 23 | grunt.loadNpmTasks('grunt-contrib-uglify'); 24 | grunt.loadNpmTasks('grunt-contrib-concat'); 25 | // 默认任务 26 | grunt.registerTask('default', ['concat', 'uglify']); 27 | }; -------------------------------------------------------------------------------- /juggle-module/README.md: -------------------------------------------------------------------------------- 1 | # juggle-module 2 | 3 | 4 | 5 | # juggle-module是模块类,支持模块加载卸载 6 | 7 | 8 | 9 | 10 | ### 依赖juggle-help,juggle-event,juggle-http,juggle-resource,juggle-mv 11 | 12 | ### 快速开始: 13 | 14 | npm install juggle-module 15 | 16 | ### 如何使用: 17 | 18 | ```html 19 | 20 | 21 | 22 | 23 | 24 | Title 25 | 26 | 27 | 28 | 29 | 30 | 31 | 88 | 89 | 90 |
91 |
92 |
93 |
94 | 95 | 96 | 97 | ``` 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /juggle-module/dist/juggle-module.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var resourceManager = window.juggle.resourceManager; 4 | var ModuleManager = function () { 5 | this.moduleUrlToData = []; 6 | this.moduleTypeToData = []; 7 | /** 8 | * 加载模块 9 | * @param url 地址 10 | * @param container 该模块容器 11 | * @param type 类型,如果已经该类型则将原模块卸载,加载新模块 12 | * @param mediator 模块控制器 13 | * @param data 额外数据 14 | */ 15 | this.loadModule = function (url, container, type, mediator, data) { 16 | var moduleData = { 17 | "url": url, 18 | "container": container, 19 | "type": type, 20 | "mediator": mediator, 21 | "data": data 22 | }; 23 | this.moduleUrlToData[url] = moduleData; 24 | resourceManager.loadResource([url], this.loadComplete, this.loadFail, this); 25 | }; 26 | this.loadFail = function (url) { 27 | 28 | }; 29 | this.loadComplete = function (url) { 30 | var moduleData = this.moduleUrlToData[url[0]]; 31 | //在未加载完成就卸载,会出现这种情况 32 | if (moduleData === null || moduleData === undefined) { 33 | return; 34 | } 35 | var resource = resourceManager.getResource(url[0]); 36 | if (moduleData.type !== null && moduleData.type !== undefined) { 37 | var oldModuleData = this.moduleTypeToData[moduleData.type]; 38 | if (oldModuleData !== null && oldModuleData !== undefined) { 39 | oldModuleData.mediator.dispose(); 40 | } 41 | this.moduleTypeToData[moduleData.type] = moduleData; 42 | } 43 | moduleData.container.innerHTML = resource; 44 | moduleData.mediator.initView(moduleData.container, moduleData.data); 45 | }; 46 | this.unLoadModule = function (url) { 47 | var moduleData = this.moduleUrlToData[url]; 48 | if (moduleData !== null && moduleData !== undefined) { 49 | moduleData.mediator.dispose(); 50 | delete this.moduleUrlToData[url]; 51 | delete this.moduleTypeToData[moduleData.type]; 52 | } 53 | } 54 | }; 55 | window.juggle.moduleManager = new ModuleManager(); 56 | })(window); -------------------------------------------------------------------------------- /juggle-module/dist/juggle-module.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e.juggle||(e.juggle={});var o=e.juggle.resourceManager;e.juggle.moduleManager=new function(){this.moduleUrlToData=[],this.moduleTypeToData=[],this.loadModule=function(e,t,a,i,l){var d={url:e,container:t,type:a,mediator:i,data:l};this.moduleUrlToData[e]=d,o.loadResource([e],this.loadComplete,this.loadFail,this)},this.loadFail=function(e){},this.loadComplete=function(e){var t=this.moduleUrlToData[e[0]];if(null!==t&&void 0!==t){var a=o.getResource(e[0]);if(null!==t.type&&void 0!==t.type){var i=this.moduleTypeToData[t.type];null!==i&&void 0!==i&&i.mediator.dispose(),this.moduleTypeToData[t.type]=t}t.container.innerHTML=a,t.mediator.initView(t.container,t.data)}},this.unLoadModule=function(e){var o=this.moduleUrlToData[e];null!==o&&void 0!==o&&(o.mediator.dispose(),delete this.moduleUrlToData[e],delete this.moduleTypeToData[o.type])}}}(window); -------------------------------------------------------------------------------- /juggle-module/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juggle-module", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "juggle-module.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/dianbaer/juggle" 12 | }, 13 | "keywords": [ 14 | "juggle", 15 | "module" 16 | ], 17 | "author": "dianbaer", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "grunt": "^1.0.1", 21 | "grunt-contrib-concat": "^1.0.1", 22 | "grunt-contrib-uglify": "^3.0.1" 23 | }, 24 | "dependencies": { 25 | "juggle-help": "^1.0.0", 26 | "juggle-event": "^1.0.0", 27 | "juggle-http": "^1.0.0", 28 | "juggle-resource": "^1.0.0", 29 | "juggle-mv": "^1.0.0" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /juggle-module/src/ModuleManager.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var resourceManager = window.juggle.resourceManager; 4 | var ModuleManager = function () { 5 | this.moduleUrlToData = []; 6 | this.moduleTypeToData = []; 7 | /** 8 | * 加载模块 9 | * @param url 地址 10 | * @param container 该模块容器 11 | * @param type 类型,如果已经该类型则将原模块卸载,加载新模块 12 | * @param mediator 模块控制器 13 | * @param data 额外数据 14 | */ 15 | this.loadModule = function (url, container, type, mediator, data) { 16 | var moduleData = { 17 | "url": url, 18 | "container": container, 19 | "type": type, 20 | "mediator": mediator, 21 | "data": data 22 | }; 23 | this.moduleUrlToData[url] = moduleData; 24 | resourceManager.loadResource([url], this.loadComplete, this.loadFail, this); 25 | }; 26 | this.loadFail = function (url) { 27 | 28 | }; 29 | this.loadComplete = function (url) { 30 | var moduleData = this.moduleUrlToData[url[0]]; 31 | //在未加载完成就卸载,会出现这种情况 32 | if (moduleData === null || moduleData === undefined) { 33 | return; 34 | } 35 | var resource = resourceManager.getResource(url[0]); 36 | if (moduleData.type !== null && moduleData.type !== undefined) { 37 | var oldModuleData = this.moduleTypeToData[moduleData.type]; 38 | if (oldModuleData !== null && oldModuleData !== undefined) { 39 | oldModuleData.mediator.dispose(); 40 | } 41 | this.moduleTypeToData[moduleData.type] = moduleData; 42 | } 43 | moduleData.container.innerHTML = resource; 44 | moduleData.mediator.initView(moduleData.container, moduleData.data); 45 | }; 46 | this.unLoadModule = function (url) { 47 | var moduleData = this.moduleUrlToData[url]; 48 | if (moduleData !== null && moduleData !== undefined) { 49 | moduleData.mediator.dispose(); 50 | delete this.moduleUrlToData[url]; 51 | delete this.moduleTypeToData[moduleData.type]; 52 | } 53 | } 54 | }; 55 | window.juggle.moduleManager = new ModuleManager(); 56 | })(window); -------------------------------------------------------------------------------- /juggle-mv-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /juggle-mv/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/ViewManager.js'//无依赖 12 | ], 13 | dest: 'dist/<%= pkg.name %>.js' 14 | } 15 | }, 16 | uglify: { 17 | build: { 18 | src: 'dist/<%= pkg.name %>.js', 19 | dest: 'dist/<%= pkg.name %>.min.js' 20 | } 21 | } 22 | }); 23 | grunt.loadNpmTasks('grunt-contrib-uglify'); 24 | grunt.loadNpmTasks('grunt-contrib-concat'); 25 | // 默认任务 26 | grunt.registerTask('default', ['concat', 'uglify']); 27 | }; -------------------------------------------------------------------------------- /juggle-mv/README.md: -------------------------------------------------------------------------------- 1 | # juggle-mv 2 | 3 | 4 | 5 | # juggle-mv是一个mv框架解除数据源与视图控制器,视图控制器之间的耦合性。 6 | 7 | 8 | ### 特点: 9 | 10 | 11 | 1、严密的闭包封装,用户只需关心数据代理proxy与视图控制器mediator的开发 12 | 13 | 14 | 15 | ### 快速开始: 16 | 17 | 18 | npm install juggle-mv 19 | 20 | ### 创建数据代理 21 | 22 | ```html 23 | 24 | function UserProxy() { 25 | juggle.Proxy.apply(this); 26 | } 27 | 28 | ``` 29 | 30 | ### 创建视图控制器 31 | 32 | 33 | ```html 34 | 35 | function IndexMediator() { 36 | this.listNotificationInterests = ["test", "test1"]; 37 | this.handleNotification = function (data) { 38 | switch (data.name) { 39 | case "test": 40 | break; 41 | case "test1": 42 | break; 43 | } 44 | }; 45 | juggle.Mediator.apply(this); 46 | } 47 | 48 | ``` 49 | 50 | ### 如何使用: 51 | 52 | 53 | ```html 54 | 55 | 56 | 57 | 58 | 59 | Title 60 | 61 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | ``` 126 | 127 | -------------------------------------------------------------------------------- /juggle-mv/dist/juggle-mv.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var ViewManager = function () { 4 | this.observerMap = []; 5 | this.registerObserver = function (notificationName, observer) { 6 | if (notificationName === null || notificationName === undefined || observer === null || observer === undefined) { 7 | return; 8 | } 9 | var observers = this.observerMap[notificationName]; 10 | if (observers) { 11 | var isHave = false; 12 | for (var i = 0; i < observers.length; i++) { 13 | if (observers[i] === observer) { 14 | isHave = true; 15 | break; 16 | } 17 | } 18 | if (!isHave) { 19 | observers.push(observer); 20 | } 21 | } else { 22 | this.observerMap[notificationName] = [observer]; 23 | } 24 | }; 25 | this.registerObserverArray = function (notificationNameArray, observer) { 26 | if (notificationNameArray === null || notificationNameArray === undefined) { 27 | return; 28 | } 29 | if (observer === null || observer === undefined) { 30 | return; 31 | } 32 | for (var i = 0; i < notificationNameArray.length; i++) { 33 | this.registerObserver(notificationNameArray[i], observer); 34 | } 35 | }; 36 | this.getNotification = function (name, body) { 37 | var obj = {}; 38 | obj.name = name; 39 | obj.body = body; 40 | return obj; 41 | }; 42 | this.notifyObservers = function (notification) { 43 | var obj = viewManager.observerMap[notification.name]; 44 | if (obj) { 45 | // 这里最好复制这个数组,防止回调的时候,在注册新的监听 46 | var observers = obj.concat(); 47 | for (var i = 0; i < observers.length; i++) { 48 | var observer = observers[i]; 49 | observer.handleNotification.call(observer, notification); 50 | } 51 | } 52 | }; 53 | this.removeObserverArray = function (notificationNameArray, observer) { 54 | if (notificationNameArray === null || notificationNameArray === undefined) { 55 | return; 56 | } 57 | if (observer === null || observer === undefined) { 58 | return; 59 | } 60 | for (var i = 0; i < notificationNameArray.length; i++) { 61 | this.removeObserver(notificationNameArray[i], observer); 62 | } 63 | }; 64 | this.removeObserver = function (notificationName, observer) { 65 | if (notificationName === null || notificationName === undefined || observer === null || observer === undefined) { 66 | return; 67 | } 68 | var observers = this.observerMap[notificationName]; 69 | if (observers !== undefined && observers !== null) { 70 | for (var i = 0; i < observers.length; i++) { 71 | if (observers[i] === observer) { 72 | observers.splice(i, 1); 73 | break; 74 | } 75 | } 76 | if (observers.length === 0) { 77 | delete this.observerMap[notificationName]; 78 | } 79 | } 80 | }; 81 | this.reset = function () { 82 | this.observerMap = []; 83 | } 84 | }; 85 | 86 | var Proxy = function () { 87 | this.notifyObservers = viewManager.notifyObservers; 88 | this.getNotification = viewManager.getNotification; 89 | }; 90 | var Mediator = function () { 91 | this.init = function () { 92 | viewManager.registerObserverArray(this.listNotificationInterests, this); 93 | }; 94 | this.dispose = function () { 95 | viewManager.removeObserverArray(this.listNotificationInterests, this); 96 | }; 97 | this.notifyObservers = viewManager.notifyObservers; 98 | this.getNotification = viewManager.getNotification; 99 | this.init(); 100 | }; 101 | var viewManager = new ViewManager(); 102 | window.juggle.Mediator = Mediator; 103 | window.juggle.Proxy = Proxy; 104 | })(window); -------------------------------------------------------------------------------- /juggle-mv/dist/juggle-mv.min.js: -------------------------------------------------------------------------------- 1 | !function(i){i.juggle||(i.juggle={});var e=new function(){this.observerMap=[],this.registerObserver=function(i,e){if(null!==i&&void 0!==i&&null!==e&&void 0!==e){var t=this.observerMap[i];if(t){for(var r=!1,s=0;s 2 | 3 | 4 | 5 | Resource1 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /juggle-resource-test/resource2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Resource2 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /juggle-resource-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /juggle-resource/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/ResourceEventType.js',//无依赖 12 | 'src/Loader.js',//resourceEventType,juggle-http,juggle-event 13 | 'src/ResourceManager.js'//依赖resourceEventType,Loader 14 | ], 15 | dest: 'dist/<%= pkg.name %>.js' 16 | } 17 | }, 18 | uglify: { 19 | build: { 20 | src: 'dist/<%= pkg.name %>.js', 21 | dest: 'dist/<%= pkg.name %>.min.js' 22 | } 23 | } 24 | }); 25 | grunt.loadNpmTasks('grunt-contrib-uglify'); 26 | grunt.loadNpmTasks('grunt-contrib-concat'); 27 | // 默认任务 28 | grunt.registerTask('default', ['concat', 'uglify']); 29 | }; -------------------------------------------------------------------------------- /juggle-resource/README.md: -------------------------------------------------------------------------------- 1 | # juggle-resource 2 | 3 | 4 | 5 | # juggle-resouce是一个资源库,支持加载多资源回调。 6 | 7 | 8 | 9 | 10 | 11 | ### 依赖juggle-help,juggle-event,juggle-http 12 | 13 | ### 快速开始: 14 | 15 | npm install juggle-resource 16 | 17 | ### 如何使用: 18 | 19 | ```html 20 | 21 | 22 | 23 | 24 | 25 | Title 26 | 27 | 28 | 29 | 30 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ``` 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /juggle-resource/dist/juggle-resource.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | function ResourceEventType() { 4 | /** 5 | * 加载完成 6 | * @type {string} 7 | */ 8 | this.LOAD_COMPLETE = "loadComplete"; 9 | /** 10 | * 加载失败 11 | * @type {string} 12 | */ 13 | this.LOAD_FAIL = "loadFail"; 14 | } 15 | 16 | window.juggle.resourceEventType = new ResourceEventType(); 17 | })(window); 18 | (function (window) { 19 | if (!window.juggle) window.juggle = {}; 20 | var EventDispatcher = window.juggle.EventDispatcher; 21 | var HttpClient = window.juggle.HttpClient; 22 | var httpEventType = window.juggle.httpEventType; 23 | var resourceEventType = window.juggle.resourceEventType; 24 | var Loader = function (loadList, data) { 25 | /** 26 | * 加载成功 27 | * @param event 28 | */ 29 | this.loadSuccess = function (event) { 30 | this.resultArray[event.mTarget.url] = event.mData; 31 | this.successNum++; 32 | if (this.successNum + this.failNum === this.loadList.length) { 33 | if (this.failNum > 0) { 34 | this.dispatchEventWith(resourceEventType.LOAD_FAIL); 35 | } else { 36 | this.dispatchEventWith(resourceEventType.LOAD_COMPLETE); 37 | } 38 | } 39 | }; 40 | /** 41 | * 加载失败 42 | * @param event 43 | */ 44 | this.loadError = function (event) { 45 | this.failNum++; 46 | if (this.successNum + this.failNum === this.loadList.length) { 47 | this.dispatchEventWith(resourceEventType.LOAD_FAIL); 48 | } 49 | 50 | }; 51 | this.loadList = loadList; 52 | this.resultArray = []; 53 | this.successNum = 0; 54 | this.failNum = 0; 55 | this.data = data; 56 | EventDispatcher.apply(this); 57 | //获取资源 58 | for (var i = 0; i < this.loadList.length; i++) { 59 | var httpClient = new HttpClient(); 60 | httpClient.send(null, this.loadList[i]); 61 | httpClient.addEventListener(httpEventType.SUCCESS, this.loadSuccess, this); 62 | httpClient.addEventListener(httpEventType.ERROR, this.loadError, this); 63 | } 64 | }; 65 | window.juggle.Loader = Loader; 66 | })(window); 67 | (function (window) { 68 | if (!window.juggle) window.juggle = {}; 69 | var Loader = window.juggle.Loader; 70 | var resourceEventType = window.juggle.resourceEventType; 71 | var ResourceManager = function () { 72 | this.resource = []; 73 | this.loadResource = function (url, success, fail, obj) { 74 | var loader = new Loader(url, [success, fail, obj]); 75 | loader.addEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete, this); 76 | loader.addEventListener(resourceEventType.LOAD_FAIL, this.loadFail, this); 77 | }; 78 | /** 79 | * 成功回调 80 | * @param event 81 | */ 82 | this.loadComplete = function (event) { 83 | event.mTarget.removeEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete); 84 | event.mTarget.removeEventListener(resourceEventType.LOAD_FAIL, this.loadComplete); 85 | for (var i = 0; i < event.mTarget.loadList.length; i++) { 86 | var url = event.mTarget.loadList[i]; 87 | this.resource[url] = event.mTarget.resultArray[url]; 88 | } 89 | event.mTarget.data[0].call(event.mTarget.data[2], event.mTarget.loadList); 90 | }; 91 | /** 92 | * 失败回调 93 | * @param event 94 | */ 95 | this.loadFail = function (event) { 96 | event.mTarget.removeEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete); 97 | event.mTarget.removeEventListener(resourceEventType.LOAD_FAIL, this.loadComplete); 98 | event.mTarget.data[1].call(event.mTarget.data[1], event.mTarget.loadList); 99 | }; 100 | this.getResource = function (url) { 101 | return this.resource[url]; 102 | } 103 | }; 104 | window.juggle.resourceManager = new ResourceManager(); 105 | })(window); -------------------------------------------------------------------------------- /juggle-resource/dist/juggle-resource.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.juggle||(t.juggle={}),t.juggle.resourceEventType=new function(){this.LOAD_COMPLETE="loadComplete",this.LOAD_FAIL="loadFail"}}(window),function(t){t.juggle||(t.juggle={});var e=t.juggle.EventDispatcher,i=t.juggle.HttpClient,s=t.juggle.httpEventType,a=t.juggle.resourceEventType;t.juggle.Loader=function(t,r){this.loadSuccess=function(t){this.resultArray[t.mTarget.url]=t.mData,++this.successNum+this.failNum===this.loadList.length&&(this.failNum>0?this.dispatchEventWith(a.LOAD_FAIL):this.dispatchEventWith(a.LOAD_COMPLETE))},this.loadError=function(t){this.failNum++,this.successNum+this.failNum===this.loadList.length&&this.dispatchEventWith(a.LOAD_FAIL)},this.loadList=t,this.resultArray=[],this.successNum=0,this.failNum=0,this.data=r,e.apply(this);for(var l=0;l 0) { 17 | this.dispatchEventWith(resourceEventType.LOAD_FAIL); 18 | } else { 19 | this.dispatchEventWith(resourceEventType.LOAD_COMPLETE); 20 | } 21 | } 22 | }; 23 | /** 24 | * 加载失败 25 | * @param event 26 | */ 27 | this.loadError = function (event) { 28 | this.failNum++; 29 | if (this.successNum + this.failNum === this.loadList.length) { 30 | this.dispatchEventWith(resourceEventType.LOAD_FAIL); 31 | } 32 | 33 | }; 34 | this.loadList = loadList; 35 | this.resultArray = []; 36 | this.successNum = 0; 37 | this.failNum = 0; 38 | this.data = data; 39 | EventDispatcher.apply(this); 40 | //获取资源 41 | for (var i = 0; i < this.loadList.length; i++) { 42 | var httpClient = new HttpClient(); 43 | httpClient.send(null, this.loadList[i]); 44 | httpClient.addEventListener(httpEventType.SUCCESS, this.loadSuccess, this); 45 | httpClient.addEventListener(httpEventType.ERROR, this.loadError, this); 46 | } 47 | }; 48 | window.juggle.Loader = Loader; 49 | })(window); -------------------------------------------------------------------------------- /juggle-resource/src/ResourceEventType.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | function ResourceEventType() { 4 | /** 5 | * 加载完成 6 | * @type {string} 7 | */ 8 | this.LOAD_COMPLETE = "loadComplete"; 9 | /** 10 | * 加载失败 11 | * @type {string} 12 | */ 13 | this.LOAD_FAIL = "loadFail"; 14 | } 15 | 16 | window.juggle.resourceEventType = new ResourceEventType(); 17 | })(window); -------------------------------------------------------------------------------- /juggle-resource/src/ResourceManager.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var Loader = window.juggle.Loader; 4 | var resourceEventType = window.juggle.resourceEventType; 5 | var ResourceManager = function () { 6 | this.resource = []; 7 | this.loadResource = function (url, success, fail, obj) { 8 | var loader = new Loader(url, [success, fail, obj]); 9 | loader.addEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete, this); 10 | loader.addEventListener(resourceEventType.LOAD_FAIL, this.loadFail, this); 11 | }; 12 | /** 13 | * 成功回调 14 | * @param event 15 | */ 16 | this.loadComplete = function (event) { 17 | event.mTarget.removeEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete); 18 | event.mTarget.removeEventListener(resourceEventType.LOAD_FAIL, this.loadComplete); 19 | for (var i = 0; i < event.mTarget.loadList.length; i++) { 20 | var url = event.mTarget.loadList[i]; 21 | this.resource[url] = event.mTarget.resultArray[url]; 22 | } 23 | event.mTarget.data[0].call(event.mTarget.data[2], event.mTarget.loadList); 24 | }; 25 | /** 26 | * 失败回调 27 | * @param event 28 | */ 29 | this.loadFail = function (event) { 30 | event.mTarget.removeEventListener(resourceEventType.LOAD_COMPLETE, this.loadComplete); 31 | event.mTarget.removeEventListener(resourceEventType.LOAD_FAIL, this.loadComplete); 32 | event.mTarget.data[1].call(event.mTarget.data[1], event.mTarget.loadList); 33 | }; 34 | this.getResource = function (url) { 35 | return this.resource[url]; 36 | } 37 | }; 38 | window.juggle.resourceManager = new ResourceManager(); 39 | })(window); -------------------------------------------------------------------------------- /juggle-tween-test/DisplayObject.js: -------------------------------------------------------------------------------- 1 | function DisplayObject(obj) { 2 | this.obj = obj; 3 | this.xValue = 0; 4 | this.yValue = 0; 5 | this.alphaValue = 0; 6 | this.visibility = "visible"; 7 | this.getX = function () { 8 | return this.xValue; 9 | }; 10 | this.setX = function (value) { 11 | this.xValue = value; 12 | this.draw(); 13 | }; 14 | this.getY = function () { 15 | return this.yValue; 16 | }; 17 | this.setY = function (value) { 18 | this.yValue = value; 19 | this.draw(); 20 | }; 21 | this.getAlpha = function () { 22 | return this.alphaValue; 23 | }; 24 | this.setAlpha = function (value) { 25 | this.alphaValue = value; 26 | this.draw(); 27 | }; 28 | this.setVisible = function (value) { 29 | if (value === true) { 30 | this.visibility = "visible"; 31 | } else { 32 | this.visibility = "hidden"; 33 | } 34 | this.draw(); 35 | }; 36 | this.draw = function () { 37 | this.obj.style.position = "absolute"; 38 | this.obj.style.top = this.yValue + "px"; 39 | this.obj.style.left = this.xValue + "px"; 40 | this.obj.style.opacity = this.alphaValue; 41 | this.obj.style.filter = "alpha(opacity=" + (this.alphaValue * 100) + "%)"; 42 | this.obj.style.visibility = this.visibility; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /juggle-tween-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 10 | 11 | 63 | 64 | 65 |
66 |
XXXXX
67 |
68 |
69 |
70 | 71 | 72 | -------------------------------------------------------------------------------- /juggle-tween/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/Transitions.js',//无依赖 12 | 'src/Tween.js',//依赖juggle-help,juggle-event,juggle-juggler,transitions 13 | 'src/TweenPool.js'//依赖Tween,juggle-help 14 | ], 15 | dest: 'dist/<%= pkg.name %>.js' 16 | } 17 | }, 18 | uglify: { 19 | build: { 20 | src: 'dist/<%= pkg.name %>.js', 21 | dest: 'dist/<%= pkg.name %>.min.js' 22 | } 23 | } 24 | }); 25 | grunt.loadNpmTasks('grunt-contrib-uglify'); 26 | grunt.loadNpmTasks('grunt-contrib-concat'); 27 | // 默认任务 28 | grunt.registerTask('default', ['concat', 'uglify']); 29 | }; -------------------------------------------------------------------------------- /juggle-tween/README.md: -------------------------------------------------------------------------------- 1 | # juggle-tween 2 | 3 | 4 | 5 | 6 | 7 | # juggle-tween是Tween类,拥有精准的动画 8 | 9 | ### 特点: 10 | 11 | 1、每次调用都是开始值+(终点-起点)*(经过时间/总时间),这是最稳定的,没有任何误差 12 | 2、连续调度,如果一次完成,剩余时间再次利用不浪费 13 | 14 | 15 | ### 依赖juggle-help,juggle-event,juggle-juggler 16 | 17 | ### 快速开始: 18 | 19 | npm install juggle-tween 20 | 21 | 22 | 23 | 24 | 线上例子地址: 25 | 26 | https://www.threecss.com/juggle-tween-test/test.html 27 | 28 | 29 | 30 | ### 如何使用: 31 | 32 | 33 | DisplayObject.js------------显示对象 34 | 35 | 36 | ```html 37 | 38 | function DisplayObject(obj) { 39 | this.obj = obj; 40 | this.xValue = 0; 41 | this.yValue = 0; 42 | this.alphaValue = 0; 43 | this.visibility = "visible"; 44 | this.getX = function () { 45 | return this.xValue; 46 | }; 47 | this.setX = function (value) { 48 | this.xValue = value; 49 | this.draw(); 50 | }; 51 | this.getY = function () { 52 | return this.yValue; 53 | }; 54 | this.setY = function (value) { 55 | this.yValue = value; 56 | this.draw(); 57 | }; 58 | this.getAlpha = function () { 59 | return this.alphaValue; 60 | }; 61 | this.setAlpha = function (value) { 62 | this.alphaValue = value; 63 | this.draw(); 64 | }; 65 | this.setVisible = function (value) { 66 | if (value === true) { 67 | this.visibility = "visible"; 68 | } else { 69 | this.visibility = "hidden"; 70 | } 71 | this.draw(); 72 | }; 73 | this.draw = function () { 74 | this.obj.style.position = "absolute"; 75 | this.obj.style.top = this.yValue + "px"; 76 | this.obj.style.left = this.xValue + "px"; 77 | this.obj.style.opacity = this.alphaValue; 78 | this.obj.style.filter = "alpha(opacity=" + (this.alphaValue * 100) + "%)"; 79 | this.obj.style.visibility = this.visibility; 80 | } 81 | } 82 | 83 | 84 | ``` 85 | 86 | test.html------------界面 87 | 88 | 89 | ```html 90 | 91 | 92 | 93 | 94 | 95 | Title 96 | 97 | 98 | 99 | 100 | 101 | 153 | 154 | 155 |
156 |
XXXXX
157 |
158 |
159 |
160 | 161 | 162 | 163 | 164 | ``` 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /juggle-tween/dist/juggle-tween.min.js: -------------------------------------------------------------------------------- 1 | !function(t){t.juggle||(t.juggle={});t.juggle.transitions=new function(){this.LINEAR="linear",this.EASE_IN="easeIn",this.EASE_OUT="easeOut",this.EASE_IN_OUT="easeInOut",this.EASE_OUT_IN="easeOutIn",this.EASE_IN_BACK="easeInBack",this.EASE_OUT_BACK="easeOutBack",this.EASE_IN_OUT_BACK="easeInOutBack",this.EASE_OUT_IN_BACK="easeOutInBack",this.EASE_IN_ELASTIC="easeInElastic",this.EASE_OUT_ELASTIC="easeOutElastic",this.EASE_IN_OUT_ELASTIC="easeInOutElastic",this.EASE_OUT_IN_ELASTIC="easeOutInElastic",this.EASE_IN_BOUNCE="easeInBounce",this.EASE_OUT_BOUNCE="easeOutBounce",this.EASE_IN_OUT_BOUNCE="easeInOutBounce",this.EASE_OUT_IN_BOUNCE="easeOutInBounce",this.sTransitions=null,this.getTransition=function(t){return null===this.sTransitions&&this.registerDefaults(),this.sTransitions[t]},this.register=function(t,e){null===this.sTransitions&&this.registerDefaults(),this.sTransitions[t]=e},this.registerDefaults=function(){this.sTransitions=[],this.register(this.LINEAR,this.linear),this.register(this.EASE_IN,this.easeIn),this.register(this.EASE_OUT,this.easeOut),this.register(this.EASE_IN_OUT,this.easeInOut),this.register(this.EASE_OUT_IN,this.easeOutIn),this.register(this.EASE_IN_BACK,this.easeInBack),this.register(this.EASE_OUT_BACK,this.easeOutBack),this.register(this.EASE_IN_OUT_BACK,this.easeInOutBack),this.register(this.EASE_OUT_IN_BACK,this.easeOutInBack),this.register(this.EASE_IN_ELASTIC,this.easeInElastic),this.register(this.EASE_OUT_ELASTIC,this.easeOutElastic),this.register(this.EASE_IN_OUT_ELASTIC,this.easeInOutElastic),this.register(this.EASE_OUT_IN_ELASTIC,this.easeOutInElastic),this.register(this.EASE_IN_BOUNCE,this.easeInBounce),this.register(this.EASE_OUT_BOUNCE,this.easeOutBounce),this.register(this.EASE_IN_OUT_BOUNCE,this.easeInOutBounce),this.register(this.EASE_OUT_IN_BOUNCE,this.easeOutInBounce)},this.linear=function(t){return t},this.easeIn=function(t){return t*t*t},this.easeOut=function(t){var e=t-1;return e*e*e+1},this.easeInOut=function(t){return this.easeCombined(this.easeIn,this.easeOut,t)},this.easeOutIn=function(t){return this.easeCombined(this.easeOut,this.easeIn,t)},this.easeInBack=function(t){var e=1.70158;return Math.pow(t,2)*((e+1)*t-e)},this.easeOutBack=function(t){var e=t-1,s=1.70158;return Math.pow(e,2)*((s+1)*e+s)+1},this.easeInOutBack=function(t){return this.easeCombined(this.easeInBack,this.easeOutBack,t)},this.easeOutInBack=function(t){return this.easeCombined(this.easeOutBack,this.easeInBack,t)},this.easeInElastic=function(t){if(0===t||1===t)return t;var e=t-1;return-1*Math.pow(2,10*e)*Math.sin((e-.075)*(2*Math.PI)/.3)},this.easeOutElastic=function(t){return 0===t||1===t?t:Math.pow(2,-10*t)*Math.sin((t-.075)*(2*Math.PI)/.3)+1},this.easeInOutElastic=function(t){return this.easeCombined(this.easeInElastic,this.easeOutElastic,t)},this.easeOutInElastic=function(t){return this.easeCombined(this.easeOutElastic,this.easeInElastic,t)},this.easeInBounce=function(t){return 1-this.easeOutBounce(1-t)},this.easeOutBounce=function(t){var e,s=7.5625,i=2.75;return t<1/i?e=s*Math.pow(t,2):t<2/i?(t-=1.5/i,e=s*Math.pow(t,2)+.75):t<2.5/i?(t-=2.25/i,e=s*Math.pow(t,2)+.9375):(t-=2.625/i,e=s*Math.pow(t,2)+.984375),e},this.easeInOutBounce=function(t){return this.easeCombined(this.easeInBounce,this.easeOutBounce,t)},this.easeOutInBounce=function(t){return this.easeCombined(this.easeOutBounce,this.easeInBounce,t)},this.easeCombined=function(t,e,s){return s<.5?.5*t.call(juggle.transitions,2*s):.5*e.call(juggle.transitions,2*(s-.5))+.5}}}(window),function(t){t.juggle||(t.juggle={});var e=t.juggle.tools,s=t.juggle.EventDispatcher,i=t.juggle.transitions,n=t.juggle.jugglerEventType;t.juggle.Tween=function(t,h,a){this.mTarget=null,this.mTransitionFunc=null,this.mProperties=null,this.mStartValues=null,this.mEndValues=null,this.mOnStart=null,this.mOnUpdate=null,this.mOnRepeat=null,this.mOnComplete=null,this.mOnStartArgs=null,this.mOnUpdateArgs=null,this.mOnRepeatArgs=null,this.mOnCompleteArgs=null,this.mTotalTime=null,this.mCurrentTime=null,this.mDelay=null,this.mRoundToInt=!1,this.mRepeatCount=null,this.mRepeatDelay=null,this.mReverse=null,this.mCurrentCycle=null,this.reset=function(t,s,i){return e.isNull(i)&&(i="linear"),this.mTarget=t,this.mCurrentTime=0,this.mTotalTime=Math.max(1e-4,s),this.mDelay=this.mRepeatDelay=0,this.mOnStart=this.mOnUpdate=this.mOnRepeat=this.mOnComplete=null,this.mOnStartArgs=this.mOnUpdateArgs=this.mOnRepeatArgs=this.mOnCompleteArgs=null,this.mRoundToInt=this.mReverse=!1,this.mRepeatCount=1,this.mCurrentCycle=-1,this.setTransition(i),this.mProperties?this.mProperties.length=0:this.mProperties=[],this.mStartValues?this.mStartValues.length=0:this.mStartValues=[],this.mEndValues?this.mEndValues.length=0:this.mEndValues=[],this},this.animate=function(t,s,i){e.isNull(this.mTarget)||(this.mProperties[this.mProperties.length]=s,this.mStartValues[this.mStartValues.length]=t.call(this.mTarget),this.mEndValues[this.mEndValues.length]=i)},this.advanceTime=function(t){if(0!==t&&(1!==this.mRepeatCount||this.mCurrentTime!==this.mTotalTime)){var s,h=this.mTotalTime-this.mCurrentTime,a=t>h?t-h:0;if(this.mCurrentTime+=t,!(this.mCurrentTime<=0)){this.mCurrentTime>this.mTotalTime&&(this.mCurrentTime=this.mTotalTime),this.mCurrentCycle<0&&(this.mCurrentCycle++,e.isNull(this.mOnStart)||this.mOnStart.call(this,this.mOnStartArgs));var u=this.mCurrentTime/this.mTotalTime,r=this.mReverse&&this.mCurrentCycle%2==1,l=this.mStartValues.length,m=r?this.mTransitionFunc.call(i,1-u):this.mTransitionFunc.call(i,u);for(s=0;s1)this.mCurrentTime=-this.mRepeatDelay,this.mCurrentCycle++,this.mRepeatCount>1&&this.mRepeatCount--,e.isNull(this.mOnRepeat)||this.mOnRepeat.call(this,this.mOnRepeatArgs);else{var E=this.mOnComplete,c=this.mOnCompleteArgs;this.dispatchEventWith(n.REMOVE_FROM_JUGGLER),e.isNull(E)||E.call(this,c)}a&&this.advanceTime(a)}}},this.isComplete=function(){return this.mCurrentTime===this.mTotalTime&&1===this.mRepeatCount},this.setTransition=function(t){this.mTransitionFunc=i.getTransition(t)},this.setDelay=function(t){this.mCurrentTime=this.mCurrentTime+this.mDelay-t,this.mDelay=t},this.reset(t,h,a),s.apply(this)}}(window),function(t){t.juggle||(t.juggle={});var e=t.juggle.tools,s=t.juggle.Tween;t.juggle.tweenPool=new function(){this.sTweenPool=[],this.fromPool=function(t,i,n){return e.isNull(n)&&(n="linear"),this.sTweenPool.length?this.sTweenPool.pop().reset(t,i,n):new s(t,i,n)},this.toPool=function(t){t.mOnStart=t.mOnUpdate=t.mOnRepeat=t.mOnComplete=null,t.mOnStartArgs=t.mOnUpdateArgs=t.mOnRepeatArgs=t.mOnCompleteArgs=null,t.mTarget=null,t.mTransitionFunc=null,t.mProperties.length=0,t.mStartValues.length=0,t.mEndValues.length=0,this.sTweenPool[this.sTweenPool.length]=t}}}(window); -------------------------------------------------------------------------------- /juggle-tween/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juggle-tween", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "juggle-tween.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/dianbaer/juggle" 12 | }, 13 | "keywords": [ 14 | "juggle","tween" 15 | ], 16 | "author": "dianbaer", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "grunt": "^1.0.1", 20 | "grunt-contrib-concat": "^1.0.1", 21 | "grunt-contrib-uglify": "^3.0.1" 22 | }, 23 | "dependencies": { 24 | "juggle-help": "^1.0.0", 25 | "juggle-event": "^1.0.0", 26 | "juggle-juggler": "^1.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /juggle-tween/src/Transitions.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var Transitions = function () { 4 | this.LINEAR = "linear"; 5 | this.EASE_IN = "easeIn"; 6 | this.EASE_OUT = "easeOut"; 7 | this.EASE_IN_OUT = "easeInOut"; 8 | this.EASE_OUT_IN = "easeOutIn"; 9 | this.EASE_IN_BACK = "easeInBack"; 10 | this.EASE_OUT_BACK = "easeOutBack"; 11 | this.EASE_IN_OUT_BACK = "easeInOutBack"; 12 | this.EASE_OUT_IN_BACK = "easeOutInBack"; 13 | this.EASE_IN_ELASTIC = "easeInElastic"; 14 | this.EASE_OUT_ELASTIC = "easeOutElastic"; 15 | this.EASE_IN_OUT_ELASTIC = "easeInOutElastic"; 16 | this.EASE_OUT_IN_ELASTIC = "easeOutInElastic"; 17 | this.EASE_IN_BOUNCE = "easeInBounce"; 18 | this.EASE_OUT_BOUNCE = "easeOutBounce"; 19 | this.EASE_IN_OUT_BOUNCE = "easeInOutBounce"; 20 | this.EASE_OUT_IN_BOUNCE = "easeOutInBounce"; 21 | 22 | this.sTransitions = null; 23 | 24 | this.getTransition = function (name) { 25 | if (this.sTransitions === null) 26 | this.registerDefaults(); 27 | return this.sTransitions[name]; 28 | }; 29 | this.register = function (name, func) { 30 | if (this.sTransitions === null) 31 | this.registerDefaults(); 32 | this.sTransitions[name] = func; 33 | }; 34 | this.registerDefaults = function () { 35 | this.sTransitions = []; 36 | 37 | this.register(this.LINEAR, this.linear); 38 | this.register(this.EASE_IN, this.easeIn); 39 | this.register(this.EASE_OUT, this.easeOut); 40 | this.register(this.EASE_IN_OUT, this.easeInOut); 41 | this.register(this.EASE_OUT_IN, this.easeOutIn); 42 | this.register(this.EASE_IN_BACK, this.easeInBack); 43 | this.register(this.EASE_OUT_BACK, this.easeOutBack); 44 | this.register(this.EASE_IN_OUT_BACK, this.easeInOutBack); 45 | this.register(this.EASE_OUT_IN_BACK, this.easeOutInBack); 46 | this.register(this.EASE_IN_ELASTIC, this.easeInElastic); 47 | this.register(this.EASE_OUT_ELASTIC, this.easeOutElastic); 48 | this.register(this.EASE_IN_OUT_ELASTIC, this.easeInOutElastic); 49 | this.register(this.EASE_OUT_IN_ELASTIC, this.easeOutInElastic); 50 | this.register(this.EASE_IN_BOUNCE, this.easeInBounce); 51 | this.register(this.EASE_OUT_BOUNCE, this.easeOutBounce); 52 | this.register(this.EASE_IN_OUT_BOUNCE, this.easeInOutBounce); 53 | this.register(this.EASE_OUT_IN_BOUNCE, this.easeOutInBounce); 54 | }; 55 | this.linear = function (ratio) { 56 | return ratio; 57 | }; 58 | 59 | this.easeIn = function (ratio) { 60 | return ratio * ratio * ratio; 61 | }; 62 | 63 | this.easeOut = function (ratio) { 64 | var invRatio = ratio - 1.0; 65 | return invRatio * invRatio * invRatio + 1; 66 | }; 67 | 68 | this.easeInOut = function (ratio) { 69 | return this.easeCombined(this.easeIn, this.easeOut, ratio); 70 | }; 71 | 72 | this.easeOutIn = function (ratio) { 73 | return this.easeCombined(this.easeOut, this.easeIn, ratio); 74 | }; 75 | 76 | this.easeInBack = function (ratio) { 77 | var s = 1.70158; 78 | return Math.pow(ratio, 2) * ((s + 1.0) * ratio - s); 79 | }; 80 | 81 | this.easeOutBack = function (ratio) { 82 | var invRatio = ratio - 1.0; 83 | var s = 1.70158; 84 | return Math.pow(invRatio, 2) * ((s + 1.0) * invRatio + s) + 1.0; 85 | }; 86 | 87 | this.easeInOutBack = function (ratio) { 88 | return this.easeCombined(this.easeInBack, this.easeOutBack, ratio); 89 | }; 90 | 91 | this.easeOutInBack = function (ratio) { 92 | return this.easeCombined(this.easeOutBack, this.easeInBack, ratio); 93 | }; 94 | 95 | this.easeInElastic = function (ratio) { 96 | if (ratio === 0 || ratio === 1) 97 | return ratio; 98 | else { 99 | var p = 0.3; 100 | var s = p / 4.0; 101 | var invRatio = ratio - 1; 102 | return -1.0 * Math.pow(2.0, 10.0 * invRatio) * Math.sin((invRatio - s) * (2.0 * Math.PI) / p); 103 | } 104 | }; 105 | 106 | this.easeOutElastic = function (ratio) { 107 | if (ratio === 0 || ratio === 1) 108 | return ratio; 109 | else { 110 | var p = 0.3; 111 | var s = p / 4.0; 112 | return Math.pow(2.0, -10.0 * ratio) * Math.sin((ratio - s) * (2.0 * Math.PI) / p) + 1; 113 | } 114 | }; 115 | 116 | this.easeInOutElastic = function (ratio) { 117 | return this.easeCombined(this.easeInElastic, this.easeOutElastic, ratio); 118 | }; 119 | 120 | this.easeOutInElastic = function (ratio) { 121 | return this.easeCombined(this.easeOutElastic, this.easeInElastic, ratio); 122 | }; 123 | 124 | this.easeInBounce = function (ratio) { 125 | return 1.0 - this.easeOutBounce(1.0 - ratio); 126 | }; 127 | 128 | this.easeOutBounce = function (ratio) { 129 | var s = 7.5625; 130 | var p = 2.75; 131 | var l; 132 | if (ratio < (1.0 / p)) { 133 | l = s * Math.pow(ratio, 2); 134 | } else { 135 | if (ratio < (2.0 / p)) { 136 | ratio -= 1.5 / p; 137 | l = s * Math.pow(ratio, 2) + 0.75; 138 | } else { 139 | if (ratio < 2.5 / p) { 140 | ratio -= 2.25 / p; 141 | l = s * Math.pow(ratio, 2) + 0.9375; 142 | } else { 143 | ratio -= 2.625 / p; 144 | l = s * Math.pow(ratio, 2) + 0.984375; 145 | } 146 | } 147 | } 148 | return l; 149 | }; 150 | 151 | this.easeInOutBounce = function (ratio) { 152 | return this.easeCombined(this.easeInBounce, this.easeOutBounce, ratio); 153 | }; 154 | 155 | this.easeOutInBounce = function (ratio) { 156 | return this.easeCombined(this.easeOutBounce, this.easeInBounce, ratio); 157 | }; 158 | 159 | this.easeCombined = function (startFunc, endFunc, ratio) { 160 | if (ratio < 0.5) 161 | return 0.5 * startFunc.call(juggle.transitions, ratio * 2.0); 162 | else 163 | return 0.5 * endFunc.call(juggle.transitions, (ratio - 0.5) * 2.0) + 0.5; 164 | } 165 | }; 166 | window.juggle.transitions = new Transitions(); 167 | })(window); -------------------------------------------------------------------------------- /juggle-tween/src/Tween.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | var EventDispatcher = window.juggle.EventDispatcher; 5 | var transitions = window.juggle.transitions; 6 | var jugglerEventType = window.juggle.jugglerEventType; 7 | /** 8 | * 核心在于每次调用都是开始值+(终点-起点)*(经过时间/总时间),这是最稳定的,没有任何误差 9 | * @param target 10 | * @param time 11 | * @param transition 12 | * @constructor 13 | */ 14 | var Tween = function (target, time, transition) { 15 | //动画目标 16 | this.mTarget = null; 17 | //动画变换函数 18 | this.mTransitionFunc = null; 19 | //设置属性的函数列表 20 | this.mProperties = null; 21 | //起始值(这个值时获取属性函数自动获取到的) 22 | this.mStartValues = null; 23 | //结束值 24 | this.mEndValues = null; 25 | //每个阶段的回调函数 26 | this.mOnStart = null; 27 | this.mOnUpdate = null; 28 | this.mOnRepeat = null; 29 | this.mOnComplete = null; 30 | //每个阶段回调函数携带的参数 31 | this.mOnStartArgs = null; 32 | this.mOnUpdateArgs = null; 33 | this.mOnRepeatArgs = null; 34 | this.mOnCompleteArgs = null; 35 | //总时间 36 | this.mTotalTime = null; 37 | //当前时间 38 | this.mCurrentTime = null; 39 | 40 | //开始动画时延迟调用时间,修改这个参数没有,需要调方法setDelay 41 | this.mDelay = null; 42 | //是否取整,取整动画不平滑 43 | this.mRoundToInt = false; 44 | //0代表无限次重复,>1代表重复次数 45 | this.mRepeatCount = null; 46 | //重复动画时延迟调用间隔 47 | this.mRepeatDelay = null; 48 | //偶数轮是否逆向 49 | this.mReverse = null; 50 | //当前第几轮,初始为-1,跟mReverse参数搭配使用 51 | this.mCurrentCycle = null; 52 | this.reset = function (target, time, transition) { 53 | if (tools.isNull(transition)) { 54 | transition = "linear"; 55 | } 56 | this.mTarget = target; 57 | this.mCurrentTime = 0.0; 58 | this.mTotalTime = Math.max(0.0001, time); 59 | this.mDelay = this.mRepeatDelay = 0.0; 60 | this.mOnStart = this.mOnUpdate = this.mOnRepeat = this.mOnComplete = null; 61 | this.mOnStartArgs = this.mOnUpdateArgs = this.mOnRepeatArgs = this.mOnCompleteArgs = null; 62 | this.mRoundToInt = this.mReverse = false; 63 | this.mRepeatCount = 1; 64 | this.mCurrentCycle = -1; 65 | this.setTransition(transition); 66 | if (this.mProperties) { 67 | this.mProperties.length = 0; 68 | } else { 69 | this.mProperties = []; 70 | } 71 | if (this.mStartValues) { 72 | this.mStartValues.length = 0; 73 | } else { 74 | this.mStartValues = []; 75 | } 76 | if (this.mEndValues) { 77 | this.mEndValues.length = 0; 78 | } else { 79 | this.mEndValues = []; 80 | } 81 | return this; 82 | }; 83 | 84 | /** 85 | * 设置动画 86 | * @param getValue 获取值得方法 87 | * @param setValue 设置值得方法 88 | * @param endValue 达到值 89 | */ 90 | this.animate = function (getValue, setValue, endValue) { 91 | if (tools.isNull(this.mTarget)) 92 | return; 93 | this.mProperties[this.mProperties.length] = setValue; 94 | this.mStartValues[this.mStartValues.length] = getValue.call(this.mTarget); 95 | this.mEndValues[this.mEndValues.length] = endValue; 96 | }; 97 | this.advanceTime = function (time) { 98 | //经历时间为0或者重复次数是1并且当前时间等于总时间 99 | if (time === 0 || (this.mRepeatCount === 1 && this.mCurrentTime === this.mTotalTime)) 100 | return; 101 | var i; 102 | var restTime = this.mTotalTime - this.mCurrentTime; 103 | //多余的时间 104 | var carryOverTime = time > restTime ? time - restTime : 0.0; 105 | this.mCurrentTime += time; 106 | //小于等于0说明还没开始 107 | if (this.mCurrentTime <= 0) 108 | return; 109 | //大于总时间则设置等于总时间,前面已经取出多余的时间 110 | else if (this.mCurrentTime > this.mTotalTime) 111 | this.mCurrentTime = this.mTotalTime; 112 | //开始动画 113 | if (this.mCurrentCycle < 0) { 114 | this.mCurrentCycle++; 115 | if (!tools.isNull(this.mOnStart)) 116 | this.mOnStart.call(this, this.mOnStartArgs); 117 | } 118 | //比例 119 | var ratio = this.mCurrentTime / this.mTotalTime; 120 | //是否逆向计算 121 | var reversed = this.mReverse && (this.mCurrentCycle % 2 === 1); 122 | var numProperties = this.mStartValues.length; 123 | //进度 124 | var mProgress = reversed ? this.mTransitionFunc.call(transitions, 1.0 - ratio) : this.mTransitionFunc.call(transitions, ratio); 125 | 126 | for (i = 0; i < numProperties; ++i) { 127 | var startValue = this.mStartValues[i]; 128 | var endValue = this.mEndValues[i]; 129 | var delta = endValue - startValue; 130 | //每次都是开始值+应该增加的值,这样没有误差 131 | var currentValue = startValue + mProgress * delta; 132 | //取整 133 | if (this.mRoundToInt) 134 | currentValue = Math.round(currentValue); 135 | //改变属性 136 | this.mProperties[i].call(this.mTarget, currentValue); 137 | } 138 | if (!tools.isNull(this.mOnUpdate)) 139 | this.mOnUpdate.call(this, this.mOnUpdateArgs); 140 | //相等时 141 | if (this.mCurrentTime === this.mTotalTime) { 142 | //无限次或者大于1次 143 | if (this.mRepeatCount === 0 || this.mRepeatCount > 1) { 144 | this.mCurrentTime = -this.mRepeatDelay; 145 | this.mCurrentCycle++; 146 | if (this.mRepeatCount > 1) 147 | this.mRepeatCount--; 148 | if (!tools.isNull(this.mOnRepeat)) 149 | this.mOnRepeat.call(this, this.mOnRepeatArgs); 150 | } else { 151 | //保存成功回调函数和回调参数,防止派发事件的时候清理这些属性,很安全 152 | var onComplete = this.mOnComplete; 153 | var onCompleteArgs = this.mOnCompleteArgs; 154 | //先派发事件,在回调完成函数 155 | this.dispatchEventWith(jugglerEventType.REMOVE_FROM_JUGGLER); 156 | if (!tools.isNull(onComplete)) 157 | onComplete.call(this, onCompleteArgs); 158 | } 159 | } 160 | //这块也不用担心,advanceTime开头有限制,如果是完成了,直接返回 161 | if (carryOverTime) 162 | this.advanceTime(carryOverTime); 163 | }; 164 | 165 | this.isComplete = function () { 166 | //这块也是,只有可能等于 167 | return this.mCurrentTime === this.mTotalTime && this.mRepeatCount === 1; 168 | }; 169 | this.setTransition = function (value) { 170 | this.mTransitionFunc = transitions.getTransition(value); 171 | }; 172 | /** 173 | * 修改延迟,先加回原先的延迟,再减去现在的延迟 174 | * @param value 175 | */ 176 | this.setDelay = function (value) { 177 | this.mCurrentTime = this.mCurrentTime + this.mDelay - value; 178 | this.mDelay = value; 179 | }; 180 | this.reset(target, time, transition); 181 | EventDispatcher.apply(this); 182 | }; 183 | window.juggle.Tween = Tween; 184 | })(window); -------------------------------------------------------------------------------- /juggle-tween/src/TweenPool.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var tools = window.juggle.tools; 4 | var Tween = window.juggle.Tween; 5 | var TweenPool = function () { 6 | this.sTweenPool = []; 7 | 8 | this.fromPool = function (target, time, transition) { 9 | if (tools.isNull(transition)) { 10 | transition = "linear"; 11 | } 12 | if (this.sTweenPool.length) 13 | return this.sTweenPool.pop().reset(target, time, transition); 14 | else { 15 | return new Tween(target, time, transition); 16 | } 17 | }; 18 | 19 | this.toPool = function (tween) { 20 | tween.mOnStart = tween.mOnUpdate = tween.mOnRepeat = tween.mOnComplete = null; 21 | tween.mOnStartArgs = tween.mOnUpdateArgs = tween.mOnRepeatArgs = tween.mOnCompleteArgs = null; 22 | tween.mTarget = null; 23 | tween.mTransitionFunc = null; 24 | tween.mProperties.length = 0; 25 | tween.mStartValues.length = 0; 26 | tween.mEndValues.length = 0; 27 | this.sTweenPool[this.sTweenPool.length] = tween; 28 | } 29 | }; 30 | window.juggle.tweenPool = new TweenPool(); 31 | })(window); -------------------------------------------------------------------------------- /juggle-websocket-test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 7 | 8 | 9 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /juggle-websocket/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | // 项目配置 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | concat: { 6 | options: { 7 | separator: '\n\r' 8 | }, 9 | dist: { 10 | src: [ 11 | 'src/WebSocketEventType.js',//无依赖 12 | 'src/WebSocketConfig.js',//无依赖 13 | 'src/WebSocketClient.js'//依赖WebSocketEventType,WebSocketConfig,juggle-event 14 | ], 15 | dest: 'dist/<%= pkg.name %>.js' 16 | } 17 | }, 18 | uglify: { 19 | build: { 20 | src: 'dist/<%= pkg.name %>.js', 21 | dest: 'dist/<%= pkg.name %>.min.js' 22 | } 23 | } 24 | }); 25 | grunt.loadNpmTasks('grunt-contrib-uglify'); 26 | grunt.loadNpmTasks('grunt-contrib-concat'); 27 | // 默认任务 28 | grunt.registerTask('default', ['concat', 'uglify']); 29 | }; -------------------------------------------------------------------------------- /juggle-websocket/README.md: -------------------------------------------------------------------------------- 1 | # juggle-websocket 2 | 3 | 4 | 5 | # juggle-websocket是一个支持事件派发的websocket客户端 6 | 7 | 8 | ### 特点: 9 | 10 | 11 | 1、支持事件派发 12 | 13 | 14 | 15 | ### 依赖juggle-help,juggle-event 16 | 17 | 18 | ### 快速开始: 19 | 20 | 21 | npm install juggle-websocket 22 | 23 | 24 | ### 如何使用: 25 | 26 | 27 | ```html 28 | 29 | 30 | 31 | 32 | 33 | Title 34 | 35 | 36 | 37 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | ``` 70 | 71 | websocket服务器(直接可用): 72 | 73 | https://github.com/dianbaer/grain/tree/master/grain-threadwebsocket-test 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /juggle-websocket/dist/juggle-websocket.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var WebSocketEventType = function () { 4 | // 链接完成 5 | this.CONNECTED = "connected"; 6 | // 关闭 7 | this.CLOSE = "close"; 8 | // 接到消息 9 | this.WSMESSAGE = "wsmessage"; 10 | this.getMessage = function (wsOpCode) { 11 | return this.WSMESSAGE + "_" + wsOpCode; 12 | } 13 | }; 14 | window.juggle.webSocketEventType = new WebSocketEventType(); 15 | })(window); 16 | (function (window) { 17 | if (!window.juggle) window.juggle = {}; 18 | var WebSocketConfig = function () { 19 | this.WSOPCODE = "wsOpCode";// 操作码 20 | }; 21 | window.juggle.webSocketConfig = new WebSocketConfig(); 22 | })(window); 23 | (function (window) { 24 | if (!window.juggle) window.juggle = {}; 25 | var EventDispatcher = window.juggle.EventDispatcher; 26 | var webSocketEventType = window.juggle.webSocketEventType; 27 | var webSocketConfig = window.juggle.webSocketConfig; 28 | /** 29 | * 创建websocket客户端 30 | * @param url 31 | * @constructor 32 | */ 33 | var WebSocketClient = function (url) { 34 | this.webSocket = null; 35 | this.isConnected = false; 36 | this.url = url; 37 | this.connect = function () { 38 | //创建链接 39 | this.webSocket = new WebSocket(this.url); 40 | //关注状态 41 | this.onOpenListener(this, this.onOpen); 42 | this.onCloseListener(this, this.onClose); 43 | this.onErrorListener(this, this.onError); 44 | this.onMessageListener(this, this.onMessage); 45 | }; 46 | this.onOpenListener = function (webSocketClient, call) { 47 | var callFunc = function (event) { 48 | call.call(webSocketClient, event); 49 | }; 50 | webSocketClient.webSocket.onopen = callFunc; 51 | 52 | }; 53 | this.onCloseListener = function (webSocketClient, call) { 54 | var callFunc = function (event) { 55 | call.call(webSocketClient, event); 56 | }; 57 | webSocketClient.webSocket.onclose = callFunc; 58 | 59 | }; 60 | this.onErrorListener = function (webSocketClient, call) { 61 | var callFunc = function (event) { 62 | call.call(webSocketClient, event); 63 | }; 64 | webSocketClient.webSocket.onerror = callFunc; 65 | 66 | }; 67 | this.onMessageListener = function (webSocketClient, call) { 68 | var callFunc = function (event) { 69 | call.call(webSocketClient, event); 70 | }; 71 | webSocketClient.webSocket.onmessage = callFunc; 72 | 73 | }; 74 | /** 75 | * 链接成功设置状态,派发事件 76 | * @param event 77 | */ 78 | this.onOpen = function (event) { 79 | this.isConnected = true; 80 | this.dispatchEventWith(webSocketEventType.CONNECTED); 81 | }; 82 | /** 83 | * 发送数据 84 | * @param data json格式的 85 | */ 86 | this.send = function (data) { 87 | if (!this.isConnected) { 88 | alert("未链接至websocket服务器"); 89 | return; 90 | } 91 | var blob = new Blob([JSON.stringify(data)]); 92 | this.webSocket.send(blob); 93 | }; 94 | /** 95 | * 接到消息派发不同类型消息的事件 96 | * @param event 97 | */ 98 | this.onMessage = function (event) { 99 | var data = JSON.parse(event.data); 100 | if (data[webSocketConfig.WSOPCODE] === null || data[webSocketConfig.WSOPCODE] === undefined) { 101 | return; 102 | } 103 | this.dispatchEventWith(webSocketEventType.getMessage(data[webSocketConfig.WSOPCODE]), false, data); 104 | }; 105 | /** 106 | * 关闭时设置状态并且派发事件 107 | * @param event 108 | */ 109 | this.onClose = function (event) { 110 | this.isConnected = false; 111 | this.dispatchEventWith(webSocketEventType.CLOSE); 112 | }; 113 | this.onError = function (event) { 114 | 115 | }; 116 | /** 117 | * 主动关闭 118 | */ 119 | this.close = function () { 120 | this.webSocket.close(); 121 | }; 122 | EventDispatcher.apply(this); 123 | this.connect(); 124 | }; 125 | window.juggle.WebSocketClient = WebSocketClient; 126 | })(window); -------------------------------------------------------------------------------- /juggle-websocket/dist/juggle-websocket.min.js: -------------------------------------------------------------------------------- 1 | !function(e){e.juggle||(e.juggle={});e.juggle.webSocketEventType=new function(){this.CONNECTED="connected",this.CLOSE="close",this.WSMESSAGE="wsmessage",this.getMessage=function(e){return this.WSMESSAGE+"_"+e}}}(window),function(e){e.juggle||(e.juggle={});e.juggle.webSocketConfig=new function(){this.WSOPCODE="wsOpCode"}}(window),function(e){e.juggle||(e.juggle={});var t=e.juggle.EventDispatcher,n=e.juggle.webSocketEventType,i=e.juggle.webSocketConfig;e.juggle.WebSocketClient=function(e){this.webSocket=null,this.isConnected=!1,this.url=e,this.connect=function(){this.webSocket=new WebSocket(this.url),this.onOpenListener(this,this.onOpen),this.onCloseListener(this,this.onClose),this.onErrorListener(this,this.onError),this.onMessageListener(this,this.onMessage)},this.onOpenListener=function(e,t){e.webSocket.onopen=function(n){t.call(e,n)}},this.onCloseListener=function(e,t){e.webSocket.onclose=function(n){t.call(e,n)}},this.onErrorListener=function(e,t){e.webSocket.onerror=function(n){t.call(e,n)}},this.onMessageListener=function(e,t){e.webSocket.onmessage=function(n){t.call(e,n)}},this.onOpen=function(e){this.isConnected=!0,this.dispatchEventWith(n.CONNECTED)},this.send=function(e){if(this.isConnected){var t=new Blob([JSON.stringify(e)]);this.webSocket.send(t)}else alert("未链接至websocket服务器")},this.onMessage=function(e){var t=JSON.parse(e.data);null!==t[i.WSOPCODE]&&void 0!==t[i.WSOPCODE]&&this.dispatchEventWith(n.getMessage(t[i.WSOPCODE]),!1,t)},this.onClose=function(e){this.isConnected=!1,this.dispatchEventWith(n.CLOSE)},this.onError=function(e){},this.close=function(){this.webSocket.close()},t.apply(this),this.connect()}}(window); -------------------------------------------------------------------------------- /juggle-websocket/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juggle-websocket", 3 | "version": "1.0.1", 4 | "description": "", 5 | "main": "juggle-websocket.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/dianbaer/juggle" 12 | }, 13 | "keywords": [ 14 | "juggle", 15 | "websocket" 16 | ], 17 | "author": "dianbaer", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "grunt": "^1.0.1", 21 | "grunt-contrib-concat": "^1.0.1", 22 | "grunt-contrib-uglify": "^3.0.1" 23 | }, 24 | "dependencies": { 25 | "juggle-help": "^1.0.0", 26 | "juggle-event": "^1.0.0" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /juggle-websocket/src/WebSocketClient.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var EventDispatcher = window.juggle.EventDispatcher; 4 | var webSocketEventType = window.juggle.webSocketEventType; 5 | var webSocketConfig = window.juggle.webSocketConfig; 6 | /** 7 | * 创建websocket客户端 8 | * @param url 9 | * @constructor 10 | */ 11 | var WebSocketClient = function (url) { 12 | this.webSocket = null; 13 | this.isConnected = false; 14 | this.url = url; 15 | this.connect = function () { 16 | //创建链接 17 | this.webSocket = new WebSocket(this.url); 18 | //关注状态 19 | this.onOpenListener(this, this.onOpen); 20 | this.onCloseListener(this, this.onClose); 21 | this.onErrorListener(this, this.onError); 22 | this.onMessageListener(this, this.onMessage); 23 | }; 24 | this.onOpenListener = function (webSocketClient, call) { 25 | var callFunc = function (event) { 26 | call.call(webSocketClient, event); 27 | }; 28 | webSocketClient.webSocket.onopen = callFunc; 29 | 30 | }; 31 | this.onCloseListener = function (webSocketClient, call) { 32 | var callFunc = function (event) { 33 | call.call(webSocketClient, event); 34 | }; 35 | webSocketClient.webSocket.onclose = callFunc; 36 | 37 | }; 38 | this.onErrorListener = function (webSocketClient, call) { 39 | var callFunc = function (event) { 40 | call.call(webSocketClient, event); 41 | }; 42 | webSocketClient.webSocket.onerror = callFunc; 43 | 44 | }; 45 | this.onMessageListener = function (webSocketClient, call) { 46 | var callFunc = function (event) { 47 | call.call(webSocketClient, event); 48 | }; 49 | webSocketClient.webSocket.onmessage = callFunc; 50 | 51 | }; 52 | /** 53 | * 链接成功设置状态,派发事件 54 | * @param event 55 | */ 56 | this.onOpen = function (event) { 57 | this.isConnected = true; 58 | this.dispatchEventWith(webSocketEventType.CONNECTED); 59 | }; 60 | /** 61 | * 发送数据 62 | * @param data json格式的 63 | */ 64 | this.send = function (data) { 65 | if (!this.isConnected) { 66 | alert("未链接至websocket服务器"); 67 | return; 68 | } 69 | var blob = new Blob([JSON.stringify(data)]); 70 | this.webSocket.send(blob); 71 | }; 72 | /** 73 | * 接到消息派发不同类型消息的事件 74 | * @param event 75 | */ 76 | this.onMessage = function (event) { 77 | var data = JSON.parse(event.data); 78 | if (data[webSocketConfig.WSOPCODE] === null || data[webSocketConfig.WSOPCODE] === undefined) { 79 | return; 80 | } 81 | this.dispatchEventWith(webSocketEventType.getMessage(data[webSocketConfig.WSOPCODE]), false, data); 82 | }; 83 | /** 84 | * 关闭时设置状态并且派发事件 85 | * @param event 86 | */ 87 | this.onClose = function (event) { 88 | this.isConnected = false; 89 | this.dispatchEventWith(webSocketEventType.CLOSE); 90 | }; 91 | this.onError = function (event) { 92 | 93 | }; 94 | /** 95 | * 主动关闭 96 | */ 97 | this.close = function () { 98 | this.webSocket.close(); 99 | }; 100 | EventDispatcher.apply(this); 101 | this.connect(); 102 | }; 103 | window.juggle.WebSocketClient = WebSocketClient; 104 | })(window); -------------------------------------------------------------------------------- /juggle-websocket/src/WebSocketConfig.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var WebSocketConfig = function () { 4 | this.WSOPCODE = "wsOpCode";// 操作码 5 | }; 6 | window.juggle.webSocketConfig = new WebSocketConfig(); 7 | })(window); -------------------------------------------------------------------------------- /juggle-websocket/src/WebSocketEventType.js: -------------------------------------------------------------------------------- 1 | (function (window) { 2 | if (!window.juggle) window.juggle = {}; 3 | var WebSocketEventType = function () { 4 | // 链接完成 5 | this.CONNECTED = "connected"; 6 | // 关闭 7 | this.CLOSE = "close"; 8 | // 接到消息 9 | this.WSMESSAGE = "wsmessage"; 10 | this.getMessage = function (wsOpCode) { 11 | return this.WSMESSAGE + "_" + wsOpCode; 12 | } 13 | }; 14 | window.juggle.webSocketEventType = new WebSocketEventType(); 15 | })(window); -------------------------------------------------------------------------------- /juggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dianbaer/juggle/b34def1c146b6ef45bb2d683a04c2dba0bc1efc1/juggle.png -------------------------------------------------------------------------------- /juggle.vsd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dianbaer/juggle/b34def1c146b6ef45bb2d683a04c2dba0bc1efc1/juggle.vsd -------------------------------------------------------------------------------- /npm.txt: -------------------------------------------------------------------------------- 1 | ### 上传npm包 2 | 3 | npm pack 4 | 5 | npm adduser 6 | 7 | npm publish 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "juggle-all", 3 | "version": "1.0.5", 4 | "description": "juggle-all", 5 | "author": "dianbaer", 6 | "license": "MIT", 7 | "main": "juggle-all.js", 8 | "typings": "", 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/dianbaer/juggle" 12 | }, 13 | "scripts": { 14 | "test": "gulp test", 15 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -w -r 0" 16 | }, 17 | "devDependencies": { 18 | "grunt": "^1.0.1", 19 | "grunt-contrib-concat": "^1.0.1", 20 | "grunt-contrib-uglify": "^3.0.1", 21 | "conventional-changelog-cli": "^1.3.3", 22 | "del": "^1.2.0", 23 | "gulp": "^3.9.0", 24 | "gulp-concat": "^2.6.0", 25 | "gulp-footer": "^1.0.5", 26 | "gulp-header": "^1.2.2", 27 | "gulp-if": "^1.2.5", 28 | "gulp-jshint": "^2.0.4", 29 | "gulp-rename": "^1.2.2", 30 | "gulp-replace": "~0.5.4", 31 | "gulp-shell": "^0.4.2", 32 | "gulp-transform-module": "~2.1.1", 33 | "gulp-uglify": "^1.2.0", 34 | "gulp-uitest": "^0.1.1", 35 | "gulp-zip": "^3.0.2", 36 | "jshint": "^2.9.4", 37 | "merge-stream": "^0.1.8", 38 | "mocha": "=3.0.2", 39 | "should": "^8.0.2", 40 | "through2": "^2.0.0", 41 | "uitest": "^1.1.4" 42 | }, 43 | "sources": { 44 | "files": [ 45 | "juggle-help/src/Tools.js" 46 | ] 47 | }, 48 | "extensions": {} 49 | } 50 | -------------------------------------------------------------------------------- /test/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | hilo test 5 | 6 | 7 | 8 | 24 | 25 | 26 |
27 |
28 | 29 | 30 | 31 | 32 | 50 | 51 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /test/tweentest.js: -------------------------------------------------------------------------------- 1 | describe('geom', function(){ 2 | 3 | beforeEach('init matrix', function(){ 4 | 5 | }); 6 | 7 | describe('Matrix', function(){ 8 | it('concat', function(){ 9 | var i = 1; 10 | i.should.eql(1); 11 | 12 | }); 13 | 14 | it('rotate', function(){ 15 | var i = 1; 16 | i.should.eql(1); 17 | }); 18 | 19 | it('scale', function(){ 20 | var i = 1; 21 | i.should.eql(1); 22 | }); 23 | 24 | it('translate', function(){ 25 | var i = 1; 26 | i.should.eql(1); 27 | }); 28 | 29 | it('identity', function(){ 30 | var i = 1; 31 | i.should.eql(1); 32 | }); 33 | 34 | it('invert', function(){ 35 | var i = 1; 36 | i.should.eql(1); 37 | }); 38 | 39 | it('transformPoint', function(){ 40 | var i = 1; 41 | i.should.eql(1); 42 | }); 43 | }); 44 | }); 45 | 46 | --------------------------------------------------------------------------------