├── .babelrc ├── .editorconfig ├── .gitignore ├── README.md ├── build └── gh-pages.js ├── docs └── images │ ├── akira.gif │ ├── haruki.gif │ ├── hideo.gif │ ├── hoshi.gif │ ├── ichiro.gif │ ├── isao.gif │ ├── jiro.gif │ ├── juro.gif │ ├── kaede.gif │ ├── kuro.gif │ ├── kyo.gif │ ├── madoka.gif │ ├── minoru.gif │ └── yoko.gif ├── examples ├── App.vue ├── index.html ├── main.js ├── me.svg └── themes.json ├── package.json ├── rollup.config.js ├── src ├── components │ └── EffectInput.vue ├── images │ └── logo.png ├── index.js └── styles │ ├── akira.styl │ ├── common.styl │ ├── fonts │ └── .gitkeep │ ├── haruki.styl │ ├── hideo.styl │ ├── hoshi.styl │ ├── ichiro.styl │ ├── index.styl │ ├── isao.styl │ ├── jiro.styl │ ├── juro.styl │ ├── kaede.styl │ ├── kuro.styl │ ├── kyo.styl │ ├── madoka.styl │ ├── manami.styl │ ├── minoru.styl │ ├── nariko.styl │ ├── template.styl │ ├── variables.styl │ └── yoko.styl └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-3" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | sites/ 5 | npm-debug.log 6 | yarn-error.log 7 | 8 | # Editor directories and files 9 | .idea 10 | *.suo 11 | *.ntvs* 12 | *.njsproj 13 | *.sln 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # effect-input 2 | 3 | [![NPM version][badge-npm-version]][url-npm] 4 | [![Node version][badge-node-version]][url-npm] 5 | [![NPM download][badge-npm-download]][url-npm] 6 | ![Dependencies][badge-dependencies] 7 | ![License][badge-license] 8 | 9 | 优雅而绚丽的适用于 Vue 2.0 的 `input` 组件。极大提高交互效果和输入愉悦性。 10 | 11 | [![NPM][image-npm]][url-npm] 12 | 13 | > 深受 [TextInputEffects][url-TextInputEffects] 的启发。 14 | 15 | 16 | 17 | ## 概览 18 | 19 | [访问在线示例](https://xbt1.github.io/effect-input) 20 | 21 | ## 安装 22 | 23 | ```bash 24 | $ yarn add effect-input # npm i -S effect-input 25 | ``` 26 | 27 | ## 使用 28 | 29 | 一个简单的例子 30 | 31 | ```javascript 32 | import EffectInput from 'effect-input' 33 | import 'effect-input/dist/index.css' 34 | 35 | Vue.use(EffectInput) 36 | ``` 37 | 38 | ```html 39 | 42 | ``` 43 | 44 | ## 主题 45 | 46 | `effect-input` 的 `type` 属性为主题名,目前有如下主题: 47 | 48 | ### `haruki` 49 | 50 | ![haruki](./docs/images/haruki.gif) 51 | 52 | ### `hoshi` 53 | 54 | ![hoshi](./docs/images/hoshi.gif) 55 | 56 | ### `kuro` 57 | 58 | ![kuro](./docs/images/kuro.gif) 59 | 60 | ### `jiro` 61 | 62 | ![jiro](./docs/images/jiro.gif) 63 | 64 | ### `minoru` 65 | 66 | ![minoru](./docs/images/minoru.gif) 67 | 68 | ### `yoko` 69 | 70 | ![yoko](./docs/images/yoko.gif) 71 | 72 | ### `hideo` 73 | 74 | ![hideo](./docs/images/hideo.gif) 75 | 76 | ### `kyo` 77 | 78 | ![kyo](./docs/images/kyo.gif) 79 | 80 | ### `akira` 81 | 82 | ![akira](./docs/images/akira.gif) 83 | 84 | ### `ichiro` 85 | 86 | ![ichiro](./docs/images/ichiro.gif) 87 | 88 | ### `juro` 89 | 90 | ![juro](./docs/images/juro.gif) 91 | 92 | ### `madoka` 93 | 94 | ![madoka](./docs/images/madoka.gif) 95 | 96 | ### `kaede` 97 | 98 | ![kaede](./docs/images/kaede.gif) 99 | 100 | ### `isao` 101 | 102 | ![isao](./docs/images/isao.gif) 103 | 104 | 105 | ## 开发 106 | 107 | ```bash 108 | $ npm install 109 | $ npm run dev 110 | ``` 111 | 112 | ## 构建 113 | 114 | ```bash 115 | $ npm run build:package # 构建 npm 包 116 | $ npm run build:example # 构建示例站点 117 | $ npm run build # build:package & build:example 118 | ``` 119 | 120 | ## TODOs 121 | 122 | - 添加更多主题 123 | - SET 2 124 | - [x] `manami` 125 | - [x] `nariko` 126 | - [ ] `nao` 127 | - [ ] `yoshiko` 128 | - [ ] `shoko` 129 | - [ ] `chisato` 130 | - [ ] `makiko` 131 | - [ ] `sae` 132 | - [ ] `kozakura` 133 | - [ ] `fumi` 134 | - [ ] `ruri` 135 | - [ ] `kohana` 136 | 137 | ## 更新日志 138 | 139 | 详见 [releases][url-releases] 140 | 141 | 142 | [badge-npm-version]: https://img.shields.io/npm/v/effect-input.svg 143 | [badge-node-version]: https://img.shields.io/node/v/effect-input.svg 144 | [badge-npm-download]: https://img.shields.io/npm/dt/effect-input.svg 145 | [badge-license]: https://img.shields.io/github/license/xbt1/effect-input.svg 146 | [badge-dependencies]: https://img.shields.io/david/dev/xbt1/effect-input.svg 147 | 148 | [url-TextInputEffects]: https://tympanus.net/Development/TextInputEffects/index.html 149 | [url-npm]: https://npmjs.org/package/effect-input 150 | [url-dependencies]: https://david-dm.org/vkbansal/effect-input 151 | [url-releases]: https://github.com/XBT1/effect-input/releases 152 | 153 | [image-npm]: https://nodei.co/npm/effect-input.png 154 | 155 | -------------------------------------------------------------------------------- /build/gh-pages.js: -------------------------------------------------------------------------------- 1 | const ghpages = require('gh-pages') 2 | 3 | ghpages.publish('sites', (err) => { 4 | err && console.log(err) 5 | }) 6 | -------------------------------------------------------------------------------- /docs/images/akira.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/akira.gif -------------------------------------------------------------------------------- /docs/images/haruki.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/haruki.gif -------------------------------------------------------------------------------- /docs/images/hideo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/hideo.gif -------------------------------------------------------------------------------- /docs/images/hoshi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/hoshi.gif -------------------------------------------------------------------------------- /docs/images/ichiro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/ichiro.gif -------------------------------------------------------------------------------- /docs/images/isao.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/isao.gif -------------------------------------------------------------------------------- /docs/images/jiro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/jiro.gif -------------------------------------------------------------------------------- /docs/images/juro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/juro.gif -------------------------------------------------------------------------------- /docs/images/kaede.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/kaede.gif -------------------------------------------------------------------------------- /docs/images/kuro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/kuro.gif -------------------------------------------------------------------------------- /docs/images/kyo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/kyo.gif -------------------------------------------------------------------------------- /docs/images/madoka.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/madoka.gif -------------------------------------------------------------------------------- /docs/images/minoru.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/minoru.gif -------------------------------------------------------------------------------- /docs/images/yoko.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/docs/images/yoko.gif -------------------------------------------------------------------------------- /examples/App.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 101 | 102 | 181 | 182 | 189 | 190 | -------------------------------------------------------------------------------- /examples/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | text-input-effects 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | 4 | import EffectInput from '../src' 5 | import '../src/styles/index.styl' 6 | 7 | // import EffectInput from 'effect-input' 8 | // import 'effect-input/dist/index.css' 9 | 10 | Vue.use(EffectInput) 11 | 12 | new Vue({ 13 | el: '#app', 14 | render: h => h(App) 15 | }) 16 | -------------------------------------------------------------------------------- /examples/me.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/themes.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | { 4 | "type": "haruki", 5 | "bgColor": "#f0efee" 6 | }, 7 | { 8 | "type": "hoshi", 9 | "bgColor": "#f9f7f6" 10 | }, 11 | { 12 | "type": "kuro", 13 | "bgColor": "#2f3238", 14 | "color": "#fff" 15 | }, 16 | { 17 | "type": "jiro", 18 | "bgColor": "#d0d6d6" 19 | }, 20 | { 21 | "type": "minoru", 22 | "bgColor": "#f9f7f6" 23 | }, 24 | { 25 | "type": "yoko", 26 | "bgColor": "#dd665c" 27 | }, 28 | { 29 | "type": "hideo", 30 | "bgColor": "#f9f7f6" 31 | }, 32 | { 33 | "type": "kyo", 34 | "bgColor": "#e8e8e8", 35 | "activeColor": "rgba(11, 43, 205, 0.6)" 36 | }, 37 | { 38 | "type": "akira", 39 | "bgColor": "#2f3238", 40 | "color": "#fff" 41 | }, 42 | { 43 | "type": "ichiro", 44 | "bgColor": "#f9f7f6" 45 | }, 46 | { 47 | "type": "juro", 48 | "color": "#fff", 49 | "bgColor": "#38a9ea" 50 | }, 51 | { 52 | "type": "madoka", 53 | "color": "#fff", 54 | "bgColor": "#2f3238" 55 | }, 56 | { 57 | "type": "kaede", 58 | "bgColor": "#f9f7f6" 59 | }, 60 | { 61 | "type": "isao", 62 | "color": "#fff", 63 | "bgColor": "#3d4444" 64 | } 65 | ], 66 | [ 67 | { 68 | "type": "manami", 69 | "bgColor": "#e8e8e8" 70 | }, 71 | { 72 | "type": "nariko", 73 | "bgColor": "#d0d6d6" 74 | } 75 | ] 76 | ] 77 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "effect-input", 3 | "description": "Text Input Effects for Vue.js - Simple ideas for enhancing text input interactions", 4 | "version": "0.1.1", 5 | "author": "XBT1 ", 6 | "main": "dist/index.common.js", 7 | "files": [ 8 | "src", 9 | "dist" 10 | ], 11 | "keywords": [ 12 | "vue", 13 | "input-effects", 14 | "vue-component" 15 | ], 16 | "scripts": { 17 | "start": "npm run dev", 18 | "dev": "cross-env NODE_ENV=development webpack-dev-server --content-base examples/ --hot", 19 | "build": "npm run build:package & npm run build:example", 20 | "build:package": "rm -fr dist && rollup -c && stylus src/styles/index.styl --out dist", 21 | "build:example": "rm -fr sites && cross-env NODE_ENV=production webpack --progress --hide-modules && cp examples/index.html sites", 22 | "ghpages": "npm run build:example && node build/gh-pages.js", 23 | "pb": "npm run build:package && npm publish" 24 | }, 25 | "dependencies": { 26 | "vue": "^2.5.0" 27 | }, 28 | "browserslist": [ 29 | "> 1%", 30 | "last 2 versions", 31 | "not ie <= 8" 32 | ], 33 | "devDependencies": { 34 | "babel-core": "^6.26.0", 35 | "babel-loader": "^7.1.2", 36 | "babel-preset-env": "^1.6.0", 37 | "babel-preset-stage-3": "^6.24.1", 38 | "cross-env": "^5.0.5", 39 | "css-loader": "^0.28.7", 40 | "file-loader": "^1.1.4", 41 | "fs-extra": "^4.0.3", 42 | "gh-pages": "^1.1.0", 43 | "rollup": "^0.52.1", 44 | "rollup-plugin-vue": "^3.0.0", 45 | "style-loader": "^0.19.0", 46 | "stylus": "^0.54.5", 47 | "stylus-loader": "^3.0.1", 48 | "url-loader": "^0.6.2", 49 | "vue-loader": "^13.0.5", 50 | "vue-template-compiler": "^2.4.4", 51 | "webpack": "^3.6.0", 52 | "webpack-dev-server": "^2.9.1" 53 | }, 54 | "license": "MIT", 55 | "repository": { 56 | "type": "git", 57 | "url": "https://github.com/XBT1/effect-input.git" 58 | }, 59 | "bugs": { 60 | "url": "https://github.com/XBT1/effect-input/issues" 61 | }, 62 | "homepage": "https://github.com/XBT1/effect-input", 63 | "engines": { 64 | "node": ">= 4.0.0", 65 | "npm": ">= 3.0.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import vue from 'rollup-plugin-vue' 2 | 3 | export default { 4 | input: 'src/index.js', 5 | output: { 6 | file: 'dist/index.common.js', 7 | format: 'cjs', 8 | exports: 'named', 9 | }, 10 | plugins: [ 11 | vue(), 12 | ], 13 | } 14 | -------------------------------------------------------------------------------- /src/components/EffectInput.vue: -------------------------------------------------------------------------------- 1 | 52 | 53 | 94 | -------------------------------------------------------------------------------- /src/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/src/images/logo.png -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import EffectInput from './components/EffectInput.vue' 2 | 3 | export { EffectInput } 4 | 5 | export default { 6 | install (Vue) { 7 | Vue.component(EffectInput.name, EffectInput) 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /src/styles/akira.styl: -------------------------------------------------------------------------------- 1 | 2 | input-color = #747981 3 | input-margin-top = 1.875em 4 | 5 | label-color = #df6589 6 | label-border-width = 0.25em 7 | label-border = label-border-width solid input-color 8 | label-active-translateY = - (input-height + label-font-size + input-margin-top) / 2 9 | 10 | .effect-input--akira 11 | margin-top: input-margin-top 12 | text-align: center 13 | 14 | .effect-input__field 15 | color: input-color 16 | text-align: center 17 | 18 | .effect-input__label 19 | @extend $input__label--vc 20 | 21 | top: 0 22 | color: label-color 23 | 24 | &::after 25 | content: "" 26 | position: absolute 27 | top: 0 28 | left: 0 29 | width: 100% 30 | height: 100% 31 | border: label-border 32 | transition: border-width 0.3s 33 | 34 | .effect-input__label-content 35 | transition: transform 0.3s 36 | 37 | // 激活状态 38 | &.effect-input--filled .effect-input__label, 39 | .effect-input__field:focus + .effect-input__label 40 | &::after 41 | border-width: (label-border-width / 2) 42 | 43 | .effect-input__label-content 44 | transform: translate3d(0, label-active-translateY, 0) 45 | -------------------------------------------------------------------------------- /src/styles/common.styl: -------------------------------------------------------------------------------- 1 | html *, 2 | html *::before, 3 | html *::after 4 | box-sizing: border-box 5 | 6 | .effect-input 7 | position: relative 8 | display: inline-block 9 | width: input-width 10 | line-height: 1 11 | font-size: input-font-size 12 | text-align: left 13 | z-index: 1 14 | 15 | .effect-input__field 16 | display: block 17 | width: 100% 18 | height: field-height 19 | background: transparent 20 | border: none 21 | color: inherit 22 | font-size: field-font-size 23 | font-weight: bold 24 | 25 | &:focus 26 | outline: none 27 | 28 | .effect-input__label 29 | display: block 30 | width: 100% 31 | font-size: label-font-size 32 | font-weight: bold 33 | color: label-color 34 | 35 | .effect-input__label-content 36 | display: block 37 | width: 100% 38 | -------------------------------------------------------------------------------- /src/styles/fonts/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CyberNika/effect-input/7c41b3c1d5e7dd0500888bdb4cee32f712764982/src/styles/fonts/.gitkeep -------------------------------------------------------------------------------- /src/styles/haruki.styl: -------------------------------------------------------------------------------- 1 | 2 | padding-horizontal = 1.2em 3 | 4 | field-font-size = 1.55em 5 | 6 | label-padding-vertical = (input-height - label-font-size) / 2 7 | lebel-decorate-active-translateY = 0.5em 8 | label-active-translateY = -(input-height / 2 + label-font-size * 1.2 + lebel-decorate-active-translateY) 9 | 10 | input-margin-top = (label-font-size + lebel-decorate-active-translateY * 2) * 1.5 11 | 12 | $input__label--vc 13 | position: absolute 14 | padding: label-padding-vertical padding-horizontal 15 | height: input-height 16 | // pointer-events: none 17 | cursor: text 18 | 19 | .effect-input--haruki 20 | margin-top: input-margin-top 21 | 22 | .effect-input__field 23 | position: relative 24 | padding: 0 (padding-horizontal / 2) 25 | color: field-color 26 | font-size: field-font-size 27 | 28 | .effect-input__label 29 | @extend $input__label--vc 30 | 31 | bottom: 0 32 | 33 | &::before, 34 | &::after 35 | content: "" 36 | position: absolute 37 | left: 0 38 | z-index: -1 39 | width: 100% 40 | height: 0.25em 41 | background-color: status-color-primary 42 | transition: transform 0.3s 43 | 44 | &::before 45 | top: 0 46 | 47 | &::after 48 | bottom: 0 49 | 50 | .effect-input__label-content 51 | transition: transform 0.3s 52 | 53 | // 激活状态 54 | &.effect-input--filled .effect-input__label, 55 | .effect-input__field:focus + .effect-input__label 56 | &::before 57 | transform: translate3d(0, -(lebel-decorate-active-translateY), 0) 58 | 59 | &::after 60 | transform: translate3d(0, lebel-decorate-active-translateY, 0) 61 | 62 | .effect-input__label-content 63 | transform: translate3d(0, label-active-translateY, 0) 64 | -------------------------------------------------------------------------------- /src/styles/hideo.styl: -------------------------------------------------------------------------------- 1 | 2 | label-bgc = #8a9ed8 3 | 4 | field-color = #aaa 5 | active-ratio = 1.5 6 | 7 | .effect-input--hideo 8 | 9 | .effect-input__field 10 | padding-left: field-height + 1 11 | background-color: #fff 12 | color: field-color 13 | transition: padding-left 0.3s 14 | 15 | .effect-input__label 16 | position: absolute 17 | left: 0 18 | top: 0 19 | display: flex 20 | align-items: center 21 | justify-content: center 22 | width: input-height 23 | height: 100% 24 | background-color: label-bgc 25 | transition: all 0.3s 26 | 27 | .effect-input__label-content 28 | width: 1em 29 | height: 1em 30 | font-size: 160% 31 | color: #fff 32 | overflow: hidden 33 | 34 | // 激活状态 35 | // &.effect-input--filled .effect-input__field, 36 | .effect-input__field:focus 37 | padding-left: (field-height / active-ratio) + 1 38 | 39 | // &.effect-input--filled .effect-input__label, 40 | .effect-input__field:focus + .effect-input__label 41 | font-size: (label-font-size / active-ratio) 42 | -------------------------------------------------------------------------------- /src/styles/hoshi.styl: -------------------------------------------------------------------------------- 1 | 2 | input-margin-top = label-font-size * 1.5 3 | padding-horizontal = 0.3em 4 | 5 | label-active-translateY = -(input-height + label-font-size) / 2 6 | label-padding-top = (input-height - label-font-size) / 2 7 | label-padding-bottom = (input-height - label-font-size) / 2 - 0.6 8 | 9 | .effect-input--hoshi 10 | margin-top: input-margin-top 11 | 12 | .effect-input__field 13 | position: relative 14 | padding: 0 padding-horizontal 15 | height: input-height - 10 16 | color: #595f6e 17 | 18 | .effect-input__label 19 | position: absolute 20 | top: 0 21 | padding: label-padding-top padding-horizontal label-padding-bottom 22 | border-bottom: 1px solid status-color-primary 23 | pointer-events: none 24 | 25 | &::after 26 | content: "" 27 | position: absolute 28 | left: 0 29 | bottom: -0.125em 30 | display: block 31 | width: 0 32 | height: 0.25em 33 | background-color: status-color-info 34 | transition: width 0.3s 35 | 36 | // .effect-input__label-content 37 | // transition: transform 0.3s 38 | 39 | // 激活状态 40 | &.effect-input--filled .effect-input__label, 41 | .effect-input__field:focus + .effect-input__label 42 | &::after 43 | width: 100% 44 | 45 | .effect-input__label-content 46 | animation: animation-hoshi-label 0.3s forwards 47 | 48 | @keyframes animation-hoshi-label 49 | 50% 50 | opacity: 0 51 | transform: translate3d(1em, 0, 0) 52 | 53 | 51% 54 | opacity: 0 55 | transform: translate3d(-1em, label-active-translateY, 0) 56 | 57 | 100% 58 | opacity: 1; 59 | transform: translate3d(0, label-active-translateY, 0); 60 | -------------------------------------------------------------------------------- /src/styles/ichiro.styl: -------------------------------------------------------------------------------- 1 | 2 | input-padding = 0.25em 3 | 4 | label-padding-vertical = ((input-height - label-font-size) / 2) + input-padding 5 | label-content-active-translateY = -3.15em 6 | 7 | input-margin-top = - label-content-active-translateY / 2 + label-font-size / 2 * 0.8 8 | 9 | .effect-input--ichiro 10 | padding: input-padding 11 | margin-top: input-margin-top 12 | 13 | .effect-input__field 14 | padding: 0 0.55em 15 | background-color: #f0f0f0 16 | color: #7f8994 17 | opacity: 0 18 | transform: scale3d(1, 0, 1) 19 | transform-origin: 50% 100% 20 | transition: transform 0.3s, opacity 0.3s 21 | 22 | .effect-input__label 23 | position: absolute 24 | left: 0 25 | top: 0 26 | height: 100% 27 | padding: label-padding-vertical 1.2em 28 | cursor: text 29 | 30 | &::before 31 | content: "" 32 | position: absolute 33 | top: 0 34 | left: 0 35 | width: 100% 36 | height: 100% 37 | background-color: #fff 38 | transform-origin: 50% 100% 39 | transition: transform 0.3s 40 | z-index: -1 41 | 42 | .effect-input__label-content 43 | transform-origin: left bottom 44 | transition: transform 0.3s 45 | 46 | // 激活状态 47 | &.effect-input--filled .effect-input__field, 48 | .effect-input__field:focus 49 | transform: scale3d(1, 1, 1) 50 | opacity: 1 51 | 52 | &.effect-input--filled .effect-input__label, 53 | .effect-input__field:focus + .effect-input__label 54 | 55 | &::before 56 | transform: scale3d(1, 1.4, 1) 57 | 58 | .effect-input__label-content 59 | transform: translate3d(0, label-content-active-translateY, 0) scale3d(0.8, 0.8, 1) translateZ(1px) 60 | -------------------------------------------------------------------------------- /src/styles/index.styl: -------------------------------------------------------------------------------- 1 | @import "variables"; 2 | 3 | // SET 1 4 | @import "common"; 5 | @import "haruki"; 6 | @import "hoshi"; 7 | @import "kuro"; 8 | @import "jiro"; 9 | @import "minoru"; 10 | @import "yoko"; 11 | @import "hideo"; 12 | @import "kyo"; 13 | @import "akira"; 14 | @import "ichiro"; 15 | @import "juro"; 16 | @import "madoka"; 17 | @import "kaede"; 18 | @import "isao"; 19 | 20 | // SET2 21 | @import "manami"; 22 | @import "nariko"; 23 | -------------------------------------------------------------------------------- /src/styles/isao.styl: -------------------------------------------------------------------------------- 1 | 2 | label-content-padding = 0.95em 0.15em 0.75em 3 | isao-transition-timing-function = cubic-bezier(0.2, 1, 0.3, 1) 4 | 5 | .effect-input--isao 6 | 7 | .effect-input__field 8 | padding: 0.75em 0.1em 0 9 | color: #afb3b8 10 | 11 | .effect-input__label 12 | position: relative 13 | color: #dadada 14 | overflow: hidden 15 | 16 | &::before 17 | content: "" 18 | position: absolute 19 | left: 0 20 | top: 0 21 | width: 100% 22 | height: 0.4em 23 | background: #dadada 24 | transform: scale3d(1, 0.4, 1) 25 | transform-origin: 50% 100% 26 | transition: transform 0.3s, background-color 0.3s 27 | transition-timing-function: isao-transition-timing-function 28 | 29 | &::after 30 | content: attr(data-content) 31 | position: absolute 32 | top: 0 33 | left: 0 34 | padding: label-content-padding 35 | color: #da7071 36 | opacity: 0 37 | transform: translate3d(0, 50%, 0) 38 | transition: opacity 0.3s, transform 0.3s 39 | transition-timing-function: isao-transition-timing-function 40 | 41 | .effect-input__label-content 42 | padding: label-content-padding 43 | transition: opacity 0.3s, transform 0.3s 44 | transition-timing-function: isao-transition-timing-function 45 | 46 | // 激活状态 47 | &.effect-input--filled .effect-input__label, 48 | .effect-input__field:focus + .effect-input__label 49 | &::before 50 | background-color: #da7071 51 | transform: scale3d(1, 1, 1) 52 | 53 | &::after 54 | opacity: 1 55 | transform: translate3d(0, 0, 0) 56 | 57 | .effect-input__label-content 58 | opacity: 0 59 | transform: translate3d(0, -50%, 0) 60 | -------------------------------------------------------------------------------- /src/styles/jiro.styl: -------------------------------------------------------------------------------- 1 | 2 | input-color = #dde2e2 3 | input-margin-top = label-font-size * 2 + 5 4 | 5 | padding-horizontal = 0.95em 6 | 7 | label-active-translateY = -(input-height + label-font-size) / 2 - 0.625em 8 | 9 | $jiro-label-pseudo 10 | content: "" 11 | position: absolute 12 | top: 0 13 | left: 0 14 | width: 100% 15 | height: 100% 16 | transition: transform 0.3s 17 | 18 | .effect-input--jiro 19 | margin-top: input-margin-top 20 | 21 | .effect-input__field 22 | padding: 0 padding-horizontal 23 | color: input-color 24 | background-color: transparent 25 | opacity: 0 26 | transition: opacity 0.3s 27 | 28 | .effect-input__label 29 | @extend $input__label--vc 30 | 31 | top: 0 32 | 33 | &::before 34 | @extend $jiro-label-pseudo 35 | 36 | border-top: 2px solid #6a7989 37 | transform: translate3d(0, 100%, 0) translate3d(0, -2px, 0) 38 | transition-delay: 0.3s 39 | 40 | &::after 41 | @extend $jiro-label-pseudo 42 | 43 | background: #6a7989 44 | transform: scale3d(1, 0, 1) 45 | transform-origin: 50% 0% 46 | z-index: -1 47 | 48 | .effect-input__label-content 49 | transition: transform 0.3s 0.3s 50 | 51 | // 激活状态 52 | &.effect-input--filled .effect-input__field, 53 | .effect-input__field:focus 54 | opacity: 1 55 | transition-delay: 0.3s 56 | 57 | &.effect-input--filled .effect-input__label, 58 | .effect-input__field:focus + .effect-input__label 59 | &::before 60 | transform: translate3d(0, 0, 0) 61 | transition-delay: 0 62 | 63 | &::after 64 | transform: scale3d(1, 1, 1) 65 | transition-delay: 0.3s 66 | transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1) 67 | 68 | .effect-input__label-content 69 | transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1) 70 | transform: translate3d(0, label-active-translateY, 0) 71 | -------------------------------------------------------------------------------- /src/styles/juro.styl: -------------------------------------------------------------------------------- 1 | 2 | active-label-content-translateY = -1.5em 3 | 4 | input-margin-top = 1em 5 | 6 | juro-color = #1784cd 7 | 8 | .effect-input--juro 9 | margin-top: input-margin-top 10 | 11 | .effect-input__field 12 | position: absolute; 13 | bottom: 0.35em 14 | padding: 0 1em 15 | color: juro-color 16 | font-size: 1em 17 | 18 | .effect-input__label 19 | background: #fff 20 | cursor: text 21 | 22 | &::before 23 | content: "" 24 | position: absolute 25 | top: 0 26 | left: 0 27 | width: 100% 28 | height: 100% 29 | border: 0 solid transparent 30 | transition: border-width 0.3s, border-color 0.3s 31 | 32 | .effect-input__label-content 33 | padding: 2em input-margin-top 34 | transition: transform 0.3s, color 0.3s 35 | text-rendering: geometricPrecision 36 | transform-origin: 0 50% 37 | 38 | // 激活状态 39 | &.effect-input--filled .effect-input__label, 40 | .effect-input__field:focus + .effect-input__label 41 | &::before 42 | border-width: 0.5em 43 | border-color: juro-color 44 | border-top-width: 2em 45 | 46 | .effect-input__label-content 47 | color: #fff 48 | transform: translate3d(0, active-label-content-translateY, 0) scale3d(0.75, 0.75, 1) translateZ(1px) 49 | -------------------------------------------------------------------------------- /src/styles/kaede.styl: -------------------------------------------------------------------------------- 1 | 2 | kaede-transition-timing-function = cubic-bezier(0.2, 1, 0.3, 1) 3 | 4 | .effect-input--kaede 5 | overflow: hidden 6 | 7 | .effect-input__field 8 | padding: 0 0.8em 9 | width: 60% 10 | background: #fff 11 | color: #9dabba 12 | transform: translate3d(-100%, 0, 0) 13 | transition: transform 0.5s 14 | transition-timing-function: kaede-transition-timing-function 15 | 16 | .effect-input__label 17 | @extend $input__label--vc 18 | 19 | top: 0 20 | background: #efeeee 21 | transition: transform 0.5s 22 | transition-timing-function: kaede-transition-timing-function 23 | 24 | // 激活状态 25 | &.effect-input--filled, 26 | .effect-input__field:focus 27 | transform: translate3d(0, 0, 0) 28 | transition-delay: 0.06s 29 | 30 | &.effect-input--filled .effect-input__label, 31 | .effect-input__field:focus + .effect-input__label 32 | transform: translate3d(60%, 0, 0) 33 | -------------------------------------------------------------------------------- /src/styles/kuro.styl: -------------------------------------------------------------------------------- 1 | 2 | input-margin-bottom = 1.875em 3 | input-color = #747981 4 | 5 | label-pseudo-border = 0.25em solid input-color 6 | label-color = #df6589 7 | label-active-translateY = (input-height + label-font-size + input-margin-bottom) / 2 8 | 9 | $kuro-label-pseudo 10 | content: "" 11 | position: absolute 12 | top: 0 13 | width: 50% 14 | height: 100% 15 | border: label-pseudo-border 16 | transition: transform 0.3s 17 | 18 | .effect-input--kuro 19 | margin-bottom: input-margin-bottom * 1.5 20 | text-align: center 21 | 22 | .effect-input__field 23 | color: input-color 24 | text-align: center 25 | 26 | .effect-input__label 27 | @extend $input__label--vc 28 | 29 | top: 0 30 | color: label-color 31 | 32 | &::before 33 | @extend $kuro-label-pseudo 34 | 35 | left: 0 36 | border-right: none 37 | 38 | &::after 39 | @extend $kuro-label-pseudo 40 | 41 | right: 0 42 | border-left: none 43 | 44 | // .effect-input__label-content 45 | 46 | // 激活状态 47 | &.effect-input--filled .effect-input__label, 48 | .effect-input__field:focus + .effect-input__label 49 | &::before 50 | transform: translate3d(-10%, 0, 0) 51 | 52 | &::after 53 | transform: translate3d(10%, 0, 0) 54 | 55 | .effect-input__label-content 56 | animation: animation-kuro-label 0.3s forwards 57 | 58 | @keyframes animation-kuro-label 59 | 50% 60 | opacity: 0 61 | transform: scale3d(0.3, 0.3, 1) 62 | 63 | 51% 64 | opacity: 0 65 | transform: translate3d(0, label-active-translateY, 0) scale3d(0.3, 0.3, 1) 66 | 67 | 100% 68 | opacity: 1 69 | transform: translate3d(0, label-active-translateY, 0) 70 | -------------------------------------------------------------------------------- /src/styles/kyo.styl: -------------------------------------------------------------------------------- 1 | 2 | 3 | .effect-input--kyo 4 | z-index: 100 5 | 6 | .effect-input__field 7 | padding: 0 (field-height / 2) 8 | border-radius: field-height 9 | background-color: #fff 10 | color: #535d92 11 | 12 | .effect-input__label 13 | padding: 0.65em 0 0.65em (field-height / 1.5) 14 | 15 | &::after 16 | content: "" 17 | position: fixed 18 | top: 0 19 | left: 0 20 | width: 100% 21 | height: 100% 22 | background-color: rgba(11, 43, 205, 0.6) 23 | opacity: 0 24 | transition: opacity 0.3s 25 | pointer-events: none 26 | z-index: -1 27 | 28 | // 激活状态 29 | .effect-input__field:focus 30 | & + .effect-input__label 31 | color: #fff 32 | 33 | &::after 34 | opacity: 1 35 | -------------------------------------------------------------------------------- /src/styles/madoka.styl: -------------------------------------------------------------------------------- 1 | 2 | input-margin-bottom = 1em + label-font-size 3 | active-label-content-translateY = input-height - label-font-size + input-margin-bottom / 2 4 | 5 | .effect-input--madoka 6 | margin-bottom: input-margin-bottom 7 | color: #7a7593 8 | 9 | // .effect-input__field 10 | 11 | .effect-input__label 12 | @extend $input__label--vc 13 | 14 | top: 0 15 | 16 | .graphic 17 | position: absolute 18 | top: 0 19 | left: 0 20 | fill: none 21 | transform: scale3d(1, -1, 1) 22 | transition: stroke-dashoffset 0.3s 23 | pointer-events: none 24 | stroke: #7A7593 25 | stroke-width: 4px 26 | stroke-dasharray: 962 27 | stroke-dashoffset: 558 28 | 29 | .effect-input__label-content 30 | transform-origin: 0 50% 31 | transition: transform 0.3s 32 | 33 | // 激活状态 34 | &.effect-input--filled .effect-input__label, 35 | .effect-input__field:focus + .effect-input__label 36 | 37 | .graphic 38 | stroke-dashoffset: 0 39 | 40 | .effect-input__label-content 41 | transform: scale3d(0.81, 0.81, 1) translate3d(0, active-label-content-translateY, 0) 42 | -------------------------------------------------------------------------------- /src/styles/manami.styl: -------------------------------------------------------------------------------- 1 | 2 | active-label-content-translateY = input-height - label-font-size * 1.5 3 | input-padding-bottom = label-font-size * 2 4 | 5 | manami-transition-timing-function = cubic-bezier(0, 0.25, 0.5, 1) 6 | 7 | $manami-label-pseudo 8 | content: "" 9 | position: absolute 10 | left: 0 11 | width: 100% 12 | background-color: #a8a8a8 13 | transition-timing-function: manami-transition-timing-function 14 | 15 | .effect-input--manami 16 | padding-bottom: input-padding-bottom 17 | height: input-height + input-padding-bottom 18 | overflow: hidden 19 | 20 | .effect-input__field 21 | padding: 0.5em 22 | color: #f9f7f6 23 | 24 | .effect-input__label 25 | @extend $input__label--vc 26 | 27 | top: 0 28 | padding-left: 0.2em 29 | padding-right: 0.2em 30 | 31 | &::before 32 | @extend $manami-label-pseudo 33 | 34 | top: -100% 35 | height: 100% 36 | transition: top 0.2s 37 | z-index: -1 38 | 39 | &::after 40 | @extend $manami-label-pseudo 41 | 42 | bottom: 0 43 | height: 0.1em 44 | opacity: 1 45 | transition: opacity 0.2s 46 | 47 | .effect-input__label-content 48 | font-size: 1.25em 49 | transition-timing-function: manami-transition-timing-function 50 | transition: transform 0.2s, color 0.2s 51 | transform-origin: 0 0 52 | 53 | // 激活状态 54 | &.effect-input--filled .effect-input__field, 55 | .effect-input__field:focus 56 | // transform: scale3d(1, 1, 1) 57 | 58 | &.effect-input--filled .effect-input__label, 59 | .effect-input__field:focus + .effect-input__label 60 | &::before 61 | top: 0 62 | 63 | &::after 64 | opacity: 0 65 | 66 | .effect-input__label-content 67 | color: #cbc4c6 68 | transform: translate3d(0, active-label-content-translateY, 0) scale3d(0.65, 0.65, 1) 69 | -------------------------------------------------------------------------------- /src/styles/minoru.styl: -------------------------------------------------------------------------------- 1 | 2 | 3 | .effect-input--minoru 4 | 5 | .effect-input__field 6 | padding: 0 0.95em 7 | color: #eca29b 8 | background: #fff 9 | box-shadow: 0 0 0 2px transparent 10 | transition: box-shadow 0.3s 11 | 12 | .effect-input__label 13 | padding: 0.9em 0.35em 14 | 15 | &::after 16 | content: "" 17 | position: absolute 18 | top: 0 19 | z-index: -1 20 | width: 100% 21 | height: input-height 22 | box-shadow: 0 0 0 0 23 | color: rgba(199, 152, 157, 0.6) 24 | 25 | // 激活状态 26 | &.effect-input--filled .effect-input__field, 27 | .effect-input__field:focus 28 | box-shadow: 0 0 0 2px #eca29b 29 | 30 | &.effect-input--filled .effect-input__label, 31 | .effect-input__field:focus + .effect-input__label 32 | &::after 33 | animation: animation-minoru-label-pseudo 0.3s forwards 34 | 35 | 36 | @keyframes animation-minoru-label-pseudo 37 | to 38 | box-shadow: 0 0 100px 50px 39 | opacity: 0 40 | -------------------------------------------------------------------------------- /src/styles/nariko.styl: -------------------------------------------------------------------------------- 1 | 2 | active-label-content-translateY = - (input-height - label-font-size) 3 | 4 | input-padding-top = label-font-size * 2 5 | 6 | nariko-transition-timing-function = cubic-bezier(0.7, 0, 0.3, 1) 7 | 8 | $nariko-label-pseudo 9 | content: "" 10 | position: absolute 11 | left: 0 12 | width: 100% 13 | transition-timing-function: nariko-transition-timing-function 14 | 15 | .effect-input--nariko 16 | padding-top: input-padding-top 17 | height: input-height + input-padding-top 18 | overflow: hidden 19 | 20 | .effect-input__field 21 | padding: 0.5em 22 | color: #f18292 23 | opacity: 0 24 | 25 | .effect-input__label 26 | @extend $input__label--vc 27 | 28 | bottom: 0 29 | padding-left: 0.5em 30 | padding-right: 0.5em 31 | 32 | &::before 33 | @extend $nariko-label-pseudo 34 | 35 | bottom: -100% 36 | height: 100% 37 | border-top: 0.2em solid #9b9f9f 38 | background-color: #fff 39 | transition: bottom transition-time 40 | transform: translate3d(0, -0.2em, 0) 41 | z-index: -1 42 | 43 | .effect-input__label-content 44 | color: #8e9191 45 | transition-timing-function: nariko-transition-timing-function 46 | transition: transform transition-time, color transition-time 47 | transform-origin: 0 0 48 | 49 | // 激活状态 50 | &.effect-input--filled .effect-input__field, 51 | .effect-input__field:focus 52 | opacity: 1 53 | transition: opacity 0s transition-time 54 | 55 | &.effect-input--filled .effect-input__label, 56 | .effect-input__field:focus + .effect-input__label 57 | &::before 58 | bottom: 0 59 | 60 | .effect-input__label-content 61 | color: #6b6e6e 62 | transform: translate3d(0, active-label-content-translateY, 0) scale3d(0.9, 0.9, 1) 63 | -------------------------------------------------------------------------------- /src/styles/template.styl: -------------------------------------------------------------------------------- 1 | 2 | 3 | .effect-input--hoshi 4 | 5 | .effect-input__field 6 | 7 | .effect-input__label 8 | 9 | .effect-input__label-content 10 | 11 | // 激活状态 12 | &.effect-input--filled .effect-input__label, 13 | .effect-input__field:focus + .effect-input__label 14 | 15 | .effect-input__label-content 16 | -------------------------------------------------------------------------------- /src/styles/variables.styl: -------------------------------------------------------------------------------- 1 | input-width = 320px 2 | input-width = 20em 3 | input-height = 4.125em 4 | input-font-size = 1em 5 | 6 | label-font-size = input-font-size 7 | label-color = #6a7989 8 | 9 | field-font-size = 1.5em 10 | field-color = #afb5bb 11 | field-height = input-height * input-font-size / field-font-size 12 | 13 | status-color-primary = #6a7989 14 | status-color-info = #1dacfc 15 | status-color-success = #2bfdac 16 | status-color-danger = #fc561f 17 | 18 | transition-time = 0.3s 19 | 20 | -------------------------------------------------------------------------------- /src/styles/yoko.styl: -------------------------------------------------------------------------------- 1 | 2 | pseudo-background-color = #c5564a 3 | 4 | $yoko-label-pseudo 5 | content: "" 6 | position: absolute 7 | left: 0 8 | width: 100% 9 | transition: transform 0.3s 10 | 11 | .effect-input--yoko 12 | 13 | .effect-input__field 14 | padding: 0 15px 15 | color: #f5f5f5 16 | opacity: 0 17 | transition: opacity 0.3s 18 | 19 | .effect-input__label 20 | position: relative 21 | color: #b04b40 22 | 23 | &::before 24 | @extend $yoko-label-pseudo 25 | 26 | bottom: 100% 27 | height: input-height 28 | background-color: pseudo-background-color 29 | transform: perspective(1000px) rotate3d(1, 0, 0, 90deg) 30 | transform-origin: 50% 100% 31 | z-index: -1 32 | 33 | &::after 34 | @extend $yoko-label-pseudo 35 | 36 | top: 0 37 | height: 4px 38 | background: #ad473c 39 | transform-origin: 50% 0% 40 | 41 | .effect-input__label-content 42 | padding: 1.2em 0.95em 43 | 44 | // 激活状态 45 | &.effect-input--filled .effect-input__label, 46 | .effect-input__field:focus + .effect-input__label 47 | &::before 48 | transform: perspective(1000px) rotate3d(1, 0, 0, 0) 49 | 50 | &::after 51 | transform: perspective(1000px) rotate3d(1, 0, 0, -90deg) 52 | 53 | &.effect-input--filled .effect-input__field, 54 | .effect-input__field:focus 55 | opacity: 1 56 | transition-delay: 0.3s 57 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var webpack = require('webpack') 3 | 4 | module.exports = { 5 | entry: './examples/main.js', 6 | output: { 7 | path: path.resolve(__dirname, 'sites'), 8 | publicPath: '', 9 | filename: 'build.js' 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.css$/, 15 | use: [ 16 | 'vue-style-loader', 17 | 'css-loader' 18 | ], 19 | }, 20 | { 21 | test: /\.styl$/, 22 | loader: 'style-loader!css-loader!stylus-loader', 23 | exclude: /node_modules/ 24 | }, 25 | { 26 | test: /\.vue$/, 27 | loader: 'vue-loader', 28 | options: { 29 | loaders: { 30 | } 31 | // other vue-loader options go here 32 | } 33 | }, 34 | { 35 | test: /\.js$/, 36 | loader: 'babel-loader', 37 | exclude: /node_modules/ 38 | }, 39 | { 40 | test: /\.(png|jpg|gif|svg)$/, 41 | loader: 'file-loader', 42 | options: { 43 | name: '[name].[ext]?[hash]' 44 | } 45 | }, 46 | { 47 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 48 | loader: 'url-loader', 49 | query: { 50 | limit: 10000, 51 | name: 'fonts/[name].[hash:7].[ext]' 52 | } 53 | } 54 | ] 55 | }, 56 | resolve: { 57 | alias: { 58 | 'vue$': 'vue/dist/vue.esm.js' 59 | }, 60 | extensions: ['*', '.js', '.vue', '.json'] 61 | }, 62 | devServer: { 63 | historyApiFallback: true, 64 | noInfo: true, 65 | overlay: true 66 | }, 67 | performance: { 68 | hints: false 69 | }, 70 | devtool: '#eval-source-map' 71 | } 72 | 73 | if (process.env.NODE_ENV === 'production') { 74 | module.exports.devtool = '#source-map' 75 | // http://vue-loader.vuejs.org/en/workflow/production.html 76 | module.exports.plugins = (module.exports.plugins || []).concat([ 77 | new webpack.DefinePlugin({ 78 | 'process.env': { 79 | NODE_ENV: '"production"' 80 | } 81 | }), 82 | new webpack.optimize.UglifyJsPlugin({ 83 | sourceMap: true, 84 | compress: { 85 | warnings: false 86 | } 87 | }), 88 | new webpack.LoaderOptionsPlugin({ 89 | minimize: true 90 | }) 91 | ]) 92 | } 93 | --------------------------------------------------------------------------------