├── .idea ├── canvasStar.iml ├── modules.xml └── vcs.xml ├── README.md ├── canvasstar.js └── index.html /.idea/canvasStar.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # canvasStar 2 | 自己写的一个少女心满满的canvasStar特效 3 | 4 | ## 使用 canvasstar.js 5 | ### 在 HTML 中创建 canvas 元素 6 | 使用需要在 html 中加入 id 为 canvas 的 canvas,并且需要自己写好 canvas的样式 7 | 8 | ### 引用 `canvasstar.js` 文件 9 | 引用的 `canvasstar.js` 必须在 canvas 元素之后 10 | 11 | ### 创建对象并调用 12 | 创建一个新的`CanvasStar`对象,并且使用`CanvasStar.init()`调用即可 13 | 14 | ``` 15 | 19 | ``` 20 | ### 修改默认参数 21 | 如果有需要,可以更改默认参数 22 | 默认参数如下: 23 | ``` 24 | /* 25 | * @para star_r:star半径系数,系数越大,半径越大 26 | * @para star_alpha:生成star的透明度,star_alpha越大,透明度越低 27 | * @para initStarsPopulation:初始化stars的个数 28 | * @para move_distance:star位移的距离,数值越大,位移越大 29 | * @para dot_r : dot半径系数,系数越大,半径越大 30 | * @para dot_speeds : dots运动的速度 31 | * @para dot_alpha : dots的透明度 32 | * @para aReduction:dot消失条件,透明度小于aReduction时消失 33 | * @para dotsMinDist:dot最小距离 34 | * @para maxDistFromCursor:dot最大距离 35 | * 36 | * */ 37 | var config = { 38 | star_r : 3, 39 | star_alpha : 5, 40 | initStarsPopulation : 150, 41 | move_distance : 0.25, 42 | dot_r : 5, 43 | dot_speeds : 0.5, 44 | dot_alpha : 0.5, 45 | dot_aReduction : 0.01, 46 | dotsMinDist : 5, 47 | maxDistFromCursor : 50, 48 | }; 49 | ``` 50 | 51 | 如需修改,在`CanvasStar.init()`时传入对象的参数 52 | ``` 53 | 66 | ``` 67 | -------------------------------------------------------------------------------- /canvasstar.js: -------------------------------------------------------------------------------- 1 | ;(function(undefined) { 2 | "use strict"; 3 | var _global; 4 | 5 | /* 6 | * @var star_r:star半径系数,系数越大,半径越大 7 | * @var star_alpha:生成star的透明度,star_alpha越大,透明度越低 8 | * @var initStarsPopulation:初始化stars的个数 9 | * @var move_distance:star位移的距离,数值越大,位移越大 10 | * @var dot_r : dot半径系数,系数越大,半径越大 11 | * @var dot_speeds : dots运动的速度 12 | * @var dot_alpha : dots的透明度 13 | * @var aReduction:dot消失条件,透明度小于aReduction时消失 14 | * @var dotsMinDist:dot最小距离 15 | * @var maxDistFromCursor:dot最大距离 16 | * 17 | * */ 18 | var config = { 19 | star_r : 3, 20 | star_alpha : 5, 21 | initStarsPopulation : 150, 22 | move_distance : 0.25, 23 | dot_r : 5, 24 | dot_speeds : 0.5, 25 | dot_alpha : 0.5, 26 | dot_aReduction : 0.01, 27 | dotsMinDist : 5, 28 | maxDistFromCursor : 50, 29 | }; 30 | var stars = [], 31 | dots = [], 32 | canvas = document.getElementById('canvas'), 33 | ctx = canvas.getContext('2d'), 34 | WIDTH, 35 | HEIGHT, 36 | mouseMoving = false, 37 | mouseMoveChecker, 38 | mouseX, 39 | mouseY; 40 | function CanvasStar(){} 41 | 42 | var initConfig = function(conf){ 43 | if( conf instanceof Object ) 44 | for( var item in conf ){ 45 | config[item] = conf[item]; 46 | } 47 | }; 48 | 49 | CanvasStar.prototype.init =function (conf) { 50 | initConfig(conf);//初始化设置 51 | 52 | ctx.strokeStyle = "white"; 53 | ctx.shadowColor = "white"; 54 | for (var i = 0; i < config.initStarsPopulation; i++) { 55 | stars[i] = new Star(i, Math.floor(Math.random()*WIDTH), Math.floor(Math.random()*HEIGHT),true); 56 | //stars[i].draw(); 57 | } 58 | ctx.shadowBlur = 0; 59 | animate(); 60 | }; 61 | 62 | 63 | 64 | function Star(id, x, y, useCache) { 65 | this.id = id; 66 | this.x = x; 67 | this.y = y; 68 | this.useCacha = useCache; 69 | this.cacheCanvas = document.createElement("canvas"); 70 | this.cacheCtx = this.cacheCanvas.getContext("2d"); 71 | this.r = Math.floor(Math.random() * config.star_r) + 1; 72 | this.cacheCtx.width = 6 * this.r; 73 | this.cacheCtx.height = 6 * this.r; 74 | var alpha = ( Math.floor(Math.random() * 10) + 1) / config.star_alpha; 75 | this.color = "rgba(255,255,255," + alpha + ")"; 76 | if (useCache) { 77 | this.cache() 78 | } 79 | } 80 | 81 | Star.prototype = { 82 | draw : function () { 83 | if (!this.useCacha) { 84 | ctx.save(); 85 | ctx.fillStyle = this.color; 86 | ctx.shadowBlur = this.r * 2; 87 | ctx.beginPath(); 88 | ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false); 89 | ctx.closePath(); 90 | ctx.fill(); 91 | ctx.restore(); 92 | } else { 93 | ctx.drawImage(this.cacheCanvas, this.x - this.r, this.y - this.r); 94 | } 95 | }, 96 | 97 | cache : function () { 98 | this.cacheCtx.save(); 99 | this.cacheCtx.fillStyle = this.color; 100 | this.cacheCtx.shadowColor = "white"; 101 | this.cacheCtx.shadowBlur = this.r * 2; 102 | this.cacheCtx.beginPath(); 103 | this.cacheCtx.arc(this.r * 3, this.r * 3, this.r, 0, 2 * Math.PI); 104 | this.cacheCtx.closePath(); 105 | this.cacheCtx.fill(); 106 | this.cacheCtx.restore(); 107 | }, 108 | 109 | move : function () { 110 | this.y -= config.move_distance; 111 | if (this.y <= -10) { 112 | this.y += HEIGHT + 10; 113 | } 114 | this.draw(); 115 | }, 116 | 117 | die : function () { 118 | stars[this.id] = null; 119 | delete stars[this.id] 120 | } 121 | }; 122 | 123 | function Dot(id, x, y, useCache) { 124 | this.id = id; 125 | this.x = x; 126 | this.y = y; 127 | this.r = Math.floor(Math.random() * config.dot_r)+1; 128 | this.speed = config.dot_speeds; 129 | this.a = config.dot_alpha; 130 | this.aReduction = config.dot_aReduction; 131 | this.useCache = useCache; 132 | this.dotCanvas = document.createElement("canvas"); 133 | this.dotCtx = this.dotCanvas.getContext("2d"); 134 | this.dotCtx.width = 6 * this.r; 135 | this.dotCtx.height = 6 * this.r; 136 | this.dotCtx.a = 0.5; 137 | this.color = "rgba(255,255,255," + this.a +")"; 138 | this.dotCtx.color = "rgba(255,255,255," + this.dotCtx.a + ")"; 139 | this.linkColor = "rgba(255,255,255," + this.a/4 + ")"; 140 | this.dir = Math.floor(Math.random()*140)+200; 141 | 142 | if( useCache){ 143 | this.cache() 144 | } 145 | } 146 | 147 | Dot.prototype = { 148 | draw : function () { 149 | if( !this.useCache){ 150 | ctx.save(); 151 | ctx.fillStyle = this.color; 152 | ctx.shadowColor = "white"; 153 | ctx.shadowBlur = this.r * 2; 154 | ctx.beginPath(); 155 | ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false); 156 | ctx.closePath(); 157 | ctx.fill(); 158 | ctx.restore(); 159 | }else{ 160 | ctx.drawImage(this.dotCanvas, this.x - this.r * 3, this.y - this.r *3); 161 | 162 | } 163 | }, 164 | 165 | cache : function () { 166 | this.dotCtx.save(); 167 | this.dotCtx.a -= this.aReduction; 168 | this.dotCtx.color = "rgba(255,255,255," + this.dotCtx.a + ")"; 169 | this.dotCtx.fillStyle = this.dotCtx.color; 170 | this.dotCtx.shadowColor = "white"; 171 | this.dotCtx.shadowBlur = this.r * 2; 172 | this.dotCtx.beginPath(); 173 | this.dotCtx.arc(this.r * 3, this.r * 3, this.r, 0, 2 * Math.PI, false); 174 | this.dotCtx.closePath(); 175 | this.dotCtx.fill(); 176 | this.dotCtx.restore(); 177 | }, 178 | link : function () { 179 | if (this.id == 0) return; 180 | var previousDot1 = getPreviousDot(this.id, 1); 181 | var previousDot2 = getPreviousDot(this.id, 2); 182 | var previousDot3 = getPreviousDot(this.id, 3); 183 | var previousDot4 = getPreviousDot(this.id, 4); 184 | 185 | 186 | if (!previousDot1) return; 187 | ctx.strokeStyle = this.linkColor; 188 | ctx.moveTo(previousDot1.x, previousDot1.y); 189 | ctx.beginPath(); 190 | ctx.lineTo(this.x, this.y); 191 | if (previousDot2 != false) ctx.lineTo(previousDot2.x, previousDot2.y); 192 | if (previousDot3 != false) ctx.lineTo(previousDot3.x, previousDot3.y); 193 | if (previousDot4 != false) ctx.lineTo(previousDot4.x, previousDot4.y); 194 | 195 | ctx.stroke(); 196 | ctx.closePath(); 197 | }, 198 | 199 | move : function () { 200 | 201 | 202 | this.a -= this.aReduction; 203 | if(this.a <= 0 ){ 204 | this.die(); 205 | return 206 | } 207 | this.dotCtx.a -= this.aReduction; 208 | this.dotCtx.color = "rgba(255,255,255," + this.dotCtx.a + ")"; 209 | this.color = "rgba(255,255,255," + this.a + ")"; 210 | this.linkColor = "rgba(255,255,255," + this.a/4 + ")"; 211 | this.x = this.x + Math.cos(degToRad(this.dir)) * this.speed; 212 | this.y = this.y + Math.sin(degToRad(this.dir)) * this.speed; 213 | 214 | this.draw(); 215 | this.link(); 216 | 217 | }, 218 | 219 | die : function () { 220 | dots[this.id] = null; 221 | delete dots[this.id]; 222 | } 223 | }; 224 | 225 | window.onmousemove = function (e) { 226 | mouseMoving = true; 227 | mouseX = e.clientX; 228 | mouseY = e.clientY; 229 | clearInterval(mouseMoveChecker); 230 | mouseMoveChecker = setInterval(function () { 231 | mouseMoving = false 232 | },1000) 233 | 234 | }; 235 | 236 | function drawIfMouseMoving() { 237 | if (!mouseMoving) return; 238 | 239 | if (dots.length == 0) { 240 | dots[0] = new Dot(0, mouseX, mouseY,true); 241 | dots[0].draw(); 242 | return; 243 | } 244 | 245 | var previousDot = getPreviousDot(dots.length, 1); 246 | var prevX = previousDot.x; 247 | var prevY = previousDot.y; 248 | 249 | var diffX = Math.abs(prevX - mouseX); 250 | var diffY = Math.abs(prevY - mouseY); 251 | 252 | if (diffX < config.dotsMinDist || diffY < config.dotsMinDist) return; 253 | 254 | var xVariation = Math.random() > .5 ? -1 : 1; 255 | xVariation = xVariation*Math.floor(Math.random() * config.maxDistFromCursor)+1; 256 | var yVariation = Math.random() > .5 ? -1 : 1; 257 | yVariation = yVariation*Math.floor(Math.random() * config.maxDistFromCursor)+1; 258 | dots[dots.length] = new Dot(dots.length, mouseX+xVariation, mouseY+yVariation,true); 259 | dots[dots.length-1].draw(); 260 | dots[dots.length-1].link(); 261 | } 262 | 263 | function getPreviousDot(id, stepback) { 264 | if(id == 0 || id - stepback < 0){ 265 | return false 266 | } 267 | if(typeof dots[id - stepback] !== "undefined"){ 268 | return dots[id - stepback] 269 | }else{ 270 | return false 271 | } 272 | } 273 | 274 | function setCanvasSize() { 275 | WIDTH = document.documentElement.clientWidth; 276 | HEIGHT = document.documentElement.clientHeight; 277 | canvas.setAttribute("width", WIDTH); 278 | canvas.setAttribute("height", HEIGHT); 279 | 280 | } 281 | 282 | function animate() { 283 | ctx.clearRect(0, 0, WIDTH, HEIGHT); 284 | 285 | for (var i in stars) { 286 | stars[i].move(); 287 | } 288 | for (var i in dots) { 289 | dots[i].move(); 290 | } 291 | drawIfMouseMoving(); 292 | requestAnimationFrame(animate); 293 | } 294 | 295 | function degToRad(deg) { 296 | return deg * (Math.PI / 180); 297 | } 298 | 299 | setCanvasSize(); 300 | 301 | 302 | 303 | // 最后将插件对象暴露给全局对象 304 | _global = (function(){ return this || (0, eval)('this'); }()); 305 | if (typeof module !== "undefined" && module.exports) { 306 | module.exports = CanvasStar; 307 | } else if (typeof define === "function" && define.amd) { 308 | define(function(){return CanvasStar;}); 309 | } else { 310 | 311 | !('CanvasStar' in _global) && (_global.CanvasStar = CanvasStar); 312 | } 313 | 314 | 315 | })(); 316 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Title 6 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 54 | 55 | --------------------------------------------------------------------------------