├── README.md ├── boomExample.gif ├── boomExample2.gif └── src ├── Boom.js ├── cd_glaive.cur ├── cd_glowsword.cur ├── css └── Boom.css ├── demo.html ├── images.jpg ├── images ├── images.jpg └── images2.jpg ├── images2.jpg └── js └── Boom.js /README.md: -------------------------------------------------------------------------------- 1 | # boomJS 2 | 3 | 一个有趣的动画效果,用 `JavaScript` 配合 `CSS3` 实现让图片爆炸的动画。 4 | 5 | [Demo演示戳我](https://chokcoco.github.io/demo/boom/demo.html) 6 | 7 | ### Example 8 | 9 | ![Boom效果演示图](https://github.com/chokcoco/boomJS/blob/master/boomExample2.gif) 10 | 11 | ![Boom效果演示图](https://github.com/chokcoco/boomJS/blob/master/boomExample.gif) 12 | 13 | ## Usage 14 | 15 | ```HTML 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 32 | ``` 33 | 34 | ## API 35 | ```javascript 36 | boom($('img'),{ 37 | // 缩放值 38 | 'scaleLevel' : 3, 39 | // 模糊值 40 | 'blurLevel': 9, 41 | // 弹射距离 42 | 'boomLevel': 4, 43 | // 爆炸时长 44 | 'boomTime':800, 45 | // 是否打开日志 46 | 'isOpenLog':true 47 | }); 48 | ``` 49 | 温馨提示,不建议将 scaleLevel 的值设太高 :) 。 50 | 51 | -------------------------------------------------------------------------------- /boomExample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/boomExample.gif -------------------------------------------------------------------------------- /boomExample2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/boomExample2.gif -------------------------------------------------------------------------------- /src/Boom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Coco 3 | * QQ:308695699 4 | * @name boomJS 1.0.0 5 | * @description 一个有趣的效果,用 JavaScript 实现让图片爆炸的动画(非Canvas) 6 | * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 7 | * 1、本组件用于是学习 jQuery 队列时做的一个小 demo,使用 JavaScript 配合 CSS3 实现一个简单的动画效果 8 | * 9 | * 2、依赖 jQuery,且需要引入 Boom.css ; 10 | 11 | * 3、初始化方法, 12 | * 1)提供 var bom = new boom() 构造函数,构建 boom 实例,调用 bom.boom(),传入 img 的 jQuery 对象,例如bom.boom($('img')) 13 | * 2)直接 boom() 进行调用,传入 img 的 jQuery 对象,例如 boom($('img')) 14 | * 15 | * 4、目前只支持未经过缩放的图片 16 | * 17 | */ 18 | (function(window, undefined) { 19 | var 20 | // 是否插入了 jQuery 21 | isInsetJq = false, 22 | // css参数预设 23 | cssOption = { 24 | position: 'absolute', 25 | width: 0, 26 | height: 0, 27 | left: 0, 28 | top: 0 29 | }, 30 | // 存储图片地址 31 | imgUrl = "", 32 | // 暴露的最终变量 33 | boom = function(elems) { 34 | return new boom.prototype.init(elems); 35 | }, 36 | // 偏移距离 37 | arrRandomOffset = [1, -4, 8, -12, 16, -20, 24, -28, 32], 38 | // 图片集 39 | imgArr = [], 40 | // 传入的图片个数 41 | imgLength = 0; 42 | 43 | // 加载js 44 | function loadScript(url, callback) { 45 | if (isInsetJq) { 46 | return; 47 | } 48 | 49 | var ref = window.document.getElementsByTagName("script")[0], 50 | script = window.document.createElement("script"); 51 | 52 | script.src = url; 53 | script.type = 'text/javascript'; 54 | script.async = false; 55 | ref.parentNode.insertBefore(script, ref); 56 | 57 | if (callback && typeof(callback) === "function") { 58 | script.onload = callback; 59 | } 60 | 61 | isInsetJq = true; 62 | } 63 | 64 | // 计算坐标并添加新的层覆盖在原图上 65 | // 返回一个 jQuery 对象(dom 节点,是一个和图片高宽绝对定位坐标一致的 div) 66 | function calcPosition(elem) { 67 | imgUrl = elem.attr('src') || ""; 68 | 69 | // 转化为 JS 对象 70 | var obj = elem[0]; 71 | 72 | // getBoundingClientRect 方法返回元素的大小及其相对于视口的位置 73 | // 这是个 JS 对象方法,注意下文和 jQuery 对象的相互转换 74 | var posi = obj.getBoundingClientRect(), 75 | // 图片的宽高和定位 76 | elemCss = { 77 | width: obj.width, 78 | height: obj.height, 79 | top: posi.top, 80 | left: posi.left, 81 | }, 82 | // 生成新的 div 的 css 样式 83 | realCss = $.extend(cssOption, elemCss); 84 | 85 | var newDiv = $(document.createElement('div')); 86 | 87 | newDiv.css(realCss); 88 | 89 | $('body').append(newDiv); 90 | 91 | return newDiv; 92 | } 93 | 94 | /** 95 | * 在原图上生成小的 div 块 96 | * @param elem 原图的 jQuery 对象 97 | */ 98 | function insertSmallDiv(elem) { 99 | var obj = elem, 100 | width = elem.width(), 101 | height = elem.height(), 102 | miniNum = 10, 103 | widthNum = 0, 104 | heightNum = 0, 105 | // div 小块的宽度 106 | newElemWidth = 0, 107 | i = 0, 108 | j = 0, 109 | elemArr = []; 110 | 111 | //console.log(width+','+height); 112 | 113 | if (width <= 10 && height <= 10) { 114 | return; 115 | } 116 | 117 | var basePoint = width > height ? height : width; 118 | 119 | //console.log('base point is :'+basePoint); 120 | 121 | if (basePoint == width) { 122 | newElemWidth = Math.floor(width / miniNum); 123 | heightNum = Math.floor(height / newElemWidth); 124 | widthNum = miniNum; 125 | } else { 126 | newElemWidth = Math.floor(height / miniNum); 127 | heightNum = Math.floor(width / newElemWidth); 128 | widthNum = miniNum; 129 | } 130 | 131 | //console.log('widthNum:'+widthNum+',height:'+heightNum+',width:'+newElemWidth); 132 | 133 | var newElemCss = { 134 | position: 'absolute', 135 | width: newElemWidth, 136 | height: newElemWidth, 137 | 'border-radius': '100%', 138 | top: 0, 139 | left: 0 140 | } 141 | 142 | // 比较宽高大小,确定插入的行数 143 | if (height > width) { 144 | // 交换 width ,height 的值 145 | widthNum = widthNum * heightNum; 146 | heightNum = widthNum / heightNum; 147 | widthNum = widthNum / heightNum; 148 | } 149 | 150 | //console.log('widthNum:'+widthNum+',heightNum:'+heightNum+',newElemWidth:'+newElemWidth); 151 | 152 | for (; i < widthNum; i++) { 153 | for (; j < heightNum; j++) { 154 | var randomSize = Math.random() * 3, 155 | newElem = document.createElement('div'), 156 | cssTop = i * newElemWidth, 157 | cssLeft = j * newElemWidth, 158 | posiElemCss = { 159 | 'background-image': 'url(' + imgUrl + ')', 160 | 'background-repeat': 'no-repeat', 161 | 'background-position': '-' + cssLeft + 'px ' + '-' + cssTop + 'px', 162 | position: 'absolute', 163 | width: newElemWidth, 164 | height: newElemWidth, 165 | 'border-radius': '100%', 166 | top: 0, 167 | left: 0, 168 | top: cssTop, 169 | left: cssLeft, 170 | transform: 'scale(' + randomSize + ')' 171 | }; 172 | // console.log('cssTop is:'+cssTop+',cssLeft is:'+cssLeft+',posiElemCss:'+posiElemCss); 173 | // console.log(newElemCss); 174 | // var curElemCss = $.extend(newELemCss,posiElemCss); 175 | $(newElem).css(posiElemCss); 176 | elemArr.push(newElem); 177 | } 178 | j = 0; 179 | } 180 | //console.log(elemArr); 181 | elem.append(elemArr); 182 | } 183 | 184 | /** 185 | * 计算 boom 动画轨迹终止点 186 | * @param center 图片中心坐标 187 | * @param div 将要运动的图片坐标 188 | * @return {x,y} 返回点 div 的动画轨迹终止点 189 | */ 190 | function ramdomPosition(center, div) { 191 | var 192 | // 直线斜率 193 | slope = 0, 194 | // 爆炸范围 195 | randomBoomDis = Math.random() * 5, 196 | // 距离 197 | distance = randomBoomDis * (center.x > center.y ? center.x : center.y), 198 | // 结果 199 | result = { 200 | x: 0, 201 | y: 0 202 | }, 203 | // div 在中心点的上方还是下方 204 | isTop = center.y - div.y > 0 ? 1 : 0; 205 | 206 | if (center.x != div.x && center.y != div.y) { 207 | slope = (center.y - div.y) / (center.x - div.x); 208 | 209 | // y = kx + b 210 | var b = center.y - (slope * center.x); 211 | 212 | //console.log('斜率slope is:'+slope+',b is:'+b+',distance is:'+distance); 213 | 214 | // 轨迹终止的Y点 215 | // (2*div.y - center.y) : (distance + center.y) 216 | result.y = (isTop == true ? (2 * div.y - center.y) : (2 * div.y - center.y)) + ((Math.random() > 0.5 ? Math.random() * 4 : -Math.random() * 4)), 217 | // 轨迹终止的X点 218 | result.x = ((result.y - b) / slope) + ((Math.random() > 0.5 ? Math.random() * 4 : -Math.random() * 4)); 219 | 220 | return result; 221 | } else if (center.x == div.x) { 222 | if (center.y > div.y) { 223 | return { 224 | x: center.x, 225 | y: center.y - distance 226 | } 227 | } else { 228 | return { 229 | x: center.x, 230 | y: center.y + distance 231 | } 232 | } 233 | } else if (center.y == div.y) { 234 | if (center.x > div.x) { 235 | return { 236 | x: center.x - distance, 237 | y: center.y 238 | } 239 | } else { 240 | return { 241 | x: center.x + distance, 242 | y: center.y 243 | } 244 | } 245 | } else { 246 | return; 247 | } 248 | } 249 | 250 | boom.prototype = { 251 | init: function(elems) { 252 | var argLength = arguments.length; 253 | 254 | if (arguments[0] !== undefined) { 255 | this.boom(elems); 256 | } 257 | 258 | return this; 259 | }, 260 | boom: function(elems) { 261 | var elemLength = elems.length; 262 | 263 | if (!elemLength) { 264 | return; 265 | } else { 266 | elem = elems.eq(imgLength++).show(); 267 | } 268 | 269 | if (imgLength == elemLength) { 270 | imgLength = 0; 271 | } 272 | 273 | var randomNum = Math.random() * 2, 274 | certerPonit = { 275 | x: Math.floor(elem.width() / 2) + randomNum, 276 | y: Math.floor(elem.height() / 2) - randomNum 277 | } 278 | 279 | var newWrap = calcPosition(elem); 280 | // insertSmallDiv(newWrap); 281 | // elem.hide(); 282 | elem 283 | .delay(300, 'shake') 284 | .queue('shake', function(next) { 285 | // 300s 后隐藏原图 286 | $(this).animate({ 287 | opacity: 0 288 | }, { 289 | duration: 1 290 | }) 291 | next(); 292 | }) 293 | // 摇晃效果 294 | .dequeue('shake') 295 | .addClass('shake') 296 | .queue('shake', function() { 297 | insertSmallDiv(newWrap); 298 | 299 | var divs = newWrap.find('div'), 300 | length = divs.length, 301 | i = 0; 302 | 303 | for (; i < length; i++) { 304 | var div = divs.eq(i), 305 | divPoint = { 306 | x: parseInt(div.css('left')), 307 | y: parseInt(div.css('top')) 308 | } 309 | 310 | // 一些随机数添加 311 | var resultPoint = ramdomPosition(certerPonit, divPoint); 312 | //console.log(resultPoint); 313 | var randomOffset = arrRandomOffset[i % 9]; 314 | 315 | divs.eq(i).animate({ 316 | left: resultPoint.x + (Math.random() > 0.5 ? randomOffset : -randomOffset), 317 | top: resultPoint.y + (Math.random() > 0.5 ? randomOffset : -randomOffset), 318 | opacity: 0 319 | }, 800); 320 | } 321 | }); 322 | } 323 | } 324 | 325 | boom.prototype.init.prototype = boom.prototype; 326 | 327 | // 暴露变量 328 | window.boom = boom; 329 | 330 | })(window) 331 | -------------------------------------------------------------------------------- /src/cd_glaive.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/cd_glaive.cur -------------------------------------------------------------------------------- /src/cd_glowsword.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/cd_glowsword.cur -------------------------------------------------------------------------------- /src/css/Boom.css: -------------------------------------------------------------------------------- 1 | .shake{animation:shake 0.2s ease-in;-webkit-animation:shakeAm 0.2s ease-in} 2 | @keyframes shakeAm{ 3 | 0%{transform:rotateZ(0deg) translate(0,0)} 4 | 12.5%{transform:rotateZ(5deg) translate(6px,6px)} 5 | 25%{transform:rotateZ(0deg) translate(-4px,5px)} 6 | 37.5%{transform:rotateZ(-5deg) translate(-6px,-6px)} 7 | 50%{transform:rotateZ(0deg) translate(0,0)} 8 | 62.5%{transform:rotateZ(3deg) translate(3px,4px)} 9 | 75%{transform:rotateZ(0deg) translate(-3px,-2px)} 10 | 87.5%{transform:rotateZ(3deg) translate(3px,-2px)} 11 | 100%{transform:rotateZ(1deg) translate(-1px,1px)} 12 | } 13 | @-webkit-keyframes shakeAm{ 14 | 0%{transform:rotateZ(0deg) translate(0,0)} 15 | 12.5%{transform:rotateZ(5deg) translate(6px,6px)} 16 | 25%{transform:rotateZ(0deg) translate(-4px,5px)} 17 | 37.5%{transform:rotateZ(-5deg) translate(-6px,-6px)} 18 | 50%{transform:rotateZ(0deg) translate(0,0)} 19 | 62.5%{transform:rotateZ(3deg) translate(3px,4px)} 20 | 75%{transform:rotateZ(0deg) translate(-3px,-2px)} 21 | 87.5%{transform:rotateZ(3deg) translate(3px,-2px)} 22 | 100%{transform:rotateZ(1deg) translate(-1px,1px)} 23 | } 24 | @-moz-keyframes shakeAm{ 25 | 0%{transform:rotateZ(0deg) translate(0,0)} 26 | 12.5%{transform:rotateZ(5deg) translate(6px,6px)} 27 | 25%{transform:rotateZ(0deg) translate(-4px,5px)} 28 | 37.5%{transform:rotateZ(-5deg) translate(-6px,-6px)} 29 | 50%{transform:rotateZ(0deg) translate(0,0)} 30 | 62.5%{transform:rotateZ(3deg) translate(3px,4px)} 31 | 75%{transform:rotateZ(0deg) translate(-3px,-2px)} 32 | 87.5%{transform:rotateZ(3deg) translate(3px,-2px)} 33 | 100%{transform:rotateZ(1deg) translate(-1px,1px)} 34 | } 35 | -------------------------------------------------------------------------------- /src/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | BoomJS演示Demo 7 | 8 | 42 | 43 | 44 |
45 | 46 | 47 |
48 | 49 | 50 | 51 |
点我BOOM
52 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/images.jpg -------------------------------------------------------------------------------- /src/images/images.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/images/images.jpg -------------------------------------------------------------------------------- /src/images/images2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/images/images2.jpg -------------------------------------------------------------------------------- /src/images2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chokcoco/boomJS/74c9ea9c2f39300696ef6f317225d434907f65c2/src/images2.jpg -------------------------------------------------------------------------------- /src/js/Boom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Coco 3 | * QQ:308695699 4 | * @name boomJS 1.0.0 5 | * @description 一个有趣的效果,用 JavaScript 实现让图片爆炸的动画(非Canvas) 6 | * -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 7 | * 1、本组件用于是学习 jQuery 队列时做的一个小 demo,使用 JavaScript 配合 CSS3 实现一个简单的动画效果 8 | * 9 | * 2、依赖 jQuery,为了方便在其他页面复用,单独出一个 Boom.css 放入核心样式; 10 | 11 | * 3、初始化方法, 12 | * 1)提供 var bom = new boom() 构造函数,构建 boom 实例,调用 bom.boom(),传入 img 的 jQuery 对象,例如bom.boom($('img')) 13 | * 2)直接 boom() 进行调用,传入 img 的 jQuery 对象,例如 boom($('img')) 14 | * 15 | * 4、动画预设,支持传入不同参数调整效果 16 | * boom($('img'),{ 17 | * 'scaleLevel' : 3, 18 | * 'blurLevel': 9, 19 | * 'boomLevel': 4, 20 | * 'boomTime':800, 21 | * 'isOpenLog':true 22 | * }); 23 | * 24 | * 5、目前只支持未经过缩放的图片 25 | * 26 | */ 27 | (function(window, undefined) { 28 | var 29 | // 是否插入了 jQuery 30 | isInsetJq = false, 31 | // css参数预设 32 | cssOption = { 33 | position: 'absolute', 34 | width: 0, 35 | height: 0, 36 | left: 0, 37 | top: 0 38 | }, 39 | // 存储图片地址 40 | imgUrl = "", 41 | // 暴露的最终变量 42 | boom = function(elems, options) { 43 | return new boom.prototype.init(elems, options); 44 | }, 45 | // 图片集 46 | imgArr = [], 47 | // 传入的图片个数 48 | imgLength = 0, 49 | // 动画效果预设参数 50 | argOptions = { 51 | // 缩放值 52 | 'scaleLevel': 3, 53 | // 模糊值 54 | 'blurLevel': 3, 55 | // 弹射距离 56 | 'boomLevel': 4, 57 | // 爆炸时长 58 | 'boomTime': 800, 59 | // 是否打开日志,所有日志写在 log 方法里 60 | 'isOpenLog': false 61 | }, 62 | // 偏移距离 63 | arrRandomOffset = [1, -4, 8, -12, 16, -20, 24, -28, 32]; 64 | 65 | // 加载js 66 | function loadScript(url, callback) { 67 | if (isInsetJq) { 68 | return; 69 | } 70 | 71 | var ref = window.document.getElementsByTagName("script")[0], 72 | script = window.document.createElement("script"); 73 | 74 | script.src = url; 75 | script.type = 'text/javascript'; 76 | script.async = false; 77 | ref.parentNode.insertBefore(script, ref); 78 | 79 | if (callback && typeof(callback) === "function") { 80 | script.onload = callback; 81 | } 82 | 83 | isInsetJq = true; 84 | } 85 | 86 | // 日志控制 87 | function log() { 88 | if (argOptions.isOpenLog) { 89 | console.log.apply(console, arguments); 90 | } 91 | } 92 | 93 | // 偏移距离设置 94 | function arrRandomOff(level) { 95 | var i = 0; 96 | 97 | // reset array 98 | arrRandomOffset = []; 99 | 100 | for (; i < 9; i++) { 101 | arrRandomOffset[i] = level * i; 102 | } 103 | 104 | log('arrRandomOffset is ' + arrRandomOffset) 105 | } 106 | 107 | // 计算坐标并添加新的层覆盖在原图上 108 | // 返回一个 jQuery 对象(dom 节点,是一个和图片高宽绝对定位坐标一致的 div) 109 | function calcPosition(elem) { 110 | imgUrl = elem.attr('src') || ""; 111 | 112 | // 转化为 JS 对象 113 | var obj = elem[0]; 114 | 115 | // getBoundingClientRect 方法返回元素的大小及其相对于视口的位置 116 | // 这是个 JS 对象方法,注意下文和 jQuery 对象的相互转换 117 | var posi = obj.getBoundingClientRect(), 118 | // 图片的宽高和定位 119 | elemCss = { 120 | width: obj.width, 121 | height: obj.height, 122 | top: posi.top, 123 | left: posi.left, 124 | }, 125 | // 生成新的 div 的 css 样式 126 | realCss = $.extend(cssOption, elemCss); 127 | 128 | var newDiv = $(document.createElement('div')); 129 | 130 | newDiv.css(realCss); 131 | 132 | $('body').append(newDiv); 133 | 134 | return newDiv; 135 | } 136 | 137 | /** 138 | * 在原图上生成小的 div 块 139 | * @param elem 原图的 jQuery 对象 140 | */ 141 | function insertSmallDiv(elem) { 142 | var obj = elem, 143 | width = elem.width(), 144 | height = elem.height(), 145 | miniNum = 10, 146 | widthNum = 0, 147 | heightNum = 0, 148 | // div 小块的宽度 149 | newElemWidth = 0, 150 | i = 0, 151 | j = 0, 152 | elemArr = []; 153 | 154 | log(width + ',' + height); 155 | 156 | if (width <= 10 && height <= 10) { 157 | return; 158 | } 159 | 160 | var basePoint = width > height ? height : width; 161 | 162 | log('base point is :' + basePoint); 163 | 164 | if (basePoint == width) { 165 | newElemWidth = Math.floor(width / miniNum); 166 | heightNum = Math.floor(height / newElemWidth); 167 | widthNum = miniNum; 168 | } else { 169 | newElemWidth = Math.floor(height / miniNum); 170 | heightNum = Math.floor(width / newElemWidth); 171 | widthNum = miniNum; 172 | } 173 | 174 | log('widthNum:' + widthNum + ',height:' + heightNum + ',width:' + newElemWidth); 175 | 176 | // 比较宽高大小,确定插入的行数 177 | if (height > width) { 178 | // 交换 width ,height 的值 179 | widthNum = widthNum * heightNum; 180 | heightNum = widthNum / heightNum; 181 | widthNum = widthNum / heightNum; 182 | } 183 | 184 | log('widthNum:' + widthNum + ',heightNum:' + heightNum + ',newElemWidth:' + newElemWidth); 185 | 186 | // 插入每个小 div 块,并定位 187 | for (; i < widthNum; i++) { 188 | for (; j < heightNum; j++) { 189 | var randomSize = Math.random() * argOptions.scaleLevel, 190 | randomBlur = Math.random() * argOptions.blurLevel, 191 | newElem = document.createElement('div'), 192 | cssTop = i * newElemWidth, 193 | cssLeft = j * newElemWidth, 194 | posiElemCss = { 195 | 'background-image': 'url(' + imgUrl + ')', 196 | 'background-repeat': 'no-repeat', 197 | 'background-position': '-' + cssLeft + 'px ' + '-' + cssTop + 'px', 198 | 'position': 'absolute', 199 | 'width': newElemWidth, 200 | 'height': newElemWidth, 201 | 'border-radius': '100%', 202 | 'top': 0, 203 | 'left': 0, 204 | 'top': cssTop, 205 | 'left': cssLeft, 206 | // 每个小块随机缩放,看上去更加真实 207 | 'transform': 'scale(' + randomSize + ')', 208 | // 加入 css3 毛玻璃效果,效果更佳,看上去更加3d 209 | '-webkit-filter': 'blur(' + randomBlur + 'px)', 210 | '-moz-filter': 'blur(' + randomBlur + 'px)', 211 | '-ms-filter': 'blur(' + randomBlur + 'px)', 212 | 'filter': 'blur(' + randomBlur + 'px)' 213 | }; 214 | log('cssTop is:' + cssTop + ',cssLeft is:' + cssLeft + ',posiElemCss:' + posiElemCss); 215 | $(newElem).css(posiElemCss); 216 | elemArr.push(newElem); 217 | } 218 | j = 0; 219 | } 220 | log(elemArr); 221 | elem.append(elemArr); 222 | } 223 | 224 | /** 225 | * 计算 boom 动画轨迹终止点 226 | * @param center 图片中心坐标 227 | * @param div 将要运动的图片坐标 228 | * @return {x,y} 返回点 div 的动画轨迹终止点 229 | */ 230 | function ramdomPosition(center, div) { 231 | var 232 | // 直线斜率 233 | slope = 0, 234 | // 爆炸范围 235 | randomBoomDis = Math.random() * 5, 236 | // 距离 237 | distance = randomBoomDis * (center.x > center.y ? center.x : center.y), 238 | // 结果 239 | result = { 240 | x: 0, 241 | y: 0 242 | }, 243 | // div 在中心点的上方还是下方 244 | isTop = center.y - div.y > 0 ? 1 : 0; 245 | 246 | if (center.x != div.x && center.y != div.y) { 247 | slope = (center.y - div.y) / (center.x - div.x); 248 | 249 | // 直线公式:y = kx + b 250 | var b = center.y - (slope * center.x), 251 | randomPosX = Math.random(), 252 | randomPosY = Math.random(); 253 | 254 | log('斜率slope is:' + slope + ',b is:' + b + ',distance is:' + distance); 255 | 256 | // 轨迹终止的Y点 257 | result.y = ((2 * div.y - center.y)) + ((randomPosX > 0.5 ? randomPosX * 4 : -randomPosX * 4)), 258 | // 轨迹终止的X点 259 | result.x = ((result.y - b) / slope) + ((randomPosY > 0.5 ? randomPosY * 4 : -randomPosY * 4)); 260 | 261 | return result; 262 | } else if (center.x == div.x) { 263 | if (center.y > div.y) { 264 | return { 265 | x: center.x, 266 | y: center.y - distance 267 | } 268 | } else { 269 | return { 270 | x: center.x, 271 | y: center.y + distance 272 | } 273 | } 274 | } else if (center.y == div.y) { 275 | if (center.x > div.x) { 276 | return { 277 | x: center.x - distance, 278 | y: center.y 279 | } 280 | } else { 281 | return { 282 | x: center.x + distance, 283 | y: center.y 284 | } 285 | } 286 | } else { 287 | return; 288 | } 289 | } 290 | 291 | // boom 对象 292 | boom.prototype = { 293 | init: function(elems, options) { 294 | var argLength = arguments.length; 295 | 296 | if (arguments[0] !== undefined) { 297 | this.boom(elems); 298 | } 299 | 300 | argOptions = $.extend(argOptions, options); 301 | 302 | log('argOptions is '); 303 | log(argOptions); 304 | 305 | // 修改弹射距离 306 | if (argOptions.boomLevel != 4) { 307 | arrRandomOff(argOptions.boomLevel); 308 | } 309 | 310 | return this; 311 | }, 312 | boom: function(elems) { 313 | var elemLength = elems.length; 314 | 315 | if (!elemLength) { 316 | return; 317 | } else { 318 | elem = elems.eq(imgLength++).css({ 319 | "opacity": "1" 320 | }); 321 | } 322 | 323 | if (imgLength == elemLength) { 324 | imgLength = 0; 325 | } 326 | 327 | var randomNum = Math.random() * 2, 328 | certerPonit = { 329 | x: Math.floor(elem.width() / 2) + randomNum, 330 | y: Math.floor(elem.height() / 2) - randomNum 331 | } 332 | 333 | var newWrap = calcPosition(elem); 334 | // insertSmallDiv(newWrap); 335 | // elem.hide(); 336 | elem 337 | .delay(200, 'shake') 338 | .queue('shake', function(next) { 339 | // 300s 后隐藏原图 340 | $(this).animate({ 341 | opacity: 0 342 | }, { 343 | duration: 1 344 | }) 345 | // 这里移除 shake 是为了二次触发 346 | .removeClass('shake'); 347 | 348 | next(); 349 | }) 350 | // 摇晃效果 351 | .dequeue('shake') 352 | .addClass('shake') 353 | .queue('shake', function() { 354 | insertSmallDiv(newWrap); 355 | 356 | var divs = newWrap.find('div'), 357 | length = divs.length, 358 | i = 0; 359 | 360 | for (; i < length; i++) { 361 | var div = divs.eq(i), 362 | divPoint = { 363 | x: parseInt(div.css('left')), 364 | y: parseInt(div.css('top')) 365 | } 366 | 367 | // 一些随机数添加 368 | var resultPoint = ramdomPosition(certerPonit, divPoint); 369 | log(resultPoint); 370 | var randomOffset = arrRandomOffset[i % 9]; 371 | 372 | divs.eq(i).animate({ 373 | left: resultPoint.x + (Math.random() > 0.5 ? randomOffset : -randomOffset), 374 | top: resultPoint.y + (Math.random() > 0.5 ? randomOffset : -randomOffset), 375 | opacity: 0 376 | }, argOptions.boomTime); 377 | } 378 | }); 379 | } 380 | } 381 | 382 | boom.prototype.init.prototype = boom.prototype; 383 | 384 | // 暴露变量 385 | window.boom = boom; 386 | 387 | })(window) 388 | --------------------------------------------------------------------------------