├── README.md
├── bin
├── Ribbon.vue
├── RibbonAnimation.vue
├── enhanceAppFile.js
└── ribbon.js
├── index.js
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | ## 💌 vuepress-plugin-ribbon-animation
2 |
3 | > 项目地址:[https://www.zpzpup.com/blog]
4 |
5 | > vue vuepress vuepress-theme-reco vuepress-plugin-ribbon 感谢支持
6 |
7 | ## 📢 说明
8 |
9 | ***放到开头,这里重点说明下,大家如果有啥问题咱就直接提‘lssues’吧,后面朋友遇到相同问题大家也可以参考***
10 |
11 | ## 🏠 项目截图
12 |
13 |
14 |
15 |
16 |
17 | ## 📎 项目配置也是很简单
18 | > npm install vuepress-plugin-ribbon-animation -D
19 |
20 | or
21 |
22 | >cnpm install vuepress-plugin-ribbon-animation -D
23 |
24 | 1.1.1 修复打包bug
25 |
26 | 1.1.2 修复组件高度bug
27 |
28 | 1.1.3 去掉console
29 |
30 | 大家目前去用1.1.3的版本 前面几个是测试用的版本 其他的大家就提lssues吧
31 |
32 | ```js
33 | // 只要把这个放进 config的plugins中就可以了 有木有很简单
34 | ["ribbon-animation", {
35 | size: 90, // 默认数据
36 | opacity: 0.3, // 透明度
37 | zIndex: -1, // 层级
38 | opt: {
39 | // 色带HSL饱和度
40 | colorSaturation: "80%",
41 | // 色带HSL亮度量
42 | colorBrightness: "60%",
43 | // 带状颜色不透明度
44 | colorAlpha: 0.65,
45 | // 在HSL颜色空间中循环显示颜色的速度有多快
46 | colorCycleSpeed: 6,
47 | // 从哪一侧开始Y轴 (top|min, middle|center, bottom|max, random)
48 | verticalPosition: "center",
49 | // 到达屏幕另一侧的速度有多快
50 | horizontalSpeed: 200,
51 | // 在任何给定时间,屏幕上会保留多少条带
52 | ribbonCount: 2,
53 | // 添加笔划以及色带填充颜色
54 | strokeSize: 0,
55 | // 通过页面滚动上的因子垂直移动色带
56 | parallaxAmount: -0.5,
57 | // 随着时间的推移,为每个功能区添加动画效果
58 | animateSections: true
59 | },
60 | ribbonShow: false, // 点击彩带 true显示 false为不显示
61 | ribbonAnimationShow: true // 滑动彩带
62 | }]
63 | ```
64 | 如果觉得很省事,帮到你了可以点个 ⭐ star 感激不尽 😁😁😁 [链接:🚀](https://github.com/JabinPeng/vuepress-plugin-ribbon-animation).
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/bin/Ribbon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
124 |
--------------------------------------------------------------------------------
/bin/RibbonAnimation.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
24 |
--------------------------------------------------------------------------------
/bin/enhanceAppFile.js:
--------------------------------------------------------------------------------
1 | import Ribbon from "./Ribbon.vue";
2 | import RibbonAnimation from './RibbonAnimation.vue'
3 | export default ({
4 | Vue
5 | }) => {
6 | Vue.component(Ribbon.name, Ribbon);
7 | Vue.component(RibbonAnimation.name, RibbonAnimation);
8 | };
9 |
--------------------------------------------------------------------------------
/bin/ribbon.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Ribbons Class File.
3 | * Creates low-poly ribbons background effect inside a target container.
4 | */
5 | (function (name, factory)
6 | {
7 | if (typeof window === "object")
8 | {
9 | window[name] = factory();
10 | }
11 |
12 | })("Ribbons", function ()
13 | {
14 | var _w = window,
15 | _b = document.body,//返回html dom中的body节点 即
16 | _d = document.documentElement;//返回html dom中的root 节点 即
17 |
18 | // random helper
19 | var random = function ()
20 | {
21 | if (arguments.length === 1) // only 1 argument
22 | {
23 | if (Array.isArray(arguments[0])) // extract index from array
24 | {
25 | var index = Math.round(random(0, arguments[0].length - 1));
26 | return arguments[0][index];
27 | }
28 | return random(0, arguments[0]); // assume numeric
29 | } else
30 | if (arguments.length === 2) // two arguments range
31 | {
32 | return Math.random() * (arguments[1] - arguments[0]) + arguments[0];
33 | }
34 | return 0; // default
35 | };
36 |
37 | // screen helper
38 | var screenInfo = function (e)
39 | {
40 | var width = Math.max(0, _w.innerWidth || _d.clientWidth || _b.clientWidth || 0),
41 | height = Math.max(0, _w.innerHeight || _d.clientHeight || _b.clientHeight || 0),
42 | scrollx = Math.max(0, _w.pageXOffset || _d.scrollLeft || _b.scrollLeft || 0) - (_d.clientLeft || 0),
43 | scrolly = Math.max(0, _w.pageYOffset || _d.scrollTop || _b.scrollTop || 0) - (_d.clientTop || 0);
44 |
45 | return {
46 | width: width,
47 | height: height,
48 | ratio: width / height,
49 | centerx: width / 2,
50 | centery: height / 2,
51 | scrollx: scrollx,
52 | scrolly: scrolly };
53 |
54 | };
55 |
56 | // mouse/input helper
57 | var mouseInfo = function (e)
58 | {
59 | var screen = screenInfo(e),
60 | mousex = e ? Math.max(0, e.pageX || e.clientX || 0) : 0,
61 | mousey = e ? Math.max(0, e.pageY || e.clientY || 0) : 0;
62 |
63 | return {
64 | mousex: mousex,
65 | mousey: mousey,
66 | centerx: mousex - screen.width / 2,
67 | centery: mousey - screen.height / 2 };
68 |
69 | };
70 |
71 | // point object
72 | var Point = function (x, y)
73 | {
74 | this.x = 0;
75 | this.y = 0;
76 | this.set(x, y);
77 | };
78 | Point.prototype = {
79 | constructor: Point,
80 |
81 | set: function (x, y)
82 | {
83 | this.x = x || 0;
84 | this.y = y || 0;
85 | },
86 | copy: function (point)
87 | {
88 | this.x = point.x || 0;
89 | this.y = point.y || 0;
90 | return this;
91 | },
92 | multiply: function (x, y)
93 | {
94 | this.x *= x || 1;
95 | this.y *= y || 1;
96 | return this;
97 | },
98 | divide: function (x, y)
99 | {
100 | this.x /= x || 1;
101 | this.y /= y || 1;
102 | return this;
103 | },
104 | add: function (x, y)
105 | {
106 | this.x += x || 0;
107 | this.y += y || 0;
108 | return this;
109 | },
110 | subtract: function (x, y)
111 | {
112 | this.x -= x || 0;
113 | this.y -= y || 0;
114 | return this;
115 | },
116 | clampX: function (min, max)
117 | {
118 | this.x = Math.max(min, Math.min(this.x, max));
119 | return this;
120 | },
121 | clampY: function (min, max)
122 | {
123 | this.y = Math.max(min, Math.min(this.y, max));
124 | return this;
125 | },
126 | flipX: function ()
127 | {
128 | this.x *= -1;
129 | return this;
130 | },
131 | flipY: function ()
132 | {
133 | this.y *= -1;
134 | return this;
135 | } };
136 |
137 |
138 | // class constructor
139 | var Factory = function (options)
140 | {
141 | this._canvas = null;
142 | this._context = null;
143 | this._sto = null;
144 | this._width = 0;
145 | this._height = 0;
146 | this._scroll = 0;
147 | this._ribbons = [];
148 | this._options = options;
149 |
150 | this._onDraw = this._onDraw.bind(this);
151 | this._onResize = this._onResize.bind(this);
152 | this._onScroll = this._onScroll.bind(this);
153 | this.setOptions(options);
154 | this.init();
155 | };
156 |
157 | // class prototype
158 | Factory.prototype = {
159 | constructor: Factory,
160 |
161 | // Set and merge local options
162 | setOptions: function (options)
163 | {
164 | if (typeof options === "object")
165 | {
166 | for (var key in options)
167 | {
168 | if (options.hasOwnProperty(key))
169 | {
170 | this._options[key] = options[key];
171 | }
172 | }
173 | }
174 | },
175 |
176 | // Initialize the ribbons effect
177 | init: function ()
178 | {
179 | try
180 | {
181 | this._canvas = document.createElement("canvas");
182 | this._canvas.style["display"] = "block";
183 | this._canvas.style["position"] = "fixed";
184 | this._canvas.style["margin"] = "0";
185 | this._canvas.style["padding"] = "0";
186 | this._canvas.style["border"] = "0";
187 | this._canvas.style["outline"] = "0";
188 | this._canvas.style["left"] = "0";
189 | this._canvas.style["top"] = "0";
190 | this._canvas.style["width"] = "100%";
191 | this._canvas.style["height"] = "100%";
192 | this._canvas.style["z-index"] = "-1";
193 | // this._canvas.style["background-color"]="#1f1f1f";
194 | this._canvas.id = "bgCanvas";
195 | this._onResize();
196 |
197 | this._context = this._canvas.getContext("2d");
198 | this._context.clearRect(0, 0, this._width, this._height);
199 | this._context.globalAlpha = this._options.colorAlpha;
200 |
201 | window.addEventListener("resize", this._onResize);
202 | window.addEventListener("scroll", this._onScroll);
203 | document.body.appendChild(this._canvas);
204 | }
205 | catch (e) {
206 | console.warn("Canvas Context Error: " + e.toString());
207 | return;
208 | }
209 | this._onDraw();
210 | },
211 |
212 | // Create a new random ribbon and to the list
213 | addRibbon: function ()
214 | {
215 | // movement data
216 | var dir = Math.round(random(1, 9)) > 5 ? "right" : "left",
217 | stop = 1000,
218 | hide = 200,
219 | min = 0 - hide,
220 | max = this._width + hide,
221 | movex = 0,
222 | movey = 0,
223 | startx = dir === "right" ? min : max,
224 | starty = Math.round(random(0, this._height));
225 |
226 | // asjust starty based on options
227 | if (/^(top|min)$/i.test(this._options.verticalPosition))
228 | {
229 | starty = 0 + hide;
230 | } else
231 | if (/^(middle|center)$/i.test(this._options.verticalPosition))
232 | {
233 | starty = this._height / 2;
234 | } else
235 | if (/^(bottom|max)$/i.test(this._options.verticalPosition))
236 | {
237 | starty = this._height - hide;
238 | }
239 |
240 | // ribbon sections data
241 | var ribbon = [],
242 | point1 = new Point(startx, starty),
243 | point2 = new Point(startx, starty),
244 | point3 = null,
245 | color = Math.round(random(0, 360)),
246 | delay = 0;
247 |
248 | // buils ribbon sections
249 | while (true)
250 | {
251 | if (stop <= 0) break;stop--;
252 |
253 | movex = Math.round((Math.random() * 1 - 0.2) * this._options.horizontalSpeed);
254 | movey = Math.round((Math.random() * 1 - 0.5) * (this._height * 0.25));
255 |
256 | point3 = new Point();
257 | point3.copy(point2);
258 |
259 | if (dir === "right")
260 | {
261 | point3.add(movex, movey);
262 | if (point2.x >= max) break;
263 | } else
264 | if (dir === "left")
265 | {
266 | point3.subtract(movex, movey);
267 | if (point2.x <= min) break;
268 | }
269 | // point3.clampY( 0, this._height );
270 |
271 | ribbon.push({ // single ribbon section
272 | point1: new Point(point1.x, point1.y),
273 | point2: new Point(point2.x, point2.y),
274 | point3: point3,
275 | color: color,
276 | delay: delay,
277 | dir: dir,
278 | alpha: 0,
279 | phase: 0 });
280 |
281 |
282 | point1.copy(point2);
283 | point2.copy(point3);
284 |
285 | delay += 4;
286 | color += this._options.colorCycleSpeed;
287 | }
288 | this._ribbons.push(ribbon);
289 | },
290 |
291 | // Draw single section
292 | _drawRibbonSection: function (section)
293 | {
294 | if (section)
295 | {
296 | if (section.phase >= 1 && section.alpha <= 0)
297 | {
298 | return true; // done
299 | }
300 | if (section.delay <= 0)
301 | {
302 | section.phase += 0.02;
303 | section.alpha = Math.sin(section.phase) * 1;
304 | section.alpha = section.alpha <= 0 ? 0 : section.alpha;
305 | section.alpha = section.alpha >= 1 ? 1 : section.alpha;
306 |
307 | if (this._options.animateSections)
308 | {
309 | var mod = Math.sin(1 + section.phase * Math.PI / 2) * 0.1;
310 |
311 | if (section.dir === "right")
312 | {
313 | section.point1.add(mod, 0);
314 | section.point2.add(mod, 0);
315 | section.point3.add(mod, 0);
316 | } else {
317 | section.point1.subtract(mod, 0);
318 | section.point2.subtract(mod, 0);
319 | section.point3.subtract(mod, 0);
320 | }
321 | section.point1.add(0, mod);
322 | section.point2.add(0, mod);
323 | section.point3.add(0, mod);
324 | }
325 | } else
326 | {section.delay -= 0.5;}
327 |
328 | var s = this._options.colorSaturation,
329 | l = this._options.colorBrightness,
330 | c = "hsla(" + section.color + ", " + s + ", " + l + ", " + section.alpha + " )";
331 |
332 | this._context.save();
333 |
334 | if (this._options.parallaxAmount !== 0)
335 | {
336 | this._context.translate(0, this._scroll * this._options.parallaxAmount);
337 | }
338 | this._context.beginPath();
339 | this._context.moveTo(section.point1.x, section.point1.y);
340 | this._context.lineTo(section.point2.x, section.point2.y);
341 | this._context.lineTo(section.point3.x, section.point3.y);
342 | this._context.fillStyle = c;
343 | this._context.fill();
344 |
345 | if (this._options.strokeSize > 0)
346 | {
347 | this._context.lineWidth = this._options.strokeSize;
348 | this._context.strokeStyle = c;
349 | this._context.lineCap = "round";
350 | this._context.stroke();
351 | }
352 | this._context.restore();
353 | }
354 | return false; // not done yet
355 | },
356 |
357 | // Draw ribbons
358 | _onDraw: function ()
359 | {
360 | // cleanup on ribbons list to rtemoved finished ribbons
361 | for (var i = 0, t = this._ribbons.length; i < t; ++i)
362 | {
363 | if (!this._ribbons[i])
364 | {
365 | this._ribbons.splice(i, 1);
366 | }
367 | }
368 |
369 | // draw new ribbons
370 | this._context.clearRect(0, 0, this._width, this._height);
371 |
372 | for (var a = 0; a < this._ribbons.length; ++a) // single ribbon
373 | {
374 | var ribbon = this._ribbons[a],
375 | numSections = ribbon.length,
376 | numDone = 0;
377 |
378 | for (var b = 0; b < numSections; ++b) // ribbon section
379 | {
380 | if (this._drawRibbonSection(ribbon[b]))
381 | {
382 | numDone++; // section done
383 | }
384 | }
385 | if (numDone >= numSections) // ribbon done
386 | {
387 | this._ribbons[a] = null;
388 | }
389 | }
390 | // maintain optional number of ribbons on canvas
391 | if (this._ribbons.length < this._options.ribbonCount)
392 | {
393 | this.addRibbon();
394 | }
395 | requestAnimationFrame(this._onDraw);
396 | },
397 |
398 | // Update container size info
399 | _onResize: function (e)
400 | {
401 | var screen = screenInfo(e);
402 | this._width = screen.width;
403 | this._height = screen.height;
404 |
405 | if (this._canvas)
406 | {
407 | this._canvas.width = this._width;
408 | this._canvas.height = this._height;
409 |
410 | if (this._context)
411 | {
412 | this._context.globalAlpha = this._options.colorAlpha;
413 | }
414 | }
415 | },
416 |
417 | // Update container size info
418 | _onScroll: function (e)
419 | {
420 | var screen = screenInfo(e);
421 | this._scroll = screen.scrolly;
422 | } };
423 | // export
424 | return Factory;
425 | });
426 | export default Ribbons
427 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | const { resolve } = require('path')
2 |
3 | module.exports = (options = {}, context) => ({
4 | define() {
5 | const {
6 | size = 90, opacity = 0.6, zIndex = -1, opt = {
7 | // 色带HSL饱和度
8 | colorSaturation: "80%",
9 | // 色带HSL亮度量
10 | colorBrightness: "60%",
11 | // 带状颜色不透明度
12 | colorAlpha: 0.65,
13 | // 在HSL颜色空间中循环显示颜色的速度有多快
14 | colorCycleSpeed: 6,
15 | // 从哪一侧开始Y轴 (top|min, middle|center, bottom|max, random)
16 | verticalPosition: "center",
17 | // 到达屏幕另一侧的速度有多快
18 | horizontalSpeed: 200,
19 | // 在任何给定时间,屏幕上会保留多少条带
20 | ribbonCount: 2,
21 | // 添加笔划以及色带填充颜色
22 | strokeSize: 0,
23 | // 通过页面滚动上的因子垂直移动色带
24 | parallaxAmount: -0.5,
25 | // 随着时间的推移,为每个功能区添加动画效果
26 | animateSections: true
27 | },
28 | ribbonShow = true,
29 | ribbonAnimationShow = true
30 | } = options
31 |
32 | return {
33 | RIBBON_SIZE: size,
34 | RIBBON_OPACITY: opacity,
35 | RIBBON_Z_INDEX: zIndex,
36 | RIBBON_OPTIONS: opt,
37 | RIBBON_SHOW: ribbonShow,
38 | RIBBONANIMATION_SHOW: ribbonAnimationShow,
39 | }
40 | },
41 | enhanceAppFiles: resolve(__dirname, "./bin/enhanceAppFile.js"),
42 | globalUIComponents: ["Ribbon", "RibbonAnimation"]
43 | });
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vuepress-plugin-ribbon-animation",
3 | "version": "1.1.2",
4 | "description": "ribbons plugin",
5 | "main": "index.js",
6 | "keywords": [
7 | "vuepress",
8 | "ribbon",
9 | "animation"
10 | ],
11 | "author": "JabinPeng",
12 | "license": "MIT",
13 | "__npminstall_done": "Wed Jan 13 2021 21:00:17 GMT+0800 (GMT+08:00)",
14 | "_from": "vuepress-plugin-ribbon-animation@1.0.0",
15 | "_resolved": "https://registry.npm.taobao.org/vuepress-plugin-ribbon-animation/download/vuepress-plugin-ribbon-animation-1.0.0.tgz",
16 | "_gitHub": "https://github.com/JabinPeng/vuepress-plugin-ribbon-animation"
17 | }
18 |
--------------------------------------------------------------------------------