├── .eslintrc ├── .gitignore ├── .stylelintrc ├── README.md ├── __test__ ├── e2e │ └── index.js ├── index.js └── play.js ├── build ├── rollup.config.base.js ├── rollup.config.common.js ├── rollup.config.es.js ├── rollup.config.min.js └── rollup.config.umd.js ├── coverage └── chrome │ ├── base.css │ ├── index.html │ ├── prettify.css │ ├── prettify.js │ ├── sort-arrow-sprite.png │ ├── sorter.js │ └── src │ ├── base.js.html │ ├── clarity.js.html │ ├── component.js.html │ ├── createchild.js.html │ ├── index.html │ ├── index.js.html │ ├── play.js.html │ ├── progressbar.js.html │ ├── progresstime.js.html │ ├── screen.js.html │ └── volume.js.html ├── demo ├── chimee.js ├── icon │ ├── pause.svg │ ├── play.svg │ ├── screen-full.svg │ ├── screen-small.svg │ ├── volume-high.svg │ ├── volume-low.svg │ └── volume-mute.svg └── index.html ├── dev.md ├── karma.conf.js ├── lib ├── index.browser.js ├── index.js ├── index.min.js └── index.mjs ├── package-lock.json ├── package.json └── src ├── .DS_Store ├── README.md ├── base.js ├── clarity.js ├── component.js ├── control.css ├── createchild.js ├── image ├── .DS_Store ├── danma-off.svg ├── danma-on.svg ├── enlarge.svg ├── loading.svg ├── pause.svg ├── play.svg ├── shrink.svg ├── spause.svg ├── splay.svg ├── vhigh.svg ├── vlow.svg └── vmute.svg ├── index.js ├── play.js ├── playbackrate.js ├── progressbar.js ├── progresstime.js ├── screen.js └── volume.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "process": true, 4 | "test": true, 5 | "expect": true, 6 | "describe": true, 7 | "it": true 8 | }, 9 | "env": { 10 | "browser": true, 11 | "commonjs": true, 12 | "es6": true, 13 | "jasmine": true 14 | }, 15 | "extends": [ 16 | ], 17 | "plugins": [ 18 | ], 19 | "parser": "babel-eslint", 20 | "parserOptions": { 21 | "sourceType": "module" 22 | }, 23 | "rules": { 24 | // 强制getter/setter成对出现在对象中 25 | "accessor-pairs": 2, 26 | // 禁止在括号内使用空格 27 | "array-bracket-spacing": 0, 28 | // 把 var 语句看作是在块级作用域范围之内 29 | "block-scoped-var": 0, 30 | // 大括号风格 31 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 32 | // 不强制要求使用骆驼拼写法 33 | "camelcase": 0, 34 | // 强制在逗号周围使用空格 35 | "comma-spacing": [2, { "before": false, "after": true }], 36 | // 逗号风格(必须要放在末尾) 37 | "comma-style": [2, "last"], 38 | // 限制圈复杂度(条件数目,0为不作限制) 39 | "complexity": 0, 40 | // 禁止在计算属性内使用空格 41 | "computed-property-spacing": 0, 42 | // 允许返回不指定的值 43 | "consistent-return": 0, 44 | // 不要求一致的 This 45 | "consistent-this": 0, 46 | // 验证构造函数中 super() 的调用 47 | "constructor-super": 2, 48 | // 多行是必须遵循大括号约定 49 | "curly": [2, "multi-line"], 50 | // 不强制要求含有default分支 51 | "default-case": 0, 52 | // 强制在点号之前换行 53 | "dot-location": [2, "property"], 54 | // 不强制要求使用点号 55 | "dot-notation": 0, 56 | // 要求文件末尾保留一行空行 57 | "eol-last": 2, 58 | // 要求使用全等号 59 | "eqeqeq": [2, "allow-null"], 60 | // 可以使用匿名函数 61 | "func-names": 0, 62 | // 不强制 function 声明或表达式的一致性 63 | "func-style": 0, 64 | // 强制 generator 函数中 * 号周围有空格 65 | "generator-star-spacing": [2, { "before": true, "after": true }], 66 | // 不要求 for-in 语句中包含 if 67 | "guard-for-in": 0, 68 | // 强制回调错误处理,必须要使用err或error。不处理则会报错 69 | "handle-callback-err": [2, "^(err|error)$" ], 70 | // 强制使用一致的缩进 71 | //"indent": [2, 2, { "SwitchCase": 1 }], 72 | // 强制在对象字面量的键和值之间使用一致的空格 73 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 74 | // 不强制使用一致的换行符风格 75 | "linebreak-style": 0, 76 | // 不强制注释周围有空行 77 | "lines-around-comment": 0, 78 | // 不强制回调函数最大嵌套深度 79 | "max-nested-callbacks": 0, 80 | // 要求构造函数首字母大写 81 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 82 | // 要求调用无参构造函数时带括号 83 | "new-parens": 2, 84 | // 不要求变量声明语句后有一行空行 85 | "newline-after-var": 0, 86 | // 不禁用alert 87 | "no-alert": 0, 88 | // 禁止使用 Array 构造函数 89 | "no-array-constructor": 2, 90 | // 禁用 caller 或 callee 91 | "no-caller": 2, 92 | // 不禁用在 catch 语句中遮盖变量 93 | "no-catch-shadow": 0, 94 | // 禁止在条件语句中出现赋值操作符 95 | "no-cond-assign": 2, 96 | // 禁止使用console符 97 | "no-console": 0, 98 | // 禁止在条件中使用常量表达式 99 | "no-constant-condition": 2, 100 | // 不禁用 continue 101 | "no-continue": 0, 102 | // 禁止在正则表达式中使用控制字符 103 | "no-control-regex": 2, 104 | // 禁用debugger 105 | // "no-debugger": 2, 106 | // 禁止删除变量 107 | "no-delete-var": 2, 108 | // 不禁止使用看起来像除法的正则表达式 109 | "no-div-regex": 0, 110 | // 禁止 function 定义中出现重名参数 111 | "no-dupe-args": 2, 112 | // 禁止对象字面量中出现重复的 key 113 | "no-dupe-keys": 2, 114 | // 禁止出现重复的 case 标签 115 | "no-duplicate-case": 2, 116 | // 不禁止 if 语句中 return 语句之后有 else 块 117 | "no-else-return": 0, 118 | // 不禁止出现空语句块 119 | "no-empty": 0, 120 | // 禁止在正则表达式中使用空字符集 121 | "no-empty-character-class": 2, 122 | // 禁止与 null 进行比较 123 | "no-eq-null": 2, 124 | // 禁止使用eval 125 | "no-eval": 2, 126 | // 禁止对 catch 子句中的异常重新赋值 127 | "no-ex-assign": 2, 128 | // 禁止扩展原生类型 129 | "no-extend-native": 2, 130 | // 禁止不必要的 .bind() 调用 131 | "no-extra-bind": 2, 132 | // 禁止不必要的布尔转换 133 | "no-extra-boolean-cast": 2, 134 | // 不禁止冗余的括号 135 | "no-extra-parens": 0, 136 | // 不禁止不必要的分号 137 | "no-extra-semi": 0, 138 | // 禁止 case 语句落空 139 | "no-fallthrough": 2, 140 | // 禁止数字字面量中使用前导和末尾小数点 141 | "no-floating-decimal": 2, 142 | // 禁止对 function 声明重新赋值 143 | "no-func-assign": 2, 144 | // 禁用隐式的eval() 145 | "no-implied-eval": 2, 146 | // 允许在代码后使用内联注释 147 | "no-inline-comments": 0, 148 | // 禁止 function 声明出现在嵌套的语句块中 149 | "no-inner-declarations": [2, "functions"], 150 | // 禁止 RegExp 构造函数中存在无效的正则表达式字符串 151 | "no-invalid-regexp": 2, 152 | // 禁止在字符串和注释之外不规则的空白 153 | "no-irregular-whitespace": 2, 154 | // 禁用迭代器 155 | "no-iterator": 2, 156 | // 不允许标签与变量同名 157 | "no-label-var": 2, 158 | // 禁用不必要的嵌套块 159 | "no-lone-blocks": 2, 160 | // 不禁止 if 作为唯一的语句出现在 else 语句中 161 | "no-lonely-if": 0, 162 | // 不禁止循环中存在函数 163 | "no-loop-func": 0, 164 | // 不禁止 require 调用与普通变量声明混合使用 165 | "no-mixed-requires": 0, 166 | // 禁止空格和 tab 的混合缩进 167 | //"no-mixed-spaces-and-tabs": 2, 168 | // 禁止出现多个空格 169 | "no-multi-spaces": 2, 170 | // 禁止多行字符串 171 | "no-multi-str": 2, 172 | // 不允许多个空行 173 | "no-multiple-empty-lines": [2, { "max": 1 }], 174 | "no-native-reassign": 2, 175 | "no-negated-in-lhs": 2, 176 | // 不禁止使用嵌套的三元表达式,但是要换行!!! 177 | "no-nested-ternary": 0, 178 | // 禁止在非赋值或条件语句中使用 new 操作符 179 | "no-new": 2, 180 | // 不禁止对 Function 对象使用 new 操作符 181 | "no-new-func": 0, 182 | // 禁用 Object 的构造函数 183 | "no-new-object": 2, 184 | // 禁止调用 require 时使用 new 操作符 185 | "no-new-require": 2, 186 | // 禁止对 String,Number 和 Boolean 使用 new 操作符 187 | "no-new-wrappers": 2, 188 | // 禁止把全局对象作为函数调用 189 | "no-obj-calls": 2, 190 | // 禁用八进制字面量 191 | "no-octal": 2, 192 | // 禁止在字符串中使用八进制转义序列 193 | "no-octal-escape": 2, 194 | // 不禁止对 function 的参数进行重新赋值 195 | "no-param-reassign": 0, 196 | // 不禁止对 __dirname 和 __filename 进行字符串连接 197 | "no-path-concat": 0, 198 | // 不禁用 process.env 199 | "no-process-env": 0, 200 | // 不禁用 process.exit() 201 | "no-process-exit": 0, 202 | // 不禁用禁用 __proto__ 属性 203 | "no-proto": 0, 204 | // 禁止重新声明变量 205 | "no-redeclare": 2, 206 | // 禁止正则表达式字面量中出现多个空格 207 | "no-regex-spaces": 2, 208 | // 不禁用通过 require 加载的指定模块 209 | "no-restricted-modules": 0, 210 | // 禁止在返回语句中赋值 211 | "no-return-assign": 2, 212 | // 不禁止使用 javascript: url 213 | "no-script-url": 0, 214 | // 禁止自身比较 215 | "no-self-compare": 2, 216 | // 不允许使用逗号操作符 217 | "no-sequences": 2, 218 | // 不禁止变量声明与外层作用域的变量同名 219 | "no-shadow": 0, 220 | // 关键字不能被遮蔽 221 | "no-shadow-restricted-names": 2, 222 | "no-spaced-func": 2, 223 | // 禁用稀疏数组 224 | "no-sparse-arrays": 2, 225 | // 不禁止使用同步方法 226 | "no-sync": 0, 227 | // 不禁用三元操作符 228 | "no-ternary": 0, 229 | // 禁止在构造函数中,在调用 super() 之前使用 this 或 super 230 | "no-this-before-super": 2, 231 | // 禁止抛出异常字面量 232 | "no-throw-literal": 2, 233 | // 禁用行尾空格 234 | "no-trailing-spaces": 2, 235 | // 禁用未声明的变量,除非它们在 /*global */ 注释中被提到 236 | "no-undef": 2, 237 | // 禁止将变量初始化为 undefined 238 | "no-undef-init": 2, 239 | // 不禁止将 undefined 作为标识符 240 | "no-undefined": 0, 241 | // 允许标识符中有悬空下划线 242 | "no-underscore-dangle": 0, 243 | // 禁止出现令人困惑的多行表达式 244 | "no-unexpected-multiline": 2, 245 | // 禁止可以在有更简单的可替代的表达式时使用三元操作符 246 | "no-unneeded-ternary": 2, 247 | // 禁止在return、throw、continue 和 break 语句之后出现不可达代码 248 | "no-unreachable": 2, 249 | "no-unused-expressions": 0, 250 | // 禁止未使用过的变量 251 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 252 | // 不禁止定义前使用 253 | "no-use-before-define": 0, 254 | // 要求使用 let 或 const 而不是 var 255 | "no-var": 2, 256 | // 不禁用 void 操作符 257 | "no-void": 0, 258 | // 不禁用警告注释 259 | "no-warning-comments": 0, 260 | // 禁用with 261 | "no-with": 2, 262 | // 不强制在花括号中使用一致的空格 263 | "object-curly-spacing": 0, 264 | // 要求对象字面量简写语法 265 | "object-shorthand": 2, 266 | // 强制函数中的变量在一起声明 267 | "one-var": [2, { "initialized": "never" }], 268 | // 不要求或禁止尽可能地简化赋值操作 269 | "operator-assignment": 0, 270 | // 强制操作符使用一致的换行符 271 | "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 272 | // 不要求或禁止块内填充 273 | "padded-blocks": 0, 274 | // 建议使用const 275 | "prefer-const": 2, 276 | // 不要求对象字面量属性名称使用引号 277 | "quote-props": 0, 278 | // 引号 279 | "quotes": [2, "single", "avoid-escape"], 280 | // parseint输入10防止八进制 281 | "radix": 0, 282 | // 用分号 283 | "semi": 1, 284 | // 不强制分号之前和之后使用一致的空格 285 | "semi-spacing": 0, 286 | // 无需变量排序 287 | "sort-vars": 0, 288 | // 要求语句块之前的空格 289 | "space-before-blocks": [2, "always"], 290 | // 强制在 function的左括号之前使用一致的空格 291 | "space-before-function-paren": [2, "always"], 292 | // 强制在圆括号内使用一致的空格 293 | "space-in-parens": [2, "never"], 294 | // 要求操作符周围有空格 295 | "space-infix-ops": 2, 296 | // 强制在一元操作符前后使用一致的空格 297 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 298 | // 强制在注释中 // 或 /* 使用一致的空格 299 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }], 300 | // 不要求严格模式 301 | "strict": 0, 302 | // 要求使用 isNaN() 检查 NaN 303 | "use-isnan": 2, 304 | // 不强制使用有效的 JSDoc 注释 305 | "valid-jsdoc": 0, 306 | // 强制 typeof 表达式与有效的字符串进行比较 307 | "valid-typeof": 2, 308 | // 不要求所有的 var 声明出现在它们所在的作用域顶部 309 | "vars-on-top": 0, 310 | // 要求 IIFE 使用括号括起来 311 | "wrap-iife": [2, "any"], 312 | // 不要求正则表达式被括号括起来 313 | "wrap-regex": 0, 314 | // 比较时,变量值必须放在首位 315 | "yoda": [2, "never"] 316 | } 317 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### OSX ### 2 | *.DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | 6 | # Icon must end with two 7 | Icon 8 | # Thumbnails 9 | ._* 10 | # Files that might appear in the root of a volume 11 | .DocumentRevisions-V100 12 | .fseventsd 13 | .Spotlight-V100 14 | .TemporaryItems 15 | .Trashes 16 | .VolumeIcon.icns 17 | .com.apple.timemachine.donotpresent 18 | # Directories potentially created on remote AFP share 19 | .AppleDB 20 | .AppleDesktop 21 | Network Trash Folder 22 | Temporary Items 23 | .apdisk 24 | 25 | ### Node ### 26 | # Logs 27 | logs 28 | *.log 29 | npm-debug.log* 30 | 31 | # Runtime data 32 | pids 33 | *.pid 34 | *.seed 35 | *.pid.lock 36 | 37 | # Directory for instrumented libs generated by jscoverage/JSCover 38 | lib-cov 39 | 40 | # Coverage directory used by tools like istanbul 41 | coverage 42 | 43 | # nyc test coverage 44 | .nyc_output 45 | 46 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 47 | .grunt 48 | 49 | # node-waf configuration 50 | .lock-wscript 51 | 52 | # Compiled binary addons (http://nodejs.org/api/addons.html) 53 | build/Release 54 | 55 | # Dependency directories 56 | node_modules 57 | jspm_packages 58 | 59 | # Optional npm cache directory 60 | .npm 61 | 62 | # Optional eslint cache 63 | .eslintcache 64 | 65 | # Optional REPL history 66 | .node_repl_history 67 | 68 | # Output of 'npm pack' 69 | *.tgz 70 | 71 | # Yarn Integrity file 72 | .yarn-integrity 73 | 74 | # Nuxt build 75 | .nuxt 76 | 77 | # Nuxt generate 78 | dist -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-standard", 3 | "rules": { 4 | "selector-type-no-unknown": [true, { 5 | "ignore": ["custom-elements", "default-namespace"] 6 | }] 7 | } 8 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chimee-plugin-controlbar 2 | 3 | ## install 4 | 5 | 安装 6 | 7 | ```shell 8 | # 依赖于 chimee, 首先需要安装 chimee 9 | npm install chimee 10 | # 安装控制条组件 11 | npm install chimee-plugin-controlbar 12 | ``` 13 | 14 | 使用 15 | 16 | ```javascript 17 | import chimee from 'chimee'; 18 | import chimeePluginControlbar from 'chimee-plugin-controlbar'; 19 | 20 | // 安装插件 21 | chimee.install(chimeePluginControlbar); 22 | const player = new chimee({ 23 | // ... 24 | // 使用插件 25 | plugin: [ 26 | chimeePluginControlbar.name // 或者 'chimeeControl' 27 | ] 28 | }); 29 | ``` 30 | 31 | **也可以在页面中引用 `/lib/index.browser.js` 然后在页面中使用 chimeePluginControlbar** 32 | 33 | ## 配置 34 | 35 | 一个配置 🌰 更详细的配置例子, 可以[参考 /demo/index.html](https://github.com/Chimeejs/chimee-plugin-controlbar/blob/master/demo/index.html) 36 | 37 | ```javascript 38 | plugin: [{ 39 | name: chimeePluginControlbar.name, 40 | majorColor: '', 41 | hoverColor: '', 42 | children: { 43 | volume: { 44 | icon: { 45 | low: '', 46 | high: '' 47 | }, 48 | layout: 'vertical' 49 | } 50 | } 51 | }] 52 | ``` 53 | 54 | ### 具体的参数配置 55 | 56 | #### name 57 | * 类型: string 58 | * 含义: 该插件名字, 在 chimee 中使用需要名字,需要唯一对应 59 | * 值: 'chimeeControl' | chimeePluginControlbar.name 60 | * 必需 61 | 62 | #### majorColor 63 | * 类型: string 64 | * 作用范围: 65 | * 该插件中,所有的 svg 图 66 | * 播放进度条,进度颜色 67 | * 声音控制条,音量颜色 68 | * 可选值: 十六进制颜色('#fff') 69 | * 默认值: '#de698c' 70 | * 非必需 71 | 72 | #### hoverColor 73 | * 类型: string 74 | * 作用范围: 75 | * 该插件中,所有的 svg 图 76 | * 可选值: 十六进制颜色('#fff') 77 | * 默认值: '#4c4c4c' 78 | * 非必需 79 | #### barShowByMouse 80 | * 类型: string 81 | * 作用:控制条显示由 82 | * move 触发 播放器的 mousemove 显示 83 | * enter/levae 鼠标进入/出,来控制 控制条显示/隐藏 84 | * 可选值: 'move', 'enter' 85 | * 默认值: 'move' 86 | * 非必需 87 | #### hideBarTime 88 | * 类型: number 89 | * 作用:hidebar 延迟时间 90 | * 默认值: 2000 91 | * 注意:barShowByMouse 为 move 时有效,enter 时为0, 用户设置无效 92 | * 非必需 93 | #### children 94 | * 类型: Object 95 | * 含义: 配置子组件是否展示/展示方式,还可以自己扩展子组件 96 | * 非必需 97 | * 目前支持的组件: play, progressTime, progressBar, volume, screen, clarity, playbackrate 98 | 99 | ##### 目前支持的组件及配置 100 | 101 | * play 102 | * 类型: Object 103 | * 含义: 配置播放暂停键 icon 及事件 104 | * 默认: {} 105 | * 可配置属性: 106 | * 生命周期: 107 | * create: 插入 dom 节点, 完成事件注册 108 | * destroy 109 | * bitmap: true/ false 是否是位图,默认 false, 如果用户采用位图的话,则把当前的默认 svg 都清空掉, 用户通过 css background 来自己设置图片 110 | * icon: play / pause 图标, 支持 svg 图 111 | * animate: 当前是一个 svg path 动画,可以传 path 来实现你想要的动画 112 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 113 | * 注意: icon animate bitmap 都是配置图的。 bitmap 优先。其次 icon ,最后取 animate 中的值 114 | 115 | 配置 🌰 116 | 117 | ```javascirpt 118 | { 119 | // 可以传两个 icon 来切换播放暂停状态 120 | icon: { 121 | play: '', 122 | pause: '' 123 | }, 124 | // 当前是一个 svg path 动画,可以传 path 来实现你想要的动画 125 | animate: { 126 | path: { 127 | play: { 128 | left: '' 129 | }, 130 | pause: { 131 | left: '' 132 | } 133 | } 134 | }, 135 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 136 | event: { 137 | click () { 138 | console.log(''); 139 | } 140 | } 141 | } 142 | ``` 143 | 144 | * progressTime 145 | * 类型: Object 146 | * 含义: 时间展示组件,用来展示播放时间/开播时间/视频总时长 147 | * 默认: {} 148 | * 可配置属性: 149 | * 生命周期: 150 | * create: 插入 dom 节点, 完成事件注册 151 | * destroy 152 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 153 | 154 | 配置 🌰 155 | 156 | ```javascirpt 157 | { 158 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 159 | event: { 160 | click () { 161 | console.log(''); 162 | } 163 | } 164 | } 165 | ``` 166 | 167 | * progressBar 168 | * 类型: Object | false 169 | * 含义: 进度条控制组件 170 | * 默认: {}, 属性值为 false 的时候,表示,他是一个占位符,不现实,可以区分左右,目前只有 progressbar 有这个功能 171 | * 可配置属性: 172 | * 生命周期: 173 | * create: 插入 dom 节点, 完成事件注册 174 | * destroy 175 | * layout: 有两种位置, 一是,居中布局。二是,位于整个控制条顶部。 176 | * 可选值: 'top' / 'baseline'(默认) 177 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 178 | 179 | 配置 🌰 180 | 181 | ```javascirpt 182 | { 183 | layout: 'top', 184 | 185 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 186 | event: { 187 | click () { 188 | console.log(''); 189 | } 190 | } 191 | } 192 | ``` 193 | 194 | * volume 195 | * 类型: Object 196 | * 含义: 声音控制组件 197 | * 默认: {} 198 | * 可配置属性: 199 | * 生命周期: 200 | * create: 插入 dom 节点, 完成事件注册 201 | * destroy 202 | * layout: 有两种位置, 一是,垂直。二是,水平。 203 | * 可选值: 'vertical' / 'horizonal'(默认) 204 | * bitmap: true/ false 是否是位图,默认 false,如果用户采用位图的话,则把当前的默认 svg 都清空掉, 用户通过 css background 来自己设置图片 205 | * icon: 音量按钮的三个状态按钮,mute / low / high 最少写前两个 206 | * [暂时不支持]animate: 也可以配置,然后自己通过 css 来控制 207 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 208 | * 注意: icon bitmap 都是配置图的。 bitmap 优先。其次 icon 209 | 210 | 配置 🌰 211 | 212 | ```javascirpt 213 | volume: { 214 | icon: { 215 | low: ``, 216 | mute: ``, 217 | high: `` 218 | }, 219 | layout: 'vertical', 220 | 221 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 222 | event: { 223 | click () { 224 | console.log(''); 225 | } 226 | } 227 | }, 228 | ``` 229 | 230 | * screen 231 | * 类型: Object 232 | * 含义: 配置全屏/非全屏 icon 及事件 233 | * 默认: {} 234 | * 可配置属性: 235 | * 生命周期: 236 | * create: 插入 dom 节点, 完成事件注册 237 | * destroy 238 | * bitmap: true/ false 是否是位图,默认 false,如果用户采用位图的话,则把当前的默认 svg 都清空掉, 用户通过 css background 来自己设置图片 239 | * icon: full / small 图标, 支持 svg 图 240 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 241 | * 注意: icon bitmap 都是配置图的。 bitmap 优先。其次 icon 242 | 243 | 配置 🌰 244 | 245 | ```javascirpt 246 | { 247 | // 可以传两个 icon 来切换播放暂停状态 248 | icon: { 249 | full: '', 250 | small: '' 251 | }, 252 | 253 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 254 | event: { 255 | click () { 256 | console.log(''); 257 | } 258 | } 259 | } 260 | ``` 261 | 262 | * clarity 263 | * 类型: Object 264 | * 含义: 切换清晰度组件 265 | * 默认: {} 266 | * 可配置参数 267 | * 生命周期: 268 | * create: 插入 dom 节点, 完成事件注册 269 | * destroy 270 | * list: [] 271 | * duration 272 | * 类型:`number` 273 | * 默认:3 274 | * 单次视频加载的时长 275 | * 若在规定的时间段内加载不成功,则放弃此次任务。 276 | * 单位为秒,对应于主视频的播放时间,也就是说若主视频暂停播放,则时间停滞,但加载仍继续。 277 | * bias 278 | * 类型:`number` 279 | * 默认:0 280 | * 偏差区间,单位为秒 281 | * 若该值小于等于0,则在主视频播放到或超过约定时间点直接切换,若新视频加载失败,则放弃此次切换。 282 | * 若该值大于0,则当主视频播放到约定时间偏差区间里,一旦视频加载成功就切换。若超出偏差空间,则放弃此次切换。 283 | * repeatTimes 284 | * 类型:`number` 285 | * 默认:0 286 | * 重复次数 287 | * 若加载视频失败,则自动重新加载,直至重复次数耗尽。默认不重复加载。 288 | * increment 289 | * 类型:`number` 290 | * 默认:0 291 | * 每次重复时递增的时间,单位为秒 292 | * 一般而言加载失败都是因为超时加载失败,故每次重复的时候应相应延长加载时间。每次重复加载都会相应叠加该值对应的时间。 293 | * immediate 294 | * 类型:`boolean` 295 | * 默认:`false` 296 | * 新视频加载成功后是否立即切换无需等待到约定时间。 297 | * 注意空数组时不展示 298 | 299 | 配置 🌰 300 | 301 | ```javascirpt 302 | { 303 | list: [ 304 | {name: '标清', src:''}, 305 | {name: '高清', src: ''}, 306 | {name: '原画', src: ''} 307 | ], 308 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 309 | event: { 310 | click () { 311 | console.log(''); 312 | } 313 | } 314 | } 315 | ``` 316 | 317 | 直播切流测试: http://chimee.org/demo/live-clarity.html 318 | 319 | 点播切流测试: http://chimee.org/demo/clarity.html 320 | 321 | * playbackrate 322 | * 类型: Object 323 | * 含义: 切换播放倍速组件 324 | * 默认: {} 325 | * 可配置参数 326 | * 生命周期: 327 | * create: 插入 dom 节点, 完成事件注册 328 | * destroy 329 | * list: [] 330 | * defualt: 默认播放速率 boolean值 331 | * 注意空数组时不展示 332 | 333 | 配置 🌰 334 | 335 | ```javascirpt 336 | { 337 | // default 通过设置 default 来标明当前播放速率 338 | list: [ 339 | {name: '0.5倍速', value: 0.5}, 340 | {name: '1倍速', value: 1, default: true}, 341 | {name: '2倍速', value: 2} 342 | ], 343 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 344 | event: { 345 | click () { 346 | console.log(''); 347 | } 348 | } 349 | } 350 | ``` 351 | 352 | * 自定义组件 353 | * 类型: Object 354 | * 含义: 自定义组件 355 | * 可配置属性: 356 | * 生命周期: 357 | * create: 插入 dom 节点, 完成事件注册 358 | * destroy 359 | * tag: 自定义标签名 360 | * html: 自定义标签中的 html 内容 361 | * event: 绑定 dom 事件, this 指向这个插件, 通过 this.$dom 可以拿到 dom 节点 362 | * 注意: css 写在自己项目中就好了 363 | 364 | 配置 🌰 365 | 366 | ```javascirpt 367 | { 368 | tag: '', 369 | html: ``, 370 | // 可以指定 event 来绑定一些事件,默认 this 是该插件,而不是 dom 371 | event: { 372 | click () { 373 | console.log(''); 374 | } 375 | } 376 | } 377 | ``` 378 | 379 | ##### 组件相关问题 380 | 381 | * Q: 子组件的默认顺序是什么? 382 | 383 | A: 在 children 没有配置的情况下会采用下面的顺序 384 | 385 | * 注意:根据 chimee 的参数 isLive 来判断是否是直播还是点播 386 | 387 | * 直播: play, progressTime, volume, screen 388 | 389 | * 点播: play, progressTime, progressTime, volume, screen 390 | 391 | * 如果用户配置了, 则按照用户的配置走,不论是否是直播还是点播 392 | 393 | * Q: 我可以控制顺序吗? 394 | 395 | A: 在 children 对象中,属性的书写顺序就是渲染顺序 396 | 397 | * 注意, progressbar 可以作为一个占位符存在 398 | 399 | * Q: 为什么我配置了一个组件后,其他默认组件就都不存在了? 400 | 401 | A: 假如 children 配置后, 会读 children 的属性,并渲染, 不会补充其他组件,所以,需要你把所有的组件都写. 402 | 403 | ## 方法 404 | 405 | * updateClarity 406 | * 含义: 更新清晰度列表 407 | * 参数:Array 清晰度列表 408 | 409 | 配置 🌰 410 | 411 | ```javascirpt 412 | function updateClarity() { 413 | player.load('http://yunxianchang.live.ujne7.com/vod-system-bj/103_368b70a5d4f-c5cc-42ff-b442-004168fc86a3.mp4'); 414 | player.on('load', function () { // 在 load 事件后 415 | player.$plugins.chimeeControl.updateClarity([ 416 | {name: '标清', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_368b70a5d4f-c5cc-42ff-b442-004168fc86a3.mp4'}, 417 | {name: '高清', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_369ed890f51-1c38-42a7-9ce2-828492660c60.mp4'}, 418 | {name: '超清', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_370cc2f40bd-a39f-472a-884f-f44fcd9c5ae0.mp4'}, 419 | {name: '原画', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_371ab0c0fda-143d-4755-8727-d3cd12dce02d.mp4'} 420 | ]); 421 | }); 422 | } 423 | ``` 424 | 425 | 426 | ## 最后 427 | 428 | 欢迎各位大佬使用。有什么问题/建议,随时提。 429 | -------------------------------------------------------------------------------- /__test__/e2e/index.js: -------------------------------------------------------------------------------- 1 | import Chimee from 'chimee'; 2 | import chimeePluginControlbar from '../../src/index'; 3 | 4 | document.body.innerHTML = ` 5 |
6 | `; 7 | Chimee.install(chimeePluginControlbar); 8 | 9 | const player = new Chimee({ 10 | wrapper: '#wrap', 11 | src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_371ab0c0fda-143d-4755-8727-d3cd12dce02d.mp4', 12 | isLive: false, 13 | majorColor: '#f00', 14 | hoverColor: '#00f', 15 | plugin: [ 16 | { 17 | name: chimeePluginControlbar.name, 18 | majorColor: '#f00', 19 | hoverColor: '#fff', 20 | children: { 21 | play: {}, 22 | progressTime: true, 23 | progressBar: { 24 | layout: 'top' // baseline 25 | }, 26 | volume: { 27 | icon: { 28 | low: ` 29 | 39 | `, 40 | mute: ` 41 | 52 | `, 53 | }, 54 | layout: 'vertical' 55 | }, 56 | clarity: [ 57 | {name: '标清', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_368b70a5d4f-c5cc-42ff-b442-004168fc86a3.mp4'}, 58 | {name: '高清', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_369ed890f51-1c38-42a7-9ce2-828492660c60.mp4'}, 59 | {name: '原画', src: 'http://yunxianchang.live.ujne7.com/vod-system-bj/103_371ab0c0fda-143d-4755-8727-d3cd12dce02d.mp4'} 60 | ], 61 | screen: true 62 | } 63 | } 64 | ], 65 | controls: true, 66 | autoplay: true 67 | }); 68 | 69 | const controls = player.$plugins.chimeeControl; 70 | 71 | 72 | describe('controls inited', async () => { 73 | expect(controls).toBeDefined(); 74 | }); 75 | 76 | describe('screen inited', async () => { 77 | const screen = await controls.children.screen; 78 | expect(screen).toBeDefined(); 79 | }); 80 | -------------------------------------------------------------------------------- /__test__/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Chimeejs/chimee-plugin-controlbar/122787e29c3f905a101c7bb722937a81abc4b600/__test__/index.js -------------------------------------------------------------------------------- /__test__/play.js: -------------------------------------------------------------------------------- 1 | import Play from '../src/play'; 2 | 3 | describe('init', function () { 4 | 5 | }); 6 | -------------------------------------------------------------------------------- /build/rollup.config.base.js: -------------------------------------------------------------------------------- 1 | const {version, name, author, license, dependencies} = require('../package.json'); 2 | const banner = ` 3 | /** 4 | * ${name} v${version} 5 | * (c) 2017 ${author} 6 | * Released under ${license} 7 | */ 8 | `; 9 | import babel from 'rollup-plugin-babel'; 10 | import resolve from 'rollup-plugin-node-resolve'; 11 | import commonjs from 'rollup-plugin-commonjs'; 12 | import postcss from 'rollup-plugin-postcss'; 13 | import uglify from 'rollup-plugin-uglify'; 14 | 15 | // PostCSS plugins 16 | import cssnano from 'cssnano'; 17 | import cssnext from 'postcss-cssnext'; 18 | import postcssReporter from 'postcss-reporter'; 19 | import stylelint from 'stylelint'; 20 | 21 | const babelConfig = { 22 | cjs: { 23 | presets: [ 24 | ['latest', {es2015: {modules: false}}], 25 | 'stage-0' 26 | ], 27 | plugins: [ 28 | 'transform-decorators-legacy', 29 | 'transform-runtime' 30 | ], 31 | exclude: 'node_modules/**', 32 | runtimeHelpers: true, 33 | babelrc: false 34 | }, 35 | es: { 36 | presets: [ 37 | ['latest', {es2015: {modules: false}}], 38 | 'stage-0' 39 | ], 40 | plugins: [ 41 | 'transform-decorators-legacy', 42 | 'transform-runtime' 43 | ], 44 | exclude: 'node_modules/**', 45 | runtimeHelpers: true, 46 | babelrc: false 47 | }, 48 | umd: { 49 | presets: ['es2015-rollup', 'stage-0'], 50 | plugins: [ 51 | 'transform-decorators-legacy', 52 | 'transform-runtime' 53 | ], 54 | exclude: 'node_modules/**', 55 | runtimeHelpers: true, 56 | babelrc: false 57 | }, 58 | iife: { 59 | presets: ['es2015-rollup', 'stage-0'], 60 | plugins: ['transform-decorators-legacy'], 61 | babelrc: false 62 | }, 63 | min: { 64 | presets: ['es2015-rollup', 'stage-0'], 65 | exclude: 'node_modules/**', 66 | plugins: [], 67 | babelrc: false 68 | } 69 | }; 70 | const externalRegExp = new RegExp(Object.keys(dependencies).join('|')); 71 | export default function (modeConf) { 72 | const mode = modeConf.output.format; 73 | const config = { 74 | input: 'src/index.js', 75 | output: { 76 | banner 77 | }, 78 | external (id) { 79 | return !/min|umd|iife/.test(mode) && externalRegExp.test(id); 80 | }, 81 | plugins: [ 82 | postcss({ 83 | plugins: [ 84 | stylelint(), 85 | postcssReporter(), 86 | cssnext(), 87 | cssnano() 88 | ], 89 | extensions: ['.css'] 90 | }), 91 | babel(babelConfig[mode]), 92 | resolve(), 93 | commonjs() 94 | ] 95 | }; 96 | modeConf.uglify && config.plugins.push(uglify()); 97 | delete modeConf.uglify; 98 | Object.assign(config, modeConf); 99 | if(mode === 'umd') { 100 | config.output.name = camelize(name); 101 | } 102 | return config; 103 | }; 104 | 105 | /** 106 | * camelize any string, e.g hello world -> helloWorld 107 | * @param {string} str only accept string! 108 | * @return {string} camelize string 109 | */ 110 | function camelize (str) { 111 | return str.replace(/(^|[^a-zA-Z]+)([a-zA-Z])/g, function (match, spilt, initials, index) { 112 | return (index === 0) ? initials.toLowerCase() : initials.toUpperCase(); 113 | }); 114 | } 115 | -------------------------------------------------------------------------------- /build/rollup.config.common.js: -------------------------------------------------------------------------------- 1 | import base from './rollup.config.base'; 2 | export default base({ 3 | output: { 4 | format: 'cjs', 5 | file: 'lib/index.js' 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /build/rollup.config.es.js: -------------------------------------------------------------------------------- 1 | import base from './rollup.config.base'; 2 | export default base({ 3 | output: { 4 | format: 'es', 5 | file: 'lib/index.mjs' 6 | } 7 | }); 8 | -------------------------------------------------------------------------------- /build/rollup.config.min.js: -------------------------------------------------------------------------------- 1 | import base from './rollup.config.base'; 2 | import replace from 'rollup-plugin-replace'; 3 | const config = base({ 4 | output: { 5 | format: 'umd', 6 | file: 'lib/index.min.js' 7 | }, 8 | uglify: true 9 | }); 10 | config.plugins.unshift(replace({ 11 | 'process.env.NODE_ENV': '"development"' 12 | })); 13 | 14 | export default config; 15 | 16 | -------------------------------------------------------------------------------- /build/rollup.config.umd.js: -------------------------------------------------------------------------------- 1 | import base from './rollup.config.base'; 2 | import replace from 'rollup-plugin-replace'; 3 | const config = base({ 4 | output: { 5 | format: 'umd', 6 | file: 'lib/index.browser.js' 7 | } 8 | }); 9 | config.plugins.unshift(replace({ 10 | 'process.env.NODE_ENV': '"development"' 11 | })); 12 | export default config; 13 | -------------------------------------------------------------------------------- /coverage/chrome/base.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | margin:0; padding: 0; 3 | height: 100%; 4 | } 5 | body { 6 | font-family: Helvetica Neue, Helvetica, Arial; 7 | font-size: 14px; 8 | color:#333; 9 | } 10 | .small { font-size: 12px; } 11 | *, *:after, *:before { 12 | -webkit-box-sizing:border-box; 13 | -moz-box-sizing:border-box; 14 | box-sizing:border-box; 15 | } 16 | h1 { font-size: 20px; margin: 0;} 17 | h2 { font-size: 14px; } 18 | pre { 19 | font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; 20 | margin: 0; 21 | padding: 0; 22 | -moz-tab-size: 2; 23 | -o-tab-size: 2; 24 | tab-size: 2; 25 | } 26 | a { color:#0074D9; text-decoration:none; } 27 | a:hover { text-decoration:underline; } 28 | .strong { font-weight: bold; } 29 | .space-top1 { padding: 10px 0 0 0; } 30 | .pad2y { padding: 20px 0; } 31 | .pad1y { padding: 10px 0; } 32 | .pad2x { padding: 0 20px; } 33 | .pad2 { padding: 20px; } 34 | .pad1 { padding: 10px; } 35 | .space-left2 { padding-left:55px; } 36 | .space-right2 { padding-right:20px; } 37 | .center { text-align:center; } 38 | .clearfix { display:block; } 39 | .clearfix:after { 40 | content:''; 41 | display:block; 42 | height:0; 43 | clear:both; 44 | visibility:hidden; 45 | } 46 | .fl { float: left; } 47 | @media only screen and (max-width:640px) { 48 | .col3 { width:100%; max-width:100%; } 49 | .hide-mobile { display:none!important; } 50 | } 51 | 52 | .quiet { 53 | color: #7f7f7f; 54 | color: rgba(0,0,0,0.5); 55 | } 56 | .quiet a { opacity: 0.7; } 57 | 58 | .fraction { 59 | font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; 60 | font-size: 10px; 61 | color: #555; 62 | background: #E8E8E8; 63 | padding: 4px 5px; 64 | border-radius: 3px; 65 | vertical-align: middle; 66 | } 67 | 68 | div.path a:link, div.path a:visited { color: #333; } 69 | table.coverage { 70 | border-collapse: collapse; 71 | margin: 10px 0 0 0; 72 | padding: 0; 73 | } 74 | 75 | table.coverage td { 76 | margin: 0; 77 | padding: 0; 78 | vertical-align: top; 79 | } 80 | table.coverage td.line-count { 81 | text-align: right; 82 | padding: 0 5px 0 20px; 83 | } 84 | table.coverage td.line-coverage { 85 | text-align: right; 86 | padding-right: 10px; 87 | min-width:20px; 88 | } 89 | 90 | table.coverage td span.cline-any { 91 | display: inline-block; 92 | padding: 0 5px; 93 | width: 100%; 94 | } 95 | .missing-if-branch { 96 | display: inline-block; 97 | margin-right: 5px; 98 | border-radius: 3px; 99 | position: relative; 100 | padding: 0 4px; 101 | background: #333; 102 | color: yellow; 103 | } 104 | 105 | .skip-if-branch { 106 | display: none; 107 | margin-right: 10px; 108 | position: relative; 109 | padding: 0 4px; 110 | background: #ccc; 111 | color: white; 112 | } 113 | .missing-if-branch .typ, .skip-if-branch .typ { 114 | color: inherit !important; 115 | } 116 | .coverage-summary { 117 | border-collapse: collapse; 118 | width: 100%; 119 | } 120 | .coverage-summary tr { border-bottom: 1px solid #bbb; } 121 | .keyline-all { border: 1px solid #ddd; } 122 | .coverage-summary td, .coverage-summary th { padding: 10px; } 123 | .coverage-summary tbody { border: 1px solid #bbb; } 124 | .coverage-summary td { border-right: 1px solid #bbb; } 125 | .coverage-summary td:last-child { border-right: none; } 126 | .coverage-summary th { 127 | text-align: left; 128 | font-weight: normal; 129 | white-space: nowrap; 130 | } 131 | .coverage-summary th.file { border-right: none !important; } 132 | .coverage-summary th.pct { } 133 | .coverage-summary th.pic, 134 | .coverage-summary th.abs, 135 | .coverage-summary td.pct, 136 | .coverage-summary td.abs { text-align: right; } 137 | .coverage-summary td.file { white-space: nowrap; } 138 | .coverage-summary td.pic { min-width: 120px !important; } 139 | .coverage-summary tfoot td { } 140 | 141 | .coverage-summary .sorter { 142 | height: 10px; 143 | width: 7px; 144 | display: inline-block; 145 | margin-left: 0.5em; 146 | background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; 147 | } 148 | .coverage-summary .sorted .sorter { 149 | background-position: 0 -20px; 150 | } 151 | .coverage-summary .sorted-desc .sorter { 152 | background-position: 0 -10px; 153 | } 154 | .status-line { height: 10px; } 155 | /* dark red */ 156 | .red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } 157 | .low .chart { border:1px solid #C21F39 } 158 | /* medium red */ 159 | .cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } 160 | /* light red */ 161 | .low, .cline-no { background:#FCE1E5 } 162 | /* light green */ 163 | .high, .cline-yes { background:rgb(230,245,208) } 164 | /* medium green */ 165 | .cstat-yes { background:rgb(161,215,106) } 166 | /* dark green */ 167 | .status-line.high, .high .cover-fill { background:rgb(77,146,33) } 168 | .high .chart { border:1px solid rgb(77,146,33) } 169 | /* dark yellow (gold) */ 170 | .medium .chart { border:1px solid #f9cd0b; } 171 | .status-line.medium, .medium .cover-fill { background: #f9cd0b; } 172 | /* light yellow */ 173 | .medium { background: #fff4c2; } 174 | /* light gray */ 175 | span.cline-neutral { background: #eaeaea; } 176 | 177 | .cbranch-no { background: yellow !important; color: #111; } 178 | 179 | .cstat-skip { background: #ddd; color: #111; } 180 | .fstat-skip { background: #ddd; color: #111 !important; } 181 | .cbranch-skip { background: #ddd !important; color: #111; } 182 | 183 | 184 | .cover-fill, .cover-empty { 185 | display:inline-block; 186 | height: 12px; 187 | } 188 | .chart { 189 | line-height: 0; 190 | } 191 | .cover-empty { 192 | background: white; 193 | } 194 | .cover-full { 195 | border-right: none !important; 196 | } 197 | pre.prettyprint { 198 | border: none !important; 199 | padding: 0 !important; 200 | margin: 0 !important; 201 | } 202 | .com { color: #999 !important; } 203 | .ignore-none { color: #999; font-weight: normal; } 204 | 205 | .wrapper { 206 | min-height: 100%; 207 | height: auto !important; 208 | height: 100%; 209 | margin: 0 auto -48px; 210 | } 211 | .footer, .push { 212 | height: 48px; 213 | } 214 | -------------------------------------------------------------------------------- /coverage/chrome/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |File | 50 |51 | | Statements | 52 |53 | | Branches | 54 |55 | | Functions | 56 |57 | | Lines | 58 |59 | |
---|---|---|---|---|---|---|---|---|---|
src/ | 63 |34.77% | 65 |7788/22400 | 66 |17.65% | 67 |2659/15064 | 68 |24.41% | 69 |1115/4568 | 70 |36.51% | 71 |7531/20628 | 72 |