Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>RxJS</title>
    <link rel="stylesheet" href="css/index.css"/>
</head>
<body>
    <div class="container">
        <div class="header">
            <button id="btn" class="left">Try!</button>
            <div class="right">
                <p><svg height="12" width="12"> <circle cx="6" cy="6" r="6" fill="#69c2d8"></circle> </svg>click</p>
                <p><svg height="12" width="12"> <circle cx="6" cy="6" r="6" fill="#ed145b"></circle> </svg>alt+click</p>
            </div>
        </div>
        <div id="marbles">
            <div class="timeline"><div class="progressbar"></div></div>
            <div class="filter">filter()</div>
            <div class="timeline"><div class="progressbar"></div></div>
        </div>
    </div>
    <script src="//code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.11.7/TweenMax.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/rxjs/2.3.22/rx.all.js"></script>
</body>
</html>
 
/* line 3, ../sass/index.scss */
body {
  font-family: sans-serif;
  color: #31332e;
}
/* line 8, ../sass/index.scss */
.right {
  float: right;
}
/* line 12, ../sass/index.scss */
.left {
  float: left;
}
/* line 16, ../sass/index.scss */
#btn {
  width: 138px;
  text-align: center;
  border: 1px solid #52b0c7;
  box-shadow: 0 3px #308fa7;
  color: white;
  font-family: Helvetica, Verdana, sans-serif;
  font-weight: lighter;
  font-style: italic;
  font-size: 13px;
  letter-spacing: 1px;
  padding: 7px 35px;
  padding-top: 9px;
  border-radius: 5px;
  position: relative;
  background: #68c2d8;
  /* Old browsers */
  background: -moz-linear-gradient(top, #68c2d8 0%, #41b2cd 100%);
  /* FF3.6+ */
  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #68c2d8), color-stop(100%, #41b2cd));
  /* Chrome,Safari4+ */
  background: -webkit-linear-gradient(top, #68c2d8 0%, #41b2cd 100%);
  /* Chrome10+,Safari5.1+ */
  background: -o-linear-gradient(top, #68c2d8 0%, #41b2cd 100%);
  /* Opera 11.10+ */
  background: -ms-linear-gradient(top, #68c2d8 0%, #41b2cd 100%);
  /* IE10+ */
  background: linear-gradient(to bottom, #68c2d8 0%, #41b2cd 100%);
  /* W3C */
  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#68c2d8', endColorstr='#41b2cd', GradientType=0);
  /* IE6-9 */
}
/* line 40, ../sass/index.scss */
#btn:active {
  box-shadow: 0 1px #308fa7;
  top: 2px;
}
/* line 45, ../sass/index.scss */
#btn:focus {
  outline: 0;
}
/* line 50, ../sass/index.scss */
.container {
  position: relative;
  width: 605px;
  padding: 60px 10px;
}
/* line 54, ../sass/index.scss */
.container .header {
  overflow: hidden;
}
/* line 57, ../sass/index.scss */
.container .header .right p {
  display: inline-block;
  margin-left: 2em;
}
/* line 61, ../sass/index.scss */
.container .header .right svg {
  margin-right: 0.5em;
}
/* line 68, ../sass/index.scss */
.event-marker {
  position: absolute;
  top: -5px;
}
/* line 71, ../sass/index.scss */
.event-marker.scale-up {
  -moz-transform: scale(0);
  -ms-transform: scale(0);
  -webkit-transform: scale(0);
  transform: scale(0);
  -moz-animation-name: scaleUp;
  -webkit-animation-name: scaleUp;
  animation-name: scaleUp;
  -moz-animation-duration: 0.3s;
  -webkit-animation-duration: 0.3s;
  animation-duration: 0.3s;
  -moz-animation-fill-mode: both;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
/* line 77, ../sass/index.scss */
.event-marker.fadeOut {
  -moz-animation-name: fadeOut;
  -webkit-animation-name: fadeOut;
  animation-name: fadeOut;
  -moz-animation-delay: 0.3s;
  -webkit-animation-delay: 0.3s;
  animation-delay: 0.3s;
  -moz-animation-duration: 0.5s;
  -webkit-animation-duration: 0.5s;
  animation-duration: 0.5s;
  -moz-animation-fill-mode: both;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
/* line 83, ../sass/index.scss */
.event-marker.go-down {
  -moz-animation-name: go-down;
  -webkit-animation-name: go-down;
  animation-name: go-down;
  -moz-animation-delay: 0.3s;
  -webkit-animation-delay: 0.3s;
  animation-delay: 0.3s;
  -moz-animation-duration: 1.2s;
  -webkit-animation-duration: 1.2s;
  animation-duration: 1.2s;
  -moz-animation-fill-mode: both;
  -webkit-animation-fill-mode: both;
  animation-fill-mode: both;
}
/* line 93, ../sass/index.scss */
.filter {
  border: 1px dashed #9e9f9d;
  text-align: center;
  padding: 18px;
  margin: 30px 0;
  font-style: italic;
  letter-spacing: 1px;
  color: #313131;
}
/* line 103, ../sass/index.scss */
.timeline {
  height: 2px;
  background: #d0d0d0;
  position: relative;
}
/* line 107, ../sass/index.scss */
.timeline::after {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  border-top: 2px solid #D0D0D0;
  border-right: 2px solid #D0D0D0;
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  position: absolute;
  right: 0;
  top: 4px;
  margin-top: -7px;
}
/* line 121, ../sass/index.scss */
.timeline .progressbar {
  width: 0;
  height: 100%;
  background: #4C4C4C;
}
/* line 126, ../sass/index.scss */
.timeline.end::after {
  border-color: #4C4C4C;
}
/* line 131, ../sass/index.scss */
#marbles {
  position: relative;
  margin-top: 60px;
}
@-moz-keyframes scaleUp {
  100% {
    transform: scale(1);
  }
}
@-webkit-keyframes scaleUp {
  100% {
    transform: scale(1);
  }
}
@keyframes scaleUp {
  100% {
    transform: scale(1);
  }
}
@-moz-keyframes fadeOut {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -moz-transform: translateY(70px);
    transform: translateY(70px);
    opacity: 0;
  }
}
@-webkit-keyframes fadeOut {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -webkit-transform: translateY(70px);
    transform: translateY(70px);
    opacity: 0;
  }
}
@keyframes fadeOut {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -moz-transform: translateY(70px);
    -ms-transform: translateY(70px);
    -webkit-transform: translateY(70px);
    transform: translateY(70px);
    opacity: 0;
  }
}
@-moz-keyframes go-down {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -moz-transform: scale(1);
    transform: scale(1);
    -moz-transform: translateY(116px);
    transform: translateY(116px);
  }
}
@-webkit-keyframes go-down {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
    -webkit-transform: translateY(116px);
    transform: translateY(116px);
  }
}
@keyframes go-down {
  0% {
    opacity: 0;
  }
  20% {
    opacity: 1;
  }
  100% {
    -moz-transform: scale(1);
    -ms-transform: scale(1);
    -webkit-transform: scale(1);
    transform: scale(1);
    -moz-transform: translateY(116px);
    -ms-transform: translateY(116px);
    -webkit-transform: translateY(116px);
    transform: translateY(116px);
  }
}
 
# global var
$btn = $('#btn')
$timeline = $('.timeline')
$progressbar = $timeline.find('.progressbar')
$marbles = $('#marbles')
btnClicks = Rx.Observable.fromEvent($btn, "click")
shockwave = '<svg height="150" width="150" style="position: absolute;pointer-events:none;"> <circle cx="50%" cy="50%" r="0" fill-opacity="1"></circle> </svg>'
click_event_marker = '<svg class="event-marker" height="12" width="12"> <circle cx="50%" cy="50%" r="50%" fill="#69c2d8"></circle> </svg>'
click_alt_event_marker = '<svg class="event-marker" height="12" width="12"> <circle cx="50%" cy="50%" r="50%" fill="#ed145b"></circle> </svg>'
$all_event_markers = $()
# ====================== 事前準備 ======================
# ===== `text()`を拡張して、リセットできるようにする =====
do ->
    original_text_fn = $.fn.text
    $.fn.text = ()->
        @each ->
            $this = $(@)
            if $this.data('original_text') then return
            $this.data('original_text', original_text_fn.apply(@))
        return original_text_fn.apply(@, arguments)
    $.fn.reset_text = ()->
        @each ()->
            $this = $(@)
            original_text = $this.data('original_text')
            if(original_text) then $this.text(original_text)
# ===== タイムラインのアニメーションの開始とリセットメソッド =====
$timeline.play = (duration, promise)->
    (new TimelineLite())
    .to($progressbar, duration / 1000, width: '100%', ease: Linear.easeNone)
    .add ()->
        $timeline.addClass('end')
        promise.resolve()
$timeline.rewind = ->
    $progressbar.css(width: 0)
    $timeline.removeClass('end')
    $all_event_markers.remove()
# ====================== メインプログラム ======================
set_program = ->
    btnClicks = Rx.Observable.fromEvent($btn, "click")
    d = new $.Deferred
    animation = {
        duration: 5000
        start_time: null
        get_percentage: ->
            time = (new Date()).getTime()
            return ((time - @start_time) / @duration) * 100
        click_alt: ()->
            @drop_event_marker(click_alt_event_marker, 'go-down')
        click: ()->
            @drop_event_marker(click_event_marker, 'fadeOut')
        shockwave: (coordinate)->
            $shockwave = $(shockwave).appendTo('body')
            $shockwave_circle = $shockwave.find('circle').attr('fill', coordinate.color)
            (new TimelineLite())
            .set($shockwave, left: coordinate.x - 75, top: coordinate.y - 75)
            .to($shockwave_circle, 0.5, attr: {'fill-opacity': 0, r: 75}, ease: Quad.easeOut)
            .add ->$shockwave.remove()
        drop_event_marker: (pointer, class_name)->
            left = @get_percentage() + '%'
            $click_event = $(pointer).css('left': left)
            $click_event[0].classList.add('scale-up')
            $click_event_down = $(pointer).css('left': left)
            $click_event_down[0].classList.add(class_name)
            $marbles.append($click_event)
            $marbles.append($click_event_down)
            $all_event_markers = $all_event_markers.add($click_event).add($click_event_down)
        start: ->
            @start_time = (new Date()).getTime()
            $timeline.play(@duration, d)
            $btn.text('click me')
    }
    btnClicks
    .take(1)# take the first event only
    .subscribe -> # when user click the button then ...
        $timeline.rewind() # init the animation of `time-line`
        animation.start() # start animation
        btnClicks
        .filter (event)->
            return event.altKey
        .takeUntil(d.promise())
        .subscribe($.proxy(animation.click_alt, animation))
        btnClicks
        .filter (event)->
            return !event.altKey
        .takeUntil(d.promise())
        .subscribe($.proxy(animation.click, animation))
        btnClicks
        .map (event)->
            return {x: event.pageX, y: event.pageY, color: if event.altKey then '#ed145b' else '#69c2d8'}
        .subscribe($.proxy(animation.shockwave, animation))
    return d.promise()
reset_program = ->
    $btn.reset_text()
    run_program()
run_program = -> set_program().then(reset_program)
run_program()
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x