├── .editorconfig ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── README.zh-CN.md ├── demo ├── App.vue ├── assets │ ├── Crested_Ibis.jpg │ └── demo.gif ├── dist │ ├── Crested_Ibis.61dac377.jpg │ ├── index.html │ ├── main.41d0c573.js │ ├── main.41d0c573.js.map │ └── main.c967b235.css ├── index.html └── main.js ├── dist ├── vue-image-painter.common.js ├── vue-image-painter.common.min.js ├── vue-image-painter.esm.js ├── vue-image-painter.esm.min.js ├── vue-image-painter.js └── vue-image-painter.min.js ├── package.json ├── scripts └── release.sh ├── src ├── ImagePainter │ ├── index.vue │ ├── mixins │ │ └── index.js │ └── style │ │ └── animation.styl └── index.js └── yarn.lock /.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 | .cache 3 | node_modules 4 | *.log 5 | .idea 6 | .vscode 7 | package-lock.json 8 | npm-debug.log 9 | dev 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | 6 | ## [0.1.3](https://github.com/komomoo/vue-image-painter/compare/v0.1.2...v0.1.3) (2019-07-05) 7 | 8 | 9 | 10 | 11 | ## [0.1.2](https://github.com/komomoo/vue-image-painter/compare/v0.1.1...v0.1.2) (2019-07-05) 12 | 13 | 14 | 15 | 16 | ## [0.1.1](https://github.com/komomoo/vue-image-painter/compare/v0.1.0...v0.1.1) (2019-07-05) 17 | 18 | 19 | ### Features 20 | 21 | * add animation blur ([69333e9](https://github.com/komomoo/vue-image-painter/commit/69333e9)) 22 | * props add animation ([d116126](https://github.com/komomoo/vue-image-painter/commit/d116126)) 23 | 24 | 25 | 26 | 27 | # 0.1.0 (2019-07-05) 28 | 29 | 30 | ### Features 31 | 32 | * demo ([11249d6](https://github.com/komomoo/vue-image-painter/commit/11249d6)) 33 | * ImagePainter ([19d8d69](https://github.com/komomoo/vue-image-painter/commit/19d8d69)) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 komo 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 | # vue-image-painter 2 | 3 | English | [简体中文](./README.zh-CN.md) 4 | 5 | ## 🌰 Example 6 | 7 | 8 | 9 | [Demo](https://komomoo.github.io/vue-image-painter/demo/dist/) 10 | 11 | [Demo Source Code](https://github.com/komomoo/vue-image-painter/blob/master/demo/App.vue) 12 | 13 | ## 🚀 QuickStart 14 | 15 | 1. Install 16 | 17 | ```bash 18 | yarn add vue-image-painter # OR npm i -S vue-image-painter 19 | ``` 20 | 21 | 2. Import 22 | 23 | ```js 24 | // main.js 25 | import ImagePainter from 'vue-image-painter' 26 | Vue.use(ImagePainter) 27 | ``` 28 | 29 | 3. Usage. Please refer to the [Demo Source Code](https://github.com/komomoo/vue-image-painter/blob/master/demo/App.vue) 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | ## 🔌 API 36 | 37 | ### Props 38 | 39 | | Name | Description | Type | Default | 40 | | --------- | --------------------------------------------------------------------------- | ------- | --------- | 41 | | src | image URL. local images must be used `require('')` | String | undefined | 42 | | alt | image alt | String | undefined | 43 | | animation | animation effect. optional key: 'draw','blur' | String | 'draw' | 44 | | duration | animation duration. unit: ms | Number | 4000 | 45 | | immediate | display images and animations immediately, don't wait for the image to load | Boolean | false | 46 | 47 | ### Events 48 | 49 | | Name | Description | Parameters | 50 | | --------- | ---------------- | ---------- | 51 | | loadStart | image load start | null | 52 | | loadEnd | image load end | null | 53 | 54 | ### Slots 55 | 56 | | Name | Description | 57 | | ------- | ------------------------------------------------------------- | 58 | | default | The content ImagePainter displays, before the image is loaded | 59 | 60 | --- 61 | 62 | 😉😘 If it is helpful to you,please encourage me with a ⭐️Star ~ 63 | 64 | ## Inspiration 65 | 66 | - [ImageDrawer.js](https://github.com/UstymUkhman/ImageDrawer.js) 67 | 68 | ## [Changelog](./CHANGELOG.md) 69 | 70 | ## License 71 | 72 | [MIT](http://opensource.org/licenses/MIT) 73 | 74 | Copyright (c) 2018-present, komo 75 | -------------------------------------------------------------------------------- /README.zh-CN.md: -------------------------------------------------------------------------------- 1 | # vue-image-painter 2 | 3 | [English](./README.md) | 简体中文 4 | 5 | ## 🌰 示例 6 | 7 | 8 | 9 | [Demo](https://komomoo.github.io/vue-image-painter/demo/dist/) 10 | 11 | [Demo 源码](https://github.com/komomoo/vue-image-painter/blob/master/demo/App.vue) 12 | 13 | ## 🚀 快速开始 14 | 15 | 1. 安装 16 | 17 | ```bash 18 | yarn add vue-image-painter # 或 npm i -S vue-image-painter 19 | ``` 20 | 21 | 2. 引入 22 | 23 | ```js 24 | // main.js 入口中 25 | import ImagePainter from 'vue-image-painter' 26 | Vue.use(ImagePainter) 27 | ``` 28 | 29 | 3. 使用,请参考[Demo 源码](https://github.com/komomoo/vue-image-painter/blob/master/demo/App.vue) 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | ## 🔌 API 36 | 37 | ### Props 38 | 39 | | 选项 | 说明 | 类型 | 默认值 | 40 | | --------- | --------------------------------------- | ------- | --------- | 41 | | src | 图片链接。本地图片须用 require('') 引入 | String | undefined | 42 | | alt | 图片描述 | String | undefined | 43 | | animation | 动画效果,可选:'draw','blur' | String | 'draw' | 44 | | duration | 动画持续时间,单位 ms | Number | 4000 | 45 | | immediate | 立即显示图片和动画,而不等图片加载完 | Boolean | false | 46 | 47 | ### Events 48 | 49 | | 事件名 | 说明 | 回调参数 | 50 | | --------- | ------------ | -------- | 51 | | loadStart | 图片加载开始 | null | 52 | | loadEnd | 图片加载结束 | null | 53 | 54 | ### Slots 55 | 56 | | 名称 | 说明 | 57 | | ------- | ------------------------------------------- | 58 | | default | 图片未加载完成前,ImagePainter 内显示的内容 | 59 | 60 | --- 61 | 62 | 😉😘 如果它对你有所帮助,可以点一下 ⭐️Star ~ 63 | 64 | ## 灵感 65 | 66 | - [ImageDrawer.js](https://github.com/UstymUkhman/ImageDrawer.js) 67 | 68 | ## [更新日志](./CHANGELOG.md) 69 | 70 | ## License 71 | 72 | [MIT](http://opensource.org/licenses/MIT) 73 | 74 | Copyright (c) 2018-present, komo 75 | -------------------------------------------------------------------------------- /demo/App.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 35 | 36 | 78 | -------------------------------------------------------------------------------- /demo/assets/Crested_Ibis.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/komomoo/vue-image-painter/29755e89175696ac55ba239e8889f369c7fae458/demo/assets/Crested_Ibis.jpg -------------------------------------------------------------------------------- /demo/assets/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/komomoo/vue-image-painter/29755e89175696ac55ba239e8889f369c7fae458/demo/assets/demo.gif -------------------------------------------------------------------------------- /demo/dist/Crested_Ibis.61dac377.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/komomoo/vue-image-painter/29755e89175696ac55ba239e8889f369c7fae458/demo/dist/Crested_Ibis.61dac377.jpg -------------------------------------------------------------------------------- /demo/dist/index.html: -------------------------------------------------------------------------------- 1 | vue-image-painter
-------------------------------------------------------------------------------- /demo/dist/main.41d0c573.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c=0&&Math.floor(e)===e&&isFinite(t)}function d(t){return r(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function v(t){return null==t?"":Array.isArray(t)||l(t)&&t.toString===c?JSON.stringify(t,null,2):String(t)}function h(t){var e=parseFloat(t);return isNaN(e)?t:e}function m(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(n,1)}}var b=Object.prototype.hasOwnProperty;function C(t,e){return b.call(t,e)}function w(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var $=/-(\w)/g,A=w(function(t){return t.replace($,function(t,e){return e?e.toUpperCase():""})}),x=w(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}),O=/\B([A-Z])/g,k=w(function(t){return t.replace(O,"-$1").toLowerCase()});function S(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function j(t,e){return t.bind(e)}var E=Function.prototype.bind?j:S;function T(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function I(t,e){for(var n in e)t[n]=e[n];return t}function D(t){for(var e={},n=0;n0,rt=tt&&tt.indexOf("edge/")>0,ot=tt&&tt.indexOf("android")>0||"android"===Y,it=tt&&/iphone|ipad|ipod|ios/.test(tt)||"ios"===Y,at=tt&&/chrome\/\d+/.test(tt)&&!rt,st=tt&&/phantomjs/.test(tt),ct=tt&&tt.match(/firefox\/(\d+)/),ut={}.watch,lt=!1;if(J)try{var ft={};Object.defineProperty(ft,"passive",{get:function(){lt=!0}}),window.addEventListener("test-passive",null,ft)}catch(as){}var pt=function(){return void 0===G&&(G=!J&&!Q&&void 0!==t&&(t.process&&"server"===t.process.env.VUE_ENV)),G},dt=J&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function vt(t){return"function"==typeof t&&/native code/.test(t.toString())}var ht,mt="undefined"!=typeof Symbol&&vt(Symbol)&&"undefined"!=typeof Reflect&&vt(Reflect.ownKeys);ht="undefined"!=typeof Set&&vt(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var yt,gt,_t,bt,Ct=N,wt=N,$t=N,At=N,xt=0,Ot=function(){this.id=xt++,this.subs=[]};Ot.prototype.addSub=function(t){this.subs.push(t)},Ot.prototype.removeSub=function(t){_(this.subs,t)},Ot.prototype.depend=function(){Ot.target&&Ot.target.addDep(this)},Ot.prototype.notify=function(){var t=this.subs.slice();for(var e=0,n=t.length;e-1)if(i&&!C(o,"default"))a=!1;else if(""===a||a===k(t)){var c=ye(String,o.type);(c<0||s0&&(on((s=an(s,(e||"")+"_"+i))[0])&&on(u)&&(l[c]=Dt(u.text+s[0].text),s.shift()),l.push.apply(l,s)):a(s)?on(u)?l[c]=Dt(u.text+s):""!==s&&l.push(Dt(s)):on(s)&&on(u)?l[c]=Dt(u.text+s.text):(o(t._isVList)&&r(s.tag)&&n(s.key)&&r(e)&&(s.key="__vlist"+e+"_"+i+"__"),l.push(s)));return l}function sn(t){var e=t.$options.provide;e&&(t._provided="function"==typeof e?e.call(t):e)}function cn(t){var e=un(t.$options.inject,t);e&&(Ht(!1),Object.keys(e).forEach(function(n){Wt(t,n,e[n])}),Ht(!0))}function un(t,e){if(t){for(var n=Object.create(null),r=mt?Reflect.ownKeys(t):Object.keys(t),o=0;o0,a=t?!!t.$stable:!i,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==e&&s===r.$key&&!i&&!r.$hasNormal)return r;for(var c in o={},t)t[c]&&"$"!==c[0]&&(o[c]=dn(n,c,t[c]))}else o={};for(var u in n)u in o||(o[u]=vn(n,u));return t&&Object.isExtensible(t)&&(t._normalized=o),q(o,"$stable",a),q(o,"$key",s),q(o,"$hasNormal",i),o}function dn(t,e,n){var r=function(){var t=arguments.length?n.apply(null,arguments):n({});return(t=t&&"object"==typeof t&&!Array.isArray(t)?[t]:rn(t))&&(0===t.length||1===t.length&&t[0].isComment)?void 0:t};return n.proxy&&Object.defineProperty(t,e,{get:r,enumerable:!0,configurable:!0}),r}function vn(t,e){return function(){return t[e]}}function hn(t,e){var n,o,i,a,c;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),o=0,i=t.length;o1?T(n):n;for(var r=T(arguments,1),o='event handler for "'+t+'"',i=0,a=n.length;idocument.createEvent("Event").timeStamp&&(jr=function(){return Er.now()})}function Tr(){var t,e;for(Sr=jr(),xr=!0,br.sort(function(t,e){return t.id-e.id}),Or=0;OrOr&&br[n].id>t.id;)n--;br.splice(n+1,0,t)}else br.push(t);Ar||(Ar=!0,ze(Tr))}}var Pr=0,Mr=function(t,e,n,r,o){this.vm=t,o&&(t._watcher=this),t._watchers.push(this),r?(this.deep=!!r.deep,this.user=!!r.user,this.lazy=!!r.lazy,this.sync=!!r.sync,this.before=r.before):this.deep=this.user=this.lazy=this.sync=!1,this.cb=n,this.id=++Pr,this.active=!0,this.dirty=this.lazy,this.deps=[],this.newDeps=[],this.depIds=new ht,this.newDepIds=new ht,this.expression="","function"==typeof e?this.getter=e:(this.getter=X(e),this.getter||(this.getter=N)),this.value=this.lazy?void 0:this.get()};Mr.prototype.get=function(){var t;St(this);var e=this.vm;try{t=this.getter.call(e,e)}catch(as){if(!this.user)throw as;we(as,e,'getter for watcher "'+this.expression+'"')}finally{this.deep&&Xe(t),jt(),this.cleanupDeps()}return t},Mr.prototype.addDep=function(t){var e=t.id;this.newDepIds.has(e)||(this.newDepIds.add(e),this.newDeps.push(t),this.depIds.has(e)||t.addSub(this))},Mr.prototype.cleanupDeps=function(){for(var t=this.deps.length;t--;){var e=this.deps[t];this.newDepIds.has(e.id)||e.removeSub(this)}var n=this.depIds;this.depIds=this.newDepIds,this.newDepIds=n,this.newDepIds.clear(),n=this.deps,this.deps=this.newDeps,this.newDeps=n,this.newDeps.length=0},Mr.prototype.update=function(){this.lazy?this.dirty=!0:this.sync?this.run():Lr(this)},Mr.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||s(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(as){we(as,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},Mr.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},Mr.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},Mr.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||_(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var Fr={enumerable:!0,configurable:!0,get:N,set:N};function Rr(t,e,n){Fr.get=function(){return this[e][n]},Fr.set=function(t){this[e][n]=t},Object.defineProperty(t,n,Fr)}function Hr(t){t._watchers=[];var e=t.$options;e.props&&Ur(t,e.props),e.methods&&Gr(t,e.methods),e.data?Br(t):Vt(t._data={},!0),e.computed&&Wr(t,e.computed),e.watch&&e.watch!==ut&&Zr(t,e.watch)}function Ur(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[],i=!t.$parent;i||Ht(!1);var a=function(i){o.push(i);var a=le(i,e,n,t);Wt(r,i,a),i in t||Rr(t,"_props",i)};for(var s in e)a(s);Ht(!0)}function Br(t){var e=t.$options.data;l(e=t._data="function"==typeof e?zr(e,t):e||{})||(e={});for(var n=Object.keys(e),r=t.$options.props,o=(t.$options.methods,n.length);o--;){var i=n[o];0,r&&C(r,i)||W(i)||Rr(t,"_data",i)}Vt(e,!0)}function zr(t,e){St();try{return t.call(e,e)}catch(as){return we(as,e,"data()"),{}}finally{jt()}}var Vr={lazy:!0};function Wr(t,e){var n=t._computedWatchers=Object.create(null),r=pt();for(var o in e){var i=e[o],a="function"==typeof i?i:i.get;0,r||(n[o]=new Mr(t,a||N,N,Vr)),o in t||qr(t,o,i)}}function qr(t,e,n){var r=!pt();"function"==typeof n?(Fr.get=r?Kr(e):Xr(n),Fr.set=N):(Fr.get=n.get?r&&!1!==n.cache?Kr(e):Xr(n.get):N,Fr.set=n.set||N),Object.defineProperty(t,e,Fr)}function Kr(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),Ot.target&&e.depend(),e.value}}function Xr(t){return function(){return t.call(this,this)}}function Gr(t,e){t.$options.props;for(var n in e)t[n]="function"!=typeof e[n]?N:E(e[n],t)}function Zr(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o-1)return this;var n=T(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}function ao(t){t.mixin=function(t){return this.options=ce(this.options,t),this}}function so(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name;var a=function(t){this._init(t)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=e++,a.options=ce(n.options,t),a.super=n,a.options.props&&co(a),a.options.computed&&uo(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,U.forEach(function(t){a[t]=n[t]}),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=I({},a.options),o[r]=a,a}}function co(t){var e=t.options.props;for(var n in e)Rr(t.prototype,"_props",n)}function uo(t){var e=t.options.computed;for(var n in e)qr(t.prototype,n,e[n])}function lo(t){U.forEach(function(e){t[e]=function(t,n){return n?("component"===e&&l(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}})}function fo(t){return t&&(t.Ctor.options.name||t.tag)}function po(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:!!f(t)&&t.test(e)}function vo(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a=n[i];if(a){var s=fo(a.componentOptions);s&&!e(s)&&ho(n,i,r,o)}}}function ho(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,_(n,e)}to(oo),Qr(oo),sr(oo),pr(oo),Zn(oo);var mo=[String,RegExp,Array],yo={name:"keep-alive",abstract:!0,props:{include:mo,exclude:mo,max:[String,Number]},created:function(){this.cache=Object.create(null),this.keys=[]},destroyed:function(){for(var t in this.cache)ho(this.cache,t,this.keys)},mounted:function(){var t=this;this.$watch("include",function(e){vo(t,function(t){return po(e,t)})}),this.$watch("exclude",function(e){vo(t,function(t){return!po(e,t)})})},render:function(){var t=this.$slots.default,e=er(t),n=e&&e.componentOptions;if(n){var r=fo(n),o=this.include,i=this.exclude;if(o&&(!r||!po(o,r))||i&&r&&po(i,r))return e;var a=this.cache,s=this.keys,c=null==e.key?n.Ctor.cid+(n.tag?"::"+n.tag:""):e.key;a[c]?(e.componentInstance=a[c].componentInstance,_(s,c),s.push(c)):(a[c]=e,s.push(c),this.max&&s.length>parseInt(this.max)&&ho(a,s[0],s,this._vnode)),e.data.keepAlive=!0}return e||t&&t[0]}},go={KeepAlive:yo};function _o(t){var e={get:function(){return z}};Object.defineProperty(t,"config",e),t.util={warn:Ct,extend:I,mergeOptions:ce,defineReactive:Wt},t.set=qt,t.delete=Kt,t.nextTick=ze,t.observable=function(t){return Vt(t),t},t.options=Object.create(null),U.forEach(function(e){t.options[e+"s"]=Object.create(null)}),t.options._base=t,I(t.options.components,go),io(t),ao(t),so(t),lo(t)}_o(oo),Object.defineProperty(oo.prototype,"$isServer",{get:pt}),Object.defineProperty(oo.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(oo,"FunctionalRenderContext",{value:En}),oo.version="2.6.10";var bo=m("style,class"),Co=m("input,textarea,option,select,progress"),wo=function(t,e,n){return"value"===n&&Co(t)&&"button"!==e||"selected"===n&&"option"===t||"checked"===n&&"input"===t||"muted"===n&&"video"===t},$o=m("contenteditable,draggable,spellcheck"),Ao=m("events,caret,typing,plaintext-only"),xo=function(t,e){return Eo(e)||"false"===e?"false":"contenteditable"===t&&Ao(e)?e:"true"},Oo=m("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),ko="http://www.w3.org/1999/xlink",So=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},jo=function(t){return So(t)?t.slice(6,t.length):""},Eo=function(t){return null==t||!1===t};function To(t){for(var e=t.data,n=t,o=t;r(o.componentInstance);)(o=o.componentInstance._vnode)&&o.data&&(e=Io(o.data,e));for(;r(n=n.parent);)n&&n.data&&(e=Io(e,n.data));return Do(e.staticClass,e.class)}function Io(t,e){return{staticClass:No(t.staticClass,e.staticClass),class:r(t.class)?[t.class,e.class]:e.class}}function Do(t,e){return r(t)||r(e)?No(t,Lo(e)):""}function No(t,e){return t?e?t+" "+e:t:e||""}function Lo(t){return Array.isArray(t)?Po(t):s(t)?Mo(t):"string"==typeof t?t:""}function Po(t){for(var e,n="",o=0,i=t.length;o-1?zo[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:zo[t]=/HTMLUnknownElement/.test(e.toString())}var Wo=m("text,number,password,search,email,tel,url");function qo(t){if("string"==typeof t){var e=document.querySelector(t);return e||document.createElement("div")}return t}function Ko(t,e){var n=document.createElement(t);return"select"!==t?n:(e.data&&e.data.attrs&&void 0!==e.data.attrs.multiple&&n.setAttribute("multiple","multiple"),n)}function Xo(t,e){return document.createElementNS(Fo[t],e)}function Go(t){return document.createTextNode(t)}function Zo(t){return document.createComment(t)}function Jo(t,e,n){t.insertBefore(e,n)}function Qo(t,e){t.removeChild(e)}function Yo(t,e){t.appendChild(e)}function ti(t){return t.parentNode}function ei(t){return t.nextSibling}function ni(t){return t.tagName}function ri(t,e){t.textContent=e}function oi(t,e){t.setAttribute(e,"")}var ii=Object.freeze({createElement:Ko,createElementNS:Xo,createTextNode:Go,createComment:Zo,insertBefore:Jo,removeChild:Qo,appendChild:Yo,parentNode:ti,nextSibling:ei,tagName:ni,setTextContent:ri,setStyleScope:oi}),ai={create:function(t,e){si(e)},update:function(t,e){t.data.ref!==e.data.ref&&(si(t,!0),si(e))},destroy:function(t){si(t,!0)}};function si(t,e){var n=t.data.ref;if(r(n)){var o=t.context,i=t.componentInstance||t.elm,a=o.$refs;e?Array.isArray(a[n])?_(a[n],i):a[n]===i&&(a[n]=void 0):t.data.refInFor?Array.isArray(a[n])?a[n].indexOf(i)<0&&a[n].push(i):a[n]=[i]:a[n]=i}}var ci=new Et("",{},[]),ui=["create","activate","update","remove","destroy"];function li(t,e){return t.key===e.key&&(t.tag===e.tag&&t.isComment===e.isComment&&r(t.data)===r(e.data)&&fi(t,e)||o(t.isAsyncPlaceholder)&&t.asyncFactory===e.asyncFactory&&n(e.asyncFactory.error))}function fi(t,e){if("input"!==t.tag)return!0;var n,o=r(n=t.data)&&r(n=n.attrs)&&n.type,i=r(n=e.data)&&r(n=n.attrs)&&n.type;return o===i||Wo(o)&&Wo(i)}function pi(t,e,n){var o,i,a={};for(o=e;o<=n;++o)r(i=t[o].key)&&(a[i]=o);return a}function di(t){var e,i,s={},c=t.modules,u=t.nodeOps;for(e=0;ev?_(t,n(o[y+1])?null:o[y+1].elm,o,d,y,i):d>y&&C(0,e,p,v)}(p,m,y,i,l):r(y)?(r(t.text)&&u.setTextContent(p,""),_(p,null,y,0,y.length-1,i)):r(m)?C(0,m,0,m.length-1):r(t.text)&&u.setTextContent(p,""):t.text!==e.text&&u.setTextContent(p,e.text),r(v)&&r(d=v.hook)&&r(d=d.postpatch)&&d(t,e)}}}function x(t,e,n){if(o(n)&&r(t.parent))t.parent.data.pendingInsert=e;else for(var i=0;i-1?Ai(t,e,n):Oo(e)?Eo(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):$o(e)?t.setAttribute(e,xo(e,n)):So(e)?Eo(n)?t.removeAttributeNS(ko,jo(e)):t.setAttributeNS(ko,e,n):Ai(t,e,n)}function Ai(t,e,n){if(Eo(n))t.removeAttribute(e);else{if(et&&!nt&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var xi={create:wi,update:wi};function Oi(t,e){var o=e.elm,i=e.data,a=t.data;if(!(n(i.staticClass)&&n(i.class)&&(n(a)||n(a.staticClass)&&n(a.class)))){var s=To(e),c=o._transitionClasses;r(c)&&(s=No(s,Lo(c))),s!==o._prevClass&&(o.setAttribute("class",s),o._prevClass=s)}}var ki,Si={create:Oi,update:Oi},ji="__r",Ei="__c";function Ti(t){if(r(t[ji])){var e=et?"change":"input";t[e]=[].concat(t[ji],t[e]||[]),delete t[ji]}r(t[Ei])&&(t.change=[].concat(t[Ei],t.change||[]),delete t[Ei])}function Ii(t,e,n){var r=ki;return function o(){null!==e.apply(null,arguments)&&Li(t,o,n,r)}}var Di=Le&&!(ct&&Number(ct[1])<=53);function Ni(t,e,n,r){if(Di){var o=Sr,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}ki.addEventListener(t,e,lt?{capture:n,passive:r}:n)}function Li(t,e,n,r){(r||ki).removeEventListener(t,e._wrapper||e,n)}function Pi(t,e){if(!n(t.data.on)||!n(e.data.on)){var r=e.data.on||{},o=t.data.on||{};ki=e.elm,Ti(r),Qe(r,o,Ni,Li,Ii,e.context),ki=void 0}}var Mi,Fi={create:Pi,update:Pi};function Ri(t,e){if(!n(t.data.domProps)||!n(e.data.domProps)){var o,i,a=e.elm,s=t.data.domProps||{},c=e.data.domProps||{};for(o in r(c.__ob__)&&(c=e.data.domProps=I({},c)),s)o in c||(a[o]="");for(o in c){if(i=c[o],"textContent"===o||"innerHTML"===o){if(e.children&&(e.children.length=0),i===s[o])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===o&&"PROGRESS"!==a.tagName){a._value=i;var u=n(i)?"":String(i);Hi(a,u)&&(a.value=u)}else if("innerHTML"===o&&Ho(a.tagName)&&n(a.innerHTML)){(Mi=Mi||document.createElement("div")).innerHTML=""+i+"";for(var l=Mi.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(i!==s[o])try{a[o]=i}catch(as){}}}}function Hi(t,e){return!t.composing&&("OPTION"===t.tagName||Ui(t,e)||Bi(t,e))}function Ui(t,e){var n=!0;try{n=document.activeElement!==t}catch(as){}return n&&t.value!==e}function Bi(t,e){var n=t.value,o=t._vModifiers;if(r(o)){if(o.number)return h(n)!==h(e);if(o.trim)return n.trim()!==e.trim()}return n!==e}var zi={create:Ri,update:Ri},Vi=w(function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach(function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}}),e});function Wi(t){var e=qi(t.style);return t.staticStyle?I(t.staticStyle,e):e}function qi(t){return Array.isArray(t)?D(t):"string"==typeof t?Vi(t):t}function Ki(t,e){var n,r={};if(e)for(var o=t;o.componentInstance;)(o=o.componentInstance._vnode)&&o.data&&(n=Wi(o.data))&&I(r,n);(n=Wi(t.data))&&I(r,n);for(var i=t;i=i.parent;)i.data&&(n=Wi(i.data))&&I(r,n);return r}var Xi,Gi=/^--/,Zi=/\s*!important$/,Ji=function(t,e,n){if(Gi.test(e))t.style.setProperty(e,n);else if(Zi.test(n))t.style.setProperty(k(e),n.replace(Zi,""),"important");else{var r=Yi(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(na).forEach(function(e){return t.classList.add(e)}):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function oa(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(na).forEach(function(e){return t.classList.remove(e)}):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function ia(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&I(e,aa(t.name||"v")),I(e,t),e}return"string"==typeof t?aa(t):void 0}}var aa=w(function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}}),sa=J&&!nt,ca="transition",ua="animation",la="transition",fa="transitionend",pa="animation",da="animationend";sa&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(la="WebkitTransition",fa="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(pa="WebkitAnimation",da="webkitAnimationEnd"));var va=J?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function ha(t){va(function(){va(t)})}function ma(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),ra(t,e))}function ya(t,e){t._transitionClasses&&_(t._transitionClasses,e),oa(t,e)}function ga(t,e,n){var r=ba(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===ca?fa:da,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout(function(){c0&&(n=ca,l=a,f=i.length):e===ua?u>0&&(n=ua,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?ca:ua:null)?n===ca?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===ca&&_a.test(r[la+"Property"])}}function Ca(t,e){for(;t.length explicit "+e+" duration is not a valid number - got "+JSON.stringify(t)+".",n.context):isNaN(t)&&Ct(" explicit "+e+" duration is NaN - the duration expression might be incorrect.",n.context)}function Oa(t){return"number"==typeof t&&!isNaN(t)}function ka(t){if(n(t))return!1;var e=t.fns;return r(e)?ka(Array.isArray(e)?e[0]:e):(t._length||t.length)>1}function Sa(t,e){!0!==e.data.show&&$a(e)}var ja=J?{create:Sa,activate:Sa,remove:function(t,e){!0!==t.data.show?Aa(t,e):e()}}:{},Ea=[xi,Si,Fi,zi,ea,ja],Ta=Ea.concat(Ci),Ia=di({nodeOps:ii,modules:Ta});nt&&document.addEventListener("selectionchange",function(){var t=document.activeElement;t&&t.vmodel&&Ha(t,"input")});var Da={inserted:function(t,e,n,r){"select"===n.tag?(r.elm&&!r.elm._vOptions?Ye(n,"postpatch",function(){Da.componentUpdated(t,e,n)}):Na(t,e,n.context),t._vOptions=[].map.call(t.options,Ma)):("textarea"===n.tag||Wo(t.type))&&(t._vModifiers=e.modifiers,e.modifiers.lazy||(t.addEventListener("compositionstart",Fa),t.addEventListener("compositionend",Ra),t.addEventListener("change",Ra),nt&&(t.vmodel=!0)))},componentUpdated:function(t,e,n){if("select"===n.tag){Na(t,e,n.context);var r=t._vOptions,o=t._vOptions=[].map.call(t.options,Ma);if(o.some(function(t,e){return!M(t,r[e])}))(t.multiple?e.value.some(function(t){return Pa(t,o)}):e.value!==e.oldValue&&Pa(e.value,o))&&Ha(t,"change")}}};function Na(t,e,n){La(t,e,n),(et||rt)&&setTimeout(function(){La(t,e,n)},0)}function La(t,e,n){var r=e.value,o=t.multiple;if(!o||Array.isArray(r)){for(var i,a,s=0,c=t.options.length;s-1,a.selected!==i&&(a.selected=i);else if(M(Ma(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function Pa(t,e){return e.every(function(e){return!M(e,t)})}function Ma(t){return"_value"in t?t._value:t.value}function Fa(t){t.target.composing=!0}function Ra(t){t.target.composing&&(t.target.composing=!1,Ha(t.target,"input"))}function Ha(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function Ua(t){return!t.componentInstance||t.data&&t.data.transition?t:Ua(t.componentInstance._vnode)}var Ba={bind:function(t,e,n){var r=e.value,o=(n=Ua(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,$a(n,function(){t.style.display=i})):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=Ua(n)).data&&n.data.transition?(n.data.show=!0,r?$a(n,function(){t.style.display=t.__vOriginalDisplay}):Aa(n,function(){t.style.display="none"})):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}},za={model:Da,show:Ba},Va={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Wa(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Wa(er(e.children)):t}function qa(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[A(i)]=o[i];return e}function Ka(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}function Xa(t){for(;t=t.parent;)if(t.data.transition)return!0}function Ga(t,e){return e.key===t.key&&e.tag===t.tag}var Za=function(t){return t.tag||tr(t)},Ja=function(t){return"show"===t.name},Qa={name:"transition",props:Va,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Za)).length){0;var r=this.mode;0;var o=n[0];if(Xa(this.$vnode))return o;var i=Wa(o);if(!i)return o;if(this._leaving)return Ka(t,o);var s="__transition-"+this._uid+"-";i.key=null==i.key?i.isComment?s+"comment":s+i.tag:a(i.key)?0===String(i.key).indexOf(s)?i.key:s+i.key:i.key;var c=(i.data||(i.data={})).transition=qa(this),u=this._vnode,l=Wa(u);if(i.data.directives&&i.data.directives.some(Ja)&&(i.data.show=!0),l&&l.data&&!Ga(i,l)&&!tr(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=I({},c);if("out-in"===r)return this._leaving=!0,Ye(f,"afterLeave",function(){e._leaving=!1,e.$forceUpdate()}),Ka(t,o);if("in-out"===r){if(tr(i))return u;var p,d=function(){p()};Ye(c,"afterEnter",d),Ye(c,"enterCancelled",d),Ye(f,"delayLeave",function(t){p=t})}}return o}}},Ya=I({tag:String,moveClass:String},Va);delete Ya.mode;var ts={props:Ya,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=lr(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=qa(this),s=0;s",license:"MIT",private:!1,repository:{type:"git",url:"https://github.com/komomoo/vue-image-painter"},keywords:["vue","image-drawer","image-painter","img-paint"],main:"dist/vue-image-painter.min.js",module:"dist/vue-image-painter.esm.min.js",scripts:{dev:"parcel demo/index.html -p 8080 --out-dir demo/dev","build:demo":"rm -rf demo/dist/ && parcel build demo/index.html --out-dir demo/dist --public-url ./",build:"dio",lint:"eslint --fix --ext .js,.ts,.vue .",release:"sh scripts/release.sh"},eslintConfig:{extends:["@momoko/vue"]},eslintIgnore:["dist"],babel:{presets:["@momoko/vue"]},browserslist:["iOS >= 9","Android >= 4.4","IE >= 9"],dependencies:{},devDependencies:{"@babel/core":"^7.3.3","@momoko/babel-preset-vue":"^0.2.0","@momoko/eslint-config-vue":"^1.0.2","dio-bundler":"^0.5.2",eslint:"^5.16.0","parcel-bundler":"^1.12.3","standard-version":"^4.4.0",vue:"^2.6.10","vue-hot-reload-api":"^2.3.2","vue-template-compiler":"^2.6.10"}}; 11 | },{}],"KCVh":[function(require,module,exports) { 12 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var e=t(require("../../../package.json"));function t(e){return e&&e.__esModule?e:{default:e}}var o=e.default.name,r={methods:{c:function(e){return e?"".concat(o).concat(e):"".concat(o)}}};exports.default=r; 13 | },{"../../../package.json":"EHrm"}],"NFMf":[function(require,module,exports) { 14 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var t=i(require("./mixins"));function i(t){return t&&t.__esModule?t:{default:t}}var e={name:"ImagePainter",mixins:[t.default],props:{src:{type:String,default:void 0},alt:{type:String,default:void 0},animation:{type:String,default:"draw"},duration:{type:Number,default:4e3},immediate:{type:Boolean,default:!1}},data:function(){return{show:!1,imgClass:void 0}},watch:{src:function(){this.init()}},mounted:function(){this.init()},methods:{init:function(){this.$emit("loadStart"),this.immediate?this.draw():this.wait()},wait:function(){this.show=!1,this.imgClass=void 0},draw:function(){this.show=!0,this.imgClass=this.animation},loadEnd:function(){this.$emit("loadEnd"),this.immediate||this.draw()}}};exports.default=e; 15 | (function(){var e=exports.default||module.exports;"function"==typeof e&&(e=e.options),Object.assign(e,{render:function(){var e=this,s=e.$createElement,t=e._self._c||s;return t("div",{class:e.c()},[t("img",{directives:[{name:"show",rawName:"v-show",value:e.show,expression:"show"}],class:[e.c("_img"),e.imgClass],style:{animationDuration:e.duration/1e3+"s"},attrs:{src:e.src,alt:e.alt},on:{load:e.loadEnd}}),e._v(" "),e.show?e._e():e._t("default")],2)},staticRenderFns:[],_compiled:!0,_scopeId:null,functional:void 0});})(); 16 | },{"./mixins":"KCVh"}],"2u/B":[function(require,module,exports) { 17 | "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var e=t(require("./ImagePainter"));function t(e){return e&&e.__esModule?e:{default:e}}e.default.install=function(t){t.component(e.default.name,e.default)};var u=e.default;exports.default=u; 18 | },{"./ImagePainter":"NFMf"}],"epB2":[function(require,module,exports) { 19 | "use strict";var e=t(require("vue")),u=t(require("./App")),r=t(require("../src"));function t(e){return e&&e.__esModule?e:{default:e}}e.default.use(r.default),e.default.config.productionTip=!0,new e.default({render:function(e){return e(u.default)}}).$mount("#app"); 20 | },{"vue":"QPfz","./App":"Js2s","../src":"2u/B"}]},{},["epB2"], null) 21 | //# sourceMappingURL=main.41d0c573.js.map 22 | -------------------------------------------------------------------------------- /demo/dist/main.c967b235.css: -------------------------------------------------------------------------------- 1 | *{padding:0;margin:0;border:none}#app,body,html{width:100%;height:100%;overflow:hidden}#app{overflow-y:scroll;box-sizing:border-box}#app>h1{font-size:24px;padding:40px 15px 20px;color:#fa8c87}#app .image-painter{min-height:300px}#app .loading-text{font-size:12px;color:#6d7a80;text-align:center;margin:160px 0}.vue-image-painter .draw{animation-timing-function:linear;animation-fill-mode:both;animation-name:draw}.vue-image-painter .blur{animation-timing-function:linear;animation-fill-mode:both;animation-name:blur}@-moz-keyframes draw{0%{filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{filter:brightness(2) contrast(2) grayscale(1)}75%{filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}to{filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes draw{0%{filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{filter:brightness(2) contrast(2) grayscale(1)}75%{filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}to{filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-o-keyframes draw{0%{filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{filter:brightness(2) contrast(2) grayscale(1)}75%{filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}to{filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{filter:brightness(2) contrast(2) grayscale(1)}75%{filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}to{filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-moz-keyframes blur{0%{filter:blur(50px);opacity:0}10%{filter:blur(30px);opacity:.6}to{filter:blur(0);opacity:1}}@-webkit-keyframes blur{0%{filter:blur(50px);opacity:0}10%{filter:blur(30px);opacity:.6}to{filter:blur(0);opacity:1}}@-o-keyframes blur{0%{filter:blur(50px);opacity:0}10%{filter:blur(30px);opacity:.6}to{filter:blur(0);opacity:1}}@keyframes blur{0%{filter:blur(50px);opacity:0}10%{filter:blur(30px);opacity:.6}to{filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%} -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | vue-image-painter 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /demo/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App' 3 | import ImagePainter from '../src' // dev 4 | 5 | Vue.use(ImagePainter) 6 | 7 | Vue.config.productionTip = true 8 | 9 | new Vue({ 10 | render: h => h(App), 11 | }).$mount('#app') 12 | -------------------------------------------------------------------------------- /dist/vue-image-painter.common.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | 'use strict'; 8 | 9 | var name = "vue-image-painter"; 10 | var version = "0.1.3"; 11 | var description = "Image draw animation effect plugin for Vue 2.x | 图像动态绘制效果"; 12 | var author = "momoko "; 13 | var license = "MIT"; 14 | var repository = { 15 | type: "git", 16 | url: "https://github.com/wannaxiao/vue-image-painter" 17 | }; 18 | var keywords = [ 19 | "vue", 20 | "image-drawer", 21 | "image-painter", 22 | "img-paint" 23 | ]; 24 | var main = "dist/vue-image-painter.min.js"; 25 | var module$1 = "dist/vue-image-painter.esm.min.js"; 26 | var scripts = { 27 | dev: "parcel demo/index.html -p 8080 --out-dir demo/dev", 28 | "build:demo": "rm -rf demo/dist/ && parcel build demo/index.html --out-dir demo/dist --public-url ./", 29 | build: "dio", 30 | lint: "eslint --fix --ext .js,.ts,.vue .", 31 | release: "sh scripts/release.sh" 32 | }; 33 | var eslintConfig = { 34 | "extends": [ 35 | "@momoko/vue" 36 | ] 37 | }; 38 | var eslintIgnore = [ 39 | "dist" 40 | ]; 41 | var babel = { 42 | presets: [ 43 | "@momoko/vue" 44 | ] 45 | }; 46 | var browserslist = [ 47 | "iOS >= 9", 48 | "Android >= 4.4", 49 | "IE >= 9" 50 | ]; 51 | var dependencies = { 52 | }; 53 | var devDependencies = { 54 | "@babel/core": "^7.3.3", 55 | "@momoko/babel-preset-vue": "^0.2.0", 56 | "@momoko/eslint-config-vue": "^1.0.2", 57 | "dio-bundler": "^0.5.2", 58 | eslint: "^5.16.0", 59 | "parcel-bundler": "^1.12.3", 60 | "standard-version": "^4.4.0", 61 | vue: "^2.6.10", 62 | "vue-hot-reload-api": "^2.3.2", 63 | "vue-template-compiler": "^2.6.10" 64 | }; 65 | var pkg = { 66 | name: name, 67 | version: version, 68 | description: description, 69 | author: author, 70 | license: license, 71 | "private": false, 72 | repository: repository, 73 | keywords: keywords, 74 | main: main, 75 | module: module$1, 76 | scripts: scripts, 77 | eslintConfig: eslintConfig, 78 | eslintIgnore: eslintIgnore, 79 | babel: babel, 80 | browserslist: browserslist, 81 | dependencies: dependencies, 82 | devDependencies: devDependencies 83 | }; 84 | 85 | var pre = pkg.name; 86 | var mixin = { 87 | methods: { 88 | // 生成 css class 89 | c: function c(className) { 90 | return className ? "".concat(pre).concat(className) : "".concat(pre); 91 | } 92 | } 93 | }; 94 | 95 | // 96 | var script = { 97 | name: 'ImagePainter', 98 | mixins: [mixin], 99 | props: { 100 | src: { 101 | // 图片链接 102 | type: String, 103 | default: undefined 104 | }, 105 | alt: { 106 | // 图片描述 107 | type: String, 108 | default: undefined 109 | }, 110 | animation: { 111 | // 动画效果,可选:'draw','blur' 112 | type: String, 113 | default: 'draw' 114 | }, 115 | duration: { 116 | // 动画持续时间 117 | type: Number, 118 | default: 4000 119 | }, 120 | immediate: { 121 | // 立即显示图片和动画,而不等图片加载完 122 | type: Boolean, 123 | default: false 124 | } 125 | }, 126 | data: function data() { 127 | return { 128 | show: false, 129 | imgClass: undefined // 图片样式类 130 | 131 | }; 132 | }, 133 | watch: { 134 | src: function src() { 135 | this.init(); 136 | } 137 | }, 138 | mounted: function mounted() { 139 | this.init(); 140 | }, 141 | methods: { 142 | init: function init() { 143 | this.$emit('loadStart'); 144 | this.immediate ? this.draw() : this.wait(); 145 | }, 146 | wait: function wait() { 147 | this.show = false; 148 | this.imgClass = undefined; 149 | }, 150 | draw: function draw() { 151 | this.show = true; 152 | this.imgClass = this.animation; 153 | }, 154 | loadEnd: function loadEnd() { 155 | this.$emit('loadEnd'); 156 | if (!this.immediate) this.draw(); 157 | } 158 | } 159 | }; 160 | 161 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier 162 | /* server only */ 163 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { 164 | if (typeof shadowMode !== 'boolean') { 165 | createInjectorSSR = createInjector; 166 | createInjector = shadowMode; 167 | shadowMode = false; 168 | } // Vue.extend constructor export interop. 169 | 170 | 171 | var options = typeof script === 'function' ? script.options : script; // render functions 172 | 173 | if (template && template.render) { 174 | options.render = template.render; 175 | options.staticRenderFns = template.staticRenderFns; 176 | options._compiled = true; // functional template 177 | 178 | if (isFunctionalTemplate) { 179 | options.functional = true; 180 | } 181 | } // scopedId 182 | 183 | 184 | if (scopeId) { 185 | options._scopeId = scopeId; 186 | } 187 | 188 | var hook; 189 | 190 | if (moduleIdentifier) { 191 | // server build 192 | hook = function hook(context) { 193 | // 2.3 injection 194 | context = context || // cached call 195 | this.$vnode && this.$vnode.ssrContext || // stateful 196 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional 197 | // 2.2 with runInNewContext: true 198 | 199 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { 200 | context = __VUE_SSR_CONTEXT__; 201 | } // inject component styles 202 | 203 | 204 | if (style) { 205 | style.call(this, createInjectorSSR(context)); 206 | } // register component module identifier for async chunk inference 207 | 208 | 209 | if (context && context._registeredComponents) { 210 | context._registeredComponents.add(moduleIdentifier); 211 | } 212 | }; // used by ssr in case component is cached and beforeCreate 213 | // never gets called 214 | 215 | 216 | options._ssrRegister = hook; 217 | } else if (style) { 218 | hook = shadowMode ? function () { 219 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); 220 | } : function (context) { 221 | style.call(this, createInjector(context)); 222 | }; 223 | } 224 | 225 | if (hook) { 226 | if (options.functional) { 227 | // register for functional component in vue file 228 | var originalRender = options.render; 229 | 230 | options.render = function renderWithStyleInjection(h, context) { 231 | hook.call(context); 232 | return originalRender(h, context); 233 | }; 234 | } else { 235 | // inject component registration as beforeCreate hook 236 | var existing = options.beforeCreate; 237 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; 238 | } 239 | } 240 | 241 | return script; 242 | } 243 | 244 | var normalizeComponent_1 = normalizeComponent; 245 | 246 | var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); 247 | function createInjector(context) { 248 | return function (id, style) { 249 | return addStyle(id, style); 250 | }; 251 | } 252 | var HEAD = document.head || document.getElementsByTagName('head')[0]; 253 | var styles = {}; 254 | 255 | function addStyle(id, css) { 256 | var group = isOldIE ? css.media || 'default' : id; 257 | var style = styles[group] || (styles[group] = { 258 | ids: new Set(), 259 | styles: [] 260 | }); 261 | 262 | if (!style.ids.has(id)) { 263 | style.ids.add(id); 264 | var code = css.source; 265 | 266 | if (css.map) { 267 | // https://developer.chrome.com/devtools/docs/javascript-debugging 268 | // this makes source maps inside style tags work properly in Chrome 269 | code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 270 | 271 | code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; 272 | } 273 | 274 | if (!style.element) { 275 | style.element = document.createElement('style'); 276 | style.element.type = 'text/css'; 277 | if (css.media) style.element.setAttribute('media', css.media); 278 | HEAD.appendChild(style.element); 279 | } 280 | 281 | if ('styleSheet' in style.element) { 282 | style.styles.push(code); 283 | style.element.styleSheet.cssText = style.styles.filter(Boolean).join('\n'); 284 | } else { 285 | var index = style.ids.size - 1; 286 | var textNode = document.createTextNode(code); 287 | var nodes = style.element.childNodes; 288 | if (nodes[index]) style.element.removeChild(nodes[index]); 289 | if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode); 290 | } 291 | } 292 | } 293 | 294 | var browser = createInjector; 295 | 296 | /* script */ 297 | var __vue_script__ = script; 298 | /* template */ 299 | 300 | var __vue_render__ = function __vue_render__() { 301 | var _vm = this; 302 | 303 | var _h = _vm.$createElement; 304 | 305 | var _c = _vm._self._c || _h; 306 | 307 | return _c('div', { 308 | class: _vm.c() 309 | }, [_c('img', { 310 | directives: [{ 311 | name: "show", 312 | rawName: "v-show", 313 | value: _vm.show, 314 | expression: "show" 315 | }], 316 | class: [_vm.c('_img'), _vm.imgClass], 317 | style: { 318 | 'animationDuration': _vm.duration / 1000 + 's' 319 | }, 320 | attrs: { 321 | "src": _vm.src, 322 | "alt": _vm.alt 323 | }, 324 | on: { 325 | "load": _vm.loadEnd 326 | } 327 | }), _vm._v(" "), !_vm.show ? _vm._t("default") : _vm._e()], 2); 328 | }; 329 | 330 | var __vue_staticRenderFns__ = []; 331 | /* style */ 332 | 333 | var __vue_inject_styles__ = function __vue_inject_styles__(inject) { 334 | if (!inject) return; 335 | inject("data-v-684a6a03_0", { 336 | source: ".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}", 337 | map: undefined, 338 | media: undefined 339 | }); 340 | }; 341 | /* scoped */ 342 | 343 | 344 | var __vue_scope_id__ = undefined; 345 | /* module identifier */ 346 | 347 | var __vue_module_identifier__ = undefined; 348 | /* functional template */ 349 | 350 | var __vue_is_functional_template__ = false; 351 | /* style inject SSR */ 352 | 353 | var ImagePainter = normalizeComponent_1({ 354 | render: __vue_render__, 355 | staticRenderFns: __vue_staticRenderFns__ 356 | }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, browser, undefined); 357 | 358 | ImagePainter.install = function (Vue) { 359 | Vue.component(ImagePainter.name, ImagePainter); 360 | }; 361 | 362 | module.exports = ImagePainter; 363 | -------------------------------------------------------------------------------- /dist/vue-image-painter.common.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | "use strict";var t="vue-image-painter",e={name:"ImagePainter",mixins:[{methods:{c:function(e){return e?"".concat(t).concat(e):"".concat(t)}}}],props:{src:{type:String,default:void 0},alt:{type:String,default:void 0},animation:{type:String,default:"draw"},duration:{type:Number,default:4e3},immediate:{type:Boolean,default:!1}},data:function(){return{show:!1,imgClass:void 0}},watch:{src:function(){this.init()}},mounted:function(){this.init()},methods:{init:function(){this.$emit("loadStart"),this.immediate?this.draw():this.wait()},wait:function(){this.show=!1,this.imgClass=void 0},draw:function(){this.show=!0,this.imgClass=this.animation},loadEnd:function(){this.$emit("loadEnd"),this.immediate||this.draw()}}};var i=function(t,e,i,a,n,r,s,o,l,c){"boolean"!=typeof s&&(l=o,o=s,s=!1);var d,m="function"==typeof i?i.options:i;if(t&&t.render&&(m.render=t.render,m.staticRenderFns=t.staticRenderFns,m._compiled=!0,n&&(m.functional=!0)),a&&(m._scopeId=a),r?(d=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,l(t)),t&&t._registeredComponents&&t._registeredComponents.add(r)},m._ssrRegister=d):e&&(d=s?function(){e.call(this,c(this.$root.$options.shadowRoot))}:function(t){e.call(this,o(t))}),d)if(m.functional){var f=m.render;m.render=function(t,e){return d.call(e),f(t,e)}}else{var u=m.beforeCreate;m.beforeCreate=u?[].concat(u,d):[d]}return i},a="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());var n=document.head||document.getElementsByTagName("head")[0],r={};var s=i({render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{class:t.c()},[i("img",{directives:[{name:"show",rawName:"v-show",value:t.show,expression:"show"}],class:[t.c("_img"),t.imgClass],style:{animationDuration:t.duration/1e3+"s"},attrs:{src:t.src,alt:t.alt},on:{load:t.loadEnd}}),t._v(" "),t.show?t._e():t._t("default")],2)},staticRenderFns:[]},function(t){t&&t("data-v-684a6a03_0",{source:".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}",map:void 0,media:void 0})},e,void 0,!1,void 0,function(t){return function(t,e){return function(t,e){var i=a?e.media||"default":t,s=r[i]||(r[i]={ids:new Set,styles:[]});if(!s.ids.has(t)){s.ids.add(t);var o=e.source;if(e.map&&(o+="\n/*# sourceURL="+e.map.sources[0]+" */",o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e.map))))+" */"),s.element||(s.element=document.createElement("style"),s.element.type="text/css",e.media&&s.element.setAttribute("media",e.media),n.appendChild(s.element)),"styleSheet"in s.element)s.styles.push(o),s.element.styleSheet.cssText=s.styles.filter(Boolean).join("\n");else{var l=s.ids.size-1,c=document.createTextNode(o),d=s.element.childNodes;d[l]&&s.element.removeChild(d[l]),d.length?s.element.insertBefore(c,d[l]):s.element.appendChild(c)}}}(t,e)}},void 0);s.install=function(t){t.component(s.name,s)},module.exports=s; -------------------------------------------------------------------------------- /dist/vue-image-painter.esm.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | var name = "vue-image-painter"; 8 | var version = "0.1.3"; 9 | var description = "Image draw animation effect plugin for Vue 2.x | 图像动态绘制效果"; 10 | var author = "momoko "; 11 | var license = "MIT"; 12 | var repository = { 13 | type: "git", 14 | url: "https://github.com/wannaxiao/vue-image-painter" 15 | }; 16 | var keywords = [ 17 | "vue", 18 | "image-drawer", 19 | "image-painter", 20 | "img-paint" 21 | ]; 22 | var main = "dist/vue-image-painter.min.js"; 23 | var module = "dist/vue-image-painter.esm.min.js"; 24 | var scripts = { 25 | dev: "parcel demo/index.html -p 8080 --out-dir demo/dev", 26 | "build:demo": "rm -rf demo/dist/ && parcel build demo/index.html --out-dir demo/dist --public-url ./", 27 | build: "dio", 28 | lint: "eslint --fix --ext .js,.ts,.vue .", 29 | release: "sh scripts/release.sh" 30 | }; 31 | var eslintConfig = { 32 | "extends": [ 33 | "@momoko/vue" 34 | ] 35 | }; 36 | var eslintIgnore = [ 37 | "dist" 38 | ]; 39 | var babel = { 40 | presets: [ 41 | "@momoko/vue" 42 | ] 43 | }; 44 | var browserslist = [ 45 | "iOS >= 9", 46 | "Android >= 4.4", 47 | "IE >= 9" 48 | ]; 49 | var dependencies = { 50 | }; 51 | var devDependencies = { 52 | "@babel/core": "^7.3.3", 53 | "@momoko/babel-preset-vue": "^0.2.0", 54 | "@momoko/eslint-config-vue": "^1.0.2", 55 | "dio-bundler": "^0.5.2", 56 | eslint: "^5.16.0", 57 | "parcel-bundler": "^1.12.3", 58 | "standard-version": "^4.4.0", 59 | vue: "^2.6.10", 60 | "vue-hot-reload-api": "^2.3.2", 61 | "vue-template-compiler": "^2.6.10" 62 | }; 63 | var pkg = { 64 | name: name, 65 | version: version, 66 | description: description, 67 | author: author, 68 | license: license, 69 | "private": false, 70 | repository: repository, 71 | keywords: keywords, 72 | main: main, 73 | module: module, 74 | scripts: scripts, 75 | eslintConfig: eslintConfig, 76 | eslintIgnore: eslintIgnore, 77 | babel: babel, 78 | browserslist: browserslist, 79 | dependencies: dependencies, 80 | devDependencies: devDependencies 81 | }; 82 | 83 | var pre = pkg.name; 84 | var mixin = { 85 | methods: { 86 | // 生成 css class 87 | c: function c(className) { 88 | return className ? "".concat(pre).concat(className) : "".concat(pre); 89 | } 90 | } 91 | }; 92 | 93 | // 94 | var script = { 95 | name: 'ImagePainter', 96 | mixins: [mixin], 97 | props: { 98 | src: { 99 | // 图片链接 100 | type: String, 101 | default: undefined 102 | }, 103 | alt: { 104 | // 图片描述 105 | type: String, 106 | default: undefined 107 | }, 108 | animation: { 109 | // 动画效果,可选:'draw','blur' 110 | type: String, 111 | default: 'draw' 112 | }, 113 | duration: { 114 | // 动画持续时间 115 | type: Number, 116 | default: 4000 117 | }, 118 | immediate: { 119 | // 立即显示图片和动画,而不等图片加载完 120 | type: Boolean, 121 | default: false 122 | } 123 | }, 124 | data: function data() { 125 | return { 126 | show: false, 127 | imgClass: undefined // 图片样式类 128 | 129 | }; 130 | }, 131 | watch: { 132 | src: function src() { 133 | this.init(); 134 | } 135 | }, 136 | mounted: function mounted() { 137 | this.init(); 138 | }, 139 | methods: { 140 | init: function init() { 141 | this.$emit('loadStart'); 142 | this.immediate ? this.draw() : this.wait(); 143 | }, 144 | wait: function wait() { 145 | this.show = false; 146 | this.imgClass = undefined; 147 | }, 148 | draw: function draw() { 149 | this.show = true; 150 | this.imgClass = this.animation; 151 | }, 152 | loadEnd: function loadEnd() { 153 | this.$emit('loadEnd'); 154 | if (!this.immediate) this.draw(); 155 | } 156 | } 157 | }; 158 | 159 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier 160 | /* server only */ 161 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { 162 | if (typeof shadowMode !== 'boolean') { 163 | createInjectorSSR = createInjector; 164 | createInjector = shadowMode; 165 | shadowMode = false; 166 | } // Vue.extend constructor export interop. 167 | 168 | 169 | var options = typeof script === 'function' ? script.options : script; // render functions 170 | 171 | if (template && template.render) { 172 | options.render = template.render; 173 | options.staticRenderFns = template.staticRenderFns; 174 | options._compiled = true; // functional template 175 | 176 | if (isFunctionalTemplate) { 177 | options.functional = true; 178 | } 179 | } // scopedId 180 | 181 | 182 | if (scopeId) { 183 | options._scopeId = scopeId; 184 | } 185 | 186 | var hook; 187 | 188 | if (moduleIdentifier) { 189 | // server build 190 | hook = function hook(context) { 191 | // 2.3 injection 192 | context = context || // cached call 193 | this.$vnode && this.$vnode.ssrContext || // stateful 194 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional 195 | // 2.2 with runInNewContext: true 196 | 197 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { 198 | context = __VUE_SSR_CONTEXT__; 199 | } // inject component styles 200 | 201 | 202 | if (style) { 203 | style.call(this, createInjectorSSR(context)); 204 | } // register component module identifier for async chunk inference 205 | 206 | 207 | if (context && context._registeredComponents) { 208 | context._registeredComponents.add(moduleIdentifier); 209 | } 210 | }; // used by ssr in case component is cached and beforeCreate 211 | // never gets called 212 | 213 | 214 | options._ssrRegister = hook; 215 | } else if (style) { 216 | hook = shadowMode ? function () { 217 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); 218 | } : function (context) { 219 | style.call(this, createInjector(context)); 220 | }; 221 | } 222 | 223 | if (hook) { 224 | if (options.functional) { 225 | // register for functional component in vue file 226 | var originalRender = options.render; 227 | 228 | options.render = function renderWithStyleInjection(h, context) { 229 | hook.call(context); 230 | return originalRender(h, context); 231 | }; 232 | } else { 233 | // inject component registration as beforeCreate hook 234 | var existing = options.beforeCreate; 235 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; 236 | } 237 | } 238 | 239 | return script; 240 | } 241 | 242 | var normalizeComponent_1 = normalizeComponent; 243 | 244 | var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); 245 | function createInjector(context) { 246 | return function (id, style) { 247 | return addStyle(id, style); 248 | }; 249 | } 250 | var HEAD = document.head || document.getElementsByTagName('head')[0]; 251 | var styles = {}; 252 | 253 | function addStyle(id, css) { 254 | var group = isOldIE ? css.media || 'default' : id; 255 | var style = styles[group] || (styles[group] = { 256 | ids: new Set(), 257 | styles: [] 258 | }); 259 | 260 | if (!style.ids.has(id)) { 261 | style.ids.add(id); 262 | var code = css.source; 263 | 264 | if (css.map) { 265 | // https://developer.chrome.com/devtools/docs/javascript-debugging 266 | // this makes source maps inside style tags work properly in Chrome 267 | code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 268 | 269 | code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; 270 | } 271 | 272 | if (!style.element) { 273 | style.element = document.createElement('style'); 274 | style.element.type = 'text/css'; 275 | if (css.media) style.element.setAttribute('media', css.media); 276 | HEAD.appendChild(style.element); 277 | } 278 | 279 | if ('styleSheet' in style.element) { 280 | style.styles.push(code); 281 | style.element.styleSheet.cssText = style.styles.filter(Boolean).join('\n'); 282 | } else { 283 | var index = style.ids.size - 1; 284 | var textNode = document.createTextNode(code); 285 | var nodes = style.element.childNodes; 286 | if (nodes[index]) style.element.removeChild(nodes[index]); 287 | if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode); 288 | } 289 | } 290 | } 291 | 292 | var browser = createInjector; 293 | 294 | /* script */ 295 | var __vue_script__ = script; 296 | /* template */ 297 | 298 | var __vue_render__ = function __vue_render__() { 299 | var _vm = this; 300 | 301 | var _h = _vm.$createElement; 302 | 303 | var _c = _vm._self._c || _h; 304 | 305 | return _c('div', { 306 | class: _vm.c() 307 | }, [_c('img', { 308 | directives: [{ 309 | name: "show", 310 | rawName: "v-show", 311 | value: _vm.show, 312 | expression: "show" 313 | }], 314 | class: [_vm.c('_img'), _vm.imgClass], 315 | style: { 316 | 'animationDuration': _vm.duration / 1000 + 's' 317 | }, 318 | attrs: { 319 | "src": _vm.src, 320 | "alt": _vm.alt 321 | }, 322 | on: { 323 | "load": _vm.loadEnd 324 | } 325 | }), _vm._v(" "), !_vm.show ? _vm._t("default") : _vm._e()], 2); 326 | }; 327 | 328 | var __vue_staticRenderFns__ = []; 329 | /* style */ 330 | 331 | var __vue_inject_styles__ = function __vue_inject_styles__(inject) { 332 | if (!inject) return; 333 | inject("data-v-684a6a03_0", { 334 | source: ".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}", 335 | map: undefined, 336 | media: undefined 337 | }); 338 | }; 339 | /* scoped */ 340 | 341 | 342 | var __vue_scope_id__ = undefined; 343 | /* module identifier */ 344 | 345 | var __vue_module_identifier__ = undefined; 346 | /* functional template */ 347 | 348 | var __vue_is_functional_template__ = false; 349 | /* style inject SSR */ 350 | 351 | var ImagePainter = normalizeComponent_1({ 352 | render: __vue_render__, 353 | staticRenderFns: __vue_staticRenderFns__ 354 | }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, browser, undefined); 355 | 356 | ImagePainter.install = function (Vue) { 357 | Vue.component(ImagePainter.name, ImagePainter); 358 | }; 359 | 360 | export default ImagePainter; 361 | -------------------------------------------------------------------------------- /dist/vue-image-painter.esm.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | var t="vue-image-painter",e={name:"ImagePainter",mixins:[{methods:{c:function(e){return e?"".concat(t).concat(e):"".concat(t)}}}],props:{src:{type:String,default:void 0},alt:{type:String,default:void 0},animation:{type:String,default:"draw"},duration:{type:Number,default:4e3},immediate:{type:Boolean,default:!1}},data:function(){return{show:!1,imgClass:void 0}},watch:{src:function(){this.init()}},mounted:function(){this.init()},methods:{init:function(){this.$emit("loadStart"),this.immediate?this.draw():this.wait()},wait:function(){this.show=!1,this.imgClass=void 0},draw:function(){this.show=!0,this.imgClass=this.animation},loadEnd:function(){this.$emit("loadEnd"),this.immediate||this.draw()}}};var i=function(t,e,i,a,n,r,s,o,l,c){"boolean"!=typeof s&&(l=o,o=s,s=!1);var d,m="function"==typeof i?i.options:i;if(t&&t.render&&(m.render=t.render,m.staticRenderFns=t.staticRenderFns,m._compiled=!0,n&&(m.functional=!0)),a&&(m._scopeId=a),r?(d=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,l(t)),t&&t._registeredComponents&&t._registeredComponents.add(r)},m._ssrRegister=d):e&&(d=s?function(){e.call(this,c(this.$root.$options.shadowRoot))}:function(t){e.call(this,o(t))}),d)if(m.functional){var f=m.render;m.render=function(t,e){return d.call(e),f(t,e)}}else{var u=m.beforeCreate;m.beforeCreate=u?[].concat(u,d):[d]}return i},a="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase());var n=document.head||document.getElementsByTagName("head")[0],r={};var s=i({render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{class:t.c()},[i("img",{directives:[{name:"show",rawName:"v-show",value:t.show,expression:"show"}],class:[t.c("_img"),t.imgClass],style:{animationDuration:t.duration/1e3+"s"},attrs:{src:t.src,alt:t.alt},on:{load:t.loadEnd}}),t._v(" "),t.show?t._e():t._t("default")],2)},staticRenderFns:[]},function(t){t&&t("data-v-684a6a03_0",{source:".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}",map:void 0,media:void 0})},e,void 0,!1,void 0,function(t){return function(t,e){return function(t,e){var i=a?e.media||"default":t,s=r[i]||(r[i]={ids:new Set,styles:[]});if(!s.ids.has(t)){s.ids.add(t);var o=e.source;if(e.map&&(o+="\n/*# sourceURL="+e.map.sources[0]+" */",o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e.map))))+" */"),s.element||(s.element=document.createElement("style"),s.element.type="text/css",e.media&&s.element.setAttribute("media",e.media),n.appendChild(s.element)),"styleSheet"in s.element)s.styles.push(o),s.element.styleSheet.cssText=s.styles.filter(Boolean).join("\n");else{var l=s.ids.size-1,c=document.createTextNode(o),d=s.element.childNodes;d[l]&&s.element.removeChild(d[l]),d.length?s.element.insertBefore(c,d[l]):s.element.appendChild(c)}}}(t,e)}},void 0);s.install=function(t){t.component(s.name,s)};export default s; -------------------------------------------------------------------------------- /dist/vue-image-painter.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | (function (global, factory) { 8 | typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : 9 | typeof define === 'function' && define.amd ? define(factory) : 10 | (global = global || self, global['vue-image-painter'] = factory()); 11 | }(this, function () { 'use strict'; 12 | 13 | var name = "vue-image-painter"; 14 | var version = "0.1.3"; 15 | var description = "Image draw animation effect plugin for Vue 2.x | 图像动态绘制效果"; 16 | var author = "momoko "; 17 | var license = "MIT"; 18 | var repository = { 19 | type: "git", 20 | url: "https://github.com/wannaxiao/vue-image-painter" 21 | }; 22 | var keywords = [ 23 | "vue", 24 | "image-drawer", 25 | "image-painter", 26 | "img-paint" 27 | ]; 28 | var main = "dist/vue-image-painter.min.js"; 29 | var module = "dist/vue-image-painter.esm.min.js"; 30 | var scripts = { 31 | dev: "parcel demo/index.html -p 8080 --out-dir demo/dev", 32 | "build:demo": "rm -rf demo/dist/ && parcel build demo/index.html --out-dir demo/dist --public-url ./", 33 | build: "dio", 34 | lint: "eslint --fix --ext .js,.ts,.vue .", 35 | release: "sh scripts/release.sh" 36 | }; 37 | var eslintConfig = { 38 | "extends": [ 39 | "@momoko/vue" 40 | ] 41 | }; 42 | var eslintIgnore = [ 43 | "dist" 44 | ]; 45 | var babel = { 46 | presets: [ 47 | "@momoko/vue" 48 | ] 49 | }; 50 | var browserslist = [ 51 | "iOS >= 9", 52 | "Android >= 4.4", 53 | "IE >= 9" 54 | ]; 55 | var dependencies = { 56 | }; 57 | var devDependencies = { 58 | "@babel/core": "^7.3.3", 59 | "@momoko/babel-preset-vue": "^0.2.0", 60 | "@momoko/eslint-config-vue": "^1.0.2", 61 | "dio-bundler": "^0.5.2", 62 | eslint: "^5.16.0", 63 | "parcel-bundler": "^1.12.3", 64 | "standard-version": "^4.4.0", 65 | vue: "^2.6.10", 66 | "vue-hot-reload-api": "^2.3.2", 67 | "vue-template-compiler": "^2.6.10" 68 | }; 69 | var pkg = { 70 | name: name, 71 | version: version, 72 | description: description, 73 | author: author, 74 | license: license, 75 | "private": false, 76 | repository: repository, 77 | keywords: keywords, 78 | main: main, 79 | module: module, 80 | scripts: scripts, 81 | eslintConfig: eslintConfig, 82 | eslintIgnore: eslintIgnore, 83 | babel: babel, 84 | browserslist: browserslist, 85 | dependencies: dependencies, 86 | devDependencies: devDependencies 87 | }; 88 | 89 | var pre = pkg.name; 90 | var mixin = { 91 | methods: { 92 | // 生成 css class 93 | c: function c(className) { 94 | return className ? "".concat(pre).concat(className) : "".concat(pre); 95 | } 96 | } 97 | }; 98 | 99 | // 100 | var script = { 101 | name: 'ImagePainter', 102 | mixins: [mixin], 103 | props: { 104 | src: { 105 | // 图片链接 106 | type: String, 107 | default: undefined 108 | }, 109 | alt: { 110 | // 图片描述 111 | type: String, 112 | default: undefined 113 | }, 114 | animation: { 115 | // 动画效果,可选:'draw','blur' 116 | type: String, 117 | default: 'draw' 118 | }, 119 | duration: { 120 | // 动画持续时间 121 | type: Number, 122 | default: 4000 123 | }, 124 | immediate: { 125 | // 立即显示图片和动画,而不等图片加载完 126 | type: Boolean, 127 | default: false 128 | } 129 | }, 130 | data: function data() { 131 | return { 132 | show: false, 133 | imgClass: undefined // 图片样式类 134 | 135 | }; 136 | }, 137 | watch: { 138 | src: function src() { 139 | this.init(); 140 | } 141 | }, 142 | mounted: function mounted() { 143 | this.init(); 144 | }, 145 | methods: { 146 | init: function init() { 147 | this.$emit('loadStart'); 148 | this.immediate ? this.draw() : this.wait(); 149 | }, 150 | wait: function wait() { 151 | this.show = false; 152 | this.imgClass = undefined; 153 | }, 154 | draw: function draw() { 155 | this.show = true; 156 | this.imgClass = this.animation; 157 | }, 158 | loadEnd: function loadEnd() { 159 | this.$emit('loadEnd'); 160 | if (!this.immediate) this.draw(); 161 | } 162 | } 163 | }; 164 | 165 | function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier 166 | /* server only */ 167 | , shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { 168 | if (typeof shadowMode !== 'boolean') { 169 | createInjectorSSR = createInjector; 170 | createInjector = shadowMode; 171 | shadowMode = false; 172 | } // Vue.extend constructor export interop. 173 | 174 | 175 | var options = typeof script === 'function' ? script.options : script; // render functions 176 | 177 | if (template && template.render) { 178 | options.render = template.render; 179 | options.staticRenderFns = template.staticRenderFns; 180 | options._compiled = true; // functional template 181 | 182 | if (isFunctionalTemplate) { 183 | options.functional = true; 184 | } 185 | } // scopedId 186 | 187 | 188 | if (scopeId) { 189 | options._scopeId = scopeId; 190 | } 191 | 192 | var hook; 193 | 194 | if (moduleIdentifier) { 195 | // server build 196 | hook = function hook(context) { 197 | // 2.3 injection 198 | context = context || // cached call 199 | this.$vnode && this.$vnode.ssrContext || // stateful 200 | this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext; // functional 201 | // 2.2 with runInNewContext: true 202 | 203 | if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { 204 | context = __VUE_SSR_CONTEXT__; 205 | } // inject component styles 206 | 207 | 208 | if (style) { 209 | style.call(this, createInjectorSSR(context)); 210 | } // register component module identifier for async chunk inference 211 | 212 | 213 | if (context && context._registeredComponents) { 214 | context._registeredComponents.add(moduleIdentifier); 215 | } 216 | }; // used by ssr in case component is cached and beforeCreate 217 | // never gets called 218 | 219 | 220 | options._ssrRegister = hook; 221 | } else if (style) { 222 | hook = shadowMode ? function () { 223 | style.call(this, createInjectorShadow(this.$root.$options.shadowRoot)); 224 | } : function (context) { 225 | style.call(this, createInjector(context)); 226 | }; 227 | } 228 | 229 | if (hook) { 230 | if (options.functional) { 231 | // register for functional component in vue file 232 | var originalRender = options.render; 233 | 234 | options.render = function renderWithStyleInjection(h, context) { 235 | hook.call(context); 236 | return originalRender(h, context); 237 | }; 238 | } else { 239 | // inject component registration as beforeCreate hook 240 | var existing = options.beforeCreate; 241 | options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; 242 | } 243 | } 244 | 245 | return script; 246 | } 247 | 248 | var normalizeComponent_1 = normalizeComponent; 249 | 250 | var isOldIE = typeof navigator !== 'undefined' && /msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()); 251 | function createInjector(context) { 252 | return function (id, style) { 253 | return addStyle(id, style); 254 | }; 255 | } 256 | var HEAD = document.head || document.getElementsByTagName('head')[0]; 257 | var styles = {}; 258 | 259 | function addStyle(id, css) { 260 | var group = isOldIE ? css.media || 'default' : id; 261 | var style = styles[group] || (styles[group] = { 262 | ids: new Set(), 263 | styles: [] 264 | }); 265 | 266 | if (!style.ids.has(id)) { 267 | style.ids.add(id); 268 | var code = css.source; 269 | 270 | if (css.map) { 271 | // https://developer.chrome.com/devtools/docs/javascript-debugging 272 | // this makes source maps inside style tags work properly in Chrome 273 | code += '\n/*# sourceURL=' + css.map.sources[0] + ' */'; // http://stackoverflow.com/a/26603875 274 | 275 | code += '\n/*# sourceMappingURL=data:application/json;base64,' + btoa(unescape(encodeURIComponent(JSON.stringify(css.map)))) + ' */'; 276 | } 277 | 278 | if (!style.element) { 279 | style.element = document.createElement('style'); 280 | style.element.type = 'text/css'; 281 | if (css.media) style.element.setAttribute('media', css.media); 282 | HEAD.appendChild(style.element); 283 | } 284 | 285 | if ('styleSheet' in style.element) { 286 | style.styles.push(code); 287 | style.element.styleSheet.cssText = style.styles.filter(Boolean).join('\n'); 288 | } else { 289 | var index = style.ids.size - 1; 290 | var textNode = document.createTextNode(code); 291 | var nodes = style.element.childNodes; 292 | if (nodes[index]) style.element.removeChild(nodes[index]); 293 | if (nodes.length) style.element.insertBefore(textNode, nodes[index]);else style.element.appendChild(textNode); 294 | } 295 | } 296 | } 297 | 298 | var browser = createInjector; 299 | 300 | /* script */ 301 | var __vue_script__ = script; 302 | /* template */ 303 | 304 | var __vue_render__ = function __vue_render__() { 305 | var _vm = this; 306 | 307 | var _h = _vm.$createElement; 308 | 309 | var _c = _vm._self._c || _h; 310 | 311 | return _c('div', { 312 | class: _vm.c() 313 | }, [_c('img', { 314 | directives: [{ 315 | name: "show", 316 | rawName: "v-show", 317 | value: _vm.show, 318 | expression: "show" 319 | }], 320 | class: [_vm.c('_img'), _vm.imgClass], 321 | style: { 322 | 'animationDuration': _vm.duration / 1000 + 's' 323 | }, 324 | attrs: { 325 | "src": _vm.src, 326 | "alt": _vm.alt 327 | }, 328 | on: { 329 | "load": _vm.loadEnd 330 | } 331 | }), _vm._v(" "), !_vm.show ? _vm._t("default") : _vm._e()], 2); 332 | }; 333 | 334 | var __vue_staticRenderFns__ = []; 335 | /* style */ 336 | 337 | var __vue_inject_styles__ = function __vue_inject_styles__(inject) { 338 | if (!inject) return; 339 | inject("data-v-684a6a03_0", { 340 | source: ".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}", 341 | map: undefined, 342 | media: undefined 343 | }); 344 | }; 345 | /* scoped */ 346 | 347 | 348 | var __vue_scope_id__ = undefined; 349 | /* module identifier */ 350 | 351 | var __vue_module_identifier__ = undefined; 352 | /* functional template */ 353 | 354 | var __vue_is_functional_template__ = false; 355 | /* style inject SSR */ 356 | 357 | var ImagePainter = normalizeComponent_1({ 358 | render: __vue_render__, 359 | staticRenderFns: __vue_staticRenderFns__ 360 | }, __vue_inject_styles__, __vue_script__, __vue_scope_id__, __vue_is_functional_template__, __vue_module_identifier__, browser, undefined); 361 | 362 | ImagePainter.install = function (Vue) { 363 | Vue.component(ImagePainter.name, ImagePainter); 364 | }; 365 | 366 | return ImagePainter; 367 | 368 | })); 369 | -------------------------------------------------------------------------------- /dist/vue-image-painter.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-image-painter v0.1.3 3 | * Copyright (c) 2018-present, momoko 4 | * Released under the MIT License. 5 | */ 6 | 7 | var t,e;t=this,e=function(){"use strict";var t="vue-image-painter",e={name:"ImagePainter",mixins:[{methods:{c:function(e){return e?"".concat(t).concat(e):"".concat(t)}}}],props:{src:{type:String,default:void 0},alt:{type:String,default:void 0},animation:{type:String,default:"draw"},duration:{type:Number,default:4e3},immediate:{type:Boolean,default:!1}},data:function(){return{show:!1,imgClass:void 0}},watch:{src:function(){this.init()}},mounted:function(){this.init()},methods:{init:function(){this.$emit("loadStart"),this.immediate?this.draw():this.wait()},wait:function(){this.show=!1,this.imgClass=void 0},draw:function(){this.show=!0,this.imgClass=this.animation},loadEnd:function(){this.$emit("loadEnd"),this.immediate||this.draw()}}},i=function(t,e,i,a,n,r,s,o,l,c){"boolean"!=typeof s&&(l=o,o=s,s=!1);var d,f="function"==typeof i?i.options:i;if(t&&t.render&&(f.render=t.render,f.staticRenderFns=t.staticRenderFns,f._compiled=!0,n&&(f.functional=!0)),a&&(f._scopeId=a),r?(d=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,l(t)),t&&t._registeredComponents&&t._registeredComponents.add(r)},f._ssrRegister=d):e&&(d=s?function(){e.call(this,c(this.$root.$options.shadowRoot))}:function(t){e.call(this,o(t))}),d)if(f.functional){var m=f.render;f.render=function(t,e){return d.call(e),m(t,e)}}else{var u=f.beforeCreate;f.beforeCreate=u?[].concat(u,d):[d]}return i},a="undefined"!=typeof navigator&&/msie [6-9]\\b/.test(navigator.userAgent.toLowerCase()),n=document.head||document.getElementsByTagName("head")[0],r={},s=i({render:function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{class:t.c()},[i("img",{directives:[{name:"show",rawName:"v-show",value:t.show,expression:"show"}],class:[t.c("_img"),t.imgClass],style:{animationDuration:t.duration/1e3+"s"},attrs:{src:t.src,alt:t.alt},on:{load:t.loadEnd}}),t._v(" "),t.show?t._e():t._t("default")],2)},staticRenderFns:[]},function(t){t&&t("data-v-684a6a03_0",{source:".vue-image-painter .draw{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:draw;animation-name:draw}.vue-image-painter .blur{-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-name:blur;animation-name:blur}@-webkit-keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@keyframes draw{0%{-webkit-filter:brightness(10) contrast(10) grayscale(1);filter:brightness(10) contrast(10) grayscale(1);opacity:0}5%{-webkit-filter:brightness(5) contrast(10) grayscale(1);filter:brightness(5) contrast(10) grayscale(1);opacity:.5}30%{-webkit-filter:brightness(3) contrast(10) grayscale(1);filter:brightness(3) contrast(10) grayscale(1);opacity:1}50%{-webkit-filter:brightness(2) contrast(2) grayscale(1);filter:brightness(2) contrast(2) grayscale(1)}75%{-webkit-filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8);filter:brightness(1.5) contrast(1) grayscale(.4) saturate(.8)}100%{-webkit-filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05);filter:brightness(1.05) contrast(1) grayscale(0) saturate(1.05)}}@-webkit-keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}@keyframes blur{0%{-webkit-filter:blur(50px);filter:blur(50px);opacity:0}10%{-webkit-filter:blur(30px);filter:blur(30px);opacity:.6}100%{-webkit-filter:blur(0);filter:blur(0);opacity:1}}.vue-image-painter{width:100%;overflow:hidden}.vue-image-painter_img{width:100%}",map:void 0,media:void 0})},e,void 0,!1,void 0,function(t){return function(t,e){return function(t,e){var i=a?e.media||"default":t,s=r[i]||(r[i]={ids:new Set,styles:[]});if(!s.ids.has(t)){s.ids.add(t);var o=e.source;if(e.map&&(o+="\n/*# sourceURL="+e.map.sources[0]+" */",o+="\n/*# sourceMappingURL=data:application/json;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(e.map))))+" */"),s.element||(s.element=document.createElement("style"),s.element.type="text/css",e.media&&s.element.setAttribute("media",e.media),n.appendChild(s.element)),"styleSheet"in s.element)s.styles.push(o),s.element.styleSheet.cssText=s.styles.filter(Boolean).join("\n");else{var l=s.ids.size-1,c=document.createTextNode(o),d=s.element.childNodes;d[l]&&s.element.removeChild(d[l]),d.length?s.element.insertBefore(c,d[l]):s.element.appendChild(c)}}}(t,e)}},void 0);return s.install=function(t){t.component(s.name,s)},s},"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self)["vue-image-painter"]=e(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-image-painter", 3 | "version": "0.1.3", 4 | "description": "🙋‍ Image draw animation effect plugin for Vue 2.x | 图像动态绘制效果", 5 | "author": "komo ", 6 | "license": "MIT", 7 | "private": false, 8 | "repository": { 9 | "type": "git", 10 | "url": "https://github.com/komomoo/vue-image-painter" 11 | }, 12 | "keywords": [ 13 | "vue", 14 | "image-drawer", 15 | "image-painter", 16 | "img-paint" 17 | ], 18 | "main": "dist/vue-image-painter.min.js", 19 | "module": "dist/vue-image-painter.esm.min.js", 20 | "scripts": { 21 | "dev": "parcel demo/index.html -p 8080 --out-dir demo/dev", 22 | "build:demo": "rm -rf demo/dist/ && parcel build demo/index.html --out-dir demo/dist --public-url ./", 23 | "build": "dio", 24 | "lint": "eslint --fix --ext .js,.ts,.vue .", 25 | "release": "sh scripts/release.sh" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "@momoko/vue" 30 | ] 31 | }, 32 | "eslintIgnore": [ 33 | "dist" 34 | ], 35 | "babel": { 36 | "presets": [ 37 | "@momoko/vue" 38 | ] 39 | }, 40 | "browserslist": [ 41 | "iOS >= 9", 42 | "Android >= 4.4", 43 | "IE >= 9" 44 | ], 45 | "dependencies": {}, 46 | "devDependencies": { 47 | "@babel/core": "^7.3.3", 48 | "@momoko/babel-preset-vue": "^0.2.0", 49 | "@momoko/eslint-config-vue": "^1.0.2", 50 | "dio-bundler": "^0.5.2", 51 | "eslint": "^5.16.0", 52 | "parcel-bundler": "^1.12.3", 53 | "standard-version": "^4.4.0", 54 | "vue": "^2.6.10", 55 | "vue-hot-reload-api": "^2.3.2", 56 | "vue-template-compiler": "^2.6.10" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /scripts/release.sh: -------------------------------------------------------------------------------- 1 | version=$(node -p "const { version } = require('./package.json'); version") 2 | 3 | git checkout master 4 | 5 | # build 6 | yarn build 7 | yarn build:demo 8 | 9 | # commit 10 | git add -A 11 | standard-version --commit-all --release-as $version 12 | 13 | # gh-pages 14 | git checkout gh-pages 15 | git merge master 16 | git checkout master 17 | 18 | # push 19 | git push --tags origin 20 | git push --all origin 21 | 22 | # publish 23 | npm publish --registry=https://registry.npmjs.org 24 | -------------------------------------------------------------------------------- /src/ImagePainter/index.vue: -------------------------------------------------------------------------------- 1 | /** 2 | * vue-image-painter 3 | * @Author komo 4 | * @Date 2019/06 5 | */ 6 | 7 | 19 | 20 | 87 | 88 | 101 | -------------------------------------------------------------------------------- /src/ImagePainter/mixins/index.js: -------------------------------------------------------------------------------- 1 | import pkg from '../../../package.json' 2 | const pre = pkg.name 3 | 4 | export default { 5 | methods: { 6 | // 生成 css class 7 | c (className) { 8 | return className ? `${pre}${className}` : `${pre}` 9 | }, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /src/ImagePainter/style/animation.styl: -------------------------------------------------------------------------------- 1 | $ = vue-image-painter; 2 | .{$} { 3 | /** 4 | * draw 5 | */ 6 | @keyframes draw { 7 | // 1st step: drawing borders with a pencil 8 | 0% { 9 | filter: brightness(10) contrast(10) grayscale(1); 10 | opacity: 0; 11 | } 12 | 13 | 5% { 14 | filter: brightness(5) contrast(10) grayscale(1); 15 | opacity: 0.5; 16 | } 17 | 18 | 30% { 19 | filter: brightness(3) contrast(10) grayscale(1); 20 | opacity: 1; 21 | } 22 | 23 | // 2nd step: define better outlines and shades with a pencil 24 | 50% { 25 | filter: brightness(2) contrast(2) grayscale(1); 26 | } 27 | 28 | // 3nd step: give it some basic, very vanish colors 29 | 75% { 30 | filter: brightness(1.5) contrast(1) grayscale(0.4) saturate(0.8); 31 | } 32 | 33 | // 4nd step: complete the picture with all its colors (a bit more bright and alive) 34 | 100% { 35 | filter: brightness(1.05) contrast(1) grayscale(0) saturate(1.05); 36 | } 37 | } 38 | 39 | .draw { 40 | animation-timing-function: linear; 41 | animation-fill-mode: both; 42 | animation-name: draw; 43 | } 44 | 45 | @keyframes blur { 46 | 0% { 47 | filter: blur(50px); 48 | opacity: 0; 49 | } 50 | 10% { 51 | filter: blur(30px); 52 | opacity: 0.6; 53 | } 54 | 55 | 100% { 56 | filter: blur(0); 57 | opacity: 1; 58 | } 59 | } 60 | 61 | .blur { 62 | animation-timing-function: linear; 63 | animation-fill-mode: both; 64 | animation-name: blur; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ImagePainter from './ImagePainter' 2 | 3 | ImagePainter.install = function (Vue) { 4 | Vue.component(ImagePainter.name, ImagePainter) 5 | } 6 | 7 | export default ImagePainter 8 | --------------------------------------------------------------------------------