2019-01-06

用 jQuery 简单封装两个小案例

jQuery 官网
示例源码

手风琴

这里实现的只是横坐标方向的,考虑的情况不多,不然咋叫简单封装呢。好啦,咱们来娱乐一下。


实现思路:

  1. 获取包裹手风琴的盒子,并将其转成 jQuery 对象。获取指定的显示宽度(除激活琴子外的琴子),以及容器盒子的宽度。
  2. 获取容器下的 li 标签列表,计算激活琴子的显示宽度和光标移开琴子容器时每个琴子的平均宽度。
  3. 给每个 li 节点对象注册 mouseentermouseleave 事件,两者都是负责光标移入移出时各琴子的宽度渐变。


函数体接受三个参数,分别为 ele, width, decorator,然后利用参数计算出各配置,下面看代码和注释

// 无论是 JS DOM 对象还是字符串,都转成 jQuery 对象(传 jQuery 对象也可以)
$ele = ele.length > 1 ? $(ele).eq(0) : $(ele)
// 若指定了宽度则按宽度来显示其余琴子,否则,被激活的琴子占满宽
width = width || 0
// 可以接受颜色组或图片地址来上样式
decorator = decorator || []
var $liArr = $ele.find('li')
var boxWidth = $ele.width()
var activeWidth = boxWidth - ($liArr.length - 1) * width
var averageWidth = boxWidth / $liArr.length

if (decorator) {
  // 通过 '.' 来判断有无文件
  if (decorator[0].indexOf('.') === -1) {
    $liArr.each(function (i, el) {
      $(el).css('backgroundColor', decorator[i])
    })
  } else {
    $liArr.each(function (i, el) {
      $(el).css('backgroundImage', 'url(' + decorator[i] + ')')
    })
  }
}


两个事件里,stop() 清除未完成的动画不可少,顺序也很重要。你可能很好奇,为什么在 "真正的动画" 开始前,给她增加一个像素,并且是动画,而不是 css,然后又在动画回调后复位了。

在这儿,我找不到更好的解决方法来保证她在动画执行时最后一个琴子完全不下坠,即使已经设置 overflow: hidden;。但可以发现这是个速度增长的问题,虽然激活琴子的动画在其它琴子前面执行(队列不会延时太迟),但现实是 1 : $liArr.length - 1 的增长速度差异,导致最后一个琴子发生闪烁和上下剧烈抖动。我试着给她们的动画加 speed 比例来调整增长速度,结果不理想,很难达到同步增长一致性。所以在两个事件里都添加多增加 1px 的动画,因为直接上 css 也崩,为什么只有 animate 拯救我 o(╥﹏╥)o。若大伙有可行的解决方案,还请多多指教。

$liArr.on('mouseenter', function () {
  $ele.stop().animate({width: boxWidth+1})
  $(this).stop().animate({width: activeWidth}, function () {
      $ele.stop().animate({width: boxWidth})
    })
    .siblings().stop().animate({width: width})

})
$ele.on('mouseleave', function () {
  $ele.stop().animate({width: boxWidth+1})
  $liArr.stop().animate({width: averageWidth})
  setTimeout(function () {
    $ele.css({width: boxWidth})
  }, 400)
})


来自四面八方的弹幕效果

函数体接受一个 options 对象,该参数必须包含 buttoninput 两个属性,containercolor 是可选的,前两者分别表示触发弹幕发射按钮,承载信息的文本域;后两者分别表示弹幕潇洒的舞台(我要整个世界),弹幕字体随机颜色组(我的颜色更多)。

实现思路:

  1. 获取了相关条件参数,处理得到三个 jQuery 对象和弹幕舞台的大小。
  2. 给按钮注册点击事件,使其获取文本域的信息、随机颜色、随机速度、随机起始点,通过规则约束控制,最后在舞台盒子外围坐标随机生成弹幕,往我们控制的方向去移动。
  3. 给文本域注册 keydown 事件,输入弹幕内容时,直接敲 Enter 就能够触发按钮的 click 的事件。

规则约束是为了避免弹幕直接在可视区域生成,于可视区域消失,这个魔术会吓着人的。


一起来看代码和注释

if (!options.button && !options.input) {
  return false
}
// 和手风琴类似的
var $btn = options.button.length > 1 ? $(options.button).eq(0) : $(options.button)
var $input = options.input.length > 1 ? $(options.input).eq(0) : $(options.input)
var $box = options.container ? $(options.container) : $('body')
var colors = options.color ? options.color : null
var width, height, disX, disY
// 辅助(也许你有其它想法),使投放弹幕起始点在盒子边界外,先往下看
disX, disY = 200
$btn.on('click', function () {
  var msg = $input.val()
  var color = colors ? colors[rndBetween(0, colors.length)] : rndColor()
  var speed = rndBetween(5000, 10000)
  var startX, startY, endX, endY
  // 为区域范围值分配发生概率
  startX = probabilityDistributor([-disX, 0, width, width + disX], [0.4, 0.3, 0.4])
})


这儿有三个函数:

rndBetween 即是 parseInt(Math.random() * (right - left) + left) 计算后的值。
rndColor 返回一个随机颜色。
probabilityDistributor 是一个区间范围内指定发生概率的分配器,返回经过随机处理的值。例如参数一 [-5, 0, 5, 10],参数二 [0.4, 0.3, 0.4],指定了 [-5, 0] 区间发生的概率为 0.4,[0, 5] 发生的概率为 0.3,以此类推。

经过上面的计算,我们已经拥有弹幕内容,颜色,速度,以及在舞台外围随机生成的 startX,接着来看约束规则。

注意:下面这两块代码也是在按钮点击事件函数命名空间下的。


// 利用走斜对角自定义的规则,确保弹幕都在容器外围生成。
if (startX < 0 || startX > width) {
  // 左右两侧,startY 可以在很大一块区域,动动手画图
  startY = rndBetween(-disY, height + disY)
} else {
  // 否则在舞台中间,Y 值不允许在中间,避免了在可视区域生成弹幕,石头剪刀布决定上下吧
  if (Math.random() < 0.5) {
    startY = rndBetween(-disY, 0)
  } else {
    startY = rndBetween(height, height + disY)
  }
}

// 上面的规则保证了起始位置一定是在舞台外围,下面是确保散场规则
// 为避免在可视区域消失,这里要使其超出容器宽度,再控制高度即可(本示例按距边界1/3来计算)
if (startX < 0 || startX > width) {
  if (startX < 0) {
    endX = rndBetween(width, width + disX)
  } else {
    endX = rndBetween(-disX, 0)
  }

  if (startY < height/3) {
    // 起始点在左右两侧且位于上部,用斜对角规则来控制
    endY = rndBetween(height/3, height + disY)
  } else if (startY > height * 2/3) {
    // 下部
    endY = rndBetween(-disY, height/3)
  } else {
    // 中间
      endY = rndBetween(-disY, height + disY)
    }
  }
else {
  // startX 在中间,那么 startY 在上下边界外,endY 走反方向即可(猜拳)
  endX = rndBetween(disX, width - disX)
  if (startY > height) {
    endY = rndBetween(-disY, 0)
  } else {
    endY = rndBetween(height, height + disY)
  }
}


自定义的规则难免有不足之处,你会发现弹幕在某些方向出现的概率很低。当然,我们的概率发生分配器是没有问题的,通过调整分配的概率确实能
改变上下或左右发生的概率。漏洞出现在规则本身,disXdisY 以及 1/3 的舞台尺寸和对角界限,这几处让我感到设计本身的不完美,难道我还能打你嘛?
就是因为凭一个随机数来确定另三个随机数,虽然可以颠倒一些顺序,但最终还是处于随机数 相互约束 的窘境,况且不想硬编码,我是无奈得两匹呀!除非,除非你帮我 (,,・∀・)ノ゛ ?

自认为,上面的代码还是挺臃肿的,多少个 if 语句了都。但不论如何,弹幕照常有吐槽,咋们的效果还是不错的,管你是丑小鸭还是白天鹅,通通飞起来。

// 接着,直接将文本节点,样式属性,动画给加上
$('<span></span>').text(msg)
  .css('position', 'absolute')
  .css('color', color)
  .css('left', startX)
  .css('top', startY)
  .animate({'left': endX, 'top': endY}, speed, 'linear', function () {
    // 表演结束
    $(this).remove()
  })
  // 弹幕的舞台
  .appendTo($box)

// 清空文本域
$input.val('')

最后注册按键事件即可。


End.
若有不足,还请高人指教。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 卡尔曼滤波视频学习记录 资源来源:Michel van Biezen SPECIAL TOPICS THE KAL...
    CDREAMY阅读 1,154评论 0 1
  • 原贴地址:http://www.bioinfo-scrounger.com/archives/639 Pathvi...
    苏慕晨枫阅读 3,398评论 0 6
  • 1 真正的平淡是指,生命中曾经历过轰轰烈烈与刻骨铭心后,才感悟到平淡的可贵。而不是一生碌碌无为,却安慰自己平凡是真...
    巴中张公子阅读 520评论 0 0
  • “ 当一个人跳进水里,真正托起他的,不是接触他皮肤的那些少量的水,而是身下大量你接触不到的水。”
    晓一岁阅读 373评论 0 1
  • 你会见到很多人,你会说出很多再见,你会有很多无奈,你会有很多相遇,你会收获很多惊喜。你会被生活学会很多。 两个人相...
    幸福的阿豪_阅读 216评论 0 0